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.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 */ 035public 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 isSchemaAware = true; 060 } 061 062 063 /** 064 * Creates a BranchNode using a logical operator and a list of children. 065 * 066 * @param assertionType the node's type 067 * @param childList the child nodes under this branch node. 068 */ 069 protected BranchNode( AssertionType assertionType, ExprNode... childList ) 070 { 071 super( assertionType ); 072 073 if ( null == children ) 074 { 075 this.children = new ArrayList<>( childList.length ); 076 } 077 078 CollectionUtils.addAll( children, childList ); 079 } 080 081 082 /** 083 * Creates a BranchNode using a logical operator. 084 * 085 * @param assertionType the node's type 086 */ 087 protected BranchNode( AssertionType assertionType ) 088 { 089 super( assertionType ); 090 091 this.children = new ArrayList<>( 2 ); 092 isSchemaAware = true; 093 } 094 095 096 /** 097 * @see ExprNode#isLeaf() 098 * @return false all the time. 099 */ 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}