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.core.normalization; 021 022 023import java.util.Iterator; 024import java.util.List; 025 026import org.apache.directory.api.ldap.model.exception.LdapException; 027import org.apache.directory.api.ldap.model.filter.ApproximateNode; 028import org.apache.directory.api.ldap.model.filter.BranchNode; 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.ExtensibleNode; 032import org.apache.directory.api.ldap.model.filter.FilterVisitor; 033import org.apache.directory.api.ldap.model.filter.GreaterEqNode; 034import org.apache.directory.api.ldap.model.filter.LeafNode; 035import org.apache.directory.api.ldap.model.filter.LessEqNode; 036import org.apache.directory.api.ldap.model.filter.OrNode; 037import org.apache.directory.api.ldap.model.filter.PresenceNode; 038import org.apache.directory.api.ldap.model.filter.SubstringNode; 039import org.apache.directory.api.ldap.model.schema.AttributeType; 040import org.apache.directory.api.ldap.model.schema.SchemaManager; 041import org.apache.directory.server.i18n.I18n; 042 043 044/** 045 * 046 * 047 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 048 */ 049public class ExpandingVisitor implements FilterVisitor 050{ 051 /** The schemaManager */ 052 private SchemaManager schemaManager; 053 054 055 /** 056 * 057 * Creates a new instance of ExpandingVisitor. 058 * 059 * @param schemaManager The server schemaManager 060 */ 061 public ExpandingVisitor( SchemaManager schemaManager ) 062 { 063 this.schemaManager = schemaManager; 064 } 065 066 067 /** 068 * {@inheritDoc} 069 */ 070 @Override 071 public boolean canVisit( ExprNode node ) 072 { 073 return node instanceof BranchNode; 074 } 075 076 077 /** 078 * {@inheritDoc} 079 */ 080 @Override 081 public List<ExprNode> getOrder( BranchNode node, List<ExprNode> children ) 082 { 083 return children; 084 } 085 086 087 /** 088 * {@inheritDoc} 089 */ 090 @Override 091 public boolean isPrefix() 092 { 093 return false; 094 } 095 096 097 /** 098 * {@inheritDoc} 099 */ 100 @Override 101 public Object visit( ExprNode node ) 102 { 103 BranchNode bnode = ( BranchNode ) node; 104 105 // -------------------------------------------------------------------- 106 // we want to check each child leaf node to see if it must be expanded 107 // children that are branch nodes are recursively visited 108 // -------------------------------------------------------------------- 109 110 final List<ExprNode> children = bnode.getChildren(); 111 int childNumber = 0; 112 113 for ( ExprNode child : children ) 114 { 115 if ( child instanceof LeafNode ) 116 { 117 LeafNode leaf = ( LeafNode ) child; 118 119 try 120 { 121 if ( schemaManager.getAttributeTypeRegistry().hasDescendants( leaf.getAttributeType() ) ) 122 { 123 // create a new OR node to hold all descendent forms 124 // add to this node the generalized leaf node and 125 // replace the old leaf with the new OR branch node 126 BranchNode orNode = new OrNode(); 127 orNode.getChildren().add( leaf ); 128 children.set( childNumber++, orNode ); 129 130 // iterate through descendants adding them to the orNode 131 Iterator<AttributeType> descendants = schemaManager.getAttributeTypeRegistry().descendants( 132 leaf.getAttributeType() ); 133 134 while ( descendants.hasNext() ) 135 { 136 LeafNode newLeaf; 137 AttributeType descendant = descendants.next(); 138 139 if ( leaf instanceof PresenceNode ) 140 { 141 newLeaf = new PresenceNode( descendant ); 142 } 143 else if ( leaf instanceof ApproximateNode ) 144 { 145 ApproximateNode approximateNode = ( ApproximateNode ) leaf; 146 147 newLeaf = new ApproximateNode( descendant, approximateNode.getValue() ); 148 } 149 else if ( leaf instanceof EqualityNode ) 150 { 151 EqualityNode equalityNode = ( EqualityNode ) leaf; 152 153 newLeaf = new EqualityNode( descendant, equalityNode.getValue() ); 154 } 155 else if ( leaf instanceof GreaterEqNode ) 156 { 157 GreaterEqNode greaterEqNode = ( GreaterEqNode ) leaf; 158 159 newLeaf = new GreaterEqNode( descendant, greaterEqNode.getValue() ); 160 } 161 else if ( leaf instanceof LessEqNode ) 162 { 163 LessEqNode lessEqNode = ( LessEqNode ) leaf; 164 165 newLeaf = new LessEqNode( descendant, lessEqNode.getValue() ); 166 } 167 else if ( leaf instanceof ExtensibleNode ) 168 { 169 ExtensibleNode extensibleNode = ( ExtensibleNode ) leaf; 170 newLeaf = new ExtensibleNode( descendant, extensibleNode.getValue(), 171 extensibleNode.getMatchingRuleId(), extensibleNode.hasDnAttributes() ); 172 } 173 else if ( leaf instanceof SubstringNode ) 174 { 175 SubstringNode substringNode = ( SubstringNode ) leaf; 176 newLeaf = new SubstringNode( descendant, substringNode.getInitial(), 177 substringNode.getFinal() ); 178 } 179 else 180 { 181 throw new IllegalStateException( I18n.err( I18n.ERR_260, leaf ) ); 182 } 183 184 orNode.addNode( newLeaf ); 185 } 186 } 187 } 188 catch ( LdapException e ) 189 { 190 // log something here and throw a runtime excpetion 191 throw new RuntimeException( I18n.err( I18n.ERR_261 ) ); 192 } 193 } 194 else 195 { 196 visit( child ); 197 } 198 } // end for loop 199 200 return null; 201 } 202}