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 */ 020package org.apache.directory.api.ldap.model.filter; 021 022 023import java.util.ArrayList; 024import java.util.List; 025 026import org.apache.commons.collections4.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 */ 035public abstract class BranchNode extends AbstractExprNode 036{ 037 /** child node list for this branch node */ 038 protected List<ExprNode> children = null; 039 040 041 /** 042 * Creates a BranchNode using a logical operator and a list of children. 043 * @param assertionType the node's type 044 * @param childList the child nodes under this branch node. 045 */ 046 protected BranchNode( AssertionType assertionType, List<ExprNode> childList ) 047 { 048 super( assertionType ); 049 050 if ( null == childList ) 051 { 052 this.children = new ArrayList<>( 2 ); 053 } 054 else 055 { 056 this.children = childList; 057 } 058 } 059 060 061 /** 062 * Creates a BranchNode using a logical operator and a list of children. 063 * 064 * @param assertionType the node's type 065 * @param childList the child nodes under this branch node. 066 */ 067 protected BranchNode( AssertionType assertionType, ExprNode... childList ) 068 { 069 super( assertionType ); 070 071 if ( null == children ) 072 { 073 this.children = new ArrayList<>( childList.length ); 074 } 075 076 CollectionUtils.addAll( children, childList ); 077 } 078 079 080 /** 081 * Creates a BranchNode using a logical operator. 082 * 083 * @param assertionType the node's type 084 */ 085 protected BranchNode( AssertionType assertionType ) 086 { 087 super( assertionType ); 088 089 this.children = new ArrayList<>( 2 ); 090 } 091 092 093 /** 094 * @see ExprNode#isLeaf() 095 * @return false all the time. 096 */ 097 @Override 098 public final boolean isLeaf() 099 { 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}