mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Gaetan Boismal
15.51.2015 bd097b6d9921718564025bcb91aaaac53c61f7c7
OPENDJ-1722 (CR-5788) Add fluent builder for AttributeType
1 files added
6 files modified
1828 ■■■■ changed files
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java 368 ●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CoreSchemaImpl.java 915 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java 234 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaElement.java 16 ●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeBuilderTestCase.java 186 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeTest.java 71 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaBuilderTestCase.java 38 ●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java
@@ -22,16 +22,23 @@
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Portions copyright 2011-2013 ForgeRock AS.
 *      Portions copyright 2011-2015 ForgeRock AS.
 */
package org.forgerock.opendj.ldap.schema;
import static com.forgerock.opendj.ldap.CoreMessages.*;
import static org.forgerock.opendj.ldap.schema.SchemaConstants.SCHEMA_PROPERTY_APPROX_RULE;
import static java.util.Arrays.*;
import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
import static org.forgerock.opendj.ldap.schema.SchemaUtils.*;
import static com.forgerock.opendj.ldap.CoreMessages.*;
import static com.forgerock.opendj.util.StaticUtils.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -52,6 +59,295 @@
 */
public final class AttributeType extends SchemaElement implements Comparable<AttributeType> {
    /** A fluent API for incrementally constructing attribute type. */
    public static final class Builder extends SchemaElementBuilder<Builder> {
        private String oid;
        private final List<String> names = new LinkedList<String>();
        private AttributeUsage attributeUsage;
        private boolean isCollective;
        private boolean isNoUserModification;
        private boolean isObsolete;
        private boolean isSingleValue;
        private String approximateMatchingRuleOID;
        private String equalityMatchingRuleOID;
        private String orderingMatchingRuleOID;
        private String substringMatchingRuleOID;
        private String superiorTypeOID;
        private String syntaxOID;
        Builder(final AttributeType at, final SchemaBuilder builder) {
            super(builder, at);
            this.oid = at.oid;
            this.attributeUsage = at.attributeUsage;
            this.isCollective = at.isCollective;
            this.isNoUserModification = at.isNoUserModification;
            this.isObsolete = at.isObsolete;
            this.isSingleValue = at.isSingleValue;
            this.names.addAll(at.names);
            this.approximateMatchingRuleOID = at.approximateMatchingRuleOID;
            this.equalityMatchingRuleOID = at.equalityMatchingRuleOID;
            this.orderingMatchingRuleOID = at.orderingMatchingRuleOID;
            this.substringMatchingRuleOID = at.substringMatchingRuleOID;
            this.superiorTypeOID = at.superiorTypeOID;
            this.syntaxOID = at.syntaxOID;
        }
        Builder(final String oid, final SchemaBuilder builder) {
            super(builder);
            this.oid = oid;
        }
        /**
         * Adds this attribute type to the schema, throwing an
         * {@code ConflictingSchemaElementException} if there is an existing
         * attribute type with the same numeric OID.
         *
         * @return The parent schema builder.
         * @throws ConflictingSchemaElementException
         *             If there is an existing attribute type with the same
         *             numeric OID.
         */
        public SchemaBuilder addToSchema() {
            return getSchemaBuilder().addAttributeType(new AttributeType(this), false);
        }
        /**
         * Adds this attribute type to the schema overwriting any existing
         * attribute type with the same numeric OID.
         *
         * @return The parent schema builder.
         */
        public SchemaBuilder addToSchemaOverwrite() {
            return getSchemaBuilder().addAttributeType(new AttributeType(this), true);
        }
        /**
         * Sets the matching rule that should be used for approximate matching
         * with this attribute type.
         *
         * @param approximateMatchingRuleOID
         *            The matching rule OID.
         * @return This builder.
         */
        public Builder approximateMatchingRule(String approximateMatchingRuleOID) {
            this.approximateMatchingRuleOID = approximateMatchingRuleOID;
            return this;
        }
        /**
         * Specifies whether this attribute type is "collective".
         *
         * @param isCollective
         *            {@code true} if this attribute type is "collective".
         * @return This builder.
         */
        public Builder collective(boolean isCollective) {
            this.isCollective = isCollective;
            return this;
        }
        @Override
        public Builder description(String description) {
            return description0(description);
        }
        /**
         * Sets the matching rule that should be used for equality matching with
         * this attribute type.
         *
         * @param equalityMatchingRuleOID
         *            The matching rule OID.
         * @return This builder.
         */
        public Builder equalityMatchingRule(String equalityMatchingRuleOID) {
            this.equalityMatchingRuleOID = equalityMatchingRuleOID;
            return this;
        }
        @Override
        public Builder extraProperties(Map<String, List<String>> extraProperties) {
            return extraProperties0(extraProperties);
        }
        @Override
        public Builder extraProperties(String extensionName, String... extensionValues) {
            return extraProperties0(extensionName, extensionValues);
        }
        @Override
        Builder getThis() {
            return this;
        }
        /**
         * Adds the provided user friendly names.
         *
         * @param names
         *            The user friendly names.
         * @return This builder.
         */
        public Builder names(final Collection<String> names) {
            this.names.addAll(names);
            return this;
        }
        /**
         * Adds the provided user friendly names.
         *
         * @param names
         *            The user friendly names.
         * @return This builder.
         */
        public Builder names(final String... names) {
            return names(asList(names));
        }
        /**
         * Specifies whether this attribute type is "no-user-modification".
         *
         * @param isNoUserModification
         *            {@code true} if this attribute type is
         *            "no-user-modification"
         * @return This builder.
         */
        public Builder noUserModification(boolean isNoUserModification) {
            this.isNoUserModification = isNoUserModification;
            return this;
        }
        /**
         * Specifies whether this schema element is obsolete.
         *
         * @param isObsolete
         *            {@code true} if this schema element is obsolete (default
         *            is {@code false}).
         * @return This builder.
         */
        public Builder obsolete(final boolean isObsolete) {
            this.isObsolete = isObsolete;
            return this;
        }
        /**
         * Sets the numeric OID which uniquely identifies this attribute type.
         *
         * @param oid
         *            The numeric OID.
         * @return This builder.
         */
        public Builder oid(final String oid) {
            this.oid = oid;
            return this;
        }
        /**
         * Sets the matching rule that should be used for ordering with this
         * attribute type.
         *
         * @param orderingMatchingRuleOID
         *            The matching rule OID.
         * @return This Builder.
         */
        public Builder orderingMatchingRule(String orderingMatchingRuleOID) {
            this.orderingMatchingRuleOID = orderingMatchingRuleOID;
            return this;
        }
        @Override
        public Builder removeAllExtraProperties() {
            return removeAllExtraProperties0();
        }
        /**
         * Removes all user defined names.
         *
         * @return This builder.
         */
        public Builder removeAllNames() {
            this.names.clear();
            return this;
        }
        @Override
        public Builder removeExtraProperty(String extensionName, String... extensionValues) {
            return removeExtraProperty0(extensionName, extensionValues);
        }
        /**
         * Removes the provided user defined name.
         *
         * @param name
         *            The user defined name to be removed.
         * @return This builder.
         */
        public Builder removeName(String name) {
            this.names.remove(name);
            return this;
        }
        /**
         * Specifies whether this attribute type is declared "single-value".
         *
         * @param isSingleValue
         *            {@code true} if this attribute type is declared
         *            "single-value".
         * @return This builder.
         */
        public Builder singleValue(boolean isSingleValue) {
            this.isSingleValue = isSingleValue;
            return this;
        }
        /**
         * Sets the matching rule that should be used for substring matching
         * with this attribute type.
         *
         * @param substringMatchingRuleOID
         *            The matching rule OID.
         * @return This builder.
         */
        public Builder substringMatchingRule(String substringMatchingRuleOID) {
            this.substringMatchingRuleOID = substringMatchingRuleOID;
            return this;
        }
        /**
         * Sets the superior type for this attribute type.
         *
         * @param superiorTypeOID
         *            The superior type OID.
         * @return This builder.
         */
        public Builder superiorType(String superiorTypeOID) {
            this.superiorTypeOID = superiorTypeOID;
            return this;
        }
        /**
         * Sets the syntax for this attribute type.
         *
         * @param syntaxOID
         *            The syntax OID.
         * @return This builder.
         */
        public Builder syntax(String syntaxOID) {
            this.syntaxOID = syntaxOID;
            return this;
        }
        /**
         * Sets the usage indicator for this attribute type.
         *
         * @param attributeUsage
         *            The attribute usage.
         * @return This builder.
         */
        public Builder usage(AttributeUsage attributeUsage) {
            this.attributeUsage = attributeUsage;
            return this;
        }
    }
    /** The approximate matching rule for this attribute type. */
    private final String approximateMatchingRuleOID;
@@ -64,9 +360,7 @@
    /** Indicates whether this attribute type is declared "collective". */
    private final boolean isCollective;
    /**
     * Indicates whether this attribute type is declared "no-user-modification".
     */
    /** Indicates whether this attribute type is declared "no-user-modification". */
    private final boolean isNoUserModification;
    /** Indicates whether this definition is declared "obsolete". */
@@ -126,34 +420,28 @@
    /** The indicates whether or not validation failed. */
    private boolean isValid;
    AttributeType(final String oid, final List<String> names, final String description,
            final boolean obsolete, final String superiorType, final String equalityMatchingRule,
            final String orderingMatchingRule, final String substringMatchingRule,
            final String approximateMatchingRule, final String syntax, final boolean singleValue,
            final boolean collective, final boolean noUserModification,
            final AttributeUsage attributeUsage, final Map<String, List<String>> extraProperties,
            final String definition) {
        super(description, extraProperties, definition);
    private AttributeType(Builder builder) {
        super(builder);
        Reject.ifTrue(builder.oid == null || builder.oid.isEmpty(), "An OID must be specified.");
        Reject.ifTrue(builder.superiorTypeOID == null && builder.syntaxOID == null,
                "Superior type and/or Syntax must not be null");
        Reject.ifNull(oid, names, attributeUsage);
        Reject.ifFalse(superiorType != null || syntax != null, "superiorType and/or syntax must not be null");
        this.oid = oid;
        this.names = names;
        this.isObsolete = obsolete;
        this.superiorTypeOID = superiorType;
        this.equalityMatchingRuleOID = equalityMatchingRule;
        this.orderingMatchingRuleOID = orderingMatchingRule;
        this.substringMatchingRuleOID = substringMatchingRule;
        this.approximateMatchingRuleOID = approximateMatchingRule;
        this.syntaxOID = syntax;
        this.isSingleValue = singleValue;
        this.isCollective = collective;
        this.isNoUserModification = noUserModification;
        this.attributeUsage = attributeUsage;
        this.isObjectClassType = "2.5.4.0".equals(oid);
        this.isPlaceHolder = false;
        this.normalizedName = StaticUtils.toLowerCase(getNameOrOID());
        oid = builder.oid;
        names = unmodifiableCopyOfList(builder.names);
        attributeUsage = builder.attributeUsage;
        isCollective = builder.isCollective;
        isNoUserModification = builder.isNoUserModification;
        isObjectClassType = "2.5.4.0".equals(oid);
        isObsolete = builder.isObsolete;
        isSingleValue = builder.isSingleValue;
        approximateMatchingRuleOID = builder.approximateMatchingRuleOID;
        equalityMatchingRuleOID = builder.equalityMatchingRuleOID;
        orderingMatchingRuleOID = builder.orderingMatchingRuleOID;
        substringMatchingRuleOID = builder.substringMatchingRuleOID;
        superiorTypeOID = builder.superiorTypeOID;
        syntaxOID = builder.syntaxOID;
        isPlaceHolder = false;
        normalizedName = toLowerCase(getNameOrOID());
    }
    /**
@@ -187,7 +475,7 @@
        this.isSingleValue = false;
        this.isCollective = false;
        this.isNoUserModification = false;
        this.attributeUsage = AttributeUsage.USER_APPLICATIONS;
        this.attributeUsage = null;
        this.isObjectClassType = false;
        this.isPlaceHolder = true;
        this.normalizedName = StaticUtils.toLowerCase(getNameOrOID());
@@ -307,7 +595,6 @@
     * @return The OID for this schema definition.
     */
    public String getOID() {
        return oid;
    }
@@ -358,7 +645,7 @@
     * @return The usage indicator for this attribute type.
     */
    public AttributeUsage getUsage() {
        return attributeUsage;
        return attributeUsage != null ? attributeUsage : AttributeUsage.USER_APPLICATIONS;
    }
    /**
@@ -453,7 +740,7 @@
     *         {@code false} if not.
     */
    public boolean isOperational() {
        return attributeUsage.isOperational();
        return getUsage().isOperational();
    }
    /**
@@ -550,13 +837,6 @@
        }
    }
    AttributeType duplicate() {
        return new AttributeType(oid, names, getDescription(), isObsolete, superiorTypeOID,
                equalityMatchingRuleOID, orderingMatchingRuleOID, substringMatchingRuleOID,
                approximateMatchingRuleOID, syntaxOID, isSingleValue, isCollective,
                isNoUserModification, attributeUsage, getExtraProperties(), toString());
    }
    @Override
    void toStringContent(final StringBuilder buffer) {
        buffer.append(oid);
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CoreSchemaImpl.java
@@ -33,7 +33,6 @@
import static org.forgerock.opendj.ldap.schema.TimeBasedMatchingRulesImpl.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -70,8 +69,6 @@
    private static final Map<String, List<String>> OPENDJ_ORIGIN = Collections.singletonMap(
            SCHEMA_PROPERTY_ORIGIN, Collections.singletonList("OpenDJ Directory Server"));
    private static final String EMPTY_STRING = "".intern();
    private static final Schema SINGLETON;
    /**
@@ -306,15 +303,25 @@
    }
    private static void addRFC3045(final SchemaBuilder builder) {
        builder.addAttributeType("1.3.6.1.1.4", Collections.singletonList("vendorName"),
                EMPTY_STRING, false, null, EMR_CASE_EXACT_IA5_OID, null, null, null,
                SYNTAX_DIRECTORY_STRING_OID, true, false, true, AttributeUsage.DSA_OPERATION,
                RFC3045_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.1.4")
               .names("vendorName")
               .equalityMatchingRule(EMR_CASE_EXACT_IA5_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC3045_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.1.5", Collections.singletonList("vendorVersion"),
                EMPTY_STRING, false, null, EMR_CASE_EXACT_IA5_OID, null, null, null,
                SYNTAX_DIRECTORY_STRING_OID, true, false, true, AttributeUsage.DSA_OPERATION,
                RFC3045_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.1.5")
               .names("vendorVersion")
               .equalityMatchingRule(EMR_CASE_EXACT_IA5_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC3045_ORIGIN)
               .addToSchema();
    }
    private static void addRFC3112(final SchemaBuilder builder) {
@@ -325,15 +332,25 @@
                .description(EMR_AUTH_PASSWORD_EXACT_DESCRIPTION).syntaxOID(SYNTAX_AUTH_PASSWORD_OID)
                .extraProperties(RFC3112_ORIGIN).implementation(new AuthPasswordExactEqualityMatchingRuleImpl())
                .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.4203.1.3.3", Collections
                .singletonList("supportedAuthPasswordSchemes"),
                "supported password storage schemes", false, null, EMR_CASE_EXACT_IA5_OID, null,
                null, null, SYNTAX_IA5_STRING_OID, false, false, false,
                AttributeUsage.DSA_OPERATION, RFC3112_ORIGIN, false);
        builder.addAttributeType("1.3.6.1.4.1.4203.1.3.4", Collections
                .singletonList("authPassword"), "password authentication information", false, null,
                EMR_AUTH_PASSWORD_EXACT_OID, null, null, null, SYNTAX_AUTH_PASSWORD_OID, false,
                false, false, AttributeUsage.USER_APPLICATIONS, RFC3112_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.4203.1.3.3")
               .names("supportedAuthPasswordSchemes")
               .description("supported password storage schemes")
               .equalityMatchingRule(EMR_CASE_EXACT_IA5_OID)
               .syntax(SYNTAX_IA5_STRING_OID)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC3112_ORIGIN)
               .addToSchema();
        builder.buildAttributeType("1.3.6.1.4.1.4203.1.3.4")
               .names("authPassword")
               .description("password authentication information")
               .equalityMatchingRule(EMR_AUTH_PASSWORD_EXACT_OID)
               .syntax(SYNTAX_AUTH_PASSWORD_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC3112_ORIGIN)
               .addToSchema();
        builder.buildObjectClass("1.3.6.1.4.1.4203.1.4.7")
                .names("authPasswordObject")
                .type(AUXILIARY)
@@ -344,201 +361,354 @@
    }
    private static void addRFC4519(final SchemaBuilder builder) {
        builder.addAttributeType("2.5.4.15", Collections.singletonList("businessCategory"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.15")
               .names("businessCategory")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.41", Collections.singletonList("name"), EMPTY_STRING,
                false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.41")
               .names("name")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.6", Arrays.asList("c", "countryName"), EMPTY_STRING, false,
                "name", null, null, null, null, SYNTAX_COUNTRY_STRING_OID, true, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.6")
               .names("c", "countryName")
               .superiorType("name")
               .syntax(SYNTAX_COUNTRY_STRING_OID)
               .singleValue(true)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.3", Arrays.asList("cn", "commonName"), EMPTY_STRING, false,
                "name", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.3")
               .names("cn", "commonName")
               .superiorType("name")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("0.9.2342.19200300.100.1.25", Arrays.asList("dc",
                "domainComponent"), EMPTY_STRING, false, null, EMR_CASE_IGNORE_IA5_OID, null,
                SMR_CASE_IGNORE_IA5_OID, null, SYNTAX_IA5_STRING_OID, true, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("0.9.2342.19200300.100.1.25")
               .names("dc", "domainComponent")
               .equalityMatchingRule(EMR_CASE_IGNORE_IA5_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_IA5_OID)
               .syntax(SYNTAX_IA5_STRING_OID)
               .singleValue(true)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.13", Collections.singletonList("description"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.13")
               .names("description")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.27", Collections.singletonList("destinationIndicator"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_PRINTABLE_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.27")
               .names("destinationIndicator")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_PRINTABLE_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.49", Collections.singletonList("distinguishedName"),
                EMPTY_STRING, false, null, EMR_DN_OID, null, null, null, SYNTAX_DN_OID, false,
                false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.49")
               .names("distinguishedName")
               .equalityMatchingRule(EMR_DN_OID)
               .syntax(SYNTAX_DN_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.46", Collections.singletonList("dnQualifier"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, OMR_CASE_IGNORE_OID,
                SMR_CASE_IGNORE_OID, null, SYNTAX_PRINTABLE_STRING_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.46")
               .names("dnQualifier")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .orderingMatchingRule(OMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_PRINTABLE_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.47", Collections.singletonList("enhancedSearchGuide"),
                EMPTY_STRING, false, null, null, null, null, null, SYNTAX_ENHANCED_GUIDE_OID,
                false, false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.47")
               .names("enhancedSearchGuide")
               .syntax(SYNTAX_ENHANCED_GUIDE_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.23", Collections.singletonList("facsimileTelephoneNumber"),
                EMPTY_STRING, false, null, null, null, null, null, SYNTAX_FAXNUMBER_OID, false,
                false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.23")
               .names("facsimileTelephoneNumber")
               .syntax(SYNTAX_FAXNUMBER_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.44", Collections.singletonList("generationQualifier"),
                EMPTY_STRING, false, "name", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.44")
               .names("generationQualifier")
               .superiorType("name")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.42", Collections.singletonList("givenName"), EMPTY_STRING,
                false, "name", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.42")
               .names("givenName")
               .superiorType("name")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.51", Collections.singletonList("houseIdentifier"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.51")
               .names("houseIdentifier")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.43", Collections.singletonList("initials"), EMPTY_STRING,
                false, "name", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.43")
               .names("initials")
               .superiorType("name")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.25", Collections.singletonList("internationalISDNNumber"),
                EMPTY_STRING, false, null, EMR_NUMERIC_STRING_OID, null, SMR_NUMERIC_STRING_OID,
                null, SYNTAX_NUMERIC_STRING_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.25")
               .names("internationalISDNNumber")
               .equalityMatchingRule(EMR_NUMERIC_STRING_OID)
               .substringMatchingRule(SMR_NUMERIC_STRING_OID)
               .syntax(SYNTAX_NUMERIC_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.7", Arrays.asList("l", "localityName"), EMPTY_STRING,
                false, "name", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.7")
               .names("l", "localityName")
               .superiorType("name")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.31", Collections.singletonList("member"), EMPTY_STRING,
                false, "distinguishedName", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.31")
               .names("member")
               .superiorType("distinguishedName")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.10", Arrays.asList("o", "organizationName"), EMPTY_STRING,
                false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.10")
               .names("o", "organizationName")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.11", Arrays.asList("ou", "organizationalUnitName"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.11")
               .names("ou", "organizationalUnitName")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.32", Collections.singletonList("owner"), EMPTY_STRING,
                false, "distinguishedName", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.32")
               .names("owner")
               .superiorType("distinguishedName")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.19", Collections
                .singletonList("physicalDeliveryOfficeName"), EMPTY_STRING, false, null,
                EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null, SYNTAX_DIRECTORY_STRING_OID,
                false, false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.19")
               .names("physicalDeliveryOfficeName")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.16", Collections.singletonList("postalAddress"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.16")
               .names("postalAddress")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.17", Collections.singletonList("postalCode"), EMPTY_STRING,
                false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.17")
               .names("postalCode")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.18", Collections.singletonList("postOfficeBox"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.18")
               .names("postOfficeBox")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.28", Collections.singletonList("preferredDeliveryMethod"),
                EMPTY_STRING, false, null, null, null, null, null, SYNTAX_DELIVERY_METHOD_OID,
                true, false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.28")
               .names("preferredDeliveryMethod")
               .syntax(SYNTAX_DELIVERY_METHOD_OID)
               .singleValue(true)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.26", Collections.singletonList("registeredAddress"),
                EMPTY_STRING, false, "postalAddress", null, null, null, null,
                SYNTAX_POSTAL_ADDRESS_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.26")
               .names("registeredAddress")
               .superiorType("postalAddress")
               .syntax(SYNTAX_POSTAL_ADDRESS_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.33", Collections.singletonList("roleOccupant"),
                EMPTY_STRING, false, "distinguishedName", null, null, null, null, null, false,
                false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.33")
               .names("roleOccupant")
               .superiorType("distinguishedName")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.14", Collections.singletonList("searchGuide"),
                EMPTY_STRING, false, null, null, null, null, null, SYNTAX_GUIDE_OID, false, false,
                false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.14")
               .names("searchGuide")
               .syntax(SYNTAX_GUIDE_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.34", Collections.singletonList("seeAlso"), EMPTY_STRING,
                false, "distinguishedName", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.34")
               .names("seeAlso")
               .superiorType("distinguishedName")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.5", Collections.singletonList("serialNumber"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_PRINTABLE_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.5")
               .names("serialNumber")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_PRINTABLE_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.4", Arrays.asList("sn", "surname"), EMPTY_STRING, false,
                "name", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.4")
               .names("sn", "surname")
               .superiorType("name")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.8", Arrays.asList("st", "stateOrProvinceName"),
                EMPTY_STRING, false, "name", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.8")
               .names("st", "stateOrProvinceName")
               .superiorType("name")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.9", Arrays.asList("street", "streetAddress"), EMPTY_STRING,
                false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.9")
               .names("street", "streetAddress")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.20", Collections.singletonList("telephoneNumber"),
                EMPTY_STRING, false, null, EMR_TELEPHONE_OID, null, SMR_TELEPHONE_OID, null,
                SYNTAX_TELEPHONE_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.20")
               .names("telephoneNumber")
               .equalityMatchingRule(EMR_TELEPHONE_OID)
               .substringMatchingRule(SMR_TELEPHONE_OID)
               .syntax(SYNTAX_TELEPHONE_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.22",
                Collections.singletonList("teletexTerminalIdentifier"), EMPTY_STRING, false, null,
                null, null, null, null, SYNTAX_TELETEX_TERM_ID_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.22")
               .names("teletexTerminalIdentifier")
               .syntax(SYNTAX_TELETEX_TERM_ID_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.21", Collections.singletonList("telexNumber"),
                EMPTY_STRING, false, null, null, null, null, null, SYNTAX_TELEX_OID, false, false,
                false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.21")
               .names("telexNumber")
               .syntax(SYNTAX_TELEX_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.12", Collections.singletonList("title"), EMPTY_STRING,
                false, "name", null, null, null, null, null, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.12")
               .names("title")
               .superiorType("name")
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("0.9.2342.19200300.100.1.1", Arrays.asList("uid", "userid"),
                EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("0.9.2342.19200300.100.1.1")
               .names("uid", "userid")
               .equalityMatchingRule(EMR_CASE_IGNORE_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.50", Collections.singletonList("uniqueMember"),
                EMPTY_STRING, false, null, EMR_UNIQUE_MEMBER_OID, null, null, null,
                SYNTAX_NAME_AND_OPTIONAL_UID_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.50")
               .names("uniqueMember")
               .equalityMatchingRule(EMR_UNIQUE_MEMBER_OID)
               .syntax(SYNTAX_NAME_AND_OPTIONAL_UID_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.35", Collections.singletonList("userPassword"),
                EMPTY_STRING, false, null, EMR_OCTET_STRING_OID, null, null, null,
                SYNTAX_OCTET_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.35")
               .names("userPassword")
               .equalityMatchingRule(EMR_OCTET_STRING_OID)
               .syntax(SYNTAX_OCTET_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.24", Collections.singletonList("x121Address"),
                EMPTY_STRING, false, null, EMR_NUMERIC_STRING_OID, null, SMR_NUMERIC_STRING_OID,
                null, SYNTAX_NUMERIC_STRING_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.24")
               .names("x121Address")
               .equalityMatchingRule(EMR_NUMERIC_STRING_OID)
               .substringMatchingRule(SMR_NUMERIC_STRING_OID)
               .syntax(SYNTAX_NUMERIC_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.45", Collections.singletonList("x500UniqueIdentifier"),
                EMPTY_STRING, false, null, EMR_BIT_STRING_OID, null, null, null,
                SYNTAX_BIT_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                RFC4519_ORIGIN, false);
        builder.buildAttributeType("2.5.4.45")
               .names("x500UniqueIdentifier")
               .equalityMatchingRule(EMR_BIT_STRING_OID)
               .syntax(SYNTAX_BIT_STRING_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4519_ORIGIN)
               .addToSchema();
        builder.buildObjectClass("2.5.6.11")
                .names("applicationProcess")
@@ -690,34 +860,68 @@
                .syntaxOID(SYNTAX_CERTIFICATE_EXACT_ASSERTION_OID).extraProperties(RFC4523_ORIGIN)
                .implementation(new CertificateExactMatchingRuleImpl()).addToSchema();
        builder.addAttributeType("2.5.4.36", Collections.singletonList("userCertificate"),
                "X.509 user certificate", false, null, EMR_CERTIFICATE_EXACT_OID, null,
                null, null, SYNTAX_CERTIFICATE_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4523_ORIGIN, false);
        builder.addAttributeType("2.5.4.37", Collections.singletonList("cACertificate"),
                "X.509 CA certificate", false, null, EMR_CERTIFICATE_EXACT_OID, null,
                null, null, SYNTAX_CERTIFICATE_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4523_ORIGIN, false);
        builder.addAttributeType("2.5.4.38", Collections.singletonList("authorityRevocationList"),
                "X.509 authority revocation list", false, null, EMR_OCTET_STRING_OID, null,
                null, null, SYNTAX_CERTLIST_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4523_ORIGIN, false);
        builder.addAttributeType("2.5.4.39", Collections.singletonList("certificateRevocationList"),
                "X.509 certificate revocation list", false, null, EMR_OCTET_STRING_OID, null,
                null, null, SYNTAX_CERTLIST_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4523_ORIGIN, false);
        builder.addAttributeType("2.5.4.40", Collections.singletonList("crossCertificatePair"),
                "X.509 cross certificate pair", false, null, EMR_OCTET_STRING_OID, null,
                null, null, SYNTAX_CERTPAIR_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4523_ORIGIN, false);
        builder.addAttributeType("2.5.4.52", Collections.singletonList("supportedAlgorithms"),
                "X.509 supported algorithms", false, null, EMR_OCTET_STRING_OID, null,
                null, null, SYNTAX_SUPPORTED_ALGORITHM_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4523_ORIGIN, false);
        builder.addAttributeType("2.5.4.53", Collections.singletonList("deltaRevocationList"),
                "X.509 delta revocation list", false, null, EMR_OCTET_STRING_OID, null,
                null, null, SYNTAX_CERTLIST_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4523_ORIGIN, false);
        builder.buildAttributeType("2.5.4.36")
               .names("userCertificate")
               .description("X.509 user certificate")
               .equalityMatchingRule(EMR_CERTIFICATE_EXACT_OID)
               .syntax(SYNTAX_CERTIFICATE_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4523_ORIGIN)
               .addToSchema();
        builder.buildAttributeType("2.5.4.37")
               .names("cACertificate")
               .description("X.509 CA certificate")
               .equalityMatchingRule(EMR_CERTIFICATE_EXACT_OID)
               .syntax(SYNTAX_CERTIFICATE_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4523_ORIGIN)
               .addToSchema();
        builder.buildAttributeType("2.5.4.38")
               .names("authorityRevocationList")
               .description("X.509 authority revocation list")
               .equalityMatchingRule(EMR_OCTET_STRING_OID)
               .syntax(SYNTAX_CERTLIST_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4523_ORIGIN)
               .addToSchema();
        builder.buildAttributeType("2.5.4.39")
               .names("certificateRevocationList")
               .description("X.509 certificate revocation list")
               .equalityMatchingRule(EMR_OCTET_STRING_OID)
               .syntax(SYNTAX_CERTLIST_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4523_ORIGIN)
               .addToSchema();
        builder.buildAttributeType("2.5.4.40")
               .names("crossCertificatePair")
               .description("X.509 cross certificate pair")
               .equalityMatchingRule(EMR_OCTET_STRING_OID)
               .syntax(SYNTAX_CERTPAIR_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4523_ORIGIN)
               .addToSchema();
        builder.buildAttributeType("2.5.4.52")
               .names("supportedAlgorithms")
               .description("X.509 supported algorithms")
               .equalityMatchingRule(EMR_OCTET_STRING_OID)
               .syntax(SYNTAX_SUPPORTED_ALGORITHM_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4523_ORIGIN)
               .addToSchema();
        builder.buildAttributeType("2.5.4.53")
               .names("deltaRevocationList")
               .description("X.509 delta revocation list")
               .equalityMatchingRule(EMR_OCTET_STRING_OID)
               .syntax(SYNTAX_CERTLIST_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4523_ORIGIN)
               .addToSchema();
        builder.buildObjectClass("2.5.6.21")
                .names("pkiUser")
@@ -803,17 +1007,30 @@
        builder.buildMatchingRule(OMR_UUID_OID).names(OMR_UUID_NAME).syntaxOID(SYNTAX_UUID_OID)
                .extraProperties(RFC4530_ORIGIN).implementation(new UUIDOrderingMatchingRuleImpl())
                .addToSchema();
        builder.addAttributeType("1.3.6.1.1.16.4", Collections.singletonList("entryUUID"),
                "UUID of the entry", false, null, EMR_UUID_OID, OMR_UUID_OID, null, null,
                SYNTAX_UUID_OID, true, false, true, AttributeUsage.DIRECTORY_OPERATION,
                RFC4530_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.1.16.4")
               .names("entryUUID")
               .description("UUID of the entry")
               .equalityMatchingRule(EMR_UUID_OID)
               .orderingMatchingRule(OMR_UUID_OID)
               .syntax(SYNTAX_UUID_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4530_ORIGIN)
               .addToSchema();
    }
    private static void addRFC5020(final SchemaBuilder builder) {
        builder.addAttributeType("1.3.6.1.1.20", Collections.singletonList("entryDN"),
                "DN of the entry", false, null, EMR_DN_OID, null, null, null,
                SYNTAX_DN_OID, true, false, true, AttributeUsage.DIRECTORY_OPERATION,
                RFC5020_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.1.20")
               .names("entryDN")
               .description("DN of the entry")
               .equalityMatchingRule(EMR_DN_OID)
               .syntax(SYNTAX_DN_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC5020_ORIGIN)
               .addToSchema();
    }
    private static void addSunProprietary(final SchemaBuilder builder) {
@@ -847,10 +1064,15 @@
    }
    private static void addForgeRockProprietary(SchemaBuilder builder) {
        builder.addAttributeType("1.3.6.1.4.1.36733.2.1.1.141", Collections.singletonList("fullVendorVersion"),
                EMPTY_STRING, false, null, EMR_CASE_EXACT_IA5_OID, null, null, null,
                SYNTAX_DIRECTORY_STRING_OID, true, false, true, AttributeUsage.DSA_OPERATION,
                OPENDJ_ORIGIN , false);
        builder.buildAttributeType("1.3.6.1.4.1.36733.2.1.1.141")
               .names("fullVendorVersion")
               .equalityMatchingRule(EMR_CASE_EXACT_IA5_OID)
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(OPENDJ_ORIGIN)
               .addToSchema();
    }
    /**
@@ -972,117 +1194,208 @@
    }
    private static void defaultAttributeTypes(final SchemaBuilder builder) {
        builder.addAttributeType("2.5.4.0", Collections.singletonList("objectClass"), EMPTY_STRING,
                false, null, EMR_OID_NAME, null, null, null, SYNTAX_OID_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.4.0")
               .names("objectClass")
               .equalityMatchingRule(EMR_OID_NAME)
               .syntax(SYNTAX_OID_OID)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.4.1", Collections.singletonList("aliasedObjectName"),
                EMPTY_STRING, false, null, EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true,
                false, false, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.4.1")
               .names("aliasedObjectName")
               .equalityMatchingRule(EMR_DN_NAME)
               .syntax(SYNTAX_DN_OID)
               .singleValue(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.18.1", Collections.singletonList("createTimestamp"),
                EMPTY_STRING, false, null, EMR_GENERALIZED_TIME_NAME, OMR_GENERALIZED_TIME_NAME,
                null, null, SYNTAX_GENERALIZED_TIME_OID, true, false, true,
                AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.18.1")
               .names("createTimestamp")
               .equalityMatchingRule(EMR_GENERALIZED_TIME_NAME)
               .orderingMatchingRule(OMR_GENERALIZED_TIME_NAME)
               .syntax(SYNTAX_GENERALIZED_TIME_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.18.2", Collections.singletonList("modifyTimestamp"),
                EMPTY_STRING, false, null, EMR_GENERALIZED_TIME_NAME, OMR_GENERALIZED_TIME_NAME,
                null, null, SYNTAX_GENERALIZED_TIME_OID, true, false, true,
                AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.18.2")
               .names("modifyTimestamp")
               .equalityMatchingRule(EMR_GENERALIZED_TIME_NAME)
               .orderingMatchingRule(OMR_GENERALIZED_TIME_NAME)
               .syntax(SYNTAX_GENERALIZED_TIME_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.18.3", Collections.singletonList("creatorsName"),
                EMPTY_STRING, false, null, EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true,
                false, true, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.18.3")
               .names("creatorsName")
               .equalityMatchingRule(EMR_DN_NAME)
               .syntax(SYNTAX_DN_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.18.4", Collections.singletonList("modifiersName"),
                EMPTY_STRING, false, null, EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true,
                false, true, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.18.4")
               .names("modifiersName")
               .equalityMatchingRule(EMR_DN_NAME)
               .syntax(SYNTAX_DN_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.18.10", Collections.singletonList("subschemaSubentry"),
                EMPTY_STRING, false, null, EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true,
                false, true, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.18.10")
               .names("subschemaSubentry")
               .equalityMatchingRule(EMR_DN_NAME)
               .syntax(SYNTAX_DN_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.5", Collections.singletonList("attributeTypes"),
                EMPTY_STRING, false, null, EMR_OID_FIRST_COMPONENT_NAME, null, null, null,
                SYNTAX_ATTRIBUTE_TYPE_OID, false, false, false, AttributeUsage.DIRECTORY_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.5")
               .names("attributeTypes")
               .equalityMatchingRule(EMR_OID_FIRST_COMPONENT_NAME)
               .syntax(SYNTAX_ATTRIBUTE_TYPE_OID)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.6", Collections.singletonList("objectClasses"),
                EMPTY_STRING, false, null, EMR_OID_FIRST_COMPONENT_NAME, null, null, null,
                SYNTAX_OBJECTCLASS_OID, false, false, false, AttributeUsage.DIRECTORY_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.6")
               .names("objectClasses")
               .equalityMatchingRule(EMR_OID_FIRST_COMPONENT_NAME)
               .syntax(SYNTAX_OBJECTCLASS_OID)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.4", Collections.singletonList("matchingRules"),
                EMPTY_STRING, false, null, EMR_OID_FIRST_COMPONENT_NAME, null, null, null,
                SYNTAX_MATCHING_RULE_OID, false, false, false, AttributeUsage.DIRECTORY_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.4")
               .names("matchingRules")
               .equalityMatchingRule(EMR_OID_FIRST_COMPONENT_NAME)
               .syntax(SYNTAX_MATCHING_RULE_OID)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.8", Collections.singletonList("matchingRuleUse"),
                EMPTY_STRING, false, null, EMR_OID_FIRST_COMPONENT_NAME, null, null, null,
                SYNTAX_MATCHING_RULE_USE_OID, false, false, false,
                AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.8")
               .names("matchingRuleUse")
               .equalityMatchingRule(EMR_OID_FIRST_COMPONENT_NAME)
               .syntax(SYNTAX_MATCHING_RULE_USE_OID)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.9", Collections.singletonList("structuralObjectClass"),
                EMPTY_STRING, false, null, EMR_OID_NAME, null, null, null, SYNTAX_OID_OID, true,
                false, true, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.9")
               .names("structuralObjectClass")
               .equalityMatchingRule(EMR_OID_NAME)
               .syntax(SYNTAX_OID_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.10", Collections.singletonList("governingStructureRule"),
                EMPTY_STRING, false, null, EMR_INTEGER_NAME, null, null, null, SYNTAX_INTEGER_OID,
                true, false, true, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.10")
               .names("governingStructureRule")
               .equalityMatchingRule(EMR_INTEGER_NAME)
               .syntax(SYNTAX_INTEGER_OID)
               .singleValue(true)
               .noUserModification(true)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.1466.101.120.5", Collections
                .singletonList("namingContexts"), EMPTY_STRING, false, null, null, null, null,
                null, SYNTAX_DN_OID, false, false, false, AttributeUsage.DSA_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.1466.101.120.5")
               .names("namingContexts")
               .syntax(SYNTAX_DN_OID)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.1466.101.120.6", Collections
                .singletonList("altServer"), EMPTY_STRING, false, null, null, null, null, null,
                SYNTAX_IA5_STRING_OID, false, false, false, AttributeUsage.DSA_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.1466.101.120.6")
               .names("altServer")
               .syntax(SYNTAX_IA5_STRING_OID)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.1466.101.120.7", Collections
                .singletonList("supportedExtension"), EMPTY_STRING, false, null, null, null, null,
                null, SYNTAX_OID_OID, false, false, false, AttributeUsage.DSA_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.1466.101.120.7")
               .names("supportedExtension")
               .syntax(SYNTAX_OID_OID)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.1466.101.120.13", Collections
                .singletonList("supportedControl"), EMPTY_STRING, false, null, null, null, null,
                null, SYNTAX_OID_OID, false, false, false, AttributeUsage.DSA_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.1466.101.120.13")
               .names("supportedControl")
               .syntax(SYNTAX_OID_OID)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.1466.101.120.14", Collections
                .singletonList("supportedSASLMechanisms"), EMPTY_STRING, false, null, null, null,
                null, null, SYNTAX_DIRECTORY_STRING_OID, false, false, false,
                AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.1466.101.120.14")
               .names("supportedSASLMechanisms")
               .syntax(SYNTAX_DIRECTORY_STRING_OID)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.4203.1.3.5", Collections
                .singletonList("supportedFeatures"), EMPTY_STRING, false, null, EMR_OID_NAME, null,
                null, null, SYNTAX_OID_OID, false, false, false, AttributeUsage.DSA_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.4203.1.3.5")
               .names("supportedFeatures")
               .equalityMatchingRule(EMR_OID_NAME)
               .syntax(SYNTAX_OID_OID)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.1466.101.120.15", Collections
                .singletonList("supportedLDAPVersion"), EMPTY_STRING, false, null, null, null,
                null, null, SYNTAX_INTEGER_OID, false, false, false, AttributeUsage.DSA_OPERATION,
                RFC4512_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.1466.101.120.15")
               .names("supportedLDAPVersion")
               .syntax(SYNTAX_INTEGER_OID)
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("1.3.6.1.4.1.1466.101.120.16", Collections
                .singletonList("ldapSyntaxes"), EMPTY_STRING, false, null,
                EMR_OID_FIRST_COMPONENT_NAME, null, null, null, SYNTAX_LDAP_SYNTAX_OID, false,
                false, false, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("1.3.6.1.4.1.1466.101.120.16")
               .names("ldapSyntaxes")
               .equalityMatchingRule(EMR_OID_FIRST_COMPONENT_NAME)
               .syntax(SYNTAX_LDAP_SYNTAX_OID)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.1", Collections.singletonList("ditStructureRules"),
                EMPTY_STRING, false, null, EMR_INTEGER_FIRST_COMPONENT_NAME, null, null, null,
                SYNTAX_DIT_STRUCTURE_RULE_OID, false, false, false,
                AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.1")
               .names("ditStructureRules")
               .equalityMatchingRule(EMR_INTEGER_FIRST_COMPONENT_NAME)
               .syntax(SYNTAX_DIT_STRUCTURE_RULE_OID)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.7", Collections.singletonList("nameForms"), EMPTY_STRING,
                false, null, EMR_OID_FIRST_COMPONENT_NAME, null, null, null, SYNTAX_NAME_FORM_OID,
                false, false, false, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.7")
               .names("nameForms")
               .equalityMatchingRule(EMR_OID_FIRST_COMPONENT_NAME)
               .syntax(SYNTAX_NAME_FORM_OID)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
        builder.addAttributeType("2.5.21.2", Collections.singletonList("ditContentRules"),
                EMPTY_STRING, false, null, EMR_OID_FIRST_COMPONENT_NAME, null, null, null,
                SYNTAX_DIT_CONTENT_RULE_OID, false, false, false,
                AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
        builder.buildAttributeType("2.5.21.2")
               .names("ditContentRules")
               .equalityMatchingRule(EMR_OID_FIRST_COMPONENT_NAME)
               .syntax(SYNTAX_DIT_CONTENT_RULE_OID)
               .usage(AttributeUsage.DIRECTORY_OPERATION)
               .extraProperties(RFC4512_ORIGIN)
               .addToSchema();
    }
    private static void defaultMatchingRules(final SchemaBuilder builder) {
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
@@ -22,11 +22,24 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2015 ForgeRock AS
 *      Portions Copyright 2014 Manuel Gaupp
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.forgerock.opendj.ldap.schema;
import static java.util.Collections.*;
import static org.forgerock.opendj.ldap.LdapException.*;
import static org.forgerock.opendj.ldap.schema.ObjectClass.*;
import static org.forgerock.opendj.ldap.schema.ObjectClassType.*;
import static org.forgerock.opendj.ldap.schema.Schema.*;
import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
import static org.forgerock.opendj.ldap.schema.SchemaOptions.*;
import static org.forgerock.opendj.ldap.schema.SchemaUtils.*;
import static com.forgerock.opendj.ldap.CoreMessages.*;
import static com.forgerock.opendj.util.StaticUtils.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -66,19 +79,6 @@
import com.forgerock.opendj.util.StaticUtils;
import com.forgerock.opendj.util.SubstringReader;
import static java.util.Collections.*;
import static org.forgerock.opendj.ldap.LdapException.*;
import static org.forgerock.opendj.ldap.schema.ObjectClass.*;
import static org.forgerock.opendj.ldap.schema.ObjectClassType.*;
import static org.forgerock.opendj.ldap.schema.Schema.*;
import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
import static org.forgerock.opendj.ldap.schema.SchemaOptions.*;
import static org.forgerock.opendj.ldap.schema.SchemaUtils.*;
import static com.forgerock.opendj.ldap.CoreMessages.*;
import static com.forgerock.opendj.util.StaticUtils.*;
/**
 * Schema builders should be used for incremental construction of new schemas.
 */
@@ -268,22 +268,10 @@
            // The next set of characters must be the OID.
            final String oid = readOID(reader, allowsMalformedNamesAndOptions());
            List<String> names = Collections.emptyList();
            String description = "".intern();
            boolean isObsolete = false;
            AttributeType.Builder atBuilder = new AttributeType.Builder(oid, this);
            atBuilder.definition(definition);
            String superiorType = null;
            String equalityMatchingRule = null;
            String orderingMatchingRule = null;
            String substringMatchingRule = null;
            String approximateMatchingRule = null;
            String syntax = null;
            boolean isSingleValue = false;
            boolean isCollective = false;
            boolean isNoUserModification = false;
            AttributeUsage attributeUsage = AttributeUsage.USER_APPLICATIONS;
            Map<String, List<String>> extraProperties = Collections.emptyMap();
            // At this point, we should have a pretty specific syntax that
            // describes what may come next, but some of the components are
            // optional and it would be pretty easy to put something in the
@@ -299,17 +287,16 @@
                    // No more tokens.
                    break;
                } else if ("name".equalsIgnoreCase(tokenName)) {
                    names = readNameDescriptors(reader, allowsMalformedNamesAndOptions());
                    atBuilder.names(readNameDescriptors(reader, allowsMalformedNamesAndOptions()));
                } else if ("desc".equalsIgnoreCase(tokenName)) {
                    // This specifies the description for the attribute type. It
                    // is an arbitrary string of characters enclosed in single
                    // quotes.
                    description = readQuotedString(reader);
                    atBuilder.description(readQuotedString(reader));
                } else if ("obsolete".equalsIgnoreCase(tokenName)) {
                    // This indicates whether the attribute type should be
                    // considered obsolete. We do not need to do any more
                    // parsing for this token.
                    isObsolete = true;
                    // considered obsolete.
                    atBuilder.obsolete(true);
                } else if ("sup".equalsIgnoreCase(tokenName)) {
                    // This specifies the name or OID of the superior attribute
                    // type from which this attribute type should inherit its
@@ -318,15 +305,15 @@
                } else if ("equality".equalsIgnoreCase(tokenName)) {
                    // This specifies the name or OID of the equality matching
                    // rule to use for this attribute type.
                    equalityMatchingRule = readOID(reader, allowsMalformedNamesAndOptions());
                    atBuilder.equalityMatchingRule(readOID(reader, allowsMalformedNamesAndOptions()));
                } else if ("ordering".equalsIgnoreCase(tokenName)) {
                    // This specifies the name or OID of the ordering matching
                    // rule to use for this attribute type.
                    orderingMatchingRule = readOID(reader, allowsMalformedNamesAndOptions());
                    atBuilder.orderingMatchingRule(readOID(reader, allowsMalformedNamesAndOptions()));
                } else if ("substr".equalsIgnoreCase(tokenName)) {
                    // This specifies the name or OID of the substring matching
                    // rule to use for this attribute type.
                    substringMatchingRule = readOID(reader, allowsMalformedNamesAndOptions());
                    atBuilder.substringMatchingRule(readOID(reader, allowsMalformedNamesAndOptions()));
                } else if ("syntax".equalsIgnoreCase(tokenName)) {
                    // This specifies the numeric OID of the syntax for this
                    // matching rule. It may optionally be immediately followed
@@ -337,27 +324,18 @@
                    // does not impose any practical limit on the length of attribute
                    // values.
                    syntax = readOIDLen(reader, allowsMalformedNamesAndOptions());
                } else if ("single-definition".equalsIgnoreCase(tokenName)) {
                    // This indicates that attributes of this type are allowed
                    // to have at most one definition. We do not need any more
                    // parsing for this token.
                    isSingleValue = true;
                } else if ("single-value".equalsIgnoreCase(tokenName)) {
                    // This indicates that attributes of this type are allowed
                    // to have at most one value. We do not need any more parsing
                    // for this token.
                    isSingleValue = true;
                    // to have at most one value.
                    atBuilder.singleValue(true);
                } else if ("collective".equalsIgnoreCase(tokenName)) {
                    // This indicates that attributes of this type are
                    // collective
                    // (i.e., have their values generated dynamically in some
                    // way). We do not need any more parsing for this token.
                    isCollective = true;
                    // This indicates that attributes of this type are collective
                    // (i.e., have their values generated dynamically in some way).
                    atBuilder.collective(true);
                } else if ("no-user-modification".equalsIgnoreCase(tokenName)) {
                    // This indicates that the values of attributes of this type
                    // are not to be modified by end users. We do not need any
                    // more parsing for this token.
                    isNoUserModification = true;
                    // are not to be modified by end users.
                    atBuilder.noUserModification(true);
                } else if ("usage".equalsIgnoreCase(tokenName)) {
                    // This specifies the usage string for this attribute type.
                    // It should be followed by one of the strings
@@ -371,17 +349,16 @@
                    while (reader.read() != ' ') {
                        length++;
                    }
                    reader.reset();
                    final String usageStr = reader.read(length);
                    if ("userapplications".equalsIgnoreCase(usageStr)) {
                        attributeUsage = AttributeUsage.USER_APPLICATIONS;
                        atBuilder.usage(AttributeUsage.USER_APPLICATIONS);
                    } else if ("directoryoperation".equalsIgnoreCase(usageStr)) {
                        attributeUsage = AttributeUsage.DIRECTORY_OPERATION;
                        atBuilder.usage(AttributeUsage.DIRECTORY_OPERATION);
                    } else if ("distributedoperation".equalsIgnoreCase(usageStr)) {
                        attributeUsage = AttributeUsage.DISTRIBUTED_OPERATION;
                        atBuilder.usage(AttributeUsage.DISTRIBUTED_OPERATION);
                    } else if ("dsaoperation".equalsIgnoreCase(usageStr)) {
                        attributeUsage = AttributeUsage.DSA_OPERATION;
                        atBuilder.usage(AttributeUsage.DSA_OPERATION);
                    } else {
                        throw new LocalizedIllegalArgumentException(
                            WARN_ATTR_SYNTAX_ATTRTYPE_INVALID_ATTRIBUTE_USAGE1.get(definition, usageStr));
@@ -392,23 +369,17 @@
                    // or an open parenthesis followed by one or more values in
                    // single quotes separated by spaces followed by a close
                    // parenthesis.
                    if (extraProperties.isEmpty()) {
                        extraProperties = new HashMap<String, List<String>>();
                    }
                    extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
                    List<String> extensions = readExtensions(reader);
                    atBuilder.extraProperties(tokenName, extensions);
                } else {
                    throw new LocalizedIllegalArgumentException(
                        ERR_ATTR_SYNTAX_ATTRTYPE_ILLEGAL_TOKEN1.get(definition, tokenName));
                }
            }
            final List<String> approxRules = extraProperties.get(SCHEMA_PROPERTY_APPROX_RULE);
            final List<String> approxRules = atBuilder.getExtraProperties().get(SCHEMA_PROPERTY_APPROX_RULE);
            if (approxRules != null && !approxRules.isEmpty()) {
                approximateMatchingRule = approxRules.get(0);
            }
            if (!extraProperties.isEmpty()) {
                extraProperties = Collections.unmodifiableMap(extraProperties);
                atBuilder.approximateMatchingRule(approxRules.get(0));
            }
            if (superiorType == null && syntax == null) {
@@ -416,96 +387,14 @@
                    WARN_ATTR_SYNTAX_ATTRTYPE_MISSING_SYNTAX_AND_SUPERIOR.get(definition));
            }
            final AttributeType attrType =
                    new AttributeType(oid, names, description, isObsolete, superiorType,
                            equalityMatchingRule, orderingMatchingRule, substringMatchingRule,
                            approximateMatchingRule, syntax, isSingleValue, isCollective,
                            isNoUserModification, attributeUsage, extraProperties, definition);
            atBuilder.superiorType(superiorType)
                     .syntax(syntax);
            addAttributeType(attrType, overwrite);
            return overwrite ? atBuilder.addToSchemaOverwrite() : atBuilder.addToSchema();
        } catch (final DecodeException e) {
            final LocalizableMessage msg =
                    ERR_ATTR_SYNTAX_ATTRTYPE_INVALID1.get(definition, e.getMessageObject());
            final LocalizableMessage msg = ERR_ATTR_SYNTAX_ATTRTYPE_INVALID1.get(definition, e.getMessageObject());
            throw new LocalizedIllegalArgumentException(msg, e.getCause());
        }
        return this;
    }
    /**
     * Adds the provided attribute type definition to this schema builder.
     *
     * @param oid
     *            The OID of the attribute type definition.
     * @param names
     *            The user-friendly names of the attribute type definition.
     * @param description
     *            The description of the attribute type definition.
     * @param obsolete
     *            {@code true} if the attribute type definition is obsolete,
     *            otherwise {@code false}.
     * @param superiorType
     *            The OID of the superior attribute type definition.
     * @param equalityMatchingRule
     *            The OID of the equality matching rule, which may be
     *            {@code null} indicating that the superior attribute type's
     *            matching rule should be used or, if none is defined, the
     *            default matching rule associated with the syntax.
     * @param orderingMatchingRule
     *            The OID of the ordering matching rule, which may be
     *            {@code null} indicating that the superior attribute type's
     *            matching rule should be used or, if none is defined, the
     *            default matching rule associated with the syntax.
     * @param substringMatchingRule
     *            The OID of the substring matching rule, which may be
     *            {@code null} indicating that the superior attribute type's
     *            matching rule should be used or, if none is defined, the
     *            default matching rule associated with the syntax.
     * @param approximateMatchingRule
     *            The OID of the approximate matching rule, which may be
     *            {@code null} indicating that the superior attribute type's
     *            matching rule should be used or, if none is defined, the
     *            default matching rule associated with the syntax.
     * @param syntax
     *            The OID of the syntax definition.
     * @param singleValue
     *            {@code true} if the attribute type definition is
     *            single-valued, otherwise {@code false}.
     * @param collective
     *            {@code true} if the attribute type definition is a collective
     *            attribute, otherwise {@code false}.
     * @param noUserModification
     *            {@code true} if the attribute type definition is read-only,
     *            otherwise {@code false}.
     * @param attributeUsage
     *            The intended use of the attribute type definition.
     * @param extraProperties
     *            A map containing additional properties associated with the
     *            attribute type definition.
     * @param overwrite
     *            {@code true} if any existing attribute type with the same OID
     *            should be overwritten.
     * @return A reference to this schema builder.
     * @throws ConflictingSchemaElementException
     *             If {@code overwrite} was {@code false} and a conflicting
     *             schema element was found.
     */
    SchemaBuilder addAttributeType(final String oid, final List<String> names,
            final String description, final boolean obsolete, final String superiorType,
            final String equalityMatchingRule, final String orderingMatchingRule,
            final String substringMatchingRule, final String approximateMatchingRule,
            final String syntax, final boolean singleValue, final boolean collective,
            final boolean noUserModification, final AttributeUsage attributeUsage,
            final Map<String, List<String>> extraProperties, final boolean overwrite) {
        lazyInitBuilder();
        final AttributeType attrType =
                new AttributeType(oid, unmodifiableCopyOfList(names), description, obsolete,
                        superiorType, equalityMatchingRule, orderingMatchingRule,
                        substringMatchingRule, approximateMatchingRule, syntax, singleValue,
                        collective, noUserModification, attributeUsage,
                        unmodifiableCopyOfExtraProperties(extraProperties), null);
        addAttributeType(attrType, overwrite);
        return this;
    }
    /**
@@ -1138,6 +1027,39 @@
    }
    /**
     * Returns an attribute type builder whose fields are initialized to the
     * values of the provided attribute type. This method should be used when
     * duplicating attribute types from external schemas or when modifying
     * existing attribute types.
     *
     * @param attributeType
     *            The attribute type source.
     * @return A builder to continue building the AttributeType.
     */
    public AttributeType.Builder buildAttributeType(final AttributeType attributeType) {
        lazyInitBuilder();
        return new AttributeType.Builder(attributeType, this);
    }
    /**
     * Returns a builder which can be used for incrementally constructing a new
     * attribute type before adding it to the schema. Example usage:
     *
     * <pre>
     * SchemaBuilder builder = ...;
     * builder.buildAttributeType("attributetype-oid").name("attribute type name").addToSchema();
     * </pre>
     *
     * @param oid
     *            The OID of the attribute type definition.
     * @return A builder to continue building the AttributeType.
     */
    public AttributeType.Builder buildAttributeType(final String oid) {
        lazyInitBuilder();
        return new AttributeType.Builder(oid, this);
    }
    /**
     * Returns a builder which can be used for incrementally constructing a new matching rule before adding it to the
     * schema. Example usage:
     *
@@ -2321,7 +2243,7 @@
        return schema;
    }
    private void addAttributeType(final AttributeType attribute, final boolean overwrite) {
    SchemaBuilder addAttributeType(final AttributeType attribute, final boolean overwrite) {
        AttributeType conflictingAttribute;
        if (numericOID2AttributeTypes.containsKey(attribute.getOID())) {
            conflictingAttribute = numericOID2AttributeTypes.get(attribute.getOID());
@@ -2348,6 +2270,8 @@
                attrs.add(attribute);
            }
        }
        return this;
    }
    private void addDITContentRule(final DITContentRule rule, final boolean overwrite) {
@@ -2556,7 +2480,7 @@
        }
        for (final AttributeType attributeType : schema.getAttributeTypes()) {
            addAttributeType(attributeType.duplicate(), overwrite);
            addAttributeType(attributeType, overwrite);
        }
        for (final ObjectClass objectClass : schema.getObjectClasses()) {
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaElement.java
@@ -102,8 +102,20 @@
         *            The optional list of values for the extended property.
         * @return This builder.
         */
        public abstract T extraProperties(final String extensionName,
                final String... extensionValues);
        public abstract T extraProperties(final String extensionName, final String... extensionValues);
        /**
         * Adds the provided extended property.
         *
         * @param extensionName
         *            The name of the extended property.
         * @param extensionValues
         *            The optional list of values for the extended property.
         * @return This builder.
         */
        public T extraProperties(final String extensionName, final List<String> extensionValues) {
            return extraProperties(extensionName, extensionValues.toArray(new String[extensionValues.size()]));
        }
        /**
         * Removes all extra properties.
opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeBuilderTestCase.java
New file
@@ -0,0 +1,186 @@
/*
 * 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 2015 ForgeRock AS.
 */
package org.forgerock.opendj.ldap.schema;
import static java.util.Collections.*;
import static org.fest.assertions.Assertions.*;
import static org.fest.assertions.MapAssert.*;
import static org.forgerock.opendj.ldap.schema.Schema.*;
import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
import java.util.List;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class AttributeTypeBuilderTestCase extends AbstractSchemaTestCase {
    @DataProvider
    Object[][] validAttributeTypes() {
        // OID, names, description, obsolete, superior type, equalityMR,
        // orderingMR, substringMR, approximateMR, syntax, singleValue,
        // collective, noUserModification, attributeUsage, extraPropertyName,
        // extraPropertyValue
        return new Object[][] {
            // Basic attribute type
            { "1.2.3.4", singletonList("MyAttributeType"), "MyAttributeType description.", false, "2.5.4.0",
                EMR_CERTIFICATE_EXACT_OID, OMR_UUID_OID, SMR_CASE_IGNORE_LIST_OID, AMR_DOUBLE_METAPHONE_OID, null,
                false, false, false, AttributeUsage.USER_APPLICATIONS, "New extra property", "New extra value", false },
            // Allowed overrides existing core schema attribute type name
            { "2.5.4.41", singletonList("name"), "MyAttributeType description.", false, null,
                EMR_CERTIFICATE_EXACT_OID, null, SMR_CASE_IGNORE_LIST_OID, AMR_DOUBLE_METAPHONE_OID,
                SYNTAX_DIRECTORY_STRING_OID, false, false, false, AttributeUsage.USER_APPLICATIONS,
                "New extra property", "New extra value", true },
            // No name provided, should be validated
            { "1.2.3.4", emptyList(), "MyAttributeType description.", false, null, EMR_CASE_IGNORE_LIST_OID,
                OMR_CASE_IGNORE_OID, null, null, SYNTAX_DIRECTORY_STRING_OID, false, false, false,
                AttributeUsage.USER_APPLICATIONS, "New extra property", "New extra value", false },
            // Empty description, should be validated
            { "1.2.3.4", singletonList("MyAttributeType"), "", false, null, EMR_CASE_IGNORE_LIST_OID, null, null,
                null, SYNTAX_DIRECTORY_STRING_OID, false, false, true, AttributeUsage.DIRECTORY_OPERATION,
                "New extra property", "New extra value", false },
        };
    }
    @Test(dataProvider = "validAttributeTypes")
    public void testValidAttributeTypeBuilder(final String oid, final List<String> names, final String description,
            final boolean obsolete, final String superiorType, final String equalityMatchingRule,
            final String orderingMatchingRule, final String substringMatchingRule,
            final String approximateMatchingRule, final String syntax, final boolean singleValue,
            final boolean collective, final boolean noUserModification, final AttributeUsage attributeUsage,
            final String extraPropertyName, String extraPropertyValue, final boolean overwrite) throws Exception {
        AttributeType.Builder atBuilder = new SchemaBuilder(getCoreSchema())
            .buildAttributeType(oid)
            .names(names)
            .description(description)
            .obsolete(obsolete)
            .superiorType(superiorType)
            .equalityMatchingRule(equalityMatchingRule)
            .orderingMatchingRule(orderingMatchingRule)
            .substringMatchingRule(substringMatchingRule)
            .approximateMatchingRule(approximateMatchingRule)
            .syntax(syntax)
            .singleValue(singleValue)
            .collective(collective)
            .noUserModification(noUserModification)
            .usage(attributeUsage)
            .extraProperties(extraPropertyName, extraPropertyValue);
        Schema schema = overwrite ? atBuilder.addToSchemaOverwrite().toSchema()
                                  : atBuilder.addToSchema().toSchema();
        assertThat(schema.getWarnings()).isEmpty();
        final AttributeType at = schema.getAttributeType(oid);
        assertThat(at).isNotNull();
        assertThat(at.getOID()).isEqualTo(oid);
        assertThat(at.getNames()).containsOnly(names.toArray());
        assertThat(at.getDescription()).isEqualTo(description);
        assertThat(at.isObsolete()).isEqualTo(obsolete);
        assertThat(at.getExtraProperties()).includes(entry(extraPropertyName, singletonList(extraPropertyValue)));
    }
    @Test
    public void testAttributeTypeBuilderDefaultValues() throws Exception {
        final String testOID = "1.1.1.42";
        final SchemaBuilder sb = new SchemaBuilder(getCoreSchema());
        AttributeType.Builder ocBuilder = sb.buildAttributeType(testOID)
                                            .names("defaultAttributeType")
                                            .syntax(SYNTAX_OID_OID)
                                            .usage(AttributeUsage.USER_APPLICATIONS);
        Schema schema = ocBuilder.addToSchema().toSchema();
        assertThat(schema.getWarnings()).isEmpty();
        AttributeType at = schema.getAttributeType(testOID);
        assertThat(at).isNotNull();
        assertThat(at.getOID()).isEqualTo(testOID);
        assertThat(at.getNames()).containsOnly("defaultAttributeType");
        assertThat(at.getDescription()).isEqualTo("");
        assertThat(at.isObsolete()).isFalse();
        assertThat(at.getSuperiorType()).isNull();
        assertThat(at.getSyntax().getOID()).isEqualTo(SYNTAX_OID_OID);
        assertThat(at.isSingleValue()).isFalse();
        assertThat(at.isCollective()).isFalse();
        assertThat(at.isNoUserModification()).isFalse();
        assertThat(at.getExtraProperties()).isEmpty();
    }
    @Test
    public void testAttributeTypeBuilderCopyConstructor() throws Exception {
        SchemaBuilder sb = new SchemaBuilder(getCoreSchema());
        AttributeType.Builder atBuilder = sb.buildAttributeType("1.1.1.42")
                                            .names("AttributeTypeToDuplicate")
                                            .description("Attribute type to duplicate")
                                            .usage(AttributeUsage.USER_APPLICATIONS)
                                            .syntax(SYNTAX_OID_OID);
        Schema schema = atBuilder.addToSchema().toSchema();
        assertThat(schema.getWarnings()).isEmpty();
        sb.buildAttributeType(schema.getAttributeType("AttributeTypeToDuplicate"))
                .oid("1.1.1.43")
                .names("Copy")
                .obsolete(true)
                .addToSchemaOverwrite();
        Schema schemaCopy = sb.toSchema();
        assertThat(schemaCopy.getWarnings()).isEmpty();
        AttributeType atCopy = schemaCopy.getAttributeType("Copy");
        assertThat(atCopy).isNotNull();
        assertThat(atCopy.getOID()).isEqualTo("1.1.1.43");
        assertThat(atCopy.getDescription()).isEqualTo("Attribute type to duplicate");
        assertThat(atCopy.isObsolete()).isTrue();
        assertThat(atCopy.getNames()).containsOnly("AttributeTypeToDuplicate", "Copy");
        assertThat(atCopy.getExtraProperties()).isEmpty();
    }
    @Test(expectedExceptions = ConflictingSchemaElementException.class)
    public void testAttributeTypeBuilderDoesNotAllowOverwrite() throws Exception {
        AttributeType.Builder atBuilder = new SchemaBuilder(getCoreSchema())
            .buildAttributeType("2.5.4.25")
            .description("MyAttributeType description")
            .names("internationalISDNNumber")
            .syntax(SYNTAX_OID_OID)
            .usage(AttributeUsage.DSA_OPERATION)
            .extraProperties("New extra property", "New extra value");
        atBuilder.addToSchema().toSchema();
    }
    @Test(expectedExceptions = IllegalArgumentException.class)
    public void testAttributeTypeBuilderDoesNotAllowEmptyOID() throws Exception {
        AttributeType.Builder atBuilder = new SchemaBuilder(getCoreSchema())
            .buildAttributeType("")
            .description("MyAttributeType description")
            .names("MyAttributeType")
            .syntax(SYNTAX_OID_DESCRIPTION)
            .usage(AttributeUsage.DIRECTORY_OPERATION)
            .extraProperties("New extra property", "New extra value");
        atBuilder.addToSchema().toSchema();
    }
}
opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeTest.java
@@ -22,14 +22,13 @@
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2015 ForgeRock AS.
 */
package org.forgerock.opendj.ldap.schema;
import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -48,28 +47,43 @@
    public AttributeTypeTest() throws Exception {
        final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
        builder.addAttributeType("1.2.1", EMPTY_NAMES, "", true, null, null, null, null, null,
                "1.3.6.1.4.1.1466.115.121.1.27", true, false, false,
                AttributeUsage.USER_APPLICATIONS, EMPTY_PROPS, false);
        builder.buildAttributeType("1.2.1")
               .names(EMPTY_NAMES)
               .obsolete(true)
               .syntax("1.3.6.1.4.1.1466.115.121.1.27")
               .singleValue(true)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .addToSchema();
        builder.addAttributeType(
                "( 1.2.2 OBSOLETE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE "
                        + " COLLECTIVE X-ORIGIN ( 'Sun Java System Identity Management' "
                        + "'user defined' ) X-SCHEMA-FILE '98sunEmp.ldif')", false);
        builder.addAttributeType("1.2.3", Collections.singletonList("testType"), "", false,
                "1.2.2", null, null, null, null, "1.3.6.1.4.1.1466.115.121.1.27", false, true,
                false, AttributeUsage.USER_APPLICATIONS, EMPTY_PROPS, false);
        builder.addAttributeType("( 1.2.4 NAME 'testType' SUP 1.2.3 SINGLE-VALUE COLLECTIVE )",
                false);
        final List<String> names = new LinkedList<String>();
        names.add("testType");
        names.add("testnamealias");
        names.add("anothernamealias");
        builder.addAttributeType("1.2.5", names, "", false, null, EMR_CASE_IGNORE_LIST_OID, null,
                SMR_CASE_IGNORE_LIST_OID, AMR_DOUBLE_METAPHONE_OID, SYNTAX_INTEGER_OID, false,
                false, true, AttributeUsage.DSA_OPERATION, EMPTY_PROPS, false);
        builder.buildAttributeType("1.2.3")
               .names("testType")
               .superiorType("1.2.2")
               .syntax("1.3.6.1.4.1.1466.115.121.1.27")
               .collective(true)
               .usage(AttributeUsage.USER_APPLICATIONS)
               .addToSchema();
        builder.addAttributeType("( 1.2.4 NAME 'testType' SUP 1.2.3 SINGLE-VALUE COLLECTIVE )", false);
        builder.buildAttributeType("1.2.5")
               .names("testType", "testnamealias", "anothernamealias")
               .equalityMatchingRule(EMR_CASE_IGNORE_LIST_OID)
               .substringMatchingRule(SMR_CASE_IGNORE_LIST_OID)
               .approximateMatchingRule(AMR_DOUBLE_METAPHONE_OID)
               .syntax(SYNTAX_INTEGER_OID)
               .noUserModification(true)
               .usage(AttributeUsage.DSA_OPERATION)
               .addToSchema();
        builder.addAttributeType("( 1.2.6 NAME ( 'testType' 'testnamealias' 'anothernamealias1' ) "
                + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SUP anothernamealias"
                + " USAGE dSAOperation NO-USER-MODIFICATION )", false);
        schema = builder.toSchema();
        if (!schema.getWarnings().isEmpty()) {
            throw new Exception("Base schema not valid!");
@@ -486,10 +500,14 @@
    @Test(expectedExceptions = IllegalArgumentException.class)
    public void testNoSupNorSyntax1() throws Exception {
        final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
        builder.addAttributeType("1.2.1", EMPTY_NAMES, "", true, null, null, null, null, null,
                null, false, false, false, AttributeUsage.DSA_OPERATION, EMPTY_PROPS, false);
        builder.addAttributeType(
                "( 1.2.2 OBSOLETE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )", false);
        builder.buildAttributeType("1.2.1")
               .names(EMPTY_NAMES)
               .obsolete(true)
               .usage(AttributeUsage.DSA_OPERATION)
               .addToSchema();
        builder.addAttributeType("( 1.2.2 OBSOLETE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )", false);
    }
    /**
@@ -520,9 +538,14 @@
    protected SchemaElement getElement(final String description,
            final Map<String, List<String>> extraProperties) throws SchemaException {
        final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
        builder.addAttributeType("1.2.3", Collections.singletonList("testType"), description,
                false, null, null, null, null, null, "1.3.6.1.4.1.1466.115.121.1.27", false, false,
                false, AttributeUsage.DSA_OPERATION, extraProperties, false);
        builder.buildAttributeType("1.2.3")
               .names("testType")
               .description(description)
               .syntax("1.3.6.1.4.1.1466.115.121.1.27")
               .usage(AttributeUsage.DSA_OPERATION)
               .extraProperties(extraProperties)
               .addToSchema();
        return builder.toSchema().getAttributeType("1.2.3");
    }
opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaBuilderTestCase.java
@@ -25,7 +25,15 @@
 */
package org.forgerock.opendj.ldap.schema;
import java.util.Collections;
import static org.fest.assertions.Assertions.*;
import static org.fest.assertions.Fail.*;
import static org.forgerock.opendj.ldap.schema.CoreSchema.*;
import static org.forgerock.opendj.ldap.schema.Schema.*;
import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
import static org.forgerock.opendj.ldap.schema.SchemaOptions.*;
import static org.forgerock.opendj.ldap.spi.LdapPromises.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.ByteString;
@@ -41,16 +49,6 @@
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.testng.annotations.Test;
import static org.fest.assertions.Assertions.*;
import static org.fest.assertions.Fail.*;
import static org.forgerock.opendj.ldap.schema.CoreSchema.*;
import static org.forgerock.opendj.ldap.schema.Schema.*;
import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
import static org.forgerock.opendj.ldap.schema.SchemaOptions.*;
import static org.forgerock.opendj.ldap.spi.LdapPromises.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
/**
 * Test SchemaBuilder.
 */
@@ -995,12 +993,11 @@
     */
    @Test(expectedExceptions = NullPointerException.class)
    public final void testSchemaBuilderAddAttributeTypeDoesntAllowNull() throws Exception {
        final SchemaBuilder scBuild = new SchemaBuilder();
        // Adding the new schema containing the customclass
        scBuild.addObjectClass("( temporary-fake-oc-id NAME 'myCustomObjClass"
                + "' SUP top AUXILIARY MAY myCustomAttribute )", false);
        scBuild.addAttributeType(null, false);
        scBuild.addAttributeType((String) null, false);
    }
    /**
@@ -1087,11 +1084,16 @@
        final SchemaBuilder scBuild2 = new SchemaBuilder(Schema.getDefaultSchema());
        scBuild2.addObjectClass("( temporary-fake-oc-id NAME 'myCustomObjClass"
                + "' SUP top AUXILIARY MAY myCustomAttribute )", false);
        scBuild2.addAttributeType("temporary-fake-attr-id", Collections
                .singletonList("myCustomAttribute"), "The new attribute type", false, null,
                "caseIgnoreOrderingMatch", "caseIgnoreOrderingMatch", "caseIgnoreSubstringsMatch",
                null, "1.3.6.1.4.1.1466.115.121.1.15", false, false, true,
                AttributeUsage.USER_APPLICATIONS, null, false);
        scBuild2.buildAttributeType("temporary-fake-attr-id")
                .names("myCustomAttribute")
                .description("The new attribute type")
                .equalityMatchingRule("caseIgnoreOrderingMatch")
                .orderingMatchingRule("caseIgnoreOrderingMatch")
                .substringMatchingRule("caseIgnoreSubstringsMatch")
                .syntax("1.3.6.1.4.1.1466.115.121.1.15")
                .usage(AttributeUsage.USER_APPLICATIONS)
                .addToSchemaOverwrite();
        Schema sc2 = scBuild2.toSchema();
        assertThat(sc2.getAttributeType("myCustomAttribute").getDescription()).isEqualTo(