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