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  @Override
087  public int hashCode()
088  {
089    AttributeType attrType = getAttributeDescription().getAttributeType();
090    int hashCode = attrType.hashCode();
091    for (ByteString value : this)
092    {
093      try
094      {
095        MatchingRule eqRule = attrType.getEqualityMatchingRule();
096        hashCode += eqRule.normalizeAttributeValue(value).hashCode();
097      }
098      catch (DecodeException e)
099      {
100        hashCode += value.hashCode();
101      }
102    }
103    return hashCode;
104  }
105
106  /**
107   * {@inheritDoc}
108   * <p>
109   * This implementation returns <code>true</code> if the
110   * {@link #size()} of this attribute is zero.
111   */
112  @Override
113  public boolean isEmpty()
114  {
115    return size() == 0;
116  }
117
118  @Override
119  public boolean isReal()
120  {
121    return !isVirtual();
122  }
123
124  @Override
125  public final String toString()
126  {
127    StringBuilder buffer = new StringBuilder();
128    toString(buffer);
129    return buffer.toString();
130  }
131}