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<ExprNode>( 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<ExprNode>( 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<ExprNode>( 2 ); 092 isSchemaAware = true; 093 } 094 095 096 /** 097 * @see ExprNode#isLeaf() 098 * @return false all the time. 099 */ 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}