001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.types;
028    
029    
030    
031    import static org.opends.server.loggers.debug.DebugLogger.*;
032    import static org.opends.server.util.Validator.*;
033    
034    import org.opends.server.api.EqualityMatchingRule;
035    import org.opends.server.loggers.debug.DebugTracer;
036    import org.opends.server.protocols.asn1.ASN1OctetString;
037    
038    
039    
040    /**
041     * This class defines a data structure that holds information about a
042     * single value of an attribute.  It will always store the value in
043     * user-provided form, and will also store either a reference to the
044     * associated attribute type or the normalized form of the value.  The
045     * normalized form of the value should only be used in cases where
046     * equality matching between two values can be performed with
047     * byte-for-byte comparisons of the normalized values.
048     */
049    @org.opends.server.types.PublicAPI(
050         stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
051         mayInstantiate=true,
052         mayExtend=false,
053         mayInvoke=true)
054    public final class AttributeValue
055    {
056      /**
057       * The tracer object for the debug logger.
058       */
059      private static final DebugTracer TRACER = getTracer();
060    
061    
062    
063      // The normalized form of this value.
064      private ByteString normalizedValue;
065    
066      // The user-provided form of this value.
067      private final ByteString value;
068    
069      // The attribute type with which this value is associated.
070      private final AttributeType attributeType;
071    
072    
073    
074      /**
075       * Creates a new attribute value with the provided information.
076       *
077       * @param  attributeType  The attribute type for this attribute
078       *                        value.  It must not be {@code null}.
079       * @param  value          The value in user-provided form for this
080       *                        attribute value.  It must not be
081       *                        {@code null}.
082       */
083      public AttributeValue(AttributeType attributeType, ByteString value)
084      {
085        ensureNotNull(attributeType, value);
086    
087        this.attributeType = attributeType;
088        this.value         = value;
089    
090        normalizedValue = null;
091      }
092    
093    
094      /**
095       * Creates a new attribute value with the provided information.
096       *
097       * @param  attributeType  The attribute type for this attribute
098       *                        value.  It must not be {@code null}.
099       * @param  value          The value in user-provided form for this
100       *                        attribute value.  It must not be
101       *                        {@code null}.
102       */
103      public AttributeValue(AttributeType attributeType, String value)
104      {
105        ensureNotNull(attributeType, value);
106    
107        this.attributeType = attributeType;
108        this.value         = new ASN1OctetString(value);
109    
110        normalizedValue = null;
111      }
112    
113    
114      /**
115       * Creates a new attribute value with the provided information.
116       * Note that this version of the constructor should only be used for
117       * attribute types in which equality matching can be performed by
118       * byte-for-byte comparison of normalized values.
119       *
120       * @param  value            The user-provided form of this value.
121       *                          It must not be {@code null}.
122       * @param  normalizedValue  The normalized form of this value.  It
123       *                          must not be {@code null}.
124       */
125      public AttributeValue(ByteString value, ByteString normalizedValue)
126      {
127        ensureNotNull(value, normalizedValue);
128    
129        this.value           = value;
130        this.normalizedValue = normalizedValue;
131    
132        attributeType = null;
133      }
134    
135    
136    
137      /**
138       * Retrieves the user-defined form of this attribute value.
139       *
140       * @return  The user-defined form of this attribute value.
141       */
142      public ByteString getValue()
143      {
144        return value;
145      }
146    
147    
148    
149      /**
150       * Retrieves the raw bytes that make up this attribute value.
151       *
152       * @return  The raw bytes that make up this attribute value.
153       */
154      public byte[] getValueBytes()
155      {
156        return value.value();
157      }
158    
159    
160    
161      /**
162       * Retrieves a string representation of the user-defined form of
163       * this attribute value.
164       *
165       * @return  The string representation of the user-defined form of
166       *          this attribute value.
167       */
168      public String getStringValue()
169      {
170        return value.stringValue();
171      }
172    
173    
174    
175      /**
176       * Retrieves the normalized form of this attribute value.
177       *
178       * @return  The normalized form of this attribute value.
179       *
180       * @throws  DirectoryException  If an error occurs while trying to
181       *                              normalize the value (e.g., if it is
182       *                              not acceptable for use with the
183       *                              associated equality matching rule).
184       */
185      public ByteString getNormalizedValue()
186             throws DirectoryException
187      {
188        if (normalizedValue == null)
189        {
190          normalizedValue = attributeType.normalize(value);
191        }
192    
193        return normalizedValue;
194      }
195    
196    
197    
198      /**
199       * Retrieves the bytes that make up the normalized form of this
200       * value.
201       *
202       * @return  The bytes that make up the normalized form of this
203       *          value.
204       *
205       * @throws  DirectoryException  If an error occurs while trying to
206       *                              normalize the value (e.g., if it is
207       *                              not acceptable for use with the
208       *                              associated equality matching rule).
209       */
210      public byte[] getNormalizedValueBytes()
211             throws DirectoryException
212      {
213        return getNormalizedValue().value();
214      }
215    
216    
217    
218      /**
219       * Retrieves a string representation of the normalized form of this
220       * attribute value.
221       *
222       * @return  The string representation of the normalized form of this
223       *          attribute value.
224       *
225       * @throws  DirectoryException  If an error occurs while trying to
226       *                              normalize the value (e.g., if it is
227       *                              not acceptable for use with the
228       *                              associated equality matching rule).
229       */
230      public String getNormalizedStringValue()
231             throws DirectoryException
232      {
233        if (normalizedValue == null)
234        {
235          normalizedValue = attributeType.normalize(value);
236        }
237    
238        return normalizedValue.stringValue();
239      }
240    
241    
242    
243    
244      /**
245       * Determines whether this attribute value is equal to the provided
246       * object.
247       *
248       * @param  o  The object for which to make the determination.
249       *
250       * @return  <CODE>true</CODE> if this attribute value is equal to
251       *          the provided object, or <CODE>false</CODE> if not.
252       */
253      public boolean equals(Object o)
254      {
255        if (this == o)
256        {
257          return true;
258        }
259    
260        if ((o != null) && (o instanceof AttributeValue))
261        {
262          AttributeValue attrValue = (AttributeValue) o;
263    
264    
265          try
266          {
267            if (attributeType != null)
268            {
269              EqualityMatchingRule matchingRule =
270                   attributeType.getEqualityMatchingRule();
271              if (matchingRule == null)
272              {
273                return getNormalizedValue().equals(
274                            attrValue.getNormalizedValue());
275              }
276              else
277              {
278                return (matchingRule.valuesMatch(getNormalizedValue(),
279                             attrValue.getNormalizedValue()) ==
280                        ConditionResult.TRUE);
281              }
282            }
283            else if (attrValue.attributeType != null)
284            {
285              EqualityMatchingRule matchingRule =
286                   attrValue.attributeType.getEqualityMatchingRule();
287              if (matchingRule == null)
288              {
289                return getNormalizedValue().equals(
290                            attrValue.getNormalizedValue());
291              }
292              else
293              {
294                return (matchingRule.valuesMatch(getNormalizedValue(),
295                             attrValue.getNormalizedValue()) ==
296                        ConditionResult.TRUE);
297              }
298            }
299            else
300            {
301              return normalizedValue.equals(
302                          attrValue.getNormalizedValue());
303            }
304          }
305          catch (Exception e)
306          {
307            if (debugEnabled())
308            {
309              TRACER.debugCaught(DebugLogLevel.ERROR, e);
310            }
311    
312            return value.equals(attrValue.getValue());
313          }
314        }
315    
316        return false;
317      }
318    
319    
320    
321      /**
322       * Retrieves the hash code for this attribute value.  It will be
323       * calculated as the sum of the first two bytes in the value, or the
324       * value of a single-byte value, or zero for an empty value.
325       *
326       * @return  A hash code for this attribute value.
327       */
328      public int hashCode()
329      {
330        try
331        {
332          if (attributeType == null)
333          {
334            if (normalizedValue != null)
335            {
336              return normalizedValue.hashCode();
337            }
338            else
339            {
340              return value.hashCode();
341            }
342          }
343          else
344          {
345            return attributeType.generateHashCode(this);
346          }
347        }
348        catch (Exception e)
349        {
350          if (debugEnabled())
351          {
352            TRACER.debugCaught(DebugLogLevel.ERROR, e);
353          }
354    
355          return value.hashCode();
356        }
357      }
358    
359    
360    
361      /**
362       * Retrieves a string representation of this attribute value.
363       *
364       * @return  A string representation of this attribute value.
365       */
366      public String toString()
367      {
368        if (value == null)
369        {
370          return "null";
371        }
372        else
373        {
374          return value.stringValue();
375        }
376      }
377    
378    
379    
380      /**
381       * Appends a string representation of this attribute value to the
382       * provided buffer.
383       *
384       * @param  buffer  The buffer to which the information should be
385       *                 appended.
386       */
387      public void toString(StringBuilder buffer)
388      {
389        buffer.append(value.toString());
390      }
391    }
392