View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    https://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.filter;
21  
22  
23  import java.util.Arrays;
24  
25  import org.apache.directory.api.i18n.I18n;
26  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
27  import org.apache.directory.api.ldap.model.entry.Value;
28  import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
29  import org.apache.directory.api.ldap.model.schema.AttributeType;
30  import org.apache.directory.api.util.Strings;
31  
32  
33  /**
34   * A simple assertion value node.
35   * 
36   * @param <T> The Value type
37   * 
38   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
39   */
40  public abstract class SimpleNode<T> extends LeafNode
41  {
42      /** the value */
43      protected Value value;
44      
45      /** The value as a byte[] */
46      protected byte[] bytes;
47  
48      /** Constants for comparisons : @gt; */
49      public static final boolean EVAL_GREATER = true;
50  
51      /** Constants for comparisons : &lt; */
52      public static final boolean EVAL_LESSER = false;
53  
54  
55      /**
56       * Creates a new SimpleNode object.
57       * 
58       * @param attribute the attribute name
59       * @param bytes the data to inject
60       * @param assertionType the type of assertion represented by this ExprNode
61       */
62      protected SimpleNode( String attribute, byte[] bytes, AssertionType assertionType )
63      {
64          super( attribute, assertionType );
65          this.bytes = bytes;
66      }
67  
68  
69      /**
70       * Creates a new SimpleNode object.
71       * 
72       * @param attributeType the attribute name
73       * @param bytes the data to inject
74       * @param assertionType the type of assertion represented by this ExprNode
75       */
76      protected SimpleNode( AttributeType attributeType, byte[] bytes, AssertionType assertionType )
77      {
78          super( attributeType, assertionType );
79          this.bytes = bytes;
80          
81          try
82          {
83              if ( attributeType.isHR() )
84              {
85                  value = new Value( attributeType, Strings.utf8ToString( bytes ) );
86              }
87              else
88              {
89                      value = new Value( attributeType, bytes );
90              }
91          }
92          catch ( LdapInvalidAttributeValueException e )
93          {
94              throw new RuntimeException( e.getMessage() );
95          }
96      }
97  
98  
99      /**
100      * Creates a new SimpleNode object.
101      * 
102      * @param attribute the attribute name
103      * @param string the value to inject
104      * @param assertionType the type of assertion represented by this ExprNode
105      */
106     protected SimpleNode( String attribute, String string, AssertionType assertionType )
107     {
108         super( attribute, assertionType );
109         bytes = Strings.getBytesUtf8( string );
110         
111         if ( attributeType != null )
112         {
113             try
114             {
115                 if ( attributeType.isHR() )
116                 {
117                     value = new Value( attributeType, string );
118                 }
119                 else
120                 {
121                     value = new Value( attributeType, bytes );
122                 }
123             }
124             catch ( LdapInvalidAttributeValueException e )
125             {
126                 throw new RuntimeException( e.getMessage() );
127             }
128         }
129     }
130 
131 
132     /**
133      * Creates a new SimpleNode object.
134      * 
135      * @param attributeType the attribute name
136      * @param value the value to test for
137      * @param assertionType the type of assertion represented by this ExprNode
138      */
139     protected SimpleNode( AttributeType attributeType, Value value, AssertionType assertionType )
140     {
141         super( attributeType, assertionType );
142         this.value = value;
143     }
144 
145 
146     /**
147      * Makes a full clone in new memory space of the current node and children
148      */
149     @SuppressWarnings("unchecked")
150     @Override
151     public ExprNode clone()
152     {
153         ExprNode clone = super.clone();
154 
155         // Clone the value, if we have one
156         if ( value != null )
157         {
158             ( ( SimpleNode<T> ) clone ).value = value.clone();
159         }
160         else
161         {
162             // clone the bytes if any
163             if ( bytes != null )
164             {
165                 ( ( SimpleNode<T> ) clone ).bytes = new byte[bytes.length];
166                 System.arraycopy( bytes, 0, ( ( SimpleNode<T> ) clone ).bytes, 0, bytes.length );
167             }
168         }
169 
170         return clone;
171     }
172 
173 
174     /**
175      * Gets the value.
176      * 
177      * @return the value
178      */
179     public final Value getValue()
180     {
181         if ( value == null )
182         {
183             return new Value( bytes );
184         }
185         else
186         {
187             return value;
188         }
189     }
190 
191 
192     /** 
193      * @return representation of value, escaped for use in a filter if required 
194      */
195     public String getEscapedValue()
196     {
197         if ( value != null )
198         {
199             return escapeFilterValue( value.getAttributeType(), value.getBytes() );
200         }
201         else
202         {
203             return escapeFilterValue( null, bytes );
204         }
205     }
206 
207 
208     /**
209      * Sets the value of this node.
210      * 
211      * @param value the value for this node
212      */
213     public void setValue( Value value )
214     {
215         this.value = value;
216         this.bytes = value.getBytes();
217     }
218 
219 
220     /**
221      * Pretty prints this expression node along with annotation information.
222      *
223      * @param buf the buffer to print into
224      * @return the same buf argument returned for call chaining
225      */
226     public StringBuilder printToBuffer( StringBuilder buf )
227     {
228         if ( ( null != getAnnotations() ) && getAnnotations().containsKey( "count" ) )
229         {
230             buf.append( ":[" );
231             buf.append( getAnnotations().get( "count" ).toString() );
232             buf.append( "] " );
233         }
234 
235         buf.append( ')' );
236 
237         return buf;
238     }
239 
240 
241     /**
242      * @see ExprNode#printRefinementToBuffer(StringBuilder)
243      * @return The buffer in which the refinement has been appended
244      * @throws UnsupportedOperationException if this node isn't a part of a refinement.
245      */
246     @Override
247     public StringBuilder printRefinementToBuffer( StringBuilder buf )
248     {
249         if ( isSchemaAware() )
250         {
251             if ( !attributeType.getOid().equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
252             {
253                 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13318_INVALID_ATTR_IN_REFINEMENT, attribute ) );
254             }
255         }
256         else
257         {
258             if ( ( attribute == null )
259                 || !( SchemaConstants.OBJECT_CLASS_AT.equalsIgnoreCase( attribute )
260                 || SchemaConstants.OBJECT_CLASS_AT_OID.equalsIgnoreCase( attribute ) ) )
261             {
262                 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13318_INVALID_ATTR_IN_REFINEMENT, attribute ) );
263             }
264         }
265 
266         buf.append( "item: " ).append( value );
267 
268         return buf;
269     }
270 
271 
272     /**
273      * @see Object#hashCode()
274      * @return the instance's hash code 
275      */
276     @Override
277     public int hashCode()
278     {
279         int h = 37;
280 
281         h = h * 17 + super.hashCode();
282         h = h * 17 + ( value == null ? 0 : value.hashCode() );
283 
284         return h;
285     }
286 
287 
288     /**
289      * @see java.lang.Object#equals(java.lang.Object)
290      */
291     @Override
292     public boolean equals( Object other )
293     {
294         if ( this == other )
295         {
296             return true;
297         }
298 
299         if ( !( other instanceof SimpleNode<?> ) )
300         {
301             return false;
302         }
303 
304         if ( other.getClass() != this.getClass() )
305         {
306             return false;
307         }
308 
309         if ( !super.equals( other ) )
310         {
311             return false;
312         }
313 
314         SimpleNode<?> otherNode = ( SimpleNode<?> ) other;
315 
316         if ( value == null )
317         {
318             if ( bytes == null )
319             {
320                 return otherNode.bytes == null;
321             }
322             else
323             {
324                 return Arrays.equals( bytes,  otherNode.bytes );
325             }
326         }
327         else
328         {
329             return value.equals( otherNode.value );
330         }
331     }
332 }