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<>( 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<>( 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<>( 2 );
92          isSchemaAware = true;
93      }
94  
95  
96      /**
97       * @see ExprNode#isLeaf()
98       * @return false all the time.
99       */
100     @Override
101     public final boolean isLeaf()
102     {
103         return false;
104     }
105 
106 
107     /**
108      * Makes a full clone in new memory space of the current node and children
109      * 
110      * @return the clone
111      */
112     @Override
113     public ExprNode clone()
114     {
115         ExprNode clone = super.clone();
116 
117         // Clone the children
118         if ( children != null )
119         {
120             ( ( BranchNode ) clone ).children = new ArrayList<>();
121 
122             for ( ExprNode child : children )
123             {
124                 ( ( BranchNode ) clone ).children.add( ( ExprNode ) child.clone() );
125             }
126         }
127 
128         return clone;
129     }
130 
131 
132     /**
133      * Adds a child node to this branch node node
134      * 
135      * @param node the child expression to add to this branch node
136      */
137     public void addNode( ExprNode node )
138     {
139         children.add( node );
140     }
141 
142 
143     /**
144      * Adds a child node to this branch node at the head rather than the tail. 
145      * 
146      * @param node the child expression to add to this branch node
147      */
148     public void addNodeToHead( ExprNode node )
149     {
150         children.add( 0, node );
151     }
152 
153 
154     /**
155      * Gets the children below this BranchNode. We purposefully do not clone the
156      * array list so that backends can sort the order of children using their
157      * own search optimization algorithms. We want backends and other parts of
158      * the system to be able to induce side effects on the tree structure.
159      * 
160      * @return the list of child nodes under this branch node.
161      */
162     public List<ExprNode> getChildren()
163     {
164         return children;
165     }
166 
167 
168     /**
169      * Sets the list of children under this node.
170      * 
171      * @param list the list of children to set.
172      */
173     public void setChildren( List<ExprNode> list )
174     {
175         children = list;
176     }
177 
178 
179     /**
180      * Convenience method that gets the first child in the children array. Its
181      * very useful for NOT nodes since they only have one child by avoiding code
182      * that looks like: <code> ( ExprNode ) m_children.get( 0 ) </code>
183      * 
184      * @return the first child
185      */
186     public ExprNode getFirstChild()
187     {
188         if ( !children.isEmpty() )
189         {
190             return children.get( 0 );
191         }
192 
193         return null;
194     }
195 
196 
197     /**
198      * @see ExprNode#accept(
199      *FilterVisitor)
200      *      
201      * @return The modified element
202      */
203     @Override
204     public final Object accept( FilterVisitor visitor )
205     {
206         if ( visitor.isPrefix() )
207         {
208             List<ExprNode> childrenList = visitor.getOrder( this, this.children );
209             ExprNode result = null;
210 
211             if ( visitor.canVisit( this ) )
212             {
213                 result = ( ExprNode ) visitor.visit( this );
214             }
215 
216             for ( ExprNode node : childrenList )
217             {
218                 node.accept( visitor );
219             }
220 
221             return result;
222         }
223         else
224         {
225             if ( visitor.canVisit( this ) )
226             {
227                 return visitor.visit( this );
228             }
229             else
230             {
231                 return null;
232             }
233         }
234     }
235 
236 
237     /**
238      * @see Object#hashCode()
239      * @return the instance's hash code 
240      */
241     @Override
242     public int hashCode()
243     {
244         int h = 37;
245 
246         h = h * 17 + super.hashCode();
247 
248         if ( children != null )
249         {
250             for ( ExprNode child : children )
251             {
252                 h = h * 17 + child.hashCode();
253             }
254         }
255 
256         return h;
257     }
258 
259 
260     /**
261      * @see java.lang.Object#equals(java.lang.Object)
262      */
263     @Override
264     public boolean equals( Object other )
265     {
266         if ( this == other )
267         {
268             return true;
269         }
270 
271         if ( !( other instanceof BranchNode ) )
272         {
273             return false;
274         }
275 
276         if ( other.getClass() != this.getClass() )
277         {
278             return false;
279         }
280 
281         BranchNode otherExprNode = ( BranchNode ) other;
282 
283         List<ExprNode> otherChildren = otherExprNode.getChildren();
284 
285         if ( otherChildren == children )
286         {
287             return true;
288         }
289 
290         if ( children.size() != otherChildren.size() )
291         {
292             return false;
293         }
294 
295         for ( int i = 0; i < children.size(); i++ )
296         {
297             ExprNode child = children.get( i );
298             ExprNode otherChild = children.get( i );
299 
300             if ( !child.equals( otherChild ) )
301             {
302                 return false;
303             }
304         }
305 
306         return true;
307     }
308 }