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