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.impl; 021 022 023import java.util.ArrayList; 024import java.util.List; 025 026import org.apache.directory.api.ldap.model.exception.LdapException; 027import org.apache.directory.api.ldap.model.filter.AndNode; 028import org.apache.directory.api.ldap.model.filter.ApproximateNode; 029import org.apache.directory.api.ldap.model.filter.EqualityNode; 030import org.apache.directory.api.ldap.model.filter.ExprNode; 031import org.apache.directory.api.ldap.model.filter.GreaterEqNode; 032import org.apache.directory.api.ldap.model.filter.LessEqNode; 033import org.apache.directory.api.ldap.model.filter.NotNode; 034import org.apache.directory.api.ldap.model.filter.OrNode; 035import org.apache.directory.api.ldap.model.filter.PresenceNode; 036import org.apache.directory.api.ldap.model.filter.ScopeNode; 037import org.apache.directory.api.ldap.model.filter.SubstringNode; 038import org.apache.directory.api.ldap.model.message.SearchScope; 039import org.apache.directory.api.ldap.model.schema.SchemaManager; 040import org.apache.directory.api.util.exception.NotImplementedException; 041import org.apache.directory.server.core.api.partition.PartitionTxn; 042import org.apache.directory.server.i18n.I18n; 043import org.apache.directory.server.xdbm.Store; 044import org.apache.directory.server.xdbm.search.Evaluator; 045import org.apache.directory.server.xdbm.search.evaluator.AndEvaluator; 046import org.apache.directory.server.xdbm.search.evaluator.ApproximateEvaluator; 047import org.apache.directory.server.xdbm.search.evaluator.EmptyEvaluator; 048import org.apache.directory.server.xdbm.search.evaluator.EqualityEvaluator; 049import org.apache.directory.server.xdbm.search.evaluator.GreaterEqEvaluator; 050import org.apache.directory.server.xdbm.search.evaluator.LessEqEvaluator; 051import org.apache.directory.server.xdbm.search.evaluator.NotEvaluator; 052import org.apache.directory.server.xdbm.search.evaluator.OneLevelScopeEvaluator; 053import org.apache.directory.server.xdbm.search.evaluator.OrEvaluator; 054import org.apache.directory.server.xdbm.search.evaluator.PresenceEvaluator; 055import org.apache.directory.server.xdbm.search.evaluator.SubstringEvaluator; 056import org.apache.directory.server.xdbm.search.evaluator.SubtreeScopeEvaluator; 057 058 059/** 060 * Top level filter expression evaluator builder implemenation. 061 * 062 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 063 */ 064public class EvaluatorBuilder 065{ 066 private final Store db; 067 private final SchemaManager schemaManager; 068 069 private static final EmptyEvaluator EMPTY_EVALLUATOR = new EmptyEvaluator(); 070 071 /** 072 * Creates a top level Evaluator where leaves are delegated to a leaf node 073 * evaluator which will be created. 074 * 075 * @param db the database this evaluator operates upon 076 * @param schemaManager the schema manager 077 */ 078 public EvaluatorBuilder( Store db, SchemaManager schemaManager ) 079 { 080 this.db = db; 081 this.schemaManager = schemaManager; 082 } 083 084 085 public <T> Evaluator<? extends ExprNode> build( PartitionTxn partitionTxn, ExprNode node ) throws LdapException 086 { 087 Object count = node.get( "count" ); 088 089 if ( ( count != null ) && ( ( Long ) count == 0L ) ) 090 { 091 return EMPTY_EVALLUATOR; 092 } 093 094 switch ( node.getAssertionType() ) 095 { 096 /* ---------- LEAF NODE HANDLING ---------- */ 097 098 case APPROXIMATE: 099 return new ApproximateEvaluator<>( ( ApproximateNode<T> ) node, db, schemaManager ); 100 101 case EQUALITY: 102 return new EqualityEvaluator<>( ( EqualityNode<T> ) node, db, schemaManager ); 103 104 case GREATEREQ: 105 return new GreaterEqEvaluator<>( ( GreaterEqNode<T> ) node, db, schemaManager ); 106 107 case LESSEQ: 108 return new LessEqEvaluator<>( ( LessEqNode<T> ) node, db, schemaManager ); 109 110 case PRESENCE: 111 return new PresenceEvaluator( ( PresenceNode ) node, db, schemaManager ); 112 113 case SCOPE: 114 if ( ( ( ScopeNode ) node ).getScope() == SearchScope.ONELEVEL ) 115 { 116 return new OneLevelScopeEvaluator<>( db, ( ScopeNode ) node ); 117 } 118 else 119 { 120 return new SubtreeScopeEvaluator( partitionTxn, db, ( ScopeNode ) node ); 121 } 122 123 case SUBSTRING: 124 return new SubstringEvaluator( ( SubstringNode ) node, db, schemaManager ); 125 126 /* ---------- LOGICAL OPERATORS ---------- */ 127 128 case AND: 129 return buildAndEvaluator( partitionTxn, ( AndNode ) node ); 130 131 case NOT: 132 return new NotEvaluator( ( NotNode ) node, build( partitionTxn, ( ( NotNode ) node ).getFirstChild() ) ); 133 134 case OR: 135 return buildOrEvaluator( partitionTxn, ( OrNode ) node ); 136 137 /* ---------- NOT IMPLEMENTED ---------- */ 138 139 case ASSERTION: 140 case EXTENSIBLE: 141 throw new NotImplementedException(); 142 143 default: 144 throw new IllegalStateException( I18n.err( I18n.ERR_260, node.getAssertionType() ) ); 145 } 146 } 147 148 149 private <T> Evaluator<? extends ExprNode> buildAndEvaluator( PartitionTxn partitionTxn, AndNode node ) throws LdapException 150 { 151 List<ExprNode> children = node.getChildren(); 152 List<Evaluator<? extends ExprNode>> evaluators = buildList( partitionTxn, children ); 153 154 int size = evaluators.size(); 155 156 switch ( size ) 157 { 158 case 0: 159 return EMPTY_EVALLUATOR; 160 161 case 1: 162 return evaluators.get( 0 ); 163 164 default: 165 return new AndEvaluator( node, evaluators ); 166 } 167 } 168 169 170 private <T> Evaluator<? extends ExprNode> buildOrEvaluator( PartitionTxn partitionTxn, OrNode node ) throws LdapException 171 { 172 List<ExprNode> children = node.getChildren(); 173 List<Evaluator<? extends ExprNode>> evaluators = buildList( partitionTxn, children ); 174 175 int size = evaluators.size(); 176 177 switch ( size ) 178 { 179 case 0: 180 return EMPTY_EVALLUATOR; 181 182 case 1: 183 return evaluators.get( 0 ); 184 185 default: 186 return new OrEvaluator( node, evaluators ); 187 } 188 } 189 190 191 private List<Evaluator<? extends ExprNode>> buildList( PartitionTxn partitionTxn, List<ExprNode> children ) throws LdapException 192 { 193 List<Evaluator<? extends ExprNode>> evaluators = new ArrayList<>( 194 children.size() ); 195 196 for ( ExprNode child : children ) 197 { 198 Evaluator<? extends ExprNode> evaluator = build( partitionTxn, child ); 199 200 if ( evaluator != null ) 201 { 202 evaluators.add( evaluator ); 203 } 204 } 205 206 return evaluators; 207 } 208 209 210 /** 211 * @return the schemaManager 212 */ 213 public SchemaManager getSchemaManager() 214 { 215 return schemaManager; 216 } 217}