001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.server.xdbm.search.evaluator; 021 022 023import java.util.Iterator; 024 025import org.apache.directory.api.ldap.model.entry.Attribute; 026import org.apache.directory.api.ldap.model.entry.Entry; 027import org.apache.directory.api.ldap.model.entry.Value; 028import org.apache.directory.api.ldap.model.exception.LdapException; 029import org.apache.directory.api.ldap.model.exception.LdapOtherException; 030import org.apache.directory.api.ldap.model.filter.EqualityNode; 031import org.apache.directory.api.ldap.model.schema.AttributeType; 032import org.apache.directory.api.ldap.model.schema.MatchingRule; 033import org.apache.directory.api.ldap.model.schema.SchemaManager; 034import org.apache.directory.api.ldap.model.schema.normalizers.NoOpNormalizer; 035import org.apache.directory.server.core.api.partition.PartitionTxn; 036import org.apache.directory.server.xdbm.Index; 037import org.apache.directory.server.xdbm.IndexEntry; 038import org.apache.directory.server.xdbm.IndexNotFoundException; 039import org.apache.directory.server.xdbm.Store; 040 041 042/** 043 * An Evaluator which determines if candidates are matched by GreaterEqNode 044 * assertions. 045 * 046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 047 */ 048public class EqualityEvaluator<T> extends LeafEvaluator<T> 049{ 050 /** 051 * Creates a new EqualityEvaluator 052 * 053 * @param node The EqualityNode 054 * @param db The Store 055 * @param schemaManager The SchemaManager 056 * @throws LdapException If the creation failed 057 */ 058 @SuppressWarnings("unchecked") 059 public EqualityEvaluator( EqualityNode<T> node, Store db, SchemaManager schemaManager ) 060 throws LdapException 061 { 062 super( node, db, schemaManager ); 063 064 if ( db.hasIndexOn( attributeType ) ) 065 { 066 try 067 { 068 idx = ( Index<T, String> ) db.getIndex( attributeType ); 069 } 070 catch ( IndexNotFoundException infe ) 071 { 072 throw new LdapOtherException( infe.getMessage(), infe ); 073 } 074 } 075 076 MatchingRule mr = attributeType.getEquality(); 077 078 if ( mr == null ) 079 { 080 normalizer = new NoOpNormalizer( attributeType.getOid() ); 081 ldapComparator = null; 082 } 083 else 084 { 085 normalizer = mr.getNormalizer(); 086 ldapComparator = mr.getLdapComparator(); 087 } 088 } 089 090 091 /** 092 * {@inheritDoc} 093 */ 094 @Override 095 public EqualityNode<T> getExpression() 096 { 097 return ( EqualityNode<T> ) node; 098 } 099 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}