View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  
18  /*
19   * $Id: SubstringEnumerator.java,v 1.2 2003/10/17 00:10:46 akarasulu Exp $
20   *
21   * -- (c) LDAPd Group                                                    --
22   * -- Please refer to the LICENSE.txt file in the root directory of      --
23   * -- any LDAPd project for copyright and distribution information.      --
24   *
25   * Created on Oct 13, 2003
26   */
27  package org.apache.ldap.server.db;
28  
29  
30  import org.apache.ldap.common.filter.ExprNode;
31  import org.apache.ldap.common.filter.SubstringNode;
32  import org.apache.ldap.common.schema.AttributeType;
33  import org.apache.ldap.common.schema.Normalizer;
34  import org.apache.ldap.server.schema.AttributeTypeRegistry;
35  import org.apache.regexp.RE;
36  import org.apache.regexp.RESyntaxException;
37  
38  import javax.naming.NamingEnumeration;
39  import javax.naming.NamingException;
40  
41  
42  /***
43   * Enumerator that creates a NamingEnumeration over the set of candidates that 
44   * satisfy a substring filter expression.
45   * 
46   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
47   * @version $Rev: 159372 $
48   */
49  public class SubstringEnumerator implements Enumerator
50  {
51      /*** Database used */
52      private final Database db;
53      /*** Evaluator used is an Avalon dependent object */
54      private final SubstringEvaluator evaluator;
55      /*** the attribute type registry */
56      private final AttributeTypeRegistry attributeTypeRegistry;
57  
58  
59      /***
60       * Creates a SubstringEnumerator for a database.
61       *
62       * @param db the database
63       * @param evaluator a substring evaluator
64       */
65      public SubstringEnumerator( Database db,
66                                  AttributeTypeRegistry attributeTypeRegistry,
67                                  SubstringEvaluator evaluator )
68      {
69          this.db = db;
70          this.evaluator = evaluator;
71          this.attributeTypeRegistry = attributeTypeRegistry;
72      }
73  
74  
75      // ------------------------------------------------------------------------
76      // SubstringEnumerator Methods
77      // ------------------------------------------------------------------------
78      
79      
80      /***
81       * @see Enumerator#enumerate(
82       * org.apache.ldap.common.filter.ExprNode)
83       */
84      public NamingEnumeration enumerate( final ExprNode node )
85          throws NamingException
86      {
87          RE regex = null;
88          Index idx = null;
89          final SubstringNode snode = ( SubstringNode ) node;
90          AttributeType type = attributeTypeRegistry.lookup( snode.getAttribute() );
91          Normalizer normalizer = type.getSubstr().getNormalizer();
92  
93          if ( db.hasUserIndexOn( snode.getAttribute() ) )
94          {
95              /*
96               * Build out regex in this block so we do not do it twice in the
97               * evaluator if there is no index on the attribute of the substr ava
98               */
99              try 
100             {
101                 regex = snode.getRegex( normalizer );
102             } 
103             catch ( RESyntaxException e ) 
104             {
105                 NamingException ne = new NamingException( "SubstringNode '" 
106                     + node + "' had incorrect syntax" );
107                 ne.setRootCause( e );
108                 throw ne;
109             }
110 
111             /*
112              * Get the user index and return an index enumeration using the the
113              * compiled regular expression.  Try to constrain even further if
114              * an initial term is available in the substring expression.
115              */
116             idx = db.getUserIndex( snode.getAttribute() );
117             if ( null == snode.getInitial() )
118             {
119                 return idx.listIndices( regex );
120             } 
121             else 
122             {
123                 return idx.listIndices( regex, snode.getInitial() );
124             }
125         }
126         
127         /*
128          * From this point on we are dealing with an enumeration over entries
129          * based on an attribute that is not indexed.  We have no choice but
130          * to perform a full table scan but need to leverage an index for the
131          * underlying enumeration.  We know that all entries are listed under 
132          * the ndn index and so this will enumerate over all entries as the 
133          * underlying enumeration.  An evaluator in an assertion is used to 
134          * constrain the result set.
135          */
136         NamingEnumeration underlying = db.getNdnIndex().listIndices();
137         IndexAssertion assertion = new IndexAssertion()
138         {
139             public boolean assertCandidate( final IndexRecord record ) throws NamingException
140             {
141                 return evaluator.evaluate( node, record );
142             }
143         };
144 
145         return new IndexAssertionEnumeration( underlying, assertion );
146     }
147 }