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 * https://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.HashMap; 024import java.util.Map; 025 026import org.apache.directory.api.i18n.I18n; 027 028 029/** 030 * Abstract implementation of a expression node. 031 * 032 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 033 */ 034public abstract class AbstractExprNode implements ExprNode 035{ 036 /** The map of annotations */ 037 protected Map<String, Object> annotations; 038 039 /** The node type */ 040 protected final AssertionType assertionType; 041 042 043 /** 044 * Creates a node by setting abstract node type. 045 * 046 * @param assertionType The node's type 047 */ 048 protected AbstractExprNode( AssertionType assertionType ) 049 { 050 this.assertionType = assertionType; 051 } 052 053 054 /** 055 * @see ExprNode#getAssertionType() 056 * 057 * @return the node's type 058 */ 059 @Override 060 public AssertionType getAssertionType() 061 { 062 return assertionType; 063 } 064 065 066 /** 067 * @see Object#equals(Object) 068 *@return <code>true</code> if both objects are equal 069 */ 070 @Override 071 public boolean equals( Object o ) 072 { 073 // Shortcut for equals object 074 if ( this == o ) 075 { 076 return true; 077 } 078 079 if ( !( o instanceof AbstractExprNode ) ) 080 { 081 return false; 082 } 083 084 AbstractExprNode that = ( AbstractExprNode ) o; 085 086 // Check the node type 087 if ( this.assertionType != that.assertionType ) 088 { 089 return false; 090 } 091 092 if ( annotations == null ) 093 { 094 return that.annotations == null; 095 } 096 else if ( that.annotations == null ) 097 { 098 return false; 099 } 100 101 // Check all the annotation 102 for ( Map.Entry<String, Object> entry : annotations.entrySet() ) 103 { 104 String key = entry.getKey(); 105 106 if ( !that.annotations.containsKey( key ) ) 107 { 108 return false; 109 } 110 111 Object thisAnnotation = entry.getValue(); 112 Object thatAnnotation = that.annotations.get( key ); 113 114 if ( thisAnnotation == null ) 115 { 116 if ( thatAnnotation != null ) 117 { 118 return false; 119 } 120 } 121 else 122 { 123 if ( !thisAnnotation.equals( thatAnnotation ) ) 124 { 125 return false; 126 } 127 } 128 } 129 130 return true; 131 } 132 133 134 /** 135 * @see Object#hashCode() 136 * @return the instance's hash code 137 */ 138 @Override 139 public int hashCode() 140 { 141 int h = 37; 142 143 if ( annotations != null ) 144 { 145 for ( Map.Entry<String, Object> entry : annotations.entrySet() ) 146 { 147 String key = entry.getKey(); 148 Object value = entry.getValue(); 149 150 h = h * 17 + key.hashCode(); 151 h = h * 17 + ( value == null ? 0 : value.hashCode() ); 152 } 153 } 154 155 return h; 156 } 157 158 159 /** 160 * @see ExprNode#get(java.lang.Object) 161 * 162 * @return the annotation value. 163 */ 164 @Override 165 public Object get( Object key ) 166 { 167 if ( null == annotations ) 168 { 169 return null; 170 } 171 172 return annotations.get( key ); 173 } 174 175 176 /** 177 * @see ExprNode#set(String, Object) 178 */ 179 @Override 180 public void set( String key, Object value ) 181 { 182 if ( null == annotations ) 183 { 184 annotations = new HashMap<>( 2 ); 185 } 186 187 annotations.put( key, value ); 188 } 189 190 191 /** 192 * Gets the annotations as a Map. 193 * 194 * @return the annotation map. 195 */ 196 protected Map<String, Object> getAnnotations() 197 { 198 return annotations; 199 } 200 201 202 /** 203 * Default implementation for this method : just throw an exception. 204 * 205 * @param buf the buffer to append to. 206 * @return The buffer in which the refinement has been appended 207 * @throws UnsupportedOperationException if this node isn't a part of a refinement. 208 */ 209 @Override 210 public StringBuilder printRefinementToBuffer( StringBuilder buf ) 211 { 212 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13303_SCOPENODE_IN_REFINEMENT ) ); 213 } 214 215 216 /** 217 * Clone the object 218 */ 219 @Override 220 public ExprNode clone() 221 { 222 try 223 { 224 ExprNode clone = ( ExprNode ) super.clone(); 225 226 if ( annotations != null ) 227 { 228 for ( Map.Entry<String, Object> entry : annotations.entrySet() ) 229 { 230 // Note : the value aren't cloned ! 231 ( ( AbstractExprNode ) clone ).annotations.put( entry.getKey(), entry.getValue() ); 232 } 233 } 234 235 return clone; 236 } 237 catch ( CloneNotSupportedException cnse ) 238 { 239 return null; 240 } 241 } 242 243 244 /** 245 * @see Object#toString() 246 */ 247 @Override 248 public String toString() 249 { 250 if ( ( null != annotations ) && annotations.containsKey( "count" ) ) 251 { 252 Long count = ( Long ) annotations.get( "count" ); 253 254 if ( count == Long.MAX_VALUE ) 255 { 256 return ":[\u221E]"; 257 } 258 259 return ":[" + count + "]"; 260 } 261 else 262 { 263 return ""; 264 } 265 } 266}