From 4e9f565b5fb89d977f4724a29afeaa4a425990c2 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 26 Apr 2016 12:33:40 +0000
Subject: [PATCH] In SDK, rename SchemaElement class to AbstractSchemaElement and introduce SchemaElement interface

---
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java                      |    2 
 opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/ObjectClassBuilderTestCase.java    |    8 
 opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElementTestCase.java |   22 +-
 opendj-core/clirr-ignored-api-changes.xml                                                     |   20 +
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Syntax.java                        |    2 
 opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeTest.java             |    2 
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java                |    2 
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectClass.java                   |    2 
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElement.java         |  287 ++++++++++++++++++++++++++
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleUse.java               |    2 
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITStructureRule.java              |    2 
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaElement.java                 |  277 ------------------------
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java                  |    2 
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java                 |    2 
 14 files changed, 340 insertions(+), 292 deletions(-)

diff --git a/opendj-core/clirr-ignored-api-changes.xml b/opendj-core/clirr-ignored-api-changes.xml
index 5e45694..1bbdd3a 100644
--- a/opendj-core/clirr-ignored-api-changes.xml
+++ b/opendj-core/clirr-ignored-api-changes.xml
@@ -67,4 +67,24 @@
     <method>org.forgerock.opendj.ldap.spi.BindResultLdapPromiseImpl newBindLdapPromise(int, org.forgerock.opendj.ldap.requests.BindRequest, org.forgerock.opendj.ldap.requests.BindClient, org.forgerock.opendj.ldap.IntermediateResponseHandler, org.forgerock.opendj.ldap.spi.LDAPConnectionImpl)</method>
     <justification>Code cleanup: remove overloaded method with unused parameter</justification>
   </difference>
+  <difference>
+    <className>%regex[org/forgerock/opendj/ldap/schema/(AttributeType|DITContentRule|DITStructureRule|MatchingRule|MatchingRuleUse|NameForm|ObjectClass|Syntax)\$Builder]</className>
+    <differenceType>7006</differenceType>
+    <method>%regex[org\.forgerock\.opendj\.ldap\.schema\.SchemaElement\$SchemaElementBuilder (description|extraProperties|removeAllExtraProperties|removeExtraProperty)\([^)]*\)]</method>   
+    <to>org.forgerock.opendj.ldap.schema.AbstractSchemaElement$SchemaElementBuilder</to>
+    <justification>Renamed class SchemaElement to AbstractSchemaElement</justification>
+  </difference>
+  <difference>
+    <className>%regex[org/forgerock/opendj/ldap/schema/(AttributeType|DITContentRule|DITStructureRule|MatchingRule|MatchingRuleUse|NameForm|ObjectClass|Syntax)]</className>
+    <differenceType>5001</differenceType>
+    <to>org/forgerock/opendj/ldap/schema/**SchemaElement</to>
+    <justification>Renamed class SchemaElement to AbstractSchemaElement</justification>
+  </difference>
+  <difference>
+    <className>%regex[org/forgerock/opendj/ldap/schema/(AttributeType|DITContentRule|DITStructureRule|MatchingRule|MatchingRuleUse|NameForm|ObjectClass|Syntax)\$Builder]</className>
+    <differenceType>5001</differenceType>
+    <to>org/forgerock/opendj/ldap/schema/**SchemaElement$SchemaElementBuilder</to>
+    <justification>Renamed class SchemaElement to AbstractSchemaElement</justification>
+  </difference>
+  
 </differences>
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElement.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElement.java
new file mode 100644
index 0000000..5ac5a04
--- /dev/null
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElement.java
@@ -0,0 +1,287 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2009 Sun Microsystems, Inc.
+ * Portions copyright 2011-2016 ForgeRock AS.
+ */
+package org.forgerock.opendj.ldap.schema;
+
+import static org.forgerock.opendj.ldap.schema.SchemaUtils.unmodifiableCopyOfExtraProperties;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.forgerock.util.Reject;
+
+/**
+ * An abstract base class for LDAP schema definitions which contain an
+ * description, and an optional set of extra properties.
+ * <p>
+ * This class defines common properties and behaviour of the various types of
+ * schema definitions (e.g. object class definitions, and attribute type
+ * definitions).
+ */
+abstract class AbstractSchemaElement implements SchemaElement {
+    static abstract class SchemaElementBuilder<T extends SchemaElementBuilder<T>> {
+        private String definition;
+        private String description;
+        private final Map<String, List<String>> extraProperties;
+        private final SchemaBuilder schemaBuilder;
+
+        SchemaElementBuilder(final SchemaBuilder schemaBuilder) {
+            this.schemaBuilder = schemaBuilder;
+            this.description = "";
+            this.extraProperties = new LinkedHashMap<>(1);
+        }
+
+        SchemaElementBuilder(final SchemaBuilder schemaBuilder, final AbstractSchemaElement copy) {
+            this.schemaBuilder = schemaBuilder;
+            this.description = copy.description;
+            this.extraProperties = new LinkedHashMap<>(copy.extraProperties);
+        }
+
+        /*
+         * The abstract methods in this class are required in order to obtain
+         * meaningful Javadoc. If the methods were defined in this class then
+         * the resulting Javadoc in sub-class is invalid. The only workaround is
+         * to make the methods abstract, provide "xxx0" implementations, and
+         * override the abstract methods in sub-classes as delegates to the
+         * "xxx0" methods. Ghastly! Thanks Javadoc.
+         */
+
+        /**
+         * Sets the description.
+         *
+         * @param description
+         *            The description, which may be {@code null} in which case
+         *            the empty string will be used.
+         * @return This builder.
+         */
+        public abstract T description(final String description);
+
+        /**
+         * Adds the provided collection of extended properties.
+         *
+         * @param extraProperties
+         *            The collection of extended properties.
+         * @return This builder.
+         */
+        public abstract T extraProperties(final Map<String, List<String>> extraProperties);
+
+        /**
+         * 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 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.
+         *
+         * @return This builder.
+         */
+        public abstract T removeAllExtraProperties();
+
+        /**
+         * Removes the specified extended property.
+         *
+         * @param extensionName
+         *            The name of the extended property.
+         * @param extensionValues
+         *            The optional list of values for the extended property,
+         *            which may be empty indicating that the entire property
+         *            should be removed.
+         * @return This builder.
+         */
+        public abstract T removeExtraProperty(final String extensionName,
+                final String... extensionValues);
+
+        T definition(final String definition) {
+            this.definition = definition;
+            return getThis();
+        }
+
+        T description0(final String description) {
+            this.description = description == null ? "" : description;
+            return getThis();
+        }
+
+        T extraProperties0(final Map<String, List<String>> extraProperties) {
+            this.extraProperties.putAll(extraProperties);
+            return getThis();
+        }
+
+        T extraProperties0(final String extensionName, final String... extensionValues) {
+            if (this.extraProperties.get(extensionName) != null) {
+                final List<String> tempExtraProperties =
+                        new ArrayList<>(this.extraProperties.get(extensionName));
+                tempExtraProperties.addAll(Arrays.asList(extensionValues));
+                this.extraProperties.put(extensionName, tempExtraProperties);
+            } else {
+                this.extraProperties.put(extensionName, Arrays.asList(extensionValues));
+            }
+            return getThis();
+        }
+
+        String getDescription() {
+            return description;
+        }
+
+        Map<String, List<String>> getExtraProperties() {
+            return extraProperties;
+        }
+
+        SchemaBuilder getSchemaBuilder() {
+            return schemaBuilder;
+        }
+
+        abstract T getThis();
+
+        T removeAllExtraProperties0() {
+            this.extraProperties.clear();
+            return getThis();
+        }
+
+        T removeExtraProperty0(final String extensionName, final String... extensionValues) {
+            if (this.extraProperties.get(extensionName) != null && extensionValues.length > 0) {
+                final List<String> tempExtraProperties =
+                        new ArrayList<>(this.extraProperties.get(extensionName));
+                tempExtraProperties.removeAll(Arrays.asList(extensionValues));
+                this.extraProperties.put(extensionName, tempExtraProperties);
+            } else if (this.extraProperties.get(extensionName) != null) {
+                this.extraProperties.remove(extensionName);
+            }
+            return getThis();
+        }
+    }
+
+    /** Lazily created string representation. */
+    private String definition;
+
+    /** The description for this definition. */
+    private final String description;
+
+    /** The set of additional name-value pairs. */
+    private final Map<String, List<String>> extraProperties;
+
+    AbstractSchemaElement() {
+        this.description = "";
+        this.extraProperties = Collections.<String, List<String>> emptyMap();
+        this.definition = null;
+    }
+
+    AbstractSchemaElement(final SchemaElementBuilder<?> builder) {
+        this.description = builder.description;
+        this.extraProperties = unmodifiableCopyOfExtraProperties(builder.extraProperties);
+        this.definition = builder.definition;
+    }
+
+    AbstractSchemaElement(final String description, final Map<String, List<String>> extraProperties,
+            final String definition) {
+        Reject.ifNull(description, extraProperties);
+        this.description = description;
+        this.extraProperties = extraProperties; // Should already be unmodifiable.
+        this.definition = definition;
+    }
+
+    @Override
+    public abstract boolean equals(Object obj);
+
+    @Override
+    public final String getDescription() {
+        return description;
+    }
+
+    @Override
+    public final Map<String, List<String>> getExtraProperties() {
+        return extraProperties;
+    }
+
+    @Override
+    public abstract int hashCode();
+
+    /**
+     * Returns the string representation of this schema element as defined in
+     * RFC 2252.
+     *
+     * @return The string representation of this schema element as defined in
+     *         RFC 2252.
+     */
+    @Override
+    public final String toString() {
+        if (definition == null) {
+            definition = buildDefinition();
+        }
+        return definition;
+    }
+
+    final void appendDescription(final StringBuilder buffer) {
+        if (description != null && description.length() > 0) {
+            buffer.append(" DESC '");
+            buffer.append(description);
+            buffer.append("'");
+        }
+    }
+
+    abstract void toStringContent(StringBuilder buffer);
+
+    private final String buildDefinition() {
+        final StringBuilder buffer = new StringBuilder();
+        buffer.append("( ");
+        toStringContent(buffer);
+        if (!extraProperties.isEmpty()) {
+            for (final Map.Entry<String, List<String>> e : extraProperties.entrySet()) {
+                final String property = e.getKey();
+                final List<String> valueList = e.getValue();
+                buffer.append(" ");
+                buffer.append(property);
+                if (valueList.size() == 1) {
+                    buffer.append(" '");
+                    buffer.append(valueList.get(0));
+                    buffer.append("'");
+                } else {
+                    buffer.append(" ( ");
+                    for (final String value : valueList) {
+                        buffer.append("'");
+                        buffer.append(value);
+                        buffer.append("' ");
+                    }
+                    buffer.append(")");
+                }
+            }
+        }
+        buffer.append(" )");
+        return buffer.toString();
+    }
+}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java
index 601cc52..4165286 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java
@@ -47,7 +47,7 @@
  * will be preserved when the associated fields are accessed via their getters
  * or via the {@link #toString()} methods.
  */
-public final class AttributeType extends SchemaElement implements Comparable<AttributeType> {
+public final class AttributeType extends AbstractSchemaElement implements Comparable<AttributeType> {
 
     /** A fluent API for incrementally constructing attribute type. */
     public static final class Builder extends SchemaElementBuilder<Builder> {
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java
index 131a386..714ad4f 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java
@@ -41,7 +41,7 @@
  * objectclass, and also indicates which auxiliary classes may be included in
  * the entry.
  */
-public final class DITContentRule extends SchemaElement {
+public final class DITContentRule extends AbstractSchemaElement {
 
     /** A fluent API for incrementally constructing DIT content rule. */
     public static final class Builder extends SchemaElementBuilder<Builder> {
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITStructureRule.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITStructureRule.java
index 6c0ccaf..2d81de9 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITStructureRule.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITStructureRule.java
@@ -40,7 +40,7 @@
  * This class defines a DIT structure rule, which is used to indicate the types
  * of children that entries may have.
  */
-public final class DITStructureRule extends SchemaElement {
+public final class DITStructureRule extends AbstractSchemaElement {
 
     /** A fluent API for incrementally constructing DIT structure rules. */
     public static final class Builder extends SchemaElementBuilder<Builder> {
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java
index aa5f7de..161e0d5 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java
@@ -48,7 +48,7 @@
  * will be preserved when the associated fields are accessed via their getters
  * or via the {@link #toString()} methods.
  */
-public final class MatchingRule extends SchemaElement {
+public final class MatchingRule extends AbstractSchemaElement {
 
     /** A fluent API for incrementally constructing matching rules. */
     public static final class Builder extends SchemaElementBuilder<Builder> {
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleUse.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleUse.java
index 24bb8cd..eb965f9 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleUse.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleUse.java
@@ -40,7 +40,7 @@
  * matching rule use definition, which may be used to restrict the set of
  * attribute types that may be used for a given matching rule.
  */
-public final class MatchingRuleUse extends SchemaElement {
+public final class MatchingRuleUse extends AbstractSchemaElement {
     /** A fluent API for incrementally constructing matching rule uses. */
     public static final class Builder extends SchemaElementBuilder<Builder> {
         private String oid;
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java
index 5be8d50..e7c659d 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java
@@ -40,7 +40,7 @@
  * form, which defines the attribute type(s) that must and/or may be used in the
  * RDN of an entry with a given structural objectclass.
  */
-public final class NameForm extends SchemaElement {
+public final class NameForm extends AbstractSchemaElement {
 
     /** A fluent API for incrementally constructing name forms. */
     public static final class Builder extends SchemaElementBuilder<Builder> {
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectClass.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectClass.java
index a6b276c..d5bf022 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectClass.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectClass.java
@@ -47,7 +47,7 @@
  * provided, the ordering will be preserved when the associated fields are
  * accessed via their getters or via the {@link #toString()} methods.
  */
-public final class ObjectClass extends SchemaElement {
+public final class ObjectClass extends AbstractSchemaElement {
 
     /** A fluent API for incrementally constructing object classes. */
     public static final class Builder extends SchemaElementBuilder<Builder> {
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaElement.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaElement.java
index c1f2eb7..e6eb43f 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaElement.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaElement.java
@@ -11,289 +11,30 @@
  * Header, with the fields enclosed by brackets [] replaced by your own identifying
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
- * Copyright 2009 Sun Microsystems, Inc.
- * Portions copyright 2011-2016 ForgeRock AS.
+ * Copyright 2016 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
-import static org.forgerock.opendj.ldap.schema.SchemaUtils.unmodifiableCopyOfExtraProperties;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.forgerock.util.Reject;
-
 /**
- * An abstract base class for LDAP schema definitions which contain an
- * description, and an optional set of extra properties.
- * <p>
- * This class defines common properties and behaviour of the various types of
- * schema definitions (e.g. object class definitions, and attribute type
- * definitions).
+ * Interface for schema elements.
  */
-abstract class SchemaElement {
-    static abstract class SchemaElementBuilder<T extends SchemaElementBuilder<T>> {
-        private String definition;
-        private String description;
-        private final Map<String, List<String>> extraProperties;
-        private final SchemaBuilder schemaBuilder;
-
-        SchemaElementBuilder(final SchemaBuilder schemaBuilder) {
-            this.schemaBuilder = schemaBuilder;
-            this.description = "";
-            this.extraProperties = new LinkedHashMap<>(1);
-        }
-
-        SchemaElementBuilder(final SchemaBuilder schemaBuilder, final SchemaElement copy) {
-            this.schemaBuilder = schemaBuilder;
-            this.description = copy.description;
-            this.extraProperties = new LinkedHashMap<>(copy.extraProperties);
-        }
-
-        /*
-         * The abstract methods in this class are required in order to obtain
-         * meaningful Javadoc. If the methods were defined in this class then
-         * the resulting Javadoc in sub-class is invalid. The only workaround is
-         * to make the methods abstract, provide "xxx0" implementations, and
-         * override the abstract methods in sub-classes as delegates to the
-         * "xxx0" methods. Ghastly! Thanks Javadoc.
-         */
-
-        /**
-         * Sets the description.
-         *
-         * @param description
-         *            The description, which may be {@code null} in which case
-         *            the empty string will be used.
-         * @return This builder.
-         */
-        public abstract T description(final String description);
-
-        /**
-         * Adds the provided collection of extended properties.
-         *
-         * @param extraProperties
-         *            The collection of extended properties.
-         * @return This builder.
-         */
-        public abstract T extraProperties(final Map<String, List<String>> extraProperties);
-
-        /**
-         * 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 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.
-         *
-         * @return This builder.
-         */
-        public abstract T removeAllExtraProperties();
-
-        /**
-         * Removes the specified extended property.
-         *
-         * @param extensionName
-         *            The name of the extended property.
-         * @param extensionValues
-         *            The optional list of values for the extended property,
-         *            which may be empty indicating that the entire property
-         *            should be removed.
-         * @return This builder.
-         */
-        public abstract T removeExtraProperty(final String extensionName,
-                final String... extensionValues);
-
-        T definition(final String definition) {
-            this.definition = definition;
-            return getThis();
-        }
-
-        T description0(final String description) {
-            this.description = description == null ? "" : description;
-            return getThis();
-        }
-
-        T extraProperties0(final Map<String, List<String>> extraProperties) {
-            this.extraProperties.putAll(extraProperties);
-            return getThis();
-        }
-
-        T extraProperties0(final String extensionName, final String... extensionValues) {
-            if (this.extraProperties.get(extensionName) != null) {
-                final List<String> tempExtraProperties =
-                        new ArrayList<>(this.extraProperties.get(extensionName));
-                tempExtraProperties.addAll(Arrays.asList(extensionValues));
-                this.extraProperties.put(extensionName, tempExtraProperties);
-            } else {
-                this.extraProperties.put(extensionName, Arrays.asList(extensionValues));
-            }
-            return getThis();
-        }
-
-        String getDescription() {
-            return description;
-        }
-
-        Map<String, List<String>> getExtraProperties() {
-            return extraProperties;
-        }
-
-        SchemaBuilder getSchemaBuilder() {
-            return schemaBuilder;
-        }
-
-        abstract T getThis();
-
-        T removeAllExtraProperties0() {
-            this.extraProperties.clear();
-            return getThis();
-        }
-
-        T removeExtraProperty0(final String extensionName, final String... extensionValues) {
-            if (this.extraProperties.get(extensionName) != null && extensionValues.length > 0) {
-                final List<String> tempExtraProperties =
-                        new ArrayList<>(this.extraProperties.get(extensionName));
-                tempExtraProperties.removeAll(Arrays.asList(extensionValues));
-                this.extraProperties.put(extensionName, tempExtraProperties);
-            } else if (this.extraProperties.get(extensionName) != null) {
-                this.extraProperties.remove(extensionName);
-            }
-            return getThis();
-        }
-    }
-
-    /** Lazily created string representation. */
-    private String definition;
-
-    /** The description for this definition. */
-    private final String description;
-
-    /** The set of additional name-value pairs. */
-    private final Map<String, List<String>> extraProperties;
-
-    SchemaElement() {
-        this.description = "";
-        this.extraProperties = Collections.<String, List<String>> emptyMap();
-        this.definition = null;
-    }
-
-    SchemaElement(final SchemaElementBuilder<?> builder) {
-        this.description = builder.description;
-        this.extraProperties = unmodifiableCopyOfExtraProperties(builder.extraProperties);
-        this.definition = builder.definition;
-    }
-
-    SchemaElement(final String description, final Map<String, List<String>> extraProperties,
-            final String definition) {
-        Reject.ifNull(description, extraProperties);
-        this.description = description;
-        this.extraProperties = extraProperties; // Should already be unmodifiable.
-        this.definition = definition;
-    }
-
-    @Override
-    public abstract boolean equals(Object obj);
+public interface SchemaElement {
 
     /**
-     * Returns the description of this schema element, or the empty string if it
-     * does not have a description.
+     * Returns the description of this schema element, or the empty string if it does not have a description.
      *
-     * @return The description of this schema element, or the empty string if it
-     *         does not have a description.
+     * @return The description of this schema element, or the empty string if it does not have a description.
      */
-    public final String getDescription() {
-        return description;
-    }
+    String getDescription();
 
     /**
-     * Returns an unmodifiable map containing all of the extra properties
-     * associated with this schema element.
+     * Returns an unmodifiable map containing all of the extra properties associated with this schema element.
      *
-     * @return An unmodifiable map containing all of the extra properties
-     *         associated with this schema element.
+     * @return An unmodifiable map containing all of the extra properties associated with this schema element.
      */
-    public final Map<String, List<String>> getExtraProperties() {
-        return extraProperties;
-    }
+    Map<String, List<String>> getExtraProperties();
 
-    @Override
-    public abstract int hashCode();
-
-    /**
-     * Returns the string representation of this schema element as defined in
-     * RFC 2252.
-     *
-     * @return The string representation of this schema element as defined in
-     *         RFC 2252.
-     */
-    @Override
-    public final String toString() {
-        if (definition == null) {
-            definition = buildDefinition();
-        }
-        return definition;
-    }
-
-    final void appendDescription(final StringBuilder buffer) {
-        if (description != null && description.length() > 0) {
-            buffer.append(" DESC '");
-            buffer.append(description);
-            buffer.append("'");
-        }
-    }
-
-    abstract void toStringContent(StringBuilder buffer);
-
-    private final String buildDefinition() {
-        final StringBuilder buffer = new StringBuilder();
-        buffer.append("( ");
-        toStringContent(buffer);
-        if (!extraProperties.isEmpty()) {
-            for (final Map.Entry<String, List<String>> e : extraProperties.entrySet()) {
-                final String property = e.getKey();
-                final List<String> valueList = e.getValue();
-                buffer.append(" ");
-                buffer.append(property);
-                if (valueList.size() == 1) {
-                    buffer.append(" '");
-                    buffer.append(valueList.get(0));
-                    buffer.append("'");
-                } else {
-                    buffer.append(" ( ");
-                    for (final String value : valueList) {
-                        buffer.append("'");
-                        buffer.append(value);
-                        buffer.append("' ");
-                    }
-                    buffer.append(")");
-                }
-            }
-        }
-        buffer.append(" )");
-        return buffer.toString();
-    }
 }
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Syntax.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Syntax.java
index 473efde..4bd02cf 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Syntax.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Syntax.java
@@ -43,7 +43,7 @@
  * will be preserved when the associated fields are accessed via their getters
  * or via the {@link #toString()} methods.
  */
-public final class Syntax extends SchemaElement {
+public final class Syntax extends AbstractSchemaElement {
 
     /** A fluent API for incrementally constructing syntaxes. */
     public static final class Builder extends SchemaElementBuilder<Builder> {
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElementTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElementTestCase.java
index f32f9c7..8124a2b 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElementTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElementTestCase.java
@@ -50,14 +50,14 @@
      *             If the test failed unexpectedly.
      */
     @Test(dataProvider = "equalsTestData")
-    public final void testEquals(final SchemaElement e1, final SchemaElement e2,
+    public final void testEquals(final AbstractSchemaElement e1, final AbstractSchemaElement e2,
             final boolean result) throws Exception {
         Assert.assertEquals(e1.equals(e2), result);
         Assert.assertEquals(e2.equals(e1), result);
     }
 
     /**
-     * Check that the {@link SchemaElement#getDescription()} method returns a
+     * Check that the {@link AbstractSchemaElement#getDescription()} method returns a
      * description.
      *
      * @throws Exception
@@ -65,12 +65,12 @@
      */
     @Test
     public final void testGetDescription() throws Exception {
-        final SchemaElement e = getElement("hello", EMPTY_PROPS);
+        final AbstractSchemaElement e = getElement("hello", EMPTY_PROPS);
         Assert.assertEquals(e.getDescription(), "hello");
     }
 
     /**
-     * Check that the {@link SchemaElement#getDescription()} method returns
+     * Check that the {@link AbstractSchemaElement#getDescription()} method returns
      * <code>null</code> when there is no description.
      *
      * @throws Exception
@@ -78,12 +78,12 @@
      */
     @Test
     public final void testGetDescriptionDefault() throws Exception {
-        final SchemaElement e = getElement("", EMPTY_PROPS);
+        final AbstractSchemaElement e = getElement("", EMPTY_PROPS);
         Assert.assertEquals(e.getDescription(), "");
     }
 
     /**
-     * Check that the {@link SchemaElement#getExtraProperties()} method
+     * Check that the {@link AbstractSchemaElement#getExtraProperties()} method
      * returns values.
      *
      * @throws Exception
@@ -95,7 +95,7 @@
         values.add("one");
         values.add("two");
         final Map<String, List<String>> props = Collections.singletonMap("test", values);
-        final SchemaElement e = getElement("", props);
+        final AbstractSchemaElement e = getElement("", props);
 
         int i = 0;
         for (final String value : e.getExtraProperties().get("test")) {
@@ -105,7 +105,7 @@
     }
 
     /**
-     * Check that the {@link SchemaElement#getExtraProperties()} method
+     * Check that the {@link AbstractSchemaElement#getExtraProperties()} method
      * returns <code>null</code> when there is no property.
      *
      * @throws Exception
@@ -113,7 +113,7 @@
      */
     @Test
     public final void testGetExtraPropertyDefault() throws Exception {
-        final SchemaElement e = getElement("", EMPTY_PROPS);
+        final AbstractSchemaElement e = getElement("", EMPTY_PROPS);
         Assert.assertNull(e.getExtraProperties().get("test"));
     }
 
@@ -130,11 +130,11 @@
      *             If the test failed unexpectedly.
      */
     @Test(dataProvider = "equalsTestData")
-    public final void testHashCode(final SchemaElement e1, final SchemaElement e2,
+    public final void testHashCode(final AbstractSchemaElement e1, final AbstractSchemaElement e2,
             final boolean result) throws Exception {
         Assert.assertEquals(e1.hashCode() == e2.hashCode(), result);
     }
 
-    protected abstract SchemaElement getElement(String description,
+    protected abstract AbstractSchemaElement getElement(String description,
             Map<String, List<String>> extraProperties) throws SchemaException;
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeTest.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeTest.java
index c261aa0..7a59c95 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeTest.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeTest.java
@@ -530,7 +530,7 @@
     }
 
     @Override
-    protected SchemaElement getElement(final String description,
+    protected AbstractSchemaElement getElement(final String description,
             final Map<String, List<String>> extraProperties) throws SchemaException {
         final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
         builder.buildAttributeType("1.2.3")
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/ObjectClassBuilderTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/ObjectClassBuilderTestCase.java
index 6269575..86de65c 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/ObjectClassBuilderTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/ObjectClassBuilderTestCase.java
@@ -171,21 +171,21 @@
         ocBuilder.addToSchema().toSchema();
     }
 
-    private void assertSchemaElementsContainsAll(final Set<? extends SchemaElement> elements,
+    private void assertSchemaElementsContainsAll(final Set<? extends AbstractSchemaElement> elements,
             final Set<String> namesOrOIDs) throws Exception {
         assertSchemaElementsContainsAll(elements, namesOrOIDs.toArray(new String[namesOrOIDs.size()]));
     }
 
 
-    private void assertSchemaElementsContainsAll(final Set<? extends SchemaElement> elements,
+    private void assertSchemaElementsContainsAll(final Set<? extends AbstractSchemaElement> elements,
             final String... namesOrOIDs) throws Exception {
         for (final String nameOrOID : namesOrOIDs) {
             assertThat(assertSchemaElementsContains(elements, nameOrOID)).isTrue();
         }
     }
 
-    private boolean assertSchemaElementsContains(final Set<? extends SchemaElement> elements, final String nameOrOID) {
-        for (final SchemaElement element : elements) {
+    private boolean assertSchemaElementsContains(final Set<? extends AbstractSchemaElement> elements, final String nameOrOID) {
+        for (final AbstractSchemaElement element : elements) {
             final String oid = element instanceof AttributeType ? ((AttributeType) element).getNameOrOID()
                                                             : ((ObjectClass) element).getNameOrOID();
             if (oid.equals(nameOrOID)) {

--
Gitblit v1.10.0