View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.filter;
21  
22  
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.commons.collections.CollectionUtils;
27  
28  
29  /**
30   * Node representing branches within the expression tree corresponding to
31   * logical operators within the filter expression.
32   * 
33   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
34   */
35  public class BranchNode extends AbstractExprNode
36  {
37      /** child node list for this branch node */
38      protected List<ExprNode> children = null;
39  
40  
41      /**
42       * Creates a BranchNode using a logical operator and a list of children.
43       * @param assertionType the node's type
44       * @param childList the child nodes under this branch node.
45       */
46      protected BranchNode( AssertionType assertionType, List<ExprNode> childList )
47      {
48          super( assertionType );
49  
50          if ( null == childList )
51          {
52              this.children = new ArrayList<ExprNode>( 2 );
53          }
54          else
55          {
56              this.children = childList;
57          }
58  
59          isSchemaAware = true;
60      }
61  
62  
63      /**
64       * Creates a BranchNode using a logical operator and a list of children.
65       * 
66       * @param assertionType the node's type
67       * @param childList the child nodes under this branch node.
68       */
69      protected BranchNode( AssertionType assertionType, ExprNode... childList )
70      {
71          super( assertionType );
72  
73          if ( null == children )
74          {
75              this.children = new ArrayList<ExprNode>( childList.length );
76          }
77  
78          CollectionUtils.addAll( children, childList );
79      }
80  
81  
82      /**
83       * Creates a BranchNode using a logical operator.
84       * 
85       * @param assertionType the node's type
86       */
87      protected BranchNode( AssertionType assertionType )
88      {
89          super( assertionType );
90  
91          this.children = new ArrayList<ExprNode>( 2 );
92          isSchemaAware = true;
93      }
94  
95  
96      /**
97       * @see ExprNode#isLeaf()
98       * @return false all the time.
99       */
100     public final boolean isLeaf()
101     {
102         return false;
103     }
104 
105 
106     /**
107      * Makes a full clone in new memory space of the current node and children
108      * 
109      * @return the clone
110      */
111     @Override
112     public ExprNode clone()
113     {
114         ExprNode clone = ( ExprNode ) super.clone();
115 
116         // Clone the children
117         if ( children != null )
118         {
119             ( ( BranchNode ) clone ).children = new ArrayList<ExprNode>();
120 
121             for ( ExprNode child : children )
122             {
123                 ( ( BranchNode ) clone ).children.add( ( ExprNode ) child.clone() );
124             }
125         }
126 
127         return clone;
128     }
129 
130 
131     /**
132      * Adds a child node to this branch node node
133      * 
134      * @param node the child expression to add to this branch node
135      */
136     public void addNode( ExprNode node )
137     {
138         children.add( node );
139     }
140 
141 
142     /**
143      * Adds a child node to this branch node at the head rather than the tail. 
144      * 
145      * @param node the child expression to add to this branch node
146      */
147     public void addNodeToHead( ExprNode node )
148     {
149         children.add( 0, node );
150     }
151 
152 
153     /**
154      * Gets the children below this BranchNode. We purposefully do not clone the
155      * array list so that backends can sort the order of children using their
156      * own search optimization algorithms. We want backends and other parts of
157      * the system to be able to induce side effects on the tree structure.
158      * 
159      * @return the list of child nodes under this branch node.
160      */
161     public List<ExprNode> getChildren()
162     {
163         return children;
164     }
165 
166 
167     /**
168      * Sets the list of children under this node.
169      * 
170      * @param list the list of children to set.
171      */
172     public void setChildren( List<ExprNode> list )
173     {
174         children = list;
175     }
176 
177 
178     /**
179      * Convenience method that gets the first child in the children array. Its
180      * very useful for NOT nodes since they only have one child by avoiding code
181      * that looks like: <code> ( ExprNode ) m_children.get( 0 ) </code>
182      * 
183      * @return the first child
184      */
185     public ExprNode getFirstChild()
186     {
187         if ( children.size() > 0 )
188         {
189             return children.get( 0 );
190         }
191 
192         return null;
193     }
194 
195 
196     /**
197      * @see ExprNode#accept(
198      *FilterVisitor)
199      *      
200      * @return The modified element
201      */
202     public final Object accept( FilterVisitor visitor )
203     {
204         if ( visitor.isPrefix() )
205         {
206             List<ExprNode> childrenList = visitor.getOrder( this, this.children );
207             ExprNode result = null;
208 
209             if ( visitor.canVisit( this ) )
210             {
211                 result = ( ExprNode ) visitor.visit( this );
212             }
213 
214             for ( ExprNode node : childrenList )
215             {
216                 node.accept( visitor );
217             }
218 
219             return result;
220         }
221         else
222         {
223             if ( visitor.canVisit( this ) )
224             {
225                 return visitor.visit( this );
226             }
227             else
228             {
229                 return null;
230             }
231         }
232     }
233 
234 
235     /**
236      * @see Object#hashCode()
237      * @return the instance's hash code 
238      */
239     public int hashCode()
240     {
241         int h = 37;
242 
243         h = h * 17 + super.hashCode();
244 
245         if ( children != null )
246         {
247             for ( ExprNode child : children )
248             {
249                 h = h * 17 + child.hashCode();
250             }
251         }
252 
253         return h;
254     }
255 
256 
257     /**
258      * @see java.lang.Object#equals(java.lang.Object)
259      */
260     public boolean equals( Object other )
261     {
262         if ( this == other )
263         {
264             return true;
265         }
266 
267         if ( !( other instanceof BranchNode ) )
268         {
269             return false;
270         }
271 
272         if ( other.getClass() != this.getClass() )
273         {
274             return false;
275         }
276 
277         BranchNode otherExprNode = ( BranchNode ) other;
278 
279         List<ExprNode> otherChildren = otherExprNode.getChildren();
280 
281         if ( otherChildren == children )
282         {
283             return true;
284         }
285 
286         if ( children.size() != otherChildren.size() )
287         {
288             return false;
289         }
290 
291         for ( int i = 0; i < children.size(); i++ )
292         {
293             ExprNode child = children.get( i );
294             ExprNode otherChild = children.get( i );
295 
296             if ( !child.equals( otherChild ) )
297             {
298                 return false;
299             }
300         }
301 
302         return true;
303     }
304 }