001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2008 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2016 ForgeRock AS.
016 */
017package org.opends.server.types;
018
019import java.util.Collection;
020
021import org.forgerock.opendj.ldap.ByteString;
022import org.forgerock.opendj.ldap.DecodeException;
023import org.forgerock.opendj.ldap.schema.AttributeType;
024import org.forgerock.opendj.ldap.schema.MatchingRule;
025
026/** An abstract base class for implementing new types of {@link Attribute}. */
027@org.opends.server.types.PublicAPI(
028    stability = org.opends.server.types.StabilityLevel.UNCOMMITTED,
029    mayInstantiate = false,
030    mayExtend = false,
031    mayInvoke = true)
032public abstract class AbstractAttribute implements Attribute
033{
034  /** Creates a new abstract attribute. */
035  protected AbstractAttribute()
036  {
037    // No implementation required.
038  }
039
040  @Override
041  public boolean containsAll(Collection<?> values)
042  {
043    for (Object value : values)
044    {
045      if (!contains(ByteString.valueOfObject(value)))
046      {
047        return false;
048      }
049    }
050    return true;
051  }
052
053  @Override
054  public final boolean equals(Object o)
055  {
056    if (this == o)
057    {
058      return true;
059    }
060    if (!(o instanceof Attribute))
061    {
062      return false;
063    }
064
065    Attribute a = (Attribute) o;
066    return getAttributeDescription().equals(a.getAttributeDescription()) && valuesEqual(a);
067  }
068
069  private boolean valuesEqual(Attribute a)
070  {
071    if (size() != a.size())
072    {
073      return false;
074    }
075
076    for (ByteString v : a)
077    {
078      if (!contains(v))
079      {
080        return false;
081      }
082    }
083    return true;
084  }
085
086  /**
087   * {@inheritDoc}
088   * <p>
089   * This implementation returns the primary name associated with this
090   * attribute's attribute type or, if there is no primary name, the
091   * attribute type's OID.
092   */
093  @Override
094  public String getName()
095  {
096    return getAttributeDescription().getAttributeType().getNameOrOID();
097  }
098
099  /**
100   * {@inheritDoc}
101   * <p>
102   * This implementation returns this attribute's name if there are no
103   * attribute options, otherwise it constructs a string comprising of
104   * this attribute's name followed by a semi-colon and a semi-colon
105   * separated list of its attribute options.
106   */
107  @Override
108  public String getNameWithOptions()
109  {
110    if (!hasOptions())
111    {
112      return getName();
113    }
114
115    StringBuilder buffer = new StringBuilder();
116    buffer.append(getName());
117    for (String option : getAttributeDescription().getOptions())
118    {
119      buffer.append(';');
120      buffer.append(option);
121    }
122    return buffer.toString();
123  }
124
125  @Override
126  public int hashCode()
127  {
128    AttributeType attrType = getAttributeDescription().getAttributeType();
129    int hashCode = attrType.hashCode();
130    for (ByteString value : this)
131    {
132      try
133      {
134        MatchingRule eqRule = attrType.getEqualityMatchingRule();
135        hashCode += eqRule.normalizeAttributeValue(value).hashCode();
136      }
137      catch (DecodeException e)
138      {
139        hashCode += value.hashCode();
140      }
141    }
142    return hashCode;
143  }
144
145  @Override
146  public boolean hasOption(String option)
147  {
148    return getAttributeDescription().hasOption(option);
149  }
150
151  /**
152   * {@inheritDoc}
153   * <p>
154   * This implementation retrieves the set of options associated with
155   * this attribute and tests to see if it is empty.
156   */
157  @Override
158  public boolean hasOptions()
159  {
160    return getAttributeDescription().hasOptions();
161  }
162
163  /**
164   * {@inheritDoc}
165   * <p>
166   * This implementation returns <code>true</code> if the
167   * {@link #size()} of this attribute is zero.
168   */
169  @Override
170  public boolean isEmpty()
171  {
172    return size() == 0;
173  }
174
175  @Override
176  public boolean isReal()
177  {
178    return !isVirtual();
179  }
180
181  @Override
182  public final String toString()
183  {
184    StringBuilder buffer = new StringBuilder();
185    toString(buffer);
186    return buffer.toString();
187  }
188}