opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractEntry.java
@@ -28,6 +28,7 @@ package org.forgerock.opendj.ldap; import java.util.Collection; import java.util.Iterator; import com.forgerock.opendj.util.Iterables; import com.forgerock.opendj.util.Predicate; @@ -43,6 +44,7 @@ private static final Predicate<Attribute, AttributeDescription> FIND_ATTRIBUTES_PREDICATE = new Predicate<Attribute, AttributeDescription>() { @Override public boolean matches(final Attribute value, final AttributeDescription p) { return value.getAttributeDescription().isSubTypeOf(p); } @@ -50,94 +52,6 @@ }; /** * Returns {@code true} if {@code object} is an entry which is equal to * {@code entry}. Two entry are considered equal if their distinguished * names are equal, they both have the same number of attributes, and every * attribute contained in the first entry is also contained in the second * entry. * * @param entry * The entry to be tested for equality. * @param object * The object to be tested for equality with the entry. * @return {@code true} if {@code object} is an entry which is equal to * {@code entry}, or {@code false} if not. */ static boolean equals(final Entry entry, final Object object) { if (entry == object) { return true; } if (!(object instanceof Entry)) { return false; } final Entry other = (Entry) object; if (!entry.getName().equals(other.getName())) { return false; } // Distinguished name is the same, compare attributes. if (entry.getAttributeCount() != other.getAttributeCount()) { return false; } for (final Attribute attribute : entry.getAllAttributes()) { final Attribute otherAttribute = other.getAttribute(attribute.getAttributeDescription()); if (!attribute.equals(otherAttribute)) { return false; } } return true; } /** * Returns the hash code for {@code entry}. It will be calculated as the sum * of the hash codes of the distinguished name and all of the attributes. * * @param entry * The entry whose hash code should be calculated. * @return The hash code for {@code entry}. */ static int hashCode(final Entry entry) { int hashCode = entry.getName().hashCode(); for (final Attribute attribute : entry.getAllAttributes()) { hashCode += attribute.hashCode(); } return hashCode; } /** * Returns a string representation of {@code entry}. * * @param entry * The entry whose string representation should be returned. * @return The string representation of {@code entry}. */ static String toString(final Entry entry) { final StringBuilder builder = new StringBuilder(); builder.append("Entry("); builder.append(entry.getName()); builder.append(", {"); boolean firstValue = true; for (final Attribute attribute : entry.getAllAttributes()) { if (!firstValue) { builder.append(", "); } builder.append(attribute); firstValue = false; } builder.append("})"); return builder.toString(); } /** * Sole constructor. */ protected AbstractEntry() { @@ -147,6 +61,7 @@ /** * {@inheritDoc} */ @Override public boolean addAttribute(final Attribute attribute) { return addAttribute(attribute, null); } @@ -154,6 +69,7 @@ /** * {@inheritDoc} */ @Override public Entry addAttribute(final String attributeDescription, final Object... values) { addAttribute(new LinkedAttribute(attributeDescription, values), null); return this; @@ -162,6 +78,7 @@ /** * {@inheritDoc} */ @Override public boolean containsAttribute(final Attribute attribute, final Collection<ByteString> missingValues) { final Attribute a = getAttribute(attribute.getAttributeDescription()); @@ -187,6 +104,7 @@ /** * {@inheritDoc} */ @Override public boolean containsAttribute(final String attributeDescription, final Object... values) { return containsAttribute(new LinkedAttribute(attributeDescription, values), null); } @@ -196,12 +114,34 @@ */ @Override public boolean equals(final Object object) { return equals(this, object); if (this == object) { return true; } else if (object instanceof Entry) { final Entry other = (Entry) object; if (!this.getName().equals(other.getName())) { return false; } // Distinguished name is the same, compare attributes. if (this.getAttributeCount() != other.getAttributeCount()) { return false; } for (final Attribute attribute : this.getAllAttributes()) { final Attribute otherAttribute = other.getAttribute(attribute.getAttributeDescription()); if (!attribute.equals(otherAttribute)) { return false; } } return true; } else { return false; } } /** * {@inheritDoc} */ @Override public Iterable<Attribute> getAllAttributes(final AttributeDescription attributeDescription) { Validator.ensureNotNull(attributeDescription); @@ -212,6 +152,7 @@ /** * {@inheritDoc} */ @Override public Iterable<Attribute> getAllAttributes(final String attributeDescription) { return getAllAttributes(AttributeDescription.valueOf(attributeDescription)); } @@ -219,6 +160,21 @@ /** * {@inheritDoc} */ @Override public Attribute getAttribute(final AttributeDescription attributeDescription) { for (final Attribute attribute : getAllAttributes()) { final AttributeDescription ad = attribute.getAttributeDescription(); if (isAssignable(attributeDescription, ad)) { return attribute; } } return null; } /** * {@inheritDoc} */ @Override public Attribute getAttribute(final String attributeDescription) { return getAttribute(AttributeDescription.valueOf(attributeDescription)); } @@ -228,26 +184,64 @@ */ @Override public int hashCode() { return hashCode(this); int hashCode = this.getName().hashCode(); for (final Attribute attribute : this.getAllAttributes()) { hashCode += attribute.hashCode(); } return hashCode; } /** * {@inheritDoc} */ public AttributeParser parseAttribute(AttributeDescription attributeDescription) { @Override public AttributeParser parseAttribute(final AttributeDescription attributeDescription) { return AttributeParser.parseAttribute(getAttribute(attributeDescription)); } /** * {@inheritDoc} */ public AttributeParser parseAttribute(String attributeDescription) { @Override public AttributeParser parseAttribute(final String attributeDescription) { return AttributeParser.parseAttribute(getAttribute(attributeDescription)); } /** * {@inheritDoc} */ @Override public boolean removeAttribute(final Attribute attribute, final Collection<ByteString> missingValues) { final Iterator<Attribute> i = getAllAttributes().iterator(); final AttributeDescription attributeDescription = attribute.getAttributeDescription(); while (i.hasNext()) { final Attribute oldAttribute = i.next(); if (isAssignable(attributeDescription, oldAttribute.getAttributeDescription())) { if (attribute.isEmpty()) { i.remove(); return true; } else { final boolean modified = oldAttribute.removeAll(attribute, missingValues); if (oldAttribute.isEmpty()) { i.remove(); return true; } return modified; } } } // Not found. if (missingValues != null) { missingValues.addAll(attribute); } return false; } /** * {@inheritDoc} */ @Override public boolean removeAttribute(final AttributeDescription attributeDescription) { return removeAttribute(Attributes.emptyAttribute(attributeDescription), null); } @@ -255,6 +249,7 @@ /** * {@inheritDoc} */ @Override public Entry removeAttribute(final String attributeDescription, final Object... values) { removeAttribute(new LinkedAttribute(attributeDescription, values), null); return this; @@ -263,12 +258,20 @@ /** * {@inheritDoc} */ @Override public boolean replaceAttribute(final Attribute attribute) { if (attribute.isEmpty()) { return removeAttribute(attribute.getAttributeDescription()); } else { removeAttribute(attribute.getAttributeDescription()); addAttribute(attribute, null); // For consistency with addAttribute and removeAttribute, preserve // the existing attribute if it already exists. final Attribute oldAttribute = getAttribute(attribute.getAttributeDescription()); if (oldAttribute != null) { oldAttribute.clear(); oldAttribute.addAll(attribute); } else { addAttribute(attribute, null); } return true; } } @@ -276,6 +279,7 @@ /** * {@inheritDoc} */ @Override public Entry replaceAttribute(final String attributeDescription, final Object... values) { replaceAttribute(new LinkedAttribute(attributeDescription, values)); return this; @@ -284,6 +288,7 @@ /** * {@inheritDoc} */ @Override public Entry setName(final String dn) { return setName(DN.valueOf(dn)); } @@ -293,7 +298,29 @@ */ @Override public String toString() { return toString(this); final StringBuilder builder = new StringBuilder(); builder.append("Entry("); builder.append(this.getName()); builder.append(", {"); boolean firstValue = true; for (final Attribute attribute : this.getAllAttributes()) { if (!firstValue) { builder.append(", "); } builder.append(attribute); firstValue = false; } builder.append("})"); return builder.toString(); } private boolean isAssignable(final AttributeDescription from, final AttributeDescription to) { if (!from.isPlaceHolder()) { return from.equals(to); } else { return from.matches(to); } } } opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AbstractMapEntry.java
@@ -37,7 +37,6 @@ */ abstract class AbstractMapEntry extends AbstractEntry { private final Map<AttributeDescription, Attribute> attributes; private DN name; /** @@ -57,12 +56,11 @@ /** * {@inheritDoc} */ @Override public final boolean addAttribute(final Attribute attribute, final Collection<ByteString> duplicateValues) { Validator.ensureNotNull(attribute); final AttributeDescription attributeDescription = attribute.getAttributeDescription(); final Attribute oldAttribute = attributes.get(attributeDescription); final Attribute oldAttribute = getAttribute(attributeDescription); if (oldAttribute != null) { return oldAttribute.addAll(attribute, duplicateValues); } else { @@ -74,6 +72,7 @@ /** * {@inheritDoc} */ @Override public final Entry clearAttributes() { attributes.clear(); return this; @@ -82,6 +81,7 @@ /** * {@inheritDoc} */ @Override public final Iterable<Attribute> getAllAttributes() { return attributes.values(); } @@ -89,15 +89,21 @@ /** * {@inheritDoc} */ @Override public final Attribute getAttribute(final AttributeDescription attributeDescription) { Validator.ensureNotNull(attributeDescription); return attributes.get(attributeDescription); final Attribute attribute = attributes.get(attributeDescription); if (attribute == null && attributeDescription.isPlaceHolder()) { // Fall-back to inefficient search using place-holder. return super.getAttribute(attributeDescription); } else { return attribute; } } /** * {@inheritDoc} */ @Override public final int getAttributeCount() { return attributes.size(); } @@ -105,6 +111,7 @@ /** * {@inheritDoc} */ @Override public final DN getName() { return name; } @@ -112,20 +119,27 @@ /** * {@inheritDoc} */ @Override public final boolean removeAttribute(final Attribute attribute, final Collection<ByteString> missingValues) { Validator.ensureNotNull(attribute); final AttributeDescription attributeDescription = attribute.getAttributeDescription(); if (attribute.isEmpty()) { return attributes.remove(attributeDescription) != null; if (attributes.remove(attributeDescription) != null) { return true; } else if (attributeDescription.isPlaceHolder()) { // Fall-back to inefficient remove using place-holder. return super.removeAttribute(attribute, missingValues); } else { return false; } } else { final Attribute oldAttribute = attributes.get(attributeDescription); final Attribute oldAttribute = getAttribute(attributeDescription); if (oldAttribute != null) { final boolean modified = oldAttribute.removeAll(attribute, missingValues); if (oldAttribute.isEmpty()) { attributes.remove(attributeDescription); // Use old attribute's description in case it is different // (e.g. this may be the case when using place-holders). attributes.remove(oldAttribute.getAttributeDescription()); return true; } return modified; @@ -141,6 +155,7 @@ /** * {@inheritDoc} */ @Override public final Entry setName(final DN dn) { Validator.ensureNotNull(dn); this.name = dn; opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AttributeDescription.java
@@ -67,7 +67,7 @@ public abstract int compareTo(Impl other); public abstract boolean containsOption(String normalizedOption); public abstract boolean hasOption(String normalizedOption); public abstract boolean equals(Impl other); @@ -128,7 +128,7 @@ } @Override public boolean containsOption(final String normalizedOption) { public boolean hasOption(final String normalizedOption) { final int sz = normalizedOptions.length; for (int i = 0; i < sz; i++) { if (normalizedOptions[i].equals(normalizedOption)) { @@ -169,7 +169,7 @@ if (other == ZERO_OPTION_IMPL) { return true; } else if (other.size() == 1) { return containsOption(other.firstNormalizedOption()); return hasOption(other.firstNormalizedOption()); } else if (other.size() > size()) { return false; } else { @@ -179,7 +179,7 @@ // not worth it. final MultiOptionImpl tmp = (MultiOptionImpl) other; for (final String normalizedOption : tmp.normalizedOptions) { if (!containsOption(normalizedOption)) { if (!hasOption(normalizedOption)) { return false; } } @@ -191,7 +191,7 @@ public boolean isSuperTypeOf(final Impl other) { // Must contain a sub-set of other's options. for (final String normalizedOption : normalizedOptions) { if (!other.containsOption(normalizedOption)) { if (!other.hasOption(normalizedOption)) { return false; } } @@ -235,13 +235,13 @@ } @Override public boolean containsOption(final String normalizedOption) { public boolean hasOption(final String normalizedOption) { return this.normalizedOption.equals(normalizedOption); } @Override public boolean equals(final Impl other) { return other.size() == 1 && other.containsOption(normalizedOption); return other.size() == 1 && other.hasOption(normalizedOption); } @Override @@ -272,7 +272,7 @@ @Override public boolean isSuperTypeOf(final Impl other) { // Other must have this option. return other.containsOption(normalizedOption); return other.hasOption(normalizedOption); } public Iterator<String> iterator() { @@ -298,7 +298,7 @@ } @Override public boolean containsOption(final String normalizedOption) { public boolean hasOption(final String normalizedOption) { return false; } @@ -391,7 +391,7 @@ Validator.ensureNotNull(option); final String normalizedOption = toLowerCase(option); if (pimpl.containsOption(normalizedOption)) { if (pimpl.hasOption(normalizedOption)) { return this; } @@ -480,7 +480,7 @@ Validator.ensureNotNull(option); final String normalizedOption = toLowerCase(option); if (!pimpl.containsOption(normalizedOption)) { if (!pimpl.hasOption(normalizedOption)) { return this; } @@ -489,8 +489,7 @@ new StringBuilder(oldAttributeDescription.length() - option.length() - 1); final String normalizedOldAttributeDescription = toLowerCase(oldAttributeDescription); final int index = normalizedOldAttributeDescription.indexOf(normalizedOption); final int index = normalizedOldAttributeDescription.indexOf(normalizedOption); builder.append(oldAttributeDescription, 0, index - 1 /* to semi-colon */); builder.append(oldAttributeDescription, index + option.length(), oldAttributeDescription .length()); @@ -1033,15 +1032,16 @@ * @throws NullPointerException * If {@code option} was {@code null}. */ public boolean containsOption(final String option) { public boolean hasOption(final String option) { final String normalizedOption = toLowerCase(option); return pimpl.containsOption(normalizedOption); return pimpl.hasOption(normalizedOption); } /** * Indicates whether the provided object is an attribute description which * is equal to this attribute description. It will be considered equal if * the attribute type and normalized sorted list of options are identical. * the attribute types are {@link AttributeType#equals equal} and normalized * sorted list of options are identical. * * @param o * The object for which to make the determination. @@ -1053,19 +1053,12 @@ public boolean equals(final Object o) { if (this == o) { return true; } if (!(o instanceof AttributeDescription)) { } else if (o instanceof AttributeDescription) { final AttributeDescription other = (AttributeDescription) o; return attributeType.equals(other.attributeType) && pimpl.equals(other.pimpl); } else { return false; } final AttributeDescription other = (AttributeDescription) o; if (!attributeType.equals(other.attributeType)) { return false; } // Attribute type is the same, compare options. return pimpl.equals(other.pimpl); } /** @@ -1125,14 +1118,34 @@ } /** * Indicates whether this attribute description is a temporary place-holder * allocated dynamically by a non-strict schema when no corresponding * registered attribute type was found. * <p> * Place holder attribute descriptions have an attribute type whose OID is * the normalized attribute name with the string {@code -oid} appended. In * addition, they will use the directory string syntax and case ignore * matching rule. * * @return {@code true} if this is a temporary place-holder attribute * description allocated dynamically by a non-strict schema when no * corresponding registered attribute type was found. * @see Schema#getAttributeType(String) * @see AttributeType#isPlaceHolder() */ public boolean isPlaceHolder() { return attributeType.isPlaceHolder(); } /** * Indicates whether or not this attribute description is a sub-type of the * provided attribute description as defined in RFC 4512 section 2.5. * Specifically, this method will return {@code true} if and only if the * following conditions are both {@code true}: * <ul> * <li>This attribute description has an attribute type which is equal to, * or is a sub-type of, the attribute type in the provided attribute * description. * <li>This attribute description has an attribute type which * {@link AttributeType#matches matches}, or is a sub-type of, the attribute * type in the provided attribute description. * <li>This attribute description contains all of the options contained in * the provided attribute description. * </ul> @@ -1160,9 +1173,9 @@ * Specifically, this method will return {@code true} if and only if the * following conditions are both {@code true}: * <ul> * <li>This attribute description has an attribute type which is equal to, * or is a super-type of, the attribute type in the provided attribute * description. * <li>This attribute description has an attribute type which * {@link AttributeType#matches matches}, or is a super-type of, the * attribute type in the provided attribute description. * <li>This attribute description contains a sub-set of the options * contained in the provided attribute description. * </ul> @@ -1177,7 +1190,7 @@ * If {@code name} was {@code null}. */ public boolean isSuperTypeOf(final AttributeDescription other) { if (!other.attributeType.isSubTypeOf(attributeType)) { if (!attributeType.isSuperTypeOf(other.attributeType)) { return false; } else { return pimpl.isSuperTypeOf(other.pimpl); @@ -1185,6 +1198,25 @@ } /** * Indicates whether the provided attribute description matches this * attribute description. It will be considered a match if the attribute * types {@link AttributeType#matches match} and the normalized sorted list * of options are identical. * * @param other * The attribute description for which to make the determination. * @return {@code true} if the provided attribute description matches this * attribute description, or {@code false} if not. */ public boolean matches(final AttributeDescription other) { if (this == other) { return true; } else { return attributeType.matches(other.attributeType) && pimpl.equals(other.pimpl); } } /** * Returns the string representation of this attribute description as * defined in RFC4512 section 2.5. * opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Attributes.java
@@ -30,6 +30,8 @@ import java.util.Collection; import java.util.Iterator; import org.forgerock.i18n.LocalizedIllegalArgumentException; import com.forgerock.opendj.util.Iterators; import com.forgerock.opendj.util.Validator; @@ -97,7 +99,6 @@ private static final class RenamedAttribute implements Attribute { private final Attribute attribute; private final AttributeDescription attributeDescription; private RenamedAttribute(final Attribute attribute, @@ -106,31 +107,38 @@ this.attributeDescription = attributeDescription; } @Override public boolean add(final ByteString value) { return attribute.add(value); } @Override public boolean add(final Object firstValue, final Object... remainingValues) { return attribute.add(firstValue, remainingValues); } @Override public boolean addAll(final Collection<? extends ByteString> values) { return attribute.addAll(values); } @Override public boolean addAll(final Collection<? extends ByteString> values, final Collection<? super ByteString> duplicateValues) { return attribute.addAll(values, duplicateValues); } @Override public void clear() { attribute.clear(); } @Override public boolean contains(final Object value) { return attribute.contains(value); } @Override public boolean containsAll(final Collection<?> values) { return attribute.containsAll(values); } @@ -140,18 +148,22 @@ return AbstractAttribute.equals(this, object); } @Override public ByteString firstValue() { return attribute.firstValue(); } @Override public String firstValueAsString() { return attribute.firstValueAsString(); } @Override public AttributeDescription getAttributeDescription() { return attributeDescription; } @Override public String getAttributeDescriptionAsString() { return attributeDescription.toString(); } @@ -161,48 +173,59 @@ return AbstractAttribute.hashCode(this); } public AttributeParser parse() { return attribute.parse(); } @Override public boolean isEmpty() { return attribute.isEmpty(); } @Override public Iterator<ByteString> iterator() { return attribute.iterator(); } @Override public AttributeParser parse() { return attribute.parse(); } @Override public boolean remove(final Object value) { return attribute.remove(value); } @Override public boolean removeAll(final Collection<?> values) { return attribute.removeAll(values); } @Override public <T> boolean removeAll(final Collection<T> values, final Collection<? super T> missingValues) { return attribute.removeAll(values, missingValues); } @Override public boolean retainAll(final Collection<?> values) { return attribute.retainAll(values); } @Override public <T> boolean retainAll(final Collection<T> values, final Collection<? super T> missingValues) { return attribute.retainAll(values, missingValues); } @Override public int size() { return attribute.size(); } @Override public ByteString[] toArray() { return attribute.toArray(); } @Override public <T> T[] toArray(final T[] array) { return attribute.toArray(array); } @@ -215,6 +238,72 @@ } /** * Singleton attribute. */ private static final class SingletonAttribute extends AbstractAttribute { private final AttributeDescription attributeDescription; private ByteString normalizedValue; private final ByteString value; private SingletonAttribute(final AttributeDescription attributeDescription, final Object value) { this.attributeDescription = attributeDescription; this.value = ByteString.valueOf(value); } @Override public boolean add(final ByteString value) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean contains(final Object value) { final ByteString normalizedValue = normalizeValue(this, ByteString.valueOf(value)); return normalizedSingleValue().equals(normalizedValue); } @Override public AttributeDescription getAttributeDescription() { return attributeDescription; } @Override public boolean isEmpty() { return false; } @Override public Iterator<ByteString> iterator() { return Iterators.singletonIterator(value); } @Override public boolean remove(final Object value) { throw new UnsupportedOperationException(); } @Override public int size() { return 1; } // Lazily computes the normalized single value. private ByteString normalizedSingleValue() { if (normalizedValue == null) { normalizedValue = normalizeValue(this, value); } return normalizedValue; } } /** * Unmodifiable attribute. */ private static final class UnmodifiableAttribute implements Attribute { @@ -225,31 +314,38 @@ this.attribute = attribute; } @Override public boolean add(final ByteString value) { throw new UnsupportedOperationException(); } @Override public boolean add(final Object firstValue, final Object... remainingValues) { throw new UnsupportedOperationException(); } @Override public boolean addAll(final Collection<? extends ByteString> values) { throw new UnsupportedOperationException(); } @Override public boolean addAll(final Collection<? extends ByteString> values, final Collection<? super ByteString> duplicateValues) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean contains(final Object value) { return attribute.contains(value); } @Override public boolean containsAll(final Collection<?> values) { return attribute.containsAll(values); } @@ -259,18 +355,22 @@ return (object == this || attribute.equals(object)); } @Override public ByteString firstValue() { return attribute.firstValue(); } @Override public String firstValueAsString() { return attribute.firstValueAsString(); } @Override public AttributeDescription getAttributeDescription() { return attribute.getAttributeDescription(); } @Override public String getAttributeDescriptionAsString() { return attribute.getAttributeDescriptionAsString(); } @@ -280,48 +380,59 @@ return attribute.hashCode(); } @Override public boolean isEmpty() { return attribute.isEmpty(); } @Override public Iterator<ByteString> iterator() { return Iterators.unmodifiableIterator(attribute.iterator()); } @Override public AttributeParser parse() { return attribute.parse(); } @Override public boolean remove(final Object value) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(final Collection<?> values) { throw new UnsupportedOperationException(); } @Override public <T> boolean removeAll(final Collection<T> values, final Collection<? super T> missingValues) { throw new UnsupportedOperationException(); } @Override public boolean retainAll(final Collection<?> values) { throw new UnsupportedOperationException(); } @Override public <T> boolean retainAll(final Collection<T> values, final Collection<? super T> missingValues) { throw new UnsupportedOperationException(); } @Override public int size() { return attribute.size(); } @Override public ByteString[] toArray() { return attribute.toArray(); } @Override public <T> T[] toArray(final T[] array) { return attribute.toArray(array); } @@ -330,12 +441,13 @@ public String toString() { return attribute.toString(); } } /** * Returns a read-only empty attribute having the specified attribute * description. * description. Attempts to modify the returned attribute either directly, * or indirectly via an iterator, result in an * {@code UnsupportedOperationException}. * * @param attributeDescription * The attribute description. @@ -348,6 +460,26 @@ } /** * Returns a read-only empty attribute having the specified attribute * description. The attribute description will be decoded using the default * schema. Attempts to modify the returned attribute either directly, or * indirectly via an iterator, result in an * {@code UnsupportedOperationException}. * * @param attributeDescription * The attribute description. * @return The empty attribute. * @throws LocalizedIllegalArgumentException * If {@code attributeDescription} could not be decoded using * the default schema. * @throws NullPointerException * If {@code attributeDescription} was {@code null}. */ public static final Attribute emptyAttribute(final String attributeDescription) { return emptyAttribute(AttributeDescription.valueOf(attributeDescription)); } /** * Returns a view of {@code attribute} having a different attribute * description. All operations on the returned attribute "pass-through" to * the underlying attribute. @@ -368,6 +500,80 @@ } /** * Returns a view of {@code attribute} having a different attribute * description. All operations on the returned attribute "pass-through" to * the underlying attribute. The attribute description will be decoded using * the default schema. * * @param attribute * The attribute to be renamed. * @param attributeDescription * The new attribute description for {@code attribute}. * @return A renamed view of {@code attribute}. * @throws LocalizedIllegalArgumentException * If {@code attributeDescription} could not be decoded using * the default schema. * @throws NullPointerException * If {@code attribute} or {@code attributeDescription} was * {@code null}. */ public static final Attribute renameAttribute(final Attribute attribute, final String attributeDescription) { Validator.ensureNotNull(attribute, attributeDescription); return renameAttribute(attribute, AttributeDescription.valueOf(attributeDescription)); } /** * Returns a read-only single-valued attribute having the specified * attribute description and value. Attempts to modify the returned * attribute either directly, or indirectly via an iterator, result in an * {@code UnsupportedOperationException}. * <p> * 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. * @return The single-valued attribute. * @throws NullPointerException * If {@code attributeDescription} or {@code value} was * {@code null}. */ public static final Attribute singletonAttribute( final AttributeDescription attributeDescription, final Object value) { return new SingletonAttribute(attributeDescription, value); } /** * Returns a read-only single-valued attribute having the specified * attribute description. The attribute description will be decoded using * the default schema. Attempts to modify the returned attribute either * directly, or indirectly via an iterator, result in an * {@code UnsupportedOperationException}. * <p> * 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. * @return The single-valued attribute. * @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 static final Attribute singletonAttribute(final String attributeDescription, final Object value) { return singletonAttribute(AttributeDescription.valueOf(attributeDescription), value); } /** * Returns a read-only view of {@code attribute}. Query operations on the * returned attribute "read-through" to the underlying attribute, and * attempts to modify the returned attribute either directly or indirectly opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/Entry.java
@@ -38,8 +38,12 @@ * {@link #addAttribute(String, Object...)} and {@link #setName(String)}). In * these cases the default schema is used unless an alternative schema is * specified in the {@code Entry} constructor. The default schema is not used * for any other purpose. In particular, an {@code Entry} will permit attributes * to be added which have been decoded using multiple schemas. * for any other purpose. In particular, an {@code Entry} may contain attributes * which have been decoded using different schemas. * <p> * When determining whether or not an entry already contains a particular * attribute, attribute descriptions will be compared using * {@link AttributeDescription#matches}. * <p> * Full LDAP modify semantics are provided via the {@link #addAttribute}, * {@link #removeAttribute}, and {@link #replaceAttribute} methods. @@ -64,12 +68,14 @@ * Ensures that this entry contains the provided attribute and values * (optional operation). This method has the following semantics: * <ul> * <li>If this entry does not already contain an attribute with the same * attribute description, then this entry will be modified such that it * contains {@code attribute}, even if it is empty. * <li>If this entry already contains an attribute with the same attribute * description, then the attribute values contained in {@code attribute} * will be merged with the existing attribute values. * <li>If this entry does not already contain an attribute with a * {@link AttributeDescription#matches matching} attribute description, then * this entry will be modified such that it contains {@code attribute}, even * if it is empty. * <li>If this entry already contains an attribute with a * {@link AttributeDescription#matches matching} attribute description, then * the attribute values contained in {@code attribute} will be merged with * the existing attribute values. * </ul> * <p> * <b>NOTE:</b> When {@code attribute} is non-empty, this method implements @@ -91,12 +97,14 @@ * Ensures that this entry contains the provided attribute and values * (optional operation). This method has the following semantics: * <ul> * <li>If this entry does not already contain an attribute with the same * attribute description, then this entry will be modified such that it * contains {@code attribute}, even if it is empty. * <li>If this entry already contains an attribute with the same attribute * description, then the attribute values contained in {@code attribute} * will be merged with the existing attribute values. * <li>If this entry does not already contain an attribute with a * {@link AttributeDescription#matches matching} attribute description, then * this entry will be modified such that it contains {@code attribute}, even * if it is empty. * <li>If this entry already contains an attribute with a * {@link AttributeDescription#matches matching} attribute description, then * the attribute values contained in {@code attribute} will be merged with * the existing attribute values. * </ul> * <p> * <b>NOTE:</b> When {@code attribute} is non-empty, this method implements @@ -121,12 +129,14 @@ * Ensures that this entry contains the provided attribute and values * (optional operation). This method has the following semantics: * <ul> * <li>If this entry does not already contain an attribute with the same * attribute description, then this entry will be modified such that it * contains {@code attribute}, even if it is empty. * <li>If this entry already contains an attribute with the same attribute * description, then the attribute values contained in {@code attribute} * will be merged with the existing attribute values. * <li>If this entry does not already contain an attribute with a * {@link AttributeDescription#matches matching} attribute description, then * this entry will be modified such that it contains {@code attribute}, even * if it is empty. * <li>If this entry already contains an attribute with a * {@link AttributeDescription#matches matching} attribute description, then * the attribute values contained in {@code attribute} will be merged with * the existing attribute values. * </ul> * <p> * The attribute description will be decoded using the schema associated opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java
@@ -74,6 +74,9 @@ // Indicates whether this definition is declared "obsolete". private final boolean isObsolete; // Indicates whether this definition is a temporary place-holder. private final boolean isPlaceHolder; // Indicates whether this attribute type is declared "single-value". private final boolean isSingleValue; @@ -162,34 +165,45 @@ } this.isObjectClassType = oid.equals("2.5.4.0"); this.isPlaceHolder = false; this.normalizedName = StaticUtils.toLowerCase(getNameOrOID()); } AttributeType(final String oid, final List<String> names, final String description, final MatchingRule equalityMatchingRule, final Syntax syntax) { super(description, Collections.<String, List<String>> emptyMap()); /** * Creates a new place-holder attribute type having the specified name, * default syntax, and default matching rule. The OID of the place-holder * attribute will be the normalized attribute type name followed by the * suffix "-oid". * * @param name * The name of the place-holder attribute type. */ AttributeType(final String name) { super("", Collections.<String, List<String>> emptyMap()); Validator.ensureNotNull(oid, names, description); final StringBuilder builder = new StringBuilder(name.length() + 4); StaticUtils.toLowerCase(name, builder); builder.append("-oid"); this.oid = oid; this.names = names; this.oid = builder.toString(); this.names = Collections.singletonList(name); this.isObsolete = false; this.superiorTypeOID = null; this.superiorType = null; this.equalityMatchingRule = Schema.getDefaultMatchingRule(); this.equalityMatchingRuleOID = equalityMatchingRule.getOID(); this.equalityMatchingRule = equalityMatchingRule; this.orderingMatchingRuleOID = null; this.substringMatchingRuleOID = null; this.approximateMatchingRuleOID = null; this.syntax = Schema.getDefaultSyntax(); this.syntaxOID = syntax.getOID(); this.syntax = syntax; this.isSingleValue = false; this.isCollective = false; this.isNoUserModification = false; this.attributeUsage = AttributeUsage.USER_APPLICATIONS; this.definition = buildDefinition(); this.isObjectClassType = oid.equals("2.5.4.0"); this.isObjectClassType = false; this.isPlaceHolder = true; this.normalizedName = StaticUtils.toLowerCase(getNameOrOID()); } @@ -200,7 +214,8 @@ * <li>The {@code objectClass} attribute is less than all other attribute * types. * <li>User attributes are less than operational attributes. * <li>Lexicographic comparison of the primary name or OID. * <li>Lexicographic comparison of the primary name and then, if equal, the * OID. * </ul> * * @param type @@ -219,9 +234,13 @@ } else { final boolean isOperational = getUsage().isOperational(); final boolean typeIsOperational = type.getUsage().isOperational(); if (isOperational == typeIsOperational) { return normalizedName.compareTo(type.normalizedName); final int tmp = normalizedName.compareTo(type.normalizedName); if (tmp == 0) { return oid.compareTo(type.oid); } else { return tmp; } } else { return isOperational ? 1 : -1; } @@ -452,6 +471,24 @@ } /** * Indicates whether this attribute type is a temporary place-holder * allocated dynamically by a non-strict schema when no registered attribute * type was found. * <p> * Place holder attribute types have an OID which is the normalized * attribute name with the string {@code -oid} appended. In addition, they * will use the directory string syntax and case ignore matching rule. * * @return {@code true} if this is a temporary place-holder attribute type * allocated dynamically by a non-strict schema when no registered * attribute type was found. * @see Schema#getAttributeType(String) */ public boolean isPlaceHolder() { return isPlaceHolder; } /** * Indicates whether this attribute type is declared "single-value". * * @return {@code true} if this attribute type is declared "single-value", @@ -475,7 +512,7 @@ public boolean isSubTypeOf(final AttributeType type) { AttributeType tmp = this; do { if (tmp.equals(type)) { if (tmp.matches(type)) { return true; } tmp = tmp.getSuperiorType(); @@ -484,6 +521,50 @@ } /** * Indicates whether or not this attribute type is a super-type of the * provided attribute type. * * @param type * The attribute type for which to make the determination. * @return {@code true} if this attribute type is a super-type of the * provided attribute type, or {@code false} if not. * @throws NullPointerException * If {@code type} was {@code null}. */ public boolean isSuperTypeOf(final AttributeType type) { return type.isSubTypeOf(this); } /** * Implements a place-holder tolerant version of {@link #equals}. This * method returns {@true} in the following cases: * <ul> * <li>this attribute type is equal to the provided attribute type as * specified by {@link #equals} * <li>this attribute type is a place-holder and the provided attribute type * has a name which matches the name of this attribute type * <li>the provided attribute type is a place-holder and this attribute type * has a name which matches the name of the provided attribute type. * </ul> * * @param type * The attribute type for which to make the determination. * @return {@code true} if the provided attribute type matches this * attribute type. */ public boolean matches(final AttributeType type) { if (this == type) { return true; } else if (oid.equals(type.oid)) { return true; } else if (isPlaceHolder != type.isPlaceHolder) { return isPlaceHolder ? type.hasName(normalizedName) : hasName(type.normalizedName); } else { return false; } } /** * Returns the string representation of this schema definition in the form * specified in RFC 2252. * @@ -591,8 +672,7 @@ boolean validate(final Schema schema, final List<AttributeType> invalidSchemaElements, final List<LocalizableMessage> warnings) { // Avoid validating this schema element more than once. This may occur // if // multiple attributes specify the same superior. // if multiple attributes specify the same superior. if (!needsValidating) { return isValid; } @@ -612,8 +692,7 @@ } // First ensure that the superior has been validated and fail if it // is // invalid. // is invalid. if (!superiorType.validate(schema, invalidSchemaElements, warnings)) { final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_INVALID_SUPERIOR_TYPE.get(getNameOrOID(), opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
@@ -73,8 +73,10 @@ public final class Schema { private static final class EmptyImpl implements Impl { private EmptyImpl() { // Nothing to do. private final boolean isStrict; private EmptyImpl(final boolean isStrict) { this.isStrict = isStrict; } public boolean allowMalformedNamesAndOptions() { @@ -95,17 +97,12 @@ @Override public AttributeType getAttributeType(final String name) { // Construct an placeholder attribute type with the given name, // the default matching rule, and the default syntax. The OID of // the attribute will be the normalized OID alias with "-oid" // appended to the given name. final StringBuilder builder = new StringBuilder(name.length() + 4); StaticUtils.toLowerCase(name, builder); builder.append("-oid"); final String noid = builder.toString(); return new AttributeType(noid, Collections.singletonList(name), "", Schema .getDefaultMatchingRule(), Schema.getDefaultSyntax()); if (isStrict) { throw new UnknownSchemaElementException(WARN_ATTR_TYPE_UNKNOWN.get(name)); } else { // Return a place-holder. return new AttributeType(name); } } @Override @@ -298,7 +295,7 @@ @Override public boolean isStrict() { return false; return isStrict; } } @@ -389,9 +386,9 @@ } private static final class NonStrictImpl implements Impl { private final Impl strictImpl; private final StrictImpl strictImpl; private NonStrictImpl(final Impl strictImpl) { private NonStrictImpl(final StrictImpl strictImpl) { this.strictImpl = strictImpl; } @@ -413,20 +410,8 @@ @Override public AttributeType getAttributeType(final String name) { if (!strictImpl.hasAttributeType(name)) { // Construct an placeholder attribute type with the given name, // the default matching rule, and the default syntax. The OID of // the attribute will be the normalized OID alias with "-oid" // appended to the given name. final StringBuilder builder = new StringBuilder(name.length() + 4); StaticUtils.toLowerCase(name, builder); builder.append("-oid"); final String noid = builder.toString(); return new AttributeType(noid, Collections.singletonList(name), "", Schema .getDefaultMatchingRule(), Schema.getDefaultSyntax()); } return strictImpl.getAttributeType(name); final AttributeType type = strictImpl.getAttributeType0(name); return type != null ? type : new AttributeType(name); } @Override @@ -735,19 +720,12 @@ @Override public AttributeType getAttributeType(final String name) { final AttributeType type = numericOID2AttributeTypes.get(name); final AttributeType type = getAttributeType0(name); if (type != null) { return type; } else { throw new UnknownSchemaElementException(WARN_ATTR_TYPE_UNKNOWN.get(name)); } final List<AttributeType> attributes = name2AttributeTypes.get(StaticUtils.toLowerCase(name)); if (attributes != null) { if (attributes.size() == 1) { return attributes.get(0); } throw new UnknownSchemaElementException(WARN_ATTR_TYPE_AMBIGIOUS.get(name)); } throw new UnknownSchemaElementException(WARN_ATTR_TYPE_UNKNOWN.get(name)); } @Override @@ -1073,28 +1051,37 @@ public boolean isStrict() { return true; } AttributeType getAttributeType0(final String name) { final AttributeType type = numericOID2AttributeTypes.get(name); if (type != null) { return type; } final List<AttributeType> attributes = name2AttributeTypes.get(StaticUtils.toLowerCase(name)); if (attributes != null) { if (attributes.size() == 1) { return attributes.get(0); } throw new UnknownSchemaElementException(WARN_ATTR_TYPE_AMBIGIOUS.get(name)); } return null; } } /* * WARNING: do not reference the core schema in the following declarations. */ private static final Schema EMPTY_SCHEMA = new Schema(new EmptyImpl()); private static final Schema EMPTY_STRICT_SCHEMA = new Schema(new EmptyImpl(true)); private static final Schema EMPTY_NON_STRICT_SCHEMA = new Schema(new EmptyImpl(false)); static final String ATTR_ATTRIBUTE_TYPES = "attributeTypes"; static final String ATTR_DIT_CONTENT_RULES = "dITContentRules"; static final String ATTR_DIT_STRUCTURE_RULES = "dITStructureRules"; static final String ATTR_LDAP_SYNTAXES = "ldapSyntaxes"; static final String ATTR_MATCHING_RULE_USE = "matchingRuleUse"; static final String ATTR_MATCHING_RULES = "matchingRules"; static final String ATTR_NAME_FORMS = "nameForms"; static final String ATTR_OBJECT_CLASSES = "objectClasses"; /** @@ -1138,7 +1125,7 @@ * @return The empty schema. */ public static Schema getEmptySchema() { return EMPTY_SCHEMA; return EMPTY_NON_STRICT_SCHEMA; } /** @@ -1457,10 +1444,13 @@ * @see Schema#isStrict() */ public Schema asNonStrictSchema() { if (impl.isStrict()) { return new Schema(new NonStrictImpl(impl)); } else { if (!impl.isStrict()) { return this; } else if (impl instanceof StrictImpl) { return new Schema(new NonStrictImpl((StrictImpl) impl)); } else { // EmptyImpl return EMPTY_NON_STRICT_SCHEMA; } } @@ -1475,13 +1465,23 @@ public Schema asStrictSchema() { if (impl.isStrict()) { return this; } else { } else if (impl instanceof NonStrictImpl) { return new Schema(((NonStrictImpl) impl).strictImpl); } else { // EmptyImpl return EMPTY_STRICT_SCHEMA; } } /** * Returns the attribute type with the specified name or numeric OID. * <p> * If the requested attribute type is not registered in this schema and this * schema is non-strict then a temporary "place-holder" attribute type will * be created and returned. Place holder attribute types have an OID which * is the normalized attribute name with the string {@code -oid} appended. * In addition, they will use the directory string syntax and case ignore * matching rule. * * @param name * The name or OID of the attribute type to retrieve. @@ -1489,6 +1489,7 @@ * @throws UnknownSchemaElementException * If this is a strict schema and the requested attribute type * was not found or if the provided name is ambiguous. * @see AttributeType#isPlaceHolder() */ public AttributeType getAttributeType(final String name) { return impl.getAttributeType(name); opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
@@ -501,7 +501,7 @@ // Ensure that the binary option is present if required. if (!syntax.isBEREncodingRequired()) { if (schemaValidationPolicy.checkAttributeValues().needsChecking() && attributeDescription.containsOption("binary")) { && attributeDescription.hasOption("binary")) { final LocalizableMessage message = ERR_LDIF_UNEXPECTED_BINARY_OPTION.get(record.lineNumber, entry.getName() .toString(), attrDescr); opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
@@ -538,7 +538,7 @@ // Ensure that the binary option is present if required. if (!syntax.isBEREncodingRequired()) { if (schemaValidationPolicy.checkAttributeValues().needsChecking() && attributeDescription.containsOption("binary")) { && attributeDescription.hasOption("binary")) { final LocalizableMessage message = ERR_LDIF_UNEXPECTED_BINARY_OPTION.get(record.lineNumber, entryDN .toString(), pair.value); opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/AttributeDescriptionTestCase.java
@@ -219,7 +219,7 @@ assertEquals(attributeDescription.isObjectClass(), isObjectClass); assertFalse(attributeDescription.hasOptions()); assertFalse(attributeDescription.containsOption("dummy")); assertFalse(attributeDescription.hasOption("dummy")); final Iterator<String> iterator = attributeDescription.getOptions().iterator(); assertFalse(iterator.hasNext()); @@ -250,19 +250,19 @@ assertTrue(attributeDescription.hasOptions()); } assertFalse(attributeDescription.containsOption("dummy")); assertFalse(attributeDescription.hasOption("dummy")); if (containsFoo) { assertTrue(attributeDescription.containsOption("foo")); assertTrue(attributeDescription.containsOption("FOO")); assertTrue(attributeDescription.containsOption("FoO")); assertTrue(attributeDescription.hasOption("foo")); assertTrue(attributeDescription.hasOption("FOO")); assertTrue(attributeDescription.hasOption("FoO")); } else { assertFalse(attributeDescription.containsOption("foo")); assertFalse(attributeDescription.containsOption("FOO")); assertFalse(attributeDescription.containsOption("FoO")); assertFalse(attributeDescription.hasOption("foo")); assertFalse(attributeDescription.hasOption("FOO")); assertFalse(attributeDescription.hasOption("FoO")); } for (final String option : options) { assertTrue(attributeDescription.containsOption(option)); assertTrue(attributeDescription.hasOption(option)); } final Iterator<String> iterator = attributeDescription.getOptions().iterator(); @@ -278,8 +278,8 @@ AttributeDescription ad1 = AttributeDescription.valueOf("cn"); AttributeDescription ad2 = ad1.withOption("test"); assertTrue(ad2.hasOptions()); assertTrue(ad2.containsOption("test")); assertFalse(ad2.containsOption("dummy")); assertTrue(ad2.hasOption("test")); assertFalse(ad2.hasOption("dummy")); assertEquals(ad2.toString(), "cn;test"); assertEquals(ad2.getOptions().iterator().next(), "test"); } @@ -296,9 +296,9 @@ AttributeDescription ad1 = AttributeDescription.valueOf("cn;test1"); AttributeDescription ad2 = ad1.withOption("test2"); assertTrue(ad2.hasOptions()); assertTrue(ad2.containsOption("test1")); assertTrue(ad2.containsOption("test2")); assertFalse(ad2.containsOption("dummy")); assertTrue(ad2.hasOption("test1")); assertTrue(ad2.hasOption("test2")); assertFalse(ad2.hasOption("dummy")); assertEquals(ad2.toString(), "cn;test1;test2"); Iterator<String> i = ad2.getOptions().iterator(); assertEquals(i.next(), "test1"); @@ -326,7 +326,7 @@ AttributeDescription ad1 = AttributeDescription.valueOf("cn;test"); AttributeDescription ad2 = ad1.withoutOption("test"); assertFalse(ad2.hasOptions()); assertFalse(ad2.containsOption("test")); assertFalse(ad2.hasOption("test")); assertEquals(ad2.toString(), "cn"); assertFalse(ad2.getOptions().iterator().hasNext()); } @@ -343,8 +343,8 @@ AttributeDescription ad1 = AttributeDescription.valueOf("cn;test1;test2"); AttributeDescription ad2 = ad1.withoutOption("test1"); assertTrue(ad2.hasOptions()); assertFalse(ad2.containsOption("test1")); assertTrue(ad2.containsOption("test2")); assertFalse(ad2.hasOption("test1")); assertTrue(ad2.hasOption("test2")); assertEquals(ad2.toString(), "cn;test2"); assertEquals(ad2.getOptions().iterator().next(), "test2"); } @@ -354,8 +354,8 @@ AttributeDescription ad1 = AttributeDescription.valueOf("cn;test1;test2"); AttributeDescription ad2 = ad1.withoutOption("test2"); assertTrue(ad2.hasOptions()); assertTrue(ad2.containsOption("test1")); assertFalse(ad2.containsOption("test2")); assertTrue(ad2.hasOption("test1")); assertFalse(ad2.hasOption("test2")); assertEquals(ad2.toString(), "cn;test1"); assertEquals(ad2.getOptions().iterator().next(), "test1"); } @@ -372,9 +372,9 @@ AttributeDescription ad1 = AttributeDescription.valueOf("cn;test1;test2;test3"); AttributeDescription ad2 = ad1.withoutOption("test1"); assertTrue(ad2.hasOptions()); assertFalse(ad2.containsOption("test1")); assertTrue(ad2.containsOption("test2")); assertTrue(ad2.containsOption("test3")); assertFalse(ad2.hasOption("test1")); assertTrue(ad2.hasOption("test2")); assertTrue(ad2.hasOption("test3")); assertEquals(ad2.toString(), "cn;test2;test3"); Iterator<String> i = ad2.getOptions().iterator(); assertEquals(i.next(), "test2"); @@ -386,9 +386,9 @@ AttributeDescription ad1 = AttributeDescription.valueOf("cn;test1;test2;test3"); AttributeDescription ad2 = ad1.withoutOption("test2"); assertTrue(ad2.hasOptions()); assertTrue(ad2.containsOption("test1")); assertFalse(ad2.containsOption("test2")); assertTrue(ad2.containsOption("test3")); assertTrue(ad2.hasOption("test1")); assertFalse(ad2.hasOption("test2")); assertTrue(ad2.hasOption("test3")); assertEquals(ad2.toString(), "cn;test1;test3"); Iterator<String> i = ad2.getOptions().iterator(); assertEquals(i.next(), "test1"); @@ -400,9 +400,9 @@ AttributeDescription ad1 = AttributeDescription.valueOf("cn;test1;test2;test3"); AttributeDescription ad2 = ad1.withoutOption("test3"); assertTrue(ad2.hasOptions()); assertTrue(ad2.containsOption("test1")); assertTrue(ad2.containsOption("test2")); assertFalse(ad2.containsOption("test3")); assertTrue(ad2.hasOption("test1")); assertTrue(ad2.hasOption("test2")); assertFalse(ad2.hasOption("test3")); assertEquals(ad2.toString(), "cn;test1;test2"); Iterator<String> i = ad2.getOptions().iterator(); assertEquals(i.next(), "test1"); opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/EntryTestCase.java
@@ -22,11 +22,21 @@ * * * Copyright 2009-2010 Sun Microsystems, Inc. * Portions copyright 2012 ForgeRock AS. */ package org.forgerock.opendj.ldap; import org.testng.Assert; import static org.fest.assertions.Assertions.assertThat; import static org.forgerock.opendj.ldap.Attributes.emptyAttribute; import static org.forgerock.opendj.ldap.Attributes.singletonAttribute; import java.util.LinkedList; import java.util.List; import org.forgerock.opendj.ldap.schema.Schema; import org.forgerock.opendj.ldap.schema.SchemaBuilder; import org.forgerock.opendj.ldif.LDIFEntryReader; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -35,60 +45,778 @@ */ @SuppressWarnings("javadoc") public final class EntryTestCase extends SdkTestCase { private static interface EntryFactory { Entry newEntry(String... ldifLines); Entry newEntry(String... ldifLines) throws Exception; } private static final class LinkedHashMapEntryFactory implements EntryFactory { public Entry newEntry(final String... ldifLines) { return new LinkedHashMapEntry(ldifLines); @Override public Entry newEntry(final String... ldifLines) throws Exception { final LDIFEntryReader reader = new LDIFEntryReader(ldifLines).setSchema(SCHEMA); final Entry entry = reader.readEntry(); assertThat(reader.hasNext()).isFalse(); return new LinkedHashMapEntry(entry); } } private static final class TreeMapEntryFactory implements EntryFactory { public Entry newEntry(final String... ldifLines) { return new TreeMapEntry(ldifLines); @Override public Entry newEntry(final String... ldifLines) throws Exception { final LDIFEntryReader reader = new LDIFEntryReader(ldifLines).setSchema(SCHEMA); final Entry entry = reader.readEntry(); assertThat(reader.hasNext()).isFalse(); return new TreeMapEntry(entry); } } private static final AttributeDescription AD_CN; private static final AttributeDescription AD_CUSTOM1; private static final AttributeDescription AD_CUSTOM2; private static final AttributeDescription AD_NAME; private static final AttributeDescription AD_SN; private static final Schema SCHEMA; static { final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema()); builder.addAttributeType("( 9.9.9.1 NAME 'custom1' SUP name )", false); builder.addAttributeType("( 9.9.9.2 NAME 'custom2' SUP name )", false); SCHEMA = builder.toSchema(); AD_CUSTOM1 = AttributeDescription.valueOf("custom1", SCHEMA); AD_CUSTOM2 = AttributeDescription.valueOf("custom2", SCHEMA); AD_CN = AttributeDescription.valueOf("cn"); AD_SN = AttributeDescription.valueOf("sn"); AD_NAME = AttributeDescription.valueOf("name"); } @DataProvider(name = "EntryFactory") public Object[][] entryFactory() { Object[][] entryFactory() { // Value, type, options, containsOptions("foo") return new Object[][] { { new TreeMapEntryFactory() }, { new LinkedHashMapEntryFactory() } }; } @Test(dataProvider = "EntryFactory") public void smokeTest(final EntryFactory factory) throws Exception { final Entry entry1 = factory.newEntry("dn: cn=Joe Bloggs,dc=example,dc=com", "objectClass: top", "objectClass: person", "cn: Joe Bloggs", "sn: Bloggs", "givenName: Joe", "description: A description"); public void testAddAttributeAttribute(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute(new LinkedAttribute("sn", "sn"))).isTrue(); assertThat(entry.getAttribute(AD_SN)).hasSize(1); } final Entry entry2 = factory.newEntry("dn: cn=Joe Bloggs,dc=example,dc=com", "changetype: add", "objectClass: top", "objectClass: person", "cn: Joe Bloggs", "sn: Bloggs", "givenName: Joe", "description: A description"); @Test(dataProvider = "EntryFactory") public void testAddAttributeAttributeCollection(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> duplicateValues = new LinkedList<ByteString>(); assertThat(entry.addAttribute(new LinkedAttribute("sn", "sn"), duplicateValues)).isTrue(); assertThat(entry.getAttribute(AD_SN)).hasSize(1); assertThat(duplicateValues).hasSize(0); } Assert.assertEquals(entry1, entry2); @Test(dataProvider = "EntryFactory") public void testAddAttributeAttributeCollectionValueMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> duplicateValues = new LinkedList<ByteString>(); assertThat(entry.addAttribute(new LinkedAttribute("cn", "newcn"), duplicateValues)) .isTrue(); assertThat(entry.getAttribute(AD_CN)).hasSize(2); assertThat(duplicateValues).hasSize(0); } for (final Entry e : new Entry[] { entry1, entry2 }) { Assert.assertEquals(e.getName(), DN.valueOf("cn=Joe Bloggs,dc=example,dc=com")); Assert.assertEquals(e.getAttributeCount(), 5); @Test(dataProvider = "EntryFactory") public void testAddAttributeAttributeCollectionValuePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> duplicateValues = new LinkedList<ByteString>(); assertThat(entry.addAttribute(new LinkedAttribute("cn", "test"), duplicateValues)) .isFalse(); assertThat(entry.getAttribute(AD_CN)).hasSize(1); assertThat(duplicateValues).hasSize(1); assertThat(duplicateValues).contains(ByteString.valueOf("test")); } Assert.assertEquals(e.getAttribute("objectClass").size(), 2); Assert.assertTrue(e.containsAttribute("objectClass", "top", "person")); Assert.assertFalse(e.containsAttribute("objectClass", "top", "person", "foo")); @Test(dataProvider = "EntryFactory") public void testAddAttributeAttributeValueMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute(new LinkedAttribute("cn", "newcn"))).isTrue(); assertThat(entry.getAttribute(AD_CN)).hasSize(2); } Assert.assertTrue(e.containsAttribute("objectClass")); Assert.assertTrue(e.containsAttribute("cn")); Assert.assertTrue(e.containsAttribute("cn", "Joe Bloggs")); Assert.assertFalse(e.containsAttribute("cn", "Jane Bloggs")); Assert.assertTrue(e.containsAttribute("sn")); Assert.assertTrue(e.containsAttribute("givenName")); Assert.assertTrue(e.containsAttribute("description")); @Test(dataProvider = "EntryFactory") public void testAddAttributeAttributeValuePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute(new LinkedAttribute("cn", "test"))).isFalse(); assertThat(entry.getAttribute(AD_CN)).hasSize(1); } Assert.assertEquals(e.getAttribute("cn").firstValueAsString(), "Joe Bloggs"); Assert.assertEquals(e.getAttribute("sn").firstValueAsString(), "Bloggs"); } @Test(dataProvider = "EntryFactory") public void testAddAttributeString(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute("sn", "sn")).isSameAs(entry); assertThat(entry.getAttribute(AD_SN)).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testAddAttributeStringCustom(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute("custom2", "custom2")).isSameAs(entry); // This is expected to be null since the type was decoded using the // default schema and a temporary oid was allocated. assertThat(entry.getAttribute(AD_CUSTOM2)).isNull(); assertThat(entry.getAttribute("custom2")).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testAddAttributeStringCustomValueMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute("custom1", "xxxx")).isSameAs(entry); assertThat(entry.getAttribute(AD_CUSTOM1)).hasSize(2); } @Test(dataProvider = "EntryFactory") public void testAddAttributeStringCustomValuePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute("custom1", "custom1")).isSameAs(entry); assertThat(entry.getAttribute(AD_CUSTOM1)).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testAddAttributeStringValueMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute("cn", "newcn")).isSameAs(entry); assertThat(entry.getAttribute(AD_CN)).hasSize(2); } @Test(dataProvider = "EntryFactory") public void testAddAttributeStringValuePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.addAttribute("cn", "test")).isSameAs(entry); assertThat(entry.getAttribute(AD_CN)).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testClearAttributes(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.clearAttributes()).isSameAs(entry); assertThat(entry.getAttributeCount()).isEqualTo(0); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeCustomMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(emptyAttribute(AD_CUSTOM2), missingValues)).isFalse(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeCustomPresent1(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(emptyAttribute(AD_CUSTOM1), missingValues)).isTrue(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeCustomPresent2(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(emptyAttribute("custom1"), missingValues)).isTrue(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeCustomValueMissing1(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat( entry.containsAttribute(singletonAttribute(AD_CUSTOM2, "missing"), missingValues)) .isFalse(); assertThat(missingValues).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(emptyAttribute(AD_SN), missingValues)).isFalse(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributePresent1(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(emptyAttribute(AD_CN), missingValues)).isTrue(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributePresent2(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(emptyAttribute("cn"), missingValues)).isTrue(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeValueCustomMissing2(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat( entry.containsAttribute(singletonAttribute(AD_CUSTOM1, "missing"), missingValues)) .isFalse(); assertThat(missingValues).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeValueCustomPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat( entry.containsAttribute(singletonAttribute(AD_CUSTOM1, "custom1"), missingValues)) .isTrue(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeValueMissing1(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(singletonAttribute(AD_SN, "missing"), missingValues)) .isFalse(); assertThat(missingValues).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeValueMissing2(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(singletonAttribute(AD_CN, "missing"), missingValues)) .isFalse(); assertThat(missingValues).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeAttributeValuePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.containsAttribute(singletonAttribute(AD_CN, "test"), missingValues)) .isTrue(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeStringCustomMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.containsAttribute("custom2")).isFalse(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeStringCustomPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.containsAttribute("custom1")).isTrue(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeStringMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.containsAttribute("sn")).isFalse(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeStringPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.containsAttribute("cn")).isTrue(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeStringValueCustom(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.containsAttribute("custom1", "custom1")).isTrue(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeStringValueMissing1(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.containsAttribute("cn", "missing")).isFalse(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeStringValueMissing2(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.containsAttribute("sn", "missing")).isFalse(); } @Test(dataProvider = "EntryFactory") public void testContainsAttributeStringValuePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.containsAttribute("cn", "test")).isTrue(); } @Test public void testEqualsHashCodeDifferentContentDifferentTypes1() throws Exception { final Entry e1 = createTestEntry(new TreeMapEntryFactory()); // Extra attributes. final Entry e2 = createTestEntry(new LinkedHashMapEntryFactory()).addAttribute("sn", "sn"); assertThat(e1).isNotEqualTo(e2); assertThat(e2).isNotEqualTo(e1); assertThat(e1.hashCode()).isNotEqualTo(e2.hashCode()); } @Test public void testEqualsHashCodeDifferentContentDifferentTypes2() throws Exception { final Entry e1 = createTestEntry(new TreeMapEntryFactory()); // Same attributes, extra values. final Entry e2 = createTestEntry(new LinkedHashMapEntryFactory()).addAttribute("cn", "newcn"); assertThat(e1).isNotEqualTo(e2); assertThat(e2).isNotEqualTo(e1); assertThat(e1.hashCode()).isNotEqualTo(e2.hashCode()); } @Test(dataProvider = "EntryFactory") public void testEqualsHashCodeDifferentContentSameTypes1(final EntryFactory factory) throws Exception { final Entry e1 = createTestEntry(factory); // Extra attributes. final Entry e2 = createTestEntry(factory).addAttribute("sn", "sn"); assertThat(e1).isNotEqualTo(e2); assertThat(e2).isNotEqualTo(e1); assertThat(e1.hashCode()).isNotEqualTo(e2.hashCode()); } @Test(dataProvider = "EntryFactory") public void testEqualsHashCodeDifferentContentSameTypes2(final EntryFactory factory) throws Exception { final Entry e1 = createTestEntry(factory); // Same attributes, extra values. final Entry e2 = createTestEntry(factory).addAttribute("cn", "newcn"); assertThat(e1).isNotEqualTo(e2); assertThat(e2).isNotEqualTo(e1); assertThat(e1.hashCode()).isNotEqualTo(e2.hashCode()); } @Test(dataProvider = "EntryFactory") public void testEqualsHashCodeDifferentDN(final EntryFactory factory) throws Exception { final Entry e1 = createTestEntry(factory); final Entry e2 = createTestEntry(factory).setName("cn=foobar"); assertThat(e1).isNotEqualTo(e2); assertThat(e1.hashCode()).isNotEqualTo(e2.hashCode()); } @Test(dataProvider = "EntryFactory") public void testEqualsHashCodeMutates(final EntryFactory factory) throws Exception { final Entry e = createTestEntry(factory); final int hc1 = e.hashCode(); e.addAttribute("sn", "sn"); final int hc2 = e.hashCode(); assertThat(hc1).isNotEqualTo(hc2); } @Test public void testEqualsHashCodeSameContentDifferentTypes() throws Exception { final Entry e1 = createTestEntry(new TreeMapEntryFactory()); final Entry e2 = createTestEntry(new LinkedHashMapEntryFactory()); assertThat(e1).isEqualTo(e2); assertThat(e2).isEqualTo(e1); assertThat(e1.hashCode()).isEqualTo(e2.hashCode()); } @Test(dataProvider = "EntryFactory") public void testEqualsHashCodeSameContentSameTypes(final EntryFactory factory) throws Exception { final Entry e1 = createTestEntry(factory); final Entry e2 = createTestEntry(factory); assertThat(e1).isEqualTo(e1); assertThat(e1).isEqualTo(e2); assertThat(e1.hashCode()).isEqualTo(e2.hashCode()); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributes(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAllAttributes().iterator()).hasSize(3); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesAttributeDescriptionMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAllAttributes(AD_SN)).hasSize(0); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesAttributeDescriptionPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAllAttributes(AD_CN)).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesAttributeDescriptionPresentOptions(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); entry.addAttribute(singletonAttribute(AD_CN.withOption("lang-fr"), "xxxx")); assertThat(entry.getAllAttributes(AD_CN)).hasSize(2); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesAttributeDescriptionSupertype(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAllAttributes(AD_NAME)).hasSize(2); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesStringCustom(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); entry.addAttribute(singletonAttribute(AD_CUSTOM1.withOption("lang-fr"), "xxxx")); assertThat(entry.getAllAttributes("custom1")).hasSize(2); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesStringCustomOptions(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); entry.addAttribute("custom2", "value1"); entry.addAttribute("custom2;lang-fr", "value2"); assertThat(entry.getAllAttributes("custom2")).hasSize(2); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesStringMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAllAttributes("sn")).hasSize(0); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesStringPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAllAttributes("cn")).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testGetAllAttributesStringSupertype(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAllAttributes("name")).hasSize(2); } @Test(dataProvider = "EntryFactory") public void testGetAttributeAttributeDescriptionMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAttribute(AD_SN)).isNull(); } @Test(dataProvider = "EntryFactory") public void testGetAttributeAttributeDescriptionPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAttribute(AD_CN)).isNotNull(); } @Test(dataProvider = "EntryFactory") public void testGetAttributeCount(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAttributeCount()).isEqualTo(3); } @Test(dataProvider = "EntryFactory") public void testGetAttributeStringCustom(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAttribute("custom1")).isNotNull(); } @Test(dataProvider = "EntryFactory") public void testGetAttributeStringMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAttribute("sn")).isNull(); } @Test(dataProvider = "EntryFactory") public void testGetAttributeStringPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.getAttribute("cn")).isNotNull(); } @Test(dataProvider = "EntryFactory") public void testGetName(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat((Object) entry.getName()).isEqualTo(DN.valueOf("cn=test")); } @Test(dataProvider = "EntryFactory") public void testParseAttributeAttributeDescriptionCustom(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.parseAttribute(AD_CUSTOM1).asString()).isEqualTo("custom1"); } @Test(dataProvider = "EntryFactory") public void testParseAttributeAttributeDescriptionMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.parseAttribute(AD_SN).asString()).isNull(); } @Test(dataProvider = "EntryFactory") public void testParseAttributeAttributeDescriptionPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.parseAttribute(AD_CN).asString()).isEqualTo("test"); } @Test(dataProvider = "EntryFactory") public void testParseAttributeStringCustom(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.parseAttribute("custom1").asString()).isEqualTo("custom1"); } @Test(dataProvider = "EntryFactory") public void testParseAttributeStringMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.parseAttribute("sn").asString()).isNull(); } @Test(dataProvider = "EntryFactory") public void testParseAttributeStringPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.parseAttribute("cn").asString()).isEqualTo("test"); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeAttributeDescriptionMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.removeAttribute(AD_SN)).isFalse(); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeAttributeDescriptionPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.removeAttribute(AD_CN)).isTrue(); assertThat(entry.getAttribute(AD_CN)).isNull(); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeAttributeMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.removeAttribute(emptyAttribute(AD_SN), missingValues)).isFalse(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeAttributePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.removeAttribute(emptyAttribute(AD_CN), missingValues)).isTrue(); assertThat(entry.getAttribute(AD_CN)).isNull(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeAttributeValueMissing1(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.removeAttribute(singletonAttribute(AD_CN, "missing"), missingValues)) .isFalse(); assertThat(entry.getAttribute(AD_CN)).isNotNull(); assertThat(missingValues).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeAttributeValueMissing2(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.removeAttribute(singletonAttribute(AD_SN, "missing"), missingValues)) .isFalse(); assertThat(missingValues).hasSize(1); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeAttributeValuePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); final List<ByteString> missingValues = new LinkedList<ByteString>(); assertThat(entry.removeAttribute(singletonAttribute(AD_CN, "test"), missingValues)) .isTrue(); assertThat(entry.getAttribute(AD_CN)).isNull(); assertThat(missingValues).isEmpty(); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeStringCustom(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.removeAttribute("custom1")).isSameAs(entry); assertThat(entry.getAttribute(AD_CUSTOM1)).isNull(); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeStringMissing(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.removeAttribute("sn")).isSameAs(entry); assertThat(entry.getAttributeCount()).isEqualTo(3); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeStringPresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.removeAttribute("cn")).isSameAs(entry); assertThat(entry.getAttribute(AD_CN)).isNull(); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeStringValueMissing1(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.removeAttribute("cn", "missing")).isSameAs(entry); assertThat(entry.getAttribute(AD_CN)).isNotNull(); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeStringValueMissing2(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.removeAttribute("sn", "missing")).isSameAs(entry); assertThat(entry.getAttributeCount()).isEqualTo(3); } @Test(dataProvider = "EntryFactory") public void testRemoveAttributeStringValuePresent(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.removeAttribute("cn", "test")).isSameAs(entry); assertThat(entry.getAttribute(AD_CN)).isNull(); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeAttributeMissingEmpty(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute(emptyAttribute(AD_SN))).isFalse(); assertThat(entry.getAttribute(AD_SN)).isNull(); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeAttributeMissingValue(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute(singletonAttribute(AD_SN, "sn"))).isTrue(); assertThat(entry.getAttribute(AD_SN)).isEqualTo(singletonAttribute(AD_SN, "sn")); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeAttributePresentEmpty(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute(emptyAttribute(AD_CN))).isTrue(); assertThat(entry.getAttribute(AD_CN)).isNull(); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeAttributePresentValue(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute(singletonAttribute(AD_CN, "newcn"))).isTrue(); assertThat(entry.getAttribute(AD_CN)).isEqualTo(singletonAttribute(AD_CN, "newcn")); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeStringCustomEmpty(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute("custom1")).isSameAs(entry); assertThat(entry.getAttribute(AD_CUSTOM1)).isNull(); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeStringCustomMissingValue(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute("custom2", "xxxx")).isSameAs(entry); // This is expected to be null since the type was decoded using the // default schema and a temporary oid was allocated. assertThat(entry.getAttribute(AD_CUSTOM2)).isNull(); assertThat(entry.getAttribute("custom2")).isEqualTo(singletonAttribute("custom2", "xxxx")); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeStringCustomValue(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute("custom1", "xxxx")).isSameAs(entry); assertThat(entry.getAttribute(AD_CUSTOM1)) .isEqualTo(singletonAttribute(AD_CUSTOM1, "xxxx")); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeStringMissingEmpty(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute("sn")).isSameAs(entry); assertThat(entry.getAttribute(AD_SN)).isNull(); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeStringMissingValue(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute("sn", "sn")).isSameAs(entry); assertThat(entry.getAttribute(AD_SN)).isEqualTo(singletonAttribute(AD_SN, "sn")); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeStringPresentEmpty(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute("cn")).isSameAs(entry); assertThat(entry.getAttribute(AD_CN)).isNull(); } @Test(dataProvider = "EntryFactory") public void testReplaceAttributeStringPresentValue(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.replaceAttribute("cn", "newcn")).isSameAs(entry); assertThat(entry.getAttribute(AD_CN)).isEqualTo(singletonAttribute(AD_CN, "newcn")); } @Test(dataProvider = "EntryFactory") public void testSetNameDN(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.setName(DN.valueOf("cn=foobar"))).isSameAs(entry); assertThat((Object) entry.getName()).isEqualTo(DN.valueOf("cn=foobar")); } @Test(dataProvider = "EntryFactory") public void testSetNameString(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); assertThat(entry.setName("cn=foobar")).isSameAs(entry); assertThat((Object) entry.getName()).isEqualTo(DN.valueOf("cn=foobar")); } @Test(dataProvider = "EntryFactory") public void testToString(final EntryFactory factory) throws Exception { final Entry entry = createTestEntry(factory); // The String representation is unspecified but we should at least // expect the DN to be present. assertThat(entry.toString()).contains("cn=test"); } private Entry createTestEntry(final EntryFactory factory) throws Exception { return factory.newEntry("dn: cn=test", "objectClass: top", "objectClass: extensibleObject", "cn: test", "custom1: custom1"); } }