/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2009-2010 Sun Microsystems, Inc. * Portions copyright 2012-2013 ForgeRock AS. */ package org.forgerock.opendj.ldap; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.NoSuchElementException; import org.forgerock.i18n.LocalizedIllegalArgumentException; import com.forgerock.opendj.util.Validator; /** * An implementation of the {@code Attribute} interface with predictable * iteration order. *
* Internally, attribute values are stored in a linked list and it's this list * which defines the iteration ordering, which is the order in which elements * were inserted into the set (insertion-order). This ordering is particularly * useful in LDAP where clients generally appreciate having things returned in * the same order they were presented. *
* All operations are supported by this implementation.
*/
public final class LinkedAttribute extends AbstractAttribute {
private static abstract class Impl {
abstract boolean add(LinkedAttribute attribute, ByteString value);
abstract void clear(LinkedAttribute attribute);
abstract boolean contains(LinkedAttribute attribute, ByteString value);
boolean containsAll(final LinkedAttribute attribute, final Collection> values) {
// TODO: could optimize if objects is a LinkedAttribute having the
// same equality matching rule.
for (final Object value : values) {
if (!contains(attribute, ByteString.valueOf(value))) {
return false;
}
}
return true;
}
abstract ByteString firstValue(LinkedAttribute attribute);
abstract Iterator
* If {@code value} is not an instance of {@code ByteString} then it will be
* converted using the {@link ByteString#valueOf(Object)} method.
*
* @param attributeDescription
* The attribute description.
* @param value
* The single attribute value.
* @throws NullPointerException
* If {@code attributeDescription} or {@code value} was
* {@code null} .
*/
public LinkedAttribute(final AttributeDescription attributeDescription, final Object value) {
this(attributeDescription);
add(value);
}
/**
* Creates a new attribute having the specified attribute description and
* attribute values.
*
* Any attribute values which are not instances of {@code ByteString} will
* be converted using the {@link ByteString#valueOf(Object)} method.
*
* @param attributeDescription
* The attribute description.
* @param values
* The attribute values.
* @throws NullPointerException
* If {@code attributeDescription} or {@code values} was
* {@code null}.
*/
public LinkedAttribute(final AttributeDescription attributeDescription,
final Object... values) {
this(attributeDescription);
add(values);
}
/**
* Creates a new attribute having the specified attribute description and
* attribute values.
*
* Any attribute values which are not instances of {@code ByteString} will
* be converted using the {@link ByteString#valueOf(Object)} method.
*
* @param attributeDescription
* The attribute description.
* @param values
* The attribute values.
* @throws NullPointerException
* If {@code attributeDescription} or {@code values} was
* {@code null}.
*/
public LinkedAttribute(final AttributeDescription attributeDescription,
final Collection> values) {
this(attributeDescription);
addAll(values, null);
}
/**
* Creates a new attribute having the specified attribute description and no
* attribute values. The attribute description will be decoded using the
* default schema.
*
* @param attributeDescription
* The attribute description.
* @throws LocalizedIllegalArgumentException
* If {@code attributeDescription} could not be decoded using
* the default schema.
* @throws NullPointerException
* If {@code attributeDescription} was {@code null}.
*/
public LinkedAttribute(final String attributeDescription) {
this(AttributeDescription.valueOf(attributeDescription));
}
/**
* Creates a new attribute having the specified attribute description and
* attribute values. The attribute description will be decoded using the
* default schema.
*
* Any attribute values which are not instances of {@code ByteString} will
* be converted using the {@link ByteString#valueOf(Object)} method.
*
* @param attributeDescription
* The attribute description.
* @param values
* The attribute values.
* @throws LocalizedIllegalArgumentException
* If {@code attributeDescription} could not be decoded using
* the default schema.
* @throws NullPointerException
* If {@code attributeDescription} or {@code values} was
* {@code null}.
*/
public LinkedAttribute(final String attributeDescription, final Collection> values) {
this(attributeDescription);
addAll(values, null);
}
/**
* Creates a new attribute having the specified attribute description and
* single attribute value. The attribute description will be decoded using
* the default schema.
*
* If {@code value} is not an instance of {@code ByteString} then it will be
* converted using the {@link ByteString#valueOf(Object)} method.
*
* @param attributeDescription
* The attribute description.
* @param value
* The single attribute value.
* @throws LocalizedIllegalArgumentException
* If {@code attributeDescription} could not be decoded using
* the default schema.
* @throws NullPointerException
* If {@code attributeDescription} or {@code value} was
* {@code null} .
*/
public LinkedAttribute(final String attributeDescription, final Object value) {
this(attributeDescription);
add(ByteString.valueOf(value));
}
/**
* Creates a new attribute having the specified attribute description and
* attribute values. The attribute description will be decoded using the
* default schema.
*
* Any attribute values which are not instances of {@code ByteString} will
* be converted using the {@link ByteString#valueOf(Object)} method.
*
* @param attributeDescription
* The attribute description.
* @param values
* The attribute values.
* @throws LocalizedIllegalArgumentException
* If {@code attributeDescription} could not be decoded using
* the default schema.
* @throws NullPointerException
* If {@code attributeDescription} or {@code values} was
* {@code null}.
*/
public LinkedAttribute(final String attributeDescription, final Object... values) {
this(attributeDescription);
add(values);
}
/**
* {@inheritDoc}
*/
@Override
public boolean add(final ByteString value) {
Validator.ensureNotNull(value);
return pimpl.add(this, value);
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
pimpl.clear(this);
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(final Object value) {
Validator.ensureNotNull(value);
return pimpl.contains(this, ByteString.valueOf(value));
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsAll(final Collection> values) {
Validator.ensureNotNull(values);
return pimpl.containsAll(this, values);
}
/**
* {@inheritDoc}
*/
@Override
public ByteString firstValue() {
return pimpl.firstValue(this);
}
/**
* {@inheritDoc}
*/
@Override
public AttributeDescription getAttributeDescription() {
return attributeDescription;
}
/**
* {@inheritDoc}
*/
@Override
public Iterator