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.evaluator;
21  
22  
23  import java.util.Iterator;
24  
25  import org.apache.directory.api.ldap.model.entry.Attribute;
26  import org.apache.directory.api.ldap.model.entry.Entry;
27  import org.apache.directory.api.ldap.model.entry.Value;
28  import org.apache.directory.api.ldap.model.exception.LdapException;
29  import org.apache.directory.api.ldap.model.filter.LessEqNode;
30  import org.apache.directory.api.ldap.model.schema.AttributeType;
31  import org.apache.directory.api.ldap.model.schema.MatchingRule;
32  import org.apache.directory.api.ldap.model.schema.SchemaManager;
33  import org.apache.directory.server.i18n.I18n;
34  import org.apache.directory.server.xdbm.Index;
35  import org.apache.directory.server.xdbm.IndexEntry;
36  import org.apache.directory.server.xdbm.Store;
37  
38  
39  /**
40   * An Evaluator which determines if candidates are matched by LessEqNode
41   * assertions.
42   *
43   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
44   */
45  public class LessEqEvaluator<T> extends LeafEvaluator<T>
46  {
47      @SuppressWarnings("unchecked")
48      public LessEqEvaluator( LessEqNode<T> node, Store db, SchemaManager schemaManager )
49          throws Exception
50      {
51          super( node, db, schemaManager );
52  
53          if ( db.hasIndexOn( attributeType ) )
54          {
55              idx = ( Index<T, Entry, String> ) db.getIndex( attributeType );
56          }
57          else
58          {
59              idx = null;
60          }
61  
62          /*
63           * We prefer matching using the Normalizer and Comparator pair from
64           * the ordering matchingRule if one is available.  It may very well
65           * not be.  If so then we resort to using the Normalizer and
66           * Comparator from the equality matchingRule as a last resort.
67           */
68          MatchingRule mr = attributeType.getOrdering();
69  
70          if ( mr == null )
71          {
72              mr = attributeType.getEquality();
73          }
74  
75          if ( mr == null )
76          {
77              throw new IllegalStateException( I18n.err( I18n.ERR_717, node ) );
78          }
79  
80          normalizer = mr.getNormalizer();
81          ldapComparator = mr.getLdapComparator();
82      }
83  
84  
85      public LessEqNode<T> getExpression()
86      {
87          return ( LessEqNode<T> ) node;
88      }
89  
90  
91      public boolean evaluate( IndexEntry<?, String> indexEntry ) throws LdapException
92      {
93          Entry entry = indexEntry.getEntry();
94  
95          // resuscitate the entry if it has not been and set entry in IndexEntry
96          if ( null == entry )
97          {
98              entry = db.fetch( indexEntry.getId() );
99  
100             if ( null == entry )
101             {
102                 // The entry is not anymore present : get out
103                 return false;
104             }
105 
106             indexEntry.setEntry( entry );
107         }
108 
109         // get the attribute
110         Attribute attr = entry.get( attributeType );
111 
112         // if the attribute does not exist just return false
113         //noinspection unchecked
114         if ( attr != null && evaluate( ( IndexEntry<Object, String> ) indexEntry, attr ) )
115         {
116             return true;
117         }
118 
119         // If we do not have the attribute, loop through the sub classes of
120         // the attributeType.  Perhaps the entry has an attribute value of a
121         // subtype (descendant) that will produce a match
122         if ( schemaManager.getAttributeTypeRegistry().hasDescendants( attributeType ) )
123         {
124             // TODO check to see if descendant handling is necessary for the
125             // index so we can match properly even when for example a name
126             // attribute is used instead of more specific commonName
127             Iterator<AttributeType> descendants = schemaManager.getAttributeTypeRegistry().descendants( attributeType );
128 
129             while ( descendants.hasNext() )
130             {
131                 AttributeType descendant = descendants.next();
132 
133                 attr = entry.get( descendant );
134 
135                 //noinspection unchecked
136                 if ( attr != null && evaluate( ( IndexEntry<Object, String> ) indexEntry, attr ) )
137                 {
138                     return true;
139                 }
140             }
141         }
142 
143         // we fell through so a match was not found - assertion was false.
144         return false;
145     }
146 
147 
148     public boolean evaluate( Entry entry ) throws Exception
149     {
150         // get the attribute
151         Attribute attr = entry.get( attributeType );
152 
153         // if the attribute does not exist just return false
154         if ( ( attr != null ) && evaluate( null, attr ) )
155         {
156             return true;
157         }
158 
159         // If we do not have the attribute, loop through the sub classes of
160         // the attributeType.  Perhaps the entry has an attribute value of a
161         // subtype (descendant) that will produce a match
162         if ( schemaManager.getAttributeTypeRegistry().hasDescendants( attributeType ) )
163         {
164             // TODO check to see if descendant handling is necessary for the
165             // index so we can match properly even when for example a name
166             // attribute is used instead of more specific commonName
167             Iterator<AttributeType> descendants = schemaManager.getAttributeTypeRegistry().descendants( attributeType );
168 
169             while ( descendants.hasNext() )
170             {
171                 AttributeType descendant = descendants.next();
172 
173                 attr = entry.get( descendant );
174 
175                 if ( attr != null && evaluate( null, attr ) )
176                 {
177                     return true;
178                 }
179             }
180         }
181 
182         // we fell through so a match was not found - assertion was false.
183         return false;
184     }
185 
186 
187     // TODO - determine if comparator and index entry should have the Value
188     // wrapper or the raw normalized value
189     private boolean evaluate( IndexEntry<Object, String> indexEntry, Attribute attribute )
190         throws LdapException
191     {
192         /*
193          * Cycle through the attribute values testing normalized version
194          * obtained from using the ordering or equality matching rule's
195          * normalizer.  The test uses the comparator obtained from the
196          * appropriate matching rule to perform the check.
197          */
198         for ( Value<?> value : attribute )
199         {
200             //noinspection unchecked
201             if ( ldapComparator.compare( value.getNormValue(), node.getValue().getNormValue() ) <= 0 )
202             {
203                 if ( indexEntry != null )
204                 {
205                     indexEntry.setKey( value.getNormValue() );
206                 }
207                 return true;
208             }
209         }
210 
211         return false;
212     }
213 
214 
215     /**
216      * @see Object#toString()
217      */
218     public String toString( String tabs )
219     {
220         StringBuilder sb = new StringBuilder();
221 
222         sb.append( tabs ).append( "LessEqEvaluator : " ).append( super.toString() ).append( "\n" );
223 
224         return sb.toString();
225     }
226 
227 
228     /**
229      * @see Object#toString()
230      */
231     public String toString()
232     {
233         return toString( "" );
234     }
235 }