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