1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.partition.impl.btree;
18
19
20 import java.math.BigInteger;
21 import java.util.Comparator;
22
23 import javax.naming.NamingEnumeration;
24 import javax.naming.NamingException;
25 import javax.naming.directory.Attribute;
26 import javax.naming.directory.Attributes;
27
28 import org.apache.ldap.common.NotImplementedException;
29 import org.apache.ldap.common.filter.ExprNode;
30 import org.apache.ldap.common.filter.LeafNode;
31 import org.apache.ldap.common.filter.PresenceNode;
32 import org.apache.ldap.common.filter.ScopeNode;
33 import org.apache.ldap.common.filter.SimpleNode;
34 import org.apache.ldap.common.schema.AttributeType;
35 import org.apache.ldap.common.schema.MatchingRule;
36 import org.apache.ldap.common.schema.Normalizer;
37 import org.apache.ldap.server.schema.AttributeTypeRegistry;
38 import org.apache.ldap.server.schema.OidRegistry;
39
40
41 /***
42 * Evaluates LeafNode assertions on candidates using a database.
43 *
44 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
45 * @version $Rev: 264732 $
46 */
47 public class LeafEvaluator implements Evaluator
48 {
49 /*** equality matching type constant */
50 private static final int EQUALITY_MATCH = 0;
51 /*** ordering matching type constant */
52 private static final int ORDERING_MATCH = 1;
53 /*** substring matching type constant */
54 private static final int SUBSTRING_MATCH = 3;
55
56
57 /*** Database used to evaluate leaf with */
58 private BTreeContextPartition db;
59 /*** Oid Registry used to translate attributeIds to OIDs */
60 private OidRegistry oidRegistry;
61 /*** AttributeType registry needed for normalizing and comparing values */
62 private AttributeTypeRegistry attributeTypeRegistry;
63 /*** Substring node evaluator we depend on */
64 private SubstringEvaluator substringEvaluator;
65 /*** ScopeNode evaluator we depend on */
66 private ScopeEvaluator scopeEvaluator;
67
68
69 /***
70 * Creates a leaf expression node evaluator.
71 *
72 * @param db
73 * @param scopeEvaluator
74 * @param substringEvaluator
75 */
76 public LeafEvaluator( BTreeContextPartition db, OidRegistry oidRegistry,
77 AttributeTypeRegistry attributeTypeRegistry,
78 ScopeEvaluator scopeEvaluator,
79 SubstringEvaluator substringEvaluator )
80 {
81 this.db = db;
82 this.oidRegistry = oidRegistry;
83 this.attributeTypeRegistry = attributeTypeRegistry;
84 this.scopeEvaluator = scopeEvaluator;
85 this.substringEvaluator = substringEvaluator;
86 }
87
88
89 public ScopeEvaluator getScopeEvaluator()
90 {
91 return scopeEvaluator;
92 }
93
94
95 public SubstringEvaluator getSubstringEvaluator()
96 {
97 return substringEvaluator;
98 }
99
100
101 /***
102 * @see org.apache.ldap.server.partition.impl.btree.Evaluator#evaluate(ExprNode, IndexRecord)
103 */
104 public boolean evaluate( ExprNode node, IndexRecord record ) throws NamingException
105 {
106 if ( node instanceof ScopeNode )
107 {
108 return scopeEvaluator.evaluate( node, record );
109 }
110
111 switch( ( ( LeafNode ) node ).getAssertionType() )
112 {
113 case( LeafNode.APPROXIMATE ):
114 return evalEquality( ( SimpleNode ) node, record );
115 case( LeafNode.EQUALITY ):
116 return evalEquality( ( SimpleNode ) node, record );
117 case( LeafNode.EXTENSIBLE ):
118 throw new NotImplementedException();
119 case( LeafNode.GREATEREQ ):
120 return evalGreater( ( SimpleNode ) node, record, true );
121 case( LeafNode.LESSEQ ):
122 return evalGreater( ( SimpleNode ) node, record, false );
123 case( LeafNode.PRESENCE ):
124 String attrId = ( ( PresenceNode ) node ).getAttribute();
125 return evalPresence( attrId, record );
126 case( LeafNode.SUBSTRING ):
127 return substringEvaluator.evaluate( node, record );
128 default:
129 throw new NamingException( "Unrecognized leaf node type: "
130 + ( ( LeafNode ) node ).getAssertionType() );
131 }
132 }
133
134
135 /***
136 * Evaluates a simple greater than or less than attribute value assertion on
137 * a perspective candidate.
138 *
139 * @param node the greater than or less than node to evaluate
140 * @param record the IndexRecord of the perspective candidate
141 * @param isGreater true if it is a greater than or equal to comparison,
142 * false if it is a less than or equal to comparison.
143 * @return the ava evaluation on the perspective candidate
144 * @throws NamingException if there is a database access failure
145 */
146 private boolean evalGreater( SimpleNode node, IndexRecord record,
147 boolean isGreater ) throws NamingException
148 {
149 String attrId = node.getAttribute();
150 BigInteger id = record.getEntryId();
151
152 if ( db.hasUserIndexOn( attrId ) )
153 {
154 Index idx = db.getUserIndex( attrId );
155
156 if ( isGreater )
157 {
158 return idx.hasValue( node.getValue(), id, true );
159 }
160
161 return idx.hasValue( node.getValue(), id, false );
162 }
163
164
165 if ( null == record.getAttributes() )
166 {
167 record.setAttributes( db.lookup( id ) );
168 }
169
170
171 Attribute attr = record.getAttributes().get( attrId );
172
173
174 if ( null == attr )
175 {
176 return false;
177 }
178
179
180
181
182
183 Normalizer normalizer = getNormalizer( attrId );
184 Comparator comparator = getComparator( attrId );
185 Object filterValue = normalizer.normalize( node.getValue() );
186 NamingEnumeration list = attr.getAll();
187
188
189
190
191
192 if ( isGreater )
193 {
194 while ( list.hasMore() )
195 {
196 Object value = normalizer.normalize( list.next() );
197
198
199 if ( 0 >= comparator.compare( value, filterValue ) )
200 {
201 return true;
202 }
203 }
204 }
205 else
206 {
207 while ( list.hasMore() )
208 {
209 Object value = normalizer.normalize( list.next() );
210
211
212 if ( 0 <= comparator.compare( value, filterValue ) )
213 {
214 return true;
215 }
216 }
217 }
218
219
220 return false;
221 }
222
223
224 /***
225 * Evaluates a simple presence attribute value assertion on a perspective
226 * candidate.
227 *
228 * @param attrId the name of the attribute tested for presence
229 * @param rec the IndexRecord of the perspective candidate
230 * @return the ava evaluation on the perspective candidate
231 * @throws NamingException if there is a database access failure
232 */
233 private boolean evalPresence( String attrId, IndexRecord rec )
234 throws NamingException
235 {
236 if ( db.hasUserIndexOn( attrId ) )
237 {
238 Index idx = db.getExistanceIndex();
239 return idx.hasValue( attrId, rec.getEntryId() );
240 }
241
242
243 if ( null == rec.getAttributes() )
244 {
245 rec.setAttributes( db.lookup( rec.getEntryId() ) );
246 }
247
248
249 Attributes attrs = rec.getAttributes();
250
251 if ( attrs == null )
252 {
253 return false;
254 }
255
256 return null != attrs.get( attrId );
257 }
258
259
260 /***
261 * Evaluates a simple equality attribute value assertion on a perspective
262 * candidate.
263 *
264 * @param node the equality node to evaluate
265 * @param rec the IndexRecord of the perspective candidate
266 * @return the ava evaluation on the perspective candidate
267 * @throws NamingException if there is a database access failure
268 */
269 private boolean evalEquality( SimpleNode node, IndexRecord rec )
270 throws NamingException
271 {
272 if ( db.hasUserIndexOn( node.getAttribute() ) )
273 {
274 Index idx = db.getUserIndex( node.getAttribute() );
275 return idx.hasValue( node.getValue(), rec.getEntryId() );
276 }
277
278 Normalizer normalizer = getNormalizer( node.getAttribute() );
279 Comparator comparator = getComparator( node.getAttribute() );
280
281
282
283
284
285
286
287
288
289
290 if ( null == rec.getAttributes() )
291 {
292 rec.setAttributes( db.lookup( rec.getEntryId() ) );
293 }
294
295
296 Attribute attr = rec.getAttributes().get( node.getAttribute() );
297
298
299 if ( null == attr )
300 {
301 return false;
302 }
303
304
305 if ( attr.contains( node.getValue() ) )
306 {
307 return true;
308 }
309
310
311 Object filterValue = normalizer.normalize( node.getValue() );
312
313
314 if ( attr.contains( filterValue ) )
315 {
316 return true;
317 }
318
319
320
321
322
323
324 NamingEnumeration list = attr.getAll();
325 while ( list.hasMore() )
326 {
327 Object value = normalizer.normalize( list.next() );
328
329 if ( 0 == comparator.compare( value, filterValue ) )
330 {
331 return true;
332 }
333 }
334
335
336 return false;
337 }
338
339
340 /***
341 * Gets the comparator for equality matching.
342 *
343 * @param attrId the attribute identifier
344 * @return the comparator for equality matching
345 * @throws NamingException if there is a failure
346 */
347 private Comparator getComparator( String attrId ) throws NamingException
348 {
349 MatchingRule mrule = getMatchingRule( attrId, EQUALITY_MATCH );
350 return mrule.getComparator();
351 }
352
353
354 /***
355 * Gets the normalizer for equality matching.
356 *
357 * @param attrId the attribute identifier
358 * @return the normalizer for equality matching
359 * @throws NamingException if there is a failure
360 */
361 private Normalizer getNormalizer( String attrId ) throws NamingException
362 {
363 MatchingRule mrule = getMatchingRule( attrId, EQUALITY_MATCH );
364 return mrule.getNormalizer();
365 }
366
367
368 /***
369 * Gets the matching rule for an attributeType.
370 *
371 * @param attrId the attribute identifier
372 * @return the matching rule
373 * @throws NamingException if there is a failure
374 */
375 private MatchingRule getMatchingRule( String attrId, int matchType )
376 throws NamingException
377 {
378 MatchingRule mrule = null;
379 String oid = oidRegistry.getOid( attrId );
380 AttributeType type = attributeTypeRegistry.lookup( oid );
381
382 switch( matchType )
383 {
384 case( EQUALITY_MATCH ):
385 mrule = type.getEquality();
386 break;
387 case( SUBSTRING_MATCH ):
388 mrule = type.getSubstr();
389 break;
390 case( ORDERING_MATCH ):
391 mrule = type.getOrdering();
392 break;
393 default:
394 throw new NamingException( "Unknown match type: " + matchType );
395 }
396
397 return mrule;
398 }
399 }