KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ldap > server > db > LeafEvaluator


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 package org.apache.ldap.server.db;
18
19
20 import org.apache.ldap.common.NotImplementedException;
21 import org.apache.ldap.common.filter.*;
22 import org.apache.ldap.common.schema.AttributeType;
23 import org.apache.ldap.common.schema.MatchingRule;
24 import org.apache.ldap.common.schema.Normalizer;
25 import org.apache.ldap.server.schema.AttributeTypeRegistry;
26 import org.apache.ldap.server.schema.OidRegistry;
27
28 import javax.naming.NamingEnumeration JavaDoc;
29 import javax.naming.NamingException JavaDoc;
30 import javax.naming.directory.Attribute JavaDoc;
31 import javax.naming.directory.Attributes JavaDoc;
32 import java.math.BigInteger JavaDoc;
33 import java.util.Comparator JavaDoc;
34
35
36 /**
37  * Evaluates LeafNode assertions on candidates using a database.
38  *
39  * @author <a HREF="mailto:dev@directory.apache.org">Apache Directory Project</a>
40  * @version $Rev: 169198 $
41  */

42 public class LeafEvaluator implements Evaluator
43 {
44     /** equality matching type constant */
45     private static final int EQUALITY_MATCH = 0;
46     /** ordering matching type constant */
47     private static final int ORDERING_MATCH = 1;
48     /** substring matching type constant */
49     private static final int SUBSTRING_MATCH = 3;
50
51
52     /** Database used to evaluate leaf with */
53     private Database db;
54     /** Oid Registry used to translate attributeIds to OIDs */
55     private OidRegistry oidRegistry;
56     /** AttributeType registry needed for normalizing and comparing values */
57     private AttributeTypeRegistry attributeTypeRegistry;
58     /** Substring node evaluator we depend on */
59     private SubstringEvaluator substringEvaluator;
60     /** ScopeNode evaluator we depend on */
61     private ScopeEvaluator scopeEvaluator;
62
63
64     /**
65      * Creates a leaf expression node evaluator.
66      *
67      * @param db
68      * @param scopeEvaluator
69      * @param substringEvaluator
70      */

71     public LeafEvaluator( Database db, OidRegistry oidRegistry,
72                           AttributeTypeRegistry attributeTypeRegistry,
73                           ScopeEvaluator scopeEvaluator,
74                           SubstringEvaluator substringEvaluator )
75     {
76         this.db = db;
77         this.oidRegistry = oidRegistry;
78         this.attributeTypeRegistry = attributeTypeRegistry;
79         this.scopeEvaluator = scopeEvaluator;
80         this.substringEvaluator = substringEvaluator;
81     }
82
83
84     public ScopeEvaluator getScopeEvaluator()
85     {
86         return scopeEvaluator;
87     }
88
89
90     public SubstringEvaluator getSubstringEvaluator()
91     {
92         return substringEvaluator;
93     }
94
95
96     /**
97      * @see org.apache.ldap.server.db.Evaluator#evaluate(ExprNode, IndexRecord)
98      */

99     public boolean evaluate( ExprNode node, IndexRecord record ) throws NamingException JavaDoc
100     {
101         if ( node instanceof ScopeNode )
102         {
103             return scopeEvaluator.evaluate( node, record );
104         }
105         
106         switch( ( ( LeafNode ) node ).getAssertionType() )
107         {
108         case( LeafNode.APPROXIMATE ):
109             return evalEquality( ( SimpleNode ) node, record );
110         case( LeafNode.EQUALITY ):
111             return evalEquality( ( SimpleNode ) node, record );
112         case( LeafNode.EXTENSIBLE ):
113             throw new NotImplementedException();
114         case( LeafNode.GREATEREQ ):
115             return evalGreater( ( SimpleNode ) node, record, true );
116         case( LeafNode.LESSEQ ):
117             return evalGreater( ( SimpleNode ) node, record, false );
118         case( LeafNode.PRESENCE ):
119             String JavaDoc attrId = ( ( PresenceNode ) node ).getAttribute();
120             return evalPresence( attrId, record );
121         case( LeafNode.SUBSTRING ):
122             return substringEvaluator.evaluate( node, record );
123         default:
124             throw new NamingException JavaDoc( "Unrecognized leaf node type: "
125                 + ( ( LeafNode ) node ).getAssertionType() );
126         }
127     }
128     
129     
130     /**
131      * Evaluates a simple greater than or less than attribute value assertion on
132      * a perspective candidate.
133      *
134      * @param node the greater than or less than node to evaluate
135      * @param record the IndexRecord of the perspective candidate
136      * @param isGreater true if it is a greater than or equal to comparison,
137      * false if it is a less than or equal to comparison.
138      * @return the ava evaluation on the perspective candidate
139      * @throws NamingException if there is a database access failure
140      */

141     private boolean evalGreater( SimpleNode node, IndexRecord record,
142         boolean isGreater ) throws NamingException JavaDoc
143     {
144         String JavaDoc attrId = node.getAttribute();
145         BigInteger JavaDoc id = record.getEntryId();
146         
147         if ( db.hasUserIndexOn( attrId ) )
148         {
149             Index idx = db.getUserIndex( attrId );
150             
151             if ( isGreater )
152             {
153                 return idx.hasValue( node.getValue(), id, true );
154             }
155             
156             return idx.hasValue( node.getValue(), id, false );
157         }
158         
159         // resusitate entry if need be
160
if ( null == record.getAttributes() )
161         {
162             record.setAttributes( db.lookup( id ) );
163         }
164         
165         // get the attribute associated with the node
166
Attribute JavaDoc attr = record.getAttributes().get( attrId );
167
168         // If we do not have the attribute just return false
169
if ( null == attr )
170         {
171             return false;
172         }
173         
174         /*
175          * We need to iterate through all values and for each value we normalize
176          * and use the comparator to determine if a match exists.
177          */

178         Normalizer normalizer = getNormalizer( attrId );
179         Comparator JavaDoc comparator = getComparator( attrId );
180         Object JavaDoc filterValue = normalizer.normalize( node.getValue() );
181         NamingEnumeration JavaDoc list = attr.getAll();
182         
183         /*
184          * Cheaper to not check isGreater in one loop - better to separate
185          * out into two loops which you choose to execute based on isGreater
186          */

187         if ( isGreater )
188         {
189             while ( list.hasMore() )
190             {
191                 Object JavaDoc value = normalizer.normalize( list.next() );
192             
193                 // Found a value that is greater than or equal to the ava value
194
if ( 0 >= comparator.compare( value, filterValue ) )
195                 {
196                     return true;
197                 }
198             }
199         }
200         else
201         {
202             while ( list.hasMore() )
203             {
204                 Object JavaDoc value = normalizer.normalize( list.next() );
205             
206                 // Found a value that is less than or equal to the ava value
207
if ( 0 <= comparator.compare( value, filterValue ) )
208                 {
209                     return true;
210                 }
211             }
212         }
213         
214         // no match so return false
215
return false;
216     }
217
218     
219     /**
220      * Evaluates a simple presence attribute value assertion on a perspective
221      * candidate.
222      *
223      * @param attrId the name of the attribute tested for presence
224      * @param rec the IndexRecord of the perspective candidate
225      * @return the ava evaluation on the perspective candidate
226      * @throws NamingException if there is a database access failure
227      */

228     private boolean evalPresence( String JavaDoc attrId, IndexRecord rec )
229         throws NamingException JavaDoc
230     {
231         if ( db.hasUserIndexOn( attrId ) )
232         {
233             Index idx = db.getExistanceIndex();
234             return idx.hasValue( attrId, rec.getEntryId() );
235         }
236         
237         // resusitate entry if need be
238
if ( null == rec.getAttributes() )
239         {
240             rec.setAttributes( db.lookup( rec.getEntryId() ) );
241         }
242         
243         // get the attribute associated with the node
244
Attributes JavaDoc attrs = rec.getAttributes();
245
246         if ( attrs == null )
247         {
248             return false;
249         }
250         
251         return null != attrs.get( attrId );
252     }
253
254
255     /**
256      * Evaluates a simple equality attribute value assertion on a perspective
257      * candidate.
258      *
259      * @param node the equality node to evaluate
260      * @param rec the IndexRecord of the perspective candidate
261      * @return the ava evaluation on the perspective candidate
262      * @throws NamingException if there is a database access failure
263      */

264     private boolean evalEquality( SimpleNode node, IndexRecord rec )
265         throws NamingException JavaDoc
266     {
267         if ( db.hasUserIndexOn( node.getAttribute() ) )
268         {
269             Index idx = db.getUserIndex( node.getAttribute() );
270             return idx.hasValue( node.getValue(), rec.getEntryId() );
271         }
272
273         Normalizer normalizer = getNormalizer( node.getAttribute() );
274         Comparator JavaDoc comparator = getComparator( node.getAttribute() );
275
276         /*
277          * Get the attribute and if it is not set in rec then resusitate it
278          * from the master table and set it in rec for use later if at all.
279          * Before iterating through all values for a match check to see if the
280          * AVA value is contained or the normalized form of the AVA value is
281          * contained.
282          */

283         
284         // resusitate entry if need be
285
if ( null == rec.getAttributes() )
286         {
287             rec.setAttributes( db.lookup( rec.getEntryId() ) );
288         }
289         
290         // get the attribute associated with the node
291
Attribute JavaDoc attr = rec.getAttributes().get( node.getAttribute() );
292         
293         // If we do not have the attribute just return false
294
if ( null == attr )
295         {
296             return false;
297         }
298         
299         // check if AVA value exists in attribute
300
if ( attr.contains( node.getValue() ) )
301         {
302             return true;
303         }
304
305         // get the normalized AVA filter value
306
Object JavaDoc filterValue = normalizer.normalize( node.getValue() );
307
308         // check if the normalized value is present
309
if ( attr.contains( filterValue ) )
310         {
311             return true;
312         }
313         
314         /*
315          * We need to now iterate through all values because we could not get
316          * a lookup to work. For each value we normalize and use the comparator
317          * to determine if a match exists.
318          */

319         NamingEnumeration JavaDoc list = attr.getAll();
320         while ( list.hasMore() )
321         {
322             Object JavaDoc value = normalizer.normalize( list.next() );
323             
324             if ( 0 == comparator.compare( value, filterValue ) )
325             {
326                 return true;
327             }
328         }
329         
330         // no match so return false
331
return false;
332     }
333
334
335     /**
336      * Gets the comparator for equality matching.
337      *
338      * @param attrId the attribute identifier
339      * @return the comparator for equality matching
340      * @throws NamingException if there is a failure
341      */

342     private Comparator JavaDoc getComparator( String JavaDoc attrId ) throws NamingException JavaDoc
343     {
344         MatchingRule mrule = getMatchingRule( attrId, EQUALITY_MATCH );
345         return mrule.getComparator();
346     }
347
348
349     /**
350      * Gets the normalizer for equality matching.
351      *
352      * @param attrId the attribute identifier
353      * @return the normalizer for equality matching
354      * @throws NamingException if there is a failure
355      */

356     private Normalizer getNormalizer( String JavaDoc attrId ) throws NamingException JavaDoc
357     {
358         MatchingRule mrule = getMatchingRule( attrId, EQUALITY_MATCH );
359         return mrule.getNormalizer();
360     }
361
362
363     /**
364      * Gets the matching rule for an attributeType.
365      *
366      * @param attrId the attribute identifier
367      * @return the matching rule
368      * @throws NamingException if there is a failure
369      */

370     private MatchingRule getMatchingRule( String JavaDoc attrId, int matchType )
371         throws NamingException JavaDoc
372     {
373         MatchingRule mrule = null;
374         String JavaDoc oid = oidRegistry.getOid( attrId );
375         AttributeType type = attributeTypeRegistry.lookup( oid );
376
377         switch( matchType )
378         {
379             case( EQUALITY_MATCH ):
380                 mrule = type.getEquality();
381                 break;
382             case( SUBSTRING_MATCH ):
383                 mrule = type.getSubstr();
384                 break;
385             case( ORDERING_MATCH ):
386                 mrule = type.getOrdering();
387                 break;
388             default:
389                 throw new NamingException JavaDoc( "Unknown match type: " + matchType );
390         }
391
392         return mrule;
393     }
394 }
395
Popular Tags