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.shared.ldap.filter;
021
022
023 import java.util.ArrayList;
024 import java.util.List;
025
026 import org.apache.commons.collections.CollectionUtils;
027
028
029 /**
030 * Node representing branches within the expression tree corresponding to
031 * logical operators within the filter expression.
032 *
033 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
034 * @version $Rev: 746607 $
035 */
036 public class BranchNode extends AbstractExprNode
037 {
038 /** child node list for this branch node */
039 protected List<ExprNode> children = null;
040
041
042 /**
043 * Creates a BranchNode using a logical operator and a list of children.
044 * @param assertionType the node's type
045 * @param childList the child nodes under this branch node.
046 */
047 protected BranchNode( AssertionType assertionType, List<ExprNode> childList )
048 {
049 super( assertionType );
050
051 if ( null == childList )
052 {
053 this.children = new ArrayList<ExprNode>( 2 );
054 }
055 else
056 {
057 this.children = childList;
058 }
059 }
060
061
062 /**
063 * Creates a BranchNode using a logical operator and a list of children.
064 *
065 * @param assertionType the node's type
066 * @param childList the child nodes under this branch node.
067 */
068 protected BranchNode( AssertionType assertionType, ExprNode... childList )
069 {
070 super( assertionType );
071
072 if ( null == children )
073 {
074 this.children = new ArrayList<ExprNode>( childList.length );
075 }
076
077 CollectionUtils.addAll( children, childList );
078 }
079
080
081 /**
082 * Creates a BranchNode using a logical operator.
083 *
084 * @param assertionType the node's type
085 */
086 protected BranchNode( AssertionType assertionType )
087 {
088 super( assertionType );
089
090 this.children = new ArrayList<ExprNode>( 2 );
091 }
092
093
094 /**
095 * @see org.apache.directory.shared.ldap.filter.ExprNode#isLeaf()
096 * @return false all the time.
097 */
098 public final boolean isLeaf()
099 {
100 return false;
101 }
102
103 /**
104 * Makes a full clone in new memory space of the current node and children
105 *
106 * @return the clone
107 */
108 @Override public ExprNode clone()
109 {
110 ExprNode clone = (ExprNode)super.clone();
111
112 // Clone the children
113 if ( children != null )
114 {
115 ((BranchNode)clone).children = new ArrayList<ExprNode>();
116
117 for ( ExprNode child : children )
118 {
119 ((BranchNode)clone).children.add( (ExprNode)child.clone() );
120 }
121 }
122
123 return clone;
124 }
125
126
127 /**
128 * Adds a child node to this branch node node
129 *
130 * @param node the child expression to add to this branch node
131 */
132 public void addNode( ExprNode node )
133 {
134 children.add( node );
135 }
136
137
138 /**
139 * Adds a child node to this branch node at the head rather than the tail.
140 *
141 * @param node the child expression to add to this branch node
142 */
143 public void addNodeToHead( ExprNode node )
144 {
145 children.add( 0, node );
146 }
147
148
149 /**
150 * Gets the children below this BranchNode. We purposefully do not clone the
151 * array list so that backends can sort the order of children using their
152 * own search optimization algorithms. We want backends and other parts of
153 * the system to be able to induce side effects on the tree structure.
154 *
155 * @return the list of child nodes under this branch node.
156 */
157 public List<ExprNode> getChildren()
158 {
159 return children;
160 }
161
162
163 /**
164 * Sets the list of children under this node.
165 *
166 * @param list the list of children to set.
167 */
168 public void setChildren( List<ExprNode> list )
169 {
170 children = list;
171 }
172
173 /**
174 * Convenience method that gets the first child in the children array. Its
175 * very useful for NOT nodes since they only have one child by avoiding code
176 * that looks like: <code> ( ExprNode ) m_children.get( 0 ) </code>
177 *
178 * @return the first child
179 */
180 public ExprNode getFirstChild()
181 {
182 if ( children.size() > 0 )
183 {
184 return children.get( 0 );
185 }
186
187 return null;
188 }
189
190
191 /**
192 * @see org.apache.directory.shared.ldap.filter.ExprNode#accept(
193 * org.apache.directory.shared.ldap.filter.FilterVisitor)
194 *
195 * @return The modified element
196 */
197 public final Object accept( FilterVisitor visitor )
198 {
199 if ( visitor.isPrefix() )
200 {
201 List<ExprNode> childrenList = visitor.getOrder( this, this.children );
202 ExprNode result = null;
203
204 if ( visitor.canVisit( this ) )
205 {
206 result = (ExprNode)visitor.visit( this );
207 }
208
209 for ( ExprNode node:childrenList )
210 {
211 node.accept( visitor );
212 }
213
214 return result;
215 }
216 else
217 {
218 if ( visitor.canVisit( this ) )
219 {
220 return visitor.visit( this );
221 }
222 else
223 {
224 return null;
225 }
226 }
227 }
228
229
230 /**
231 * (non-Javadoc)
232 *
233 * @see Object#hashCode()
234 * @return the instance's hash code
235 */
236 public int hashCode()
237 {
238 int h = 37;
239
240 h = h*17 + super.hashCode();
241
242 if ( children != null )
243 {
244 for ( ExprNode child:children )
245 {
246 h = h*17 + child.hashCode();
247 }
248 }
249
250 return h;
251 }
252
253 /*
254 * (non-Javadoc)
255 *
256 * @see java.lang.Object#equals(java.lang.Object)
257 */
258 public boolean equals( Object other )
259 {
260 if ( this == other )
261 {
262 return true;
263 }
264
265 if ( !( other instanceof BranchNode ) )
266 {
267 return false;
268 }
269
270 if ( other.getClass() != this.getClass() )
271 {
272 return false;
273 }
274
275 BranchNode otherExprNode = ( BranchNode ) other;
276
277 List<ExprNode> otherChildren = otherExprNode.getChildren();
278
279 if ( otherChildren == children )
280 {
281 return true;
282 }
283
284 if ( children.size() != otherChildren.size() )
285 {
286 return false;
287 }
288
289 for ( int i = 0; i < children.size(); i++ )
290 {
291 ExprNode child = children.get( i );
292 ExprNode otherChild = children.get( i );
293
294 if ( !child.equals( otherChild ) )
295 {
296 return false;
297 }
298 }
299
300 return true;
301 }
302 }