AttributeBuilder.java revision f15e69d46eb0444e28427f49fb519ea476c7feae
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * CDDL HEADER START
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The contents of this file are subject to the terms of the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Common Development and Distribution License, Version 1.0 only
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * (the "License"). You may not use this file except in compliance
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * with the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * or http://forgerock.org/license/CDDLv1.0.html.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * See the License for the specific language governing permissions
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * and limitations under the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * When distributing Covered Code, include this CDDL HEADER in each
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * file and include the License file at legal-notices/CDDLv1_0.txt.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If applicable, add the following below this CDDL HEADER, with the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * fields enclosed by brackets "[]" replaced with your own identifying
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * information:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Portions Copyright [yyyy] [name of copyright owner]
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * CDDL HEADER END
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Copyright 2006-2010 Sun Microsystems, Inc.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Portions Copyright 2012-2015 ForgeRock AS
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport org.forgerock.i18n.slf4j.LocalizedLogger;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport org.forgerock.opendj.ldap.ConditionResult;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport org.forgerock.opendj.ldap.DecodeException;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport org.forgerock.opendj.ldap.schema.MatchingRule;
f2f3d0d9b622a1d1f9b282ba8d8fd9e5353efb5ePeter Majorimport static org.opends.server.util.StaticUtils.*;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * This class provides an interface for creating new non-virtual
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * {@link Attribute}s, or "real" attributes.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * An attribute can be created incrementally using either
7be5aa496ae10e8d30aa6675df55e074cbb5cfedMark de Reeper * {@link #AttributeBuilder(AttributeType)} or
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * {@link #AttributeBuilder(AttributeType, String)}. The caller is
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * then free to add new options using {@link #setOption(String)} and
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * new values using {@link #add(ByteString)} or
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * {@link #addAll(Collection)}. Once all the options and values have
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * been added, the attribute can be retrieved using the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * {@link #toAttribute()} method.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * A real attribute can also be created based on the values taken from
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * another attribute using the {@link #AttributeBuilder(Attribute)}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * constructor. The caller is then free to modify the values within
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * the attribute before retrieving the updated attribute using the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * {@link #toAttribute()} method.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The {@link org.opends.server.types.Attributes} class contains
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * convenience factory methods,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * e.g. {@link org.opends.server.types.Attributes#empty(String)} for
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * creating empty attributes, and
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * {@link org.opends.server.types.Attributes#create(String, String)}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * for creating single-valued attributes.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * <code>AttributeBuilder</code>s can be re-used. Once an
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * <code>AttributeBuilder</code> has been converted to an
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * {@link Attribute} using {@link #toAttribute()}, its state is reset
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * so that its attribute type, user-provided name, options, and values
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * are all undefined:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * AttributeBuilder builder = new AttributeBuilder();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * for (int i = 0; i < 10; i++)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * builder.setAttributeType("myAttribute" + i);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * builder.setOption("an-option");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * builder.add("a value");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Attribute attribute = builder.toAttribute();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * // Do something with attribute...
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * <b>Implementation Note:</b> this class is optimized for the common
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * case where there is only a single value. By doing so, we avoid
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * using unnecessary storage space and also performing any unnecessary
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * normalization. In addition, this class is optimized for the common
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * cases where there are zero or one attribute type options.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster stability = org.opends.server.types.StabilityLevel.UNCOMMITTED,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterpublic final class AttributeBuilder implements Iterable<ByteString>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * A real attribute - options handled by sub-classes.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private static abstract class RealAttribute
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** The attribute type for this attribute. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** The name of this attribute as provided by the end user. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The unmodifiable set of attribute values, which are lazily normalized.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * When required, the attribute values are normalized according to the equality
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * matching rule.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Creates a new real attribute.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param attributeType
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The attribute type.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param name
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The user-provided attribute name.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param values
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The attribute values.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private RealAttribute(AttributeType attributeType, String name, Set<AttributeValue> values)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster public final ConditionResult approximatelyEqualTo(ByteString assertionValue)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster MatchingRule matchingRule = attributeType.getApproximateMatchingRule();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster assertion = matchingRule.getAssertion(assertionValue);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ConditionResult result = ConditionResult.FALSE;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster result = assertion.matches(matchingRule.normalizeAttributeValue(v.getValue()));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // We couldn't normalize one of the attribute values. If we
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // can't find a definite match, then we should return
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // "undefined".
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster public final boolean contains(ByteString value)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return values.contains(createAttributeValue(attributeType, value));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster public ConditionResult matchesEqualityAssertion(ByteString assertionValue)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster MatchingRule eqRule = getAttributeType().getEqualityMatchingRule();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster final Assertion assertion = eqRule.getAssertion(assertionValue);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (assertion.matches(value.getNormalizedValue()).toBoolean())
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster public final ConditionResult greaterThanOrEqualTo(ByteString assertionValue)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster MatchingRule matchingRule = attributeType.getOrderingMatchingRule();
7be5aa496ae10e8d30aa6675df55e074cbb5cfedMark de Reeper assertion = matchingRule.getGreaterOrEqualAssertion(assertionValue);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ConditionResult result = ConditionResult.FALSE;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (assertion.matches(matchingRule.normalizeAttributeValue(v.getValue())).toBoolean())
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // We couldn't normalize one of the attribute values. If we
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // can't find a definite match, then we should return "undefined".
f2f3d0d9b622a1d1f9b282ba8d8fd9e5353efb5ePeter Major public final boolean isVirtual()
f2f3d0d9b622a1d1f9b282ba8d8fd9e5353efb5ePeter Major return false;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster public final ConditionResult lessThanOrEqualTo(ByteString assertionValue)
f2f3d0d9b622a1d1f9b282ba8d8fd9e5353efb5ePeter Major MatchingRule matchingRule = attributeType.getOrderingMatchingRule();
f2f3d0d9b622a1d1f9b282ba8d8fd9e5353efb5ePeter Major assertion = matchingRule.getLessOrEqualAssertion(assertionValue);
catch (Exception e)
return result;
public final ConditionResult matchesSubstring(ByteString subInitial, List<ByteString> subAny, ByteString subFinal)
catch (DecodeException e)
catch (Exception e)
return result;
public final int size()
public int hashCode()
return hashCode;
private static final class RealAttributeManyOptions
extends RealAttribute
private RealAttributeManyOptions(
return options;
public boolean hasOptions()
private RealAttributeNoOptions(AttributeType attributeType, String name, Set<AttributeValue> values)
return getName();
public boolean hasOptions()
private static final class RealAttributeSingleOption
extends RealAttribute
private RealAttributeSingleOption(
return option;
public boolean hasOptions()
private T firstElement;
public SmallSet()
public boolean add(T e)
firstElement = e;
switch (c.size())
public void clear()
return new Iterator<T>()
private boolean hasNext = true;
public boolean hasNext()
return hasNext;
public T next()
if (!hasNext)
throw new NoSuchElementException();
hasNext = false;
return firstElement;
public void remove()
throw new UnsupportedOperationException();
throws IllegalStateException
throw new IllegalStateException();
public int size()
private static final class AttributeValue
return normalizedValue;
boolean isNormalized()
return value;
else if (o instanceof AttributeValue)
catch (Exception e)
public int hashCode()
catch (Exception e)
public AttributeBuilder()
this(attribute, false);
if (!omitValues)
if (!isNewValue)
return isNewValue;
private static AttributeValue createAttributeValue(AttributeType attributeType, ByteString attributeValue)
catch (DecodeException e)
return attributeValue;
boolean wasModified = false;
return wasModified;
boolean wasModified = false;
return wasModified;
boolean wasModified = false;
return wasModified;
public void clear()
if (!contains(v))
return attributeType;
public boolean isEmpty()
boolean wasModified = false;
return wasModified;
boolean wasModified = false;
return wasModified;
clear();
clear();
clear();
public void setAttributeType(
boolean isModified = false;
return isModified;
public int size()
public boolean hasNext()
public void remove()
throw new UnsupportedOperationException();
boolean isNormalized()
return attribute;