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 */ 020 package org.apache.directory.shared.ldap.filter; 021 022 023 import java.util.ArrayList; 024 import java.util.List; 025 026 import 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 * @version $Rev: 746607 $ 035 */ 036 public class BranchNode extends AbstractExprNode 037 { 038 /** child node list for this branch node */ 039 protected List<ExprNode> children = null; 040 041 042 /** 043 * Creates a BranchNode using a logical operator and a list of children. 044 * @param assertionType the node's type 045 * @param childList the child nodes under this branch node. 046 */ 047 protected BranchNode( AssertionType assertionType, List<ExprNode> childList ) 048 { 049 super( assertionType ); 050 051 if ( null == childList ) 052 { 053 this.children = new ArrayList<ExprNode>( 2 ); 054 } 055 else 056 { 057 this.children = childList; 058 } 059 } 060 061 062 /** 063 * Creates a BranchNode using a logical operator and a list of children. 064 * 065 * @param assertionType the node's type 066 * @param childList the child nodes under this branch node. 067 */ 068 protected BranchNode( AssertionType assertionType, ExprNode... childList ) 069 { 070 super( assertionType ); 071 072 if ( null == children ) 073 { 074 this.children = new ArrayList<ExprNode>( childList.length ); 075 } 076 077 CollectionUtils.addAll( children, childList ); 078 } 079 080 081 /** 082 * Creates a BranchNode using a logical operator. 083 * 084 * @param assertionType the node's type 085 */ 086 protected BranchNode( AssertionType assertionType ) 087 { 088 super( assertionType ); 089 090 this.children = new ArrayList<ExprNode>( 2 ); 091 } 092 093 094 /** 095 * @see org.apache.directory.shared.ldap.filter.ExprNode#isLeaf() 096 * @return false all the time. 097 */ 098 public final boolean isLeaf() 099 { 100 return false; 101 } 102 103 /** 104 * Makes a full clone in new memory space of the current node and children 105 * 106 * @return the clone 107 */ 108 @Override public ExprNode clone() 109 { 110 ExprNode clone = (ExprNode)super.clone(); 111 112 // Clone the children 113 if ( children != null ) 114 { 115 ((BranchNode)clone).children = new ArrayList<ExprNode>(); 116 117 for ( ExprNode child : children ) 118 { 119 ((BranchNode)clone).children.add( (ExprNode)child.clone() ); 120 } 121 } 122 123 return clone; 124 } 125 126 127 /** 128 * Adds a child node to this branch node node 129 * 130 * @param node the child expression to add to this branch node 131 */ 132 public void addNode( ExprNode node ) 133 { 134 children.add( node ); 135 } 136 137 138 /** 139 * Adds a child node to this branch node at the head rather than the tail. 140 * 141 * @param node the child expression to add to this branch node 142 */ 143 public void addNodeToHead( ExprNode node ) 144 { 145 children.add( 0, node ); 146 } 147 148 149 /** 150 * Gets the children below this BranchNode. We purposefully do not clone the 151 * array list so that backends can sort the order of children using their 152 * own search optimization algorithms. We want backends and other parts of 153 * the system to be able to induce side effects on the tree structure. 154 * 155 * @return the list of child nodes under this branch node. 156 */ 157 public List<ExprNode> getChildren() 158 { 159 return children; 160 } 161 162 163 /** 164 * Sets the list of children under this node. 165 * 166 * @param list the list of children to set. 167 */ 168 public void setChildren( List<ExprNode> list ) 169 { 170 children = list; 171 } 172 173 /** 174 * Convenience method that gets the first child in the children array. Its 175 * very useful for NOT nodes since they only have one child by avoiding code 176 * that looks like: <code> ( ExprNode ) m_children.get( 0 ) </code> 177 * 178 * @return the first child 179 */ 180 public ExprNode getFirstChild() 181 { 182 if ( children.size() > 0 ) 183 { 184 return children.get( 0 ); 185 } 186 187 return null; 188 } 189 190 191 /** 192 * @see org.apache.directory.shared.ldap.filter.ExprNode#accept( 193 * org.apache.directory.shared.ldap.filter.FilterVisitor) 194 * 195 * @return The modified element 196 */ 197 public final Object accept( FilterVisitor visitor ) 198 { 199 if ( visitor.isPrefix() ) 200 { 201 List<ExprNode> childrenList = visitor.getOrder( this, this.children ); 202 ExprNode result = null; 203 204 if ( visitor.canVisit( this ) ) 205 { 206 result = (ExprNode)visitor.visit( this ); 207 } 208 209 for ( ExprNode node:childrenList ) 210 { 211 node.accept( visitor ); 212 } 213 214 return result; 215 } 216 else 217 { 218 if ( visitor.canVisit( this ) ) 219 { 220 return visitor.visit( this ); 221 } 222 else 223 { 224 return null; 225 } 226 } 227 } 228 229 230 /** 231 * (non-Javadoc) 232 * 233 * @see Object#hashCode() 234 * @return the instance's hash code 235 */ 236 public int hashCode() 237 { 238 int h = 37; 239 240 h = h*17 + super.hashCode(); 241 242 if ( children != null ) 243 { 244 for ( ExprNode child:children ) 245 { 246 h = h*17 + child.hashCode(); 247 } 248 } 249 250 return h; 251 } 252 253 /* 254 * (non-Javadoc) 255 * 256 * @see java.lang.Object#equals(java.lang.Object) 257 */ 258 public boolean equals( Object other ) 259 { 260 if ( this == other ) 261 { 262 return true; 263 } 264 265 if ( !( other instanceof BranchNode ) ) 266 { 267 return false; 268 } 269 270 if ( other.getClass() != this.getClass() ) 271 { 272 return false; 273 } 274 275 BranchNode otherExprNode = ( BranchNode ) other; 276 277 List<ExprNode> otherChildren = otherExprNode.getChildren(); 278 279 if ( otherChildren == children ) 280 { 281 return true; 282 } 283 284 if ( children.size() != otherChildren.size() ) 285 { 286 return false; 287 } 288 289 for ( int i = 0; i < children.size(); i++ ) 290 { 291 ExprNode child = children.get( i ); 292 ExprNode otherChild = children.get( i ); 293 294 if ( !child.equals( otherChild ) ) 295 { 296 return false; 297 } 298 } 299 300 return true; 301 } 302 }