View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.xdbm.search.impl;
21  
22  
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.directory.api.ldap.model.exception.LdapException;
27  import org.apache.directory.api.ldap.model.filter.AndNode;
28  import org.apache.directory.api.ldap.model.filter.ApproximateNode;
29  import org.apache.directory.api.ldap.model.filter.EqualityNode;
30  import org.apache.directory.api.ldap.model.filter.ExprNode;
31  import org.apache.directory.api.ldap.model.filter.GreaterEqNode;
32  import org.apache.directory.api.ldap.model.filter.LessEqNode;
33  import org.apache.directory.api.ldap.model.filter.NotNode;
34  import org.apache.directory.api.ldap.model.filter.OrNode;
35  import org.apache.directory.api.ldap.model.filter.PresenceNode;
36  import org.apache.directory.api.ldap.model.filter.ScopeNode;
37  import org.apache.directory.api.ldap.model.filter.SubstringNode;
38  import org.apache.directory.api.ldap.model.message.SearchScope;
39  import org.apache.directory.api.ldap.model.schema.SchemaManager;
40  import org.apache.directory.api.util.exception.NotImplementedException;
41  import org.apache.directory.server.core.api.partition.PartitionTxn;
42  import org.apache.directory.server.i18n.I18n;
43  import org.apache.directory.server.xdbm.Store;
44  import org.apache.directory.server.xdbm.search.Evaluator;
45  import org.apache.directory.server.xdbm.search.evaluator.AndEvaluator;
46  import org.apache.directory.server.xdbm.search.evaluator.ApproximateEvaluator;
47  import org.apache.directory.server.xdbm.search.evaluator.EmptyEvaluator;
48  import org.apache.directory.server.xdbm.search.evaluator.EqualityEvaluator;
49  import org.apache.directory.server.xdbm.search.evaluator.GreaterEqEvaluator;
50  import org.apache.directory.server.xdbm.search.evaluator.LessEqEvaluator;
51  import org.apache.directory.server.xdbm.search.evaluator.NotEvaluator;
52  import org.apache.directory.server.xdbm.search.evaluator.OneLevelScopeEvaluator;
53  import org.apache.directory.server.xdbm.search.evaluator.OrEvaluator;
54  import org.apache.directory.server.xdbm.search.evaluator.PresenceEvaluator;
55  import org.apache.directory.server.xdbm.search.evaluator.SubstringEvaluator;
56  import org.apache.directory.server.xdbm.search.evaluator.SubtreeScopeEvaluator;
57  
58  
59  /**
60   * Top level filter expression evaluator builder implemenation.
61   * 
62   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
63   */
64  public class EvaluatorBuilder
65  {
66      private final Store db;
67      private final SchemaManager schemaManager;
68  
69      private static final EmptyEvaluatorch/evaluator/EmptyEvaluator.html#EmptyEvaluator">EmptyEvaluator EMPTY_EVALLUATOR = new EmptyEvaluator();
70  
71      /**
72       * Creates a top level Evaluator where leaves are delegated to a leaf node
73       * evaluator which will be created.
74       *
75       * @param db the database this evaluator operates upon
76       * @param schemaManager the schema manager
77       */
78      public EvaluatorBuilder( Store db, SchemaManager schemaManager )
79      {
80          this.db = db;
81          this.schemaManager = schemaManager;
82      }
83  
84  
85      public <T> Evaluator<? extends ExprNode> build( PartitionTxn partitionTxn, ExprNode node ) throws LdapException
86      {
87          Object count = node.get( "count" );
88  
89          if ( ( count != null ) && ( ( Long ) count == 0L ) )
90          {
91              return EMPTY_EVALLUATOR;
92          }
93  
94          switch ( node.getAssertionType() )
95          {
96          /* ---------- LEAF NODE HANDLING ---------- */
97  
98              case APPROXIMATE:
99                  return new ApproximateEvaluator<>( ( ApproximateNode<T> ) node, db, schemaManager );
100 
101             case EQUALITY:
102                 return new EqualityEvaluator<>( ( EqualityNode<T> ) node, db, schemaManager );
103 
104             case GREATEREQ:
105                 return new GreaterEqEvaluator<>( ( GreaterEqNode<T> ) node, db, schemaManager );
106 
107             case LESSEQ:
108                 return new LessEqEvaluator<>( ( LessEqNode<T> ) node, db, schemaManager );
109 
110             case PRESENCE:
111                 return new PresenceEvaluator( ( PresenceNode ) node, db, schemaManager );
112 
113             case SCOPE:
114                 if ( ( ( ScopeNode ) node ).getScope() == SearchScope.ONELEVEL )
115                 {
116                     return new OneLevelScopeEvaluator<>( db, ( ScopeNode ) node );
117                 }
118                 else
119                 {
120                     return new SubtreeScopeEvaluator( partitionTxn, db, ( ScopeNode ) node );
121                 }
122 
123             case SUBSTRING:
124                 return new SubstringEvaluator( ( SubstringNode ) node, db, schemaManager );
125 
126                 /* ---------- LOGICAL OPERATORS ---------- */
127 
128             case AND:
129                 return buildAndEvaluator( partitionTxn, ( AndNode ) node );
130 
131             case NOT:
132                 return new NotEvaluator( ( NotNode ) node, build( partitionTxn, ( ( NotNode ) node ).getFirstChild() ) );
133 
134             case OR:
135                 return buildOrEvaluator( partitionTxn, ( OrNode ) node );
136 
137                 /* ----------  NOT IMPLEMENTED  ---------- */
138 
139             case ASSERTION:
140             case EXTENSIBLE:
141                 throw new NotImplementedException();
142 
143             default:
144                 throw new IllegalStateException( I18n.err( I18n.ERR_260, node.getAssertionType() ) );
145         }
146     }
147 
148 
149     private <T> Evaluator<? extends ExprNode> buildAndEvaluator( PartitionTxn partitionTxn, AndNode node ) throws LdapException
150     {
151         List<ExprNode> children = node.getChildren();
152         List<Evaluator<? extends ExprNode>> evaluators = buildList( partitionTxn, children );
153 
154         int size = evaluators.size();
155 
156         switch ( size )
157         {
158             case 0:
159                 return EMPTY_EVALLUATOR;
160 
161             case 1:
162                 return evaluators.get( 0 );
163 
164             default:
165                 return new AndEvaluator( node, evaluators );
166         }
167     }
168 
169 
170     private <T> Evaluator<? extends ExprNode> buildOrEvaluator( PartitionTxn partitionTxn, OrNode node ) throws LdapException
171     {
172         List<ExprNode> children = node.getChildren();
173         List<Evaluator<? extends ExprNode>> evaluators = buildList( partitionTxn, children );
174 
175         int size = evaluators.size();
176 
177         switch ( size )
178         {
179             case 0:
180                 return EMPTY_EVALLUATOR;
181 
182             case 1:
183                 return evaluators.get( 0 );
184 
185             default:
186                 return new OrEvaluator( node, evaluators );
187         }
188     }
189 
190 
191     private List<Evaluator<? extends ExprNode>> buildList( PartitionTxn partitionTxn, List<ExprNode> children ) throws LdapException
192     {
193         List<Evaluator<? extends ExprNode>> evaluators = new ArrayList<>(
194             children.size() );
195 
196         for ( ExprNode child : children )
197         {
198             Evaluator<? extends ExprNode> evaluator = build( partitionTxn, child );
199 
200             if ( evaluator != null )
201             {
202                 evaluators.add( evaluator );
203             }
204         }
205 
206         return evaluators;
207     }
208 
209 
210     /**
211      * @return the schemaManager
212      */
213     public SchemaManager getSchemaManager()
214     {
215         return schemaManager;
216     }
217 }