From 97233d69036f6475b984105b2affb0b3f565400c Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 02 Aug 2016 14:19:47 +0000
Subject: [PATCH] OPENDJ-3196 Remove multiple names mapping from Schema class

---
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java        |   83 ++++++-------
 opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java |  232 ++++++++++++++++++++++++-------------
 2 files changed, 190 insertions(+), 125 deletions(-)

diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
index 2aa9187..2e6d442 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
@@ -17,6 +17,8 @@
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static com.forgerock.opendj.util.StaticUtils.toLowerCase;
+
 import static com.forgerock.opendj.ldap.CoreMessages.*;
 import static org.forgerock.opendj.ldap.AttributeDescription.*;
 
@@ -46,8 +48,6 @@
 import org.forgerock.util.Options;
 import org.forgerock.util.Reject;
 
-import com.forgerock.opendj.util.StaticUtils;
-
 /**
  * This class defines a data structure that holds information about the
  * components of the LDAP schema. It includes the following kinds of elements:
@@ -354,13 +354,13 @@
 
     static final class StrictImpl implements Impl {
         private final Map<Integer, DITStructureRule> id2StructureRules;
-        private final Map<String, List<AttributeType>> name2AttributeTypes;
-        private final Map<String, List<DITContentRule>> name2ContentRules;
-        private final Map<String, List<MatchingRule>> name2MatchingRules;
-        private final Map<String, List<MatchingRuleUse>> name2MatchingRuleUses;
-        private final Map<String, List<NameForm>> name2NameForms;
-        private final Map<String, List<ObjectClass>> name2ObjectClasses;
-        private final Map<String, List<DITStructureRule>> name2StructureRules;
+        private final Map<String, AttributeType> name2AttributeTypes;
+        private final Map<String, DITContentRule> name2ContentRules;
+        private final Map<String, MatchingRule> name2MatchingRules;
+        private final Map<String, MatchingRuleUse> name2MatchingRuleUses;
+        private final Map<String, NameForm> name2NameForms;
+        private final Map<String, ObjectClass> name2ObjectClasses;
+        private final Map<String, DITStructureRule> name2StructureRules;
         private final Map<String, List<DITStructureRule>> nameForm2StructureRules;
         private final Map<String, AttributeType> numericOID2AttributeTypes;
         private final Map<String, DITContentRule> numericOID2ContentRules;
@@ -390,13 +390,13 @@
                 final Map<String, NameForm> numericOID2NameForms,
                 final Map<String, DITContentRule> numericOID2ContentRules,
                 final Map<Integer, DITStructureRule> id2StructureRules,
-                final Map<String, List<MatchingRule>> name2MatchingRules,
-                final Map<String, List<MatchingRuleUse>> name2MatchingRuleUses,
-                final Map<String, List<AttributeType>> name2AttributeTypes,
-                final Map<String, List<ObjectClass>> name2ObjectClasses,
-                final Map<String, List<NameForm>> name2NameForms,
-                final Map<String, List<DITContentRule>> name2ContentRules,
-                final Map<String, List<DITStructureRule>> name2StructureRules,
+                final Map<String, MatchingRule> name2MatchingRules,
+                final Map<String, MatchingRuleUse> name2MatchingRuleUses,
+                final Map<String, AttributeType> name2AttributeTypes,
+                final Map<String, ObjectClass> name2ObjectClasses,
+                final Map<String, NameForm> name2NameForms,
+                final Map<String, DITContentRule> name2ContentRules,
+                final Map<String, DITStructureRule> name2StructureRules,
                 final Map<String, List<NameForm>> objectClass2NameForms,
                 final Map<String, List<DITStructureRule>> nameForm2StructureRules,
                 final List<LocalizableMessage> warnings) {
@@ -481,9 +481,9 @@
             if (rule != null) {
                 return rule;
             }
-            final List<DITContentRule> rules = name2ContentRules.get(StaticUtils.toLowerCase(nameOrOid));
-            if (rules != null && rules.size() == 1) {
-                return rules.get(0);
+            final DITContentRule rule2 = name2ContentRules.get(toLowerCase(nameOrOid));
+            if (rule2 != null) {
+                return rule2;
             }
             throw new UnknownSchemaElementException(WARN_DCR_UNKNOWN.get(nameOrOid));
         }
@@ -514,9 +514,9 @@
 
         @Override
         public DITStructureRule getDITStructureRule(final String name) {
-            List<DITStructureRule> rules = name2StructureRules.get(StaticUtils.toLowerCase(name));
-            if (rules != null && rules.size() == 1) {
-                return rules.get(0);
+            DITStructureRule rule = name2StructureRules.get(toLowerCase(name));
+            if (rule != null) {
+                return rule;
             }
             throw new UnknownSchemaElementException(WARN_DIT_SR_UNKNOWN.get(name));
         }
@@ -532,9 +532,9 @@
             if (rule != null) {
                 return rule;
             }
-            final List<MatchingRule> rules = name2MatchingRules.get(StaticUtils.toLowerCase(nameOrOid));
-            if (rules != null && rules.size() == 1) {
-                return rules.get(0);
+            final MatchingRule rule2 = name2MatchingRules.get(toLowerCase(nameOrOid));
+            if (rule2 != null) {
+                return rule2;
             }
             throw new UnknownSchemaElementException(WARN_MR_UNKNOWN.get(nameOrOid));
         }
@@ -555,9 +555,9 @@
             if (use != null) {
                 return use;
             }
-            final List<MatchingRuleUse> uses = name2MatchingRuleUses.get(StaticUtils.toLowerCase(nameOrOid));
-            if (uses != null && uses.size() == 1) {
-                return uses.get(0);
+            final MatchingRuleUse use2 = name2MatchingRuleUses.get(toLowerCase(nameOrOid));
+            if (use2 != null) {
+                return use2;
             }
             throw new UnknownSchemaElementException(WARN_MRU_UNKNOWN.get(nameOrOid));
         }
@@ -573,9 +573,9 @@
             if (form != null) {
                 return form;
             }
-            final List<NameForm> forms = name2NameForms.get(StaticUtils.toLowerCase(nameOrOid));
-            if (forms != null && forms.size() == 1) {
-                return forms.get(0);
+            final NameForm form2 = name2NameForms.get(toLowerCase(nameOrOid));
+            if (form2 != null) {
+                return form2;
             }
             throw new UnknownSchemaElementException(WARN_NAMEFORM_UNKNOWN.get(nameOrOid));
         }
@@ -608,9 +608,9 @@
             if (oc != null) {
                 return oc;
             }
-            final List<ObjectClass> classes = name2ObjectClasses.get(StaticUtils.toLowerCase(nameOrOid));
-            if (classes != null && classes.size() == 1) {
-                return classes.get(0);
+            final ObjectClass oc2 = name2ObjectClasses.get(toLowerCase(nameOrOid));
+            if (oc2 != null) {
+                return oc2;
             }
             return null;
         }
@@ -647,13 +647,13 @@
         @Override
         public boolean hasAttributeType(final String nameOrOid) {
             return numericOID2AttributeTypes.containsKey(nameOrOid)
-                    || name2AttributeTypes.containsKey(StaticUtils.toLowerCase(nameOrOid));
+                    || name2AttributeTypes.containsKey(toLowerCase(nameOrOid));
         }
 
         @Override
         public boolean hasDITContentRule(final String nameOrOid) {
             return numericOID2ContentRules.containsKey(nameOrOid)
-                    || name2ContentRules.containsKey(StaticUtils.toLowerCase(nameOrOid));
+                    || name2ContentRules.containsKey(toLowerCase(nameOrOid));
         }
 
         @Override
@@ -664,25 +664,25 @@
         @Override
         public boolean hasMatchingRule(final String nameOrOid) {
             return numericOID2MatchingRules.containsKey(nameOrOid)
-                    || name2MatchingRules.containsKey(StaticUtils.toLowerCase(nameOrOid));
+                    || name2MatchingRules.containsKey(toLowerCase(nameOrOid));
         }
 
         @Override
         public boolean hasMatchingRuleUse(final String nameOrOid) {
             return numericOID2MatchingRuleUses.containsKey(nameOrOid)
-                    || name2MatchingRuleUses.containsKey(StaticUtils.toLowerCase(nameOrOid));
+                    || name2MatchingRuleUses.containsKey(toLowerCase(nameOrOid));
         }
 
         @Override
         public boolean hasNameForm(final String nameOrOid) {
             return numericOID2NameForms.containsKey(nameOrOid)
-                    || name2NameForms.containsKey(StaticUtils.toLowerCase(nameOrOid));
+                    || name2NameForms.containsKey(toLowerCase(nameOrOid));
         }
 
         @Override
         public boolean hasObjectClass(final String nameOrOid) {
             return numericOID2ObjectClasses.containsKey(nameOrOid)
-                    || name2ObjectClasses.containsKey(StaticUtils.toLowerCase(nameOrOid));
+                    || name2ObjectClasses.containsKey(toLowerCase(nameOrOid));
         }
 
         @Override
@@ -700,8 +700,7 @@
             if (type != null) {
                 return type;
             }
-            final List<AttributeType> attrs = name2AttributeTypes.get(StaticUtils.toLowerCase(nameOrOid));
-            return attrs != null && attrs.size() == 1 ? attrs.get(0) : null;
+            return name2AttributeTypes.get(toLowerCase(nameOrOid));
         }
     }
 
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
index 723980c..8b18e82 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
@@ -1953,13 +1953,13 @@
 
         final AttributeType element = numericOID2AttributeTypes.get(nameOrOid);
         if (element != null) {
-            removeAttributeType(element);
+            removeAttributeType(element, null);
             return true;
         }
         final List<AttributeType> elements = name2AttributeTypes.get(toLowerCase(nameOrOid));
         if (elements != null) {
             for (final AttributeType e : elements) {
-                removeAttributeType(e);
+                removeAttributeType(e, null);
             }
             return true;
         }
@@ -1978,13 +1978,13 @@
 
         final DITContentRule element = numericOID2ContentRules.get(nameOrOid);
         if (element != null) {
-            removeDITContentRule(element);
+            removeDITContentRule(element, null);
             return true;
         }
         final List<DITContentRule> elements = name2ContentRules.get(toLowerCase(nameOrOid));
         if (elements != null) {
             for (final DITContentRule e : elements) {
-                removeDITContentRule(e);
+                removeDITContentRule(e, null);
             }
             return true;
         }
@@ -2003,7 +2003,7 @@
 
         final DITStructureRule element = id2StructureRules.get(ruleID);
         if (element != null) {
-            removeDITStructureRule(element);
+            removeDITStructureRule(element, null);
             return true;
         }
         return false;
@@ -2021,13 +2021,13 @@
 
         final MatchingRule element = numericOID2MatchingRules.get(nameOrOid);
         if (element != null) {
-            removeMatchingRule(element);
+            removeMatchingRule(element, null);
             return true;
         }
         final List<MatchingRule> elements = name2MatchingRules.get(toLowerCase(nameOrOid));
         if (elements != null) {
             for (final MatchingRule e : elements) {
-                removeMatchingRule(e);
+                removeMatchingRule(e, null);
             }
             return true;
         }
@@ -2046,13 +2046,13 @@
 
         final MatchingRuleUse element = numericOID2MatchingRuleUses.get(nameOrOid);
         if (element != null) {
-            removeMatchingRuleUse(element);
+            removeMatchingRuleUse(element, null);
             return true;
         }
         final List<MatchingRuleUse> elements = name2MatchingRuleUses.get(toLowerCase(nameOrOid));
         if (elements != null) {
             for (final MatchingRuleUse e : elements) {
-                removeMatchingRuleUse(e);
+                removeMatchingRuleUse(e, null);
             }
             return true;
         }
@@ -2071,13 +2071,13 @@
 
         final NameForm element = numericOID2NameForms.get(nameOrOid);
         if (element != null) {
-            removeNameForm(element);
+            removeNameForm(element, null);
             return true;
         }
         final List<NameForm> elements = name2NameForms.get(toLowerCase(nameOrOid));
         if (elements != null) {
             for (final NameForm e : elements) {
-                removeNameForm(e);
+                removeNameForm(e, null);
             }
             return true;
         }
@@ -2096,13 +2096,13 @@
 
         final ObjectClass element = numericOID2ObjectClasses.get(nameOrOid);
         if (element != null) {
-            removeObjectClass(element);
+            removeObjectClass(element, null);
             return true;
         }
         final List<ObjectClass> elements = name2ObjectClasses.get(toLowerCase(nameOrOid));
         if (elements != null) {
             for (final ObjectClass e : elements) {
-                removeObjectClass(e);
+                removeObjectClass(e, null);
             }
             return true;
         }
@@ -2121,7 +2121,7 @@
 
         final Syntax element = numericOID2Syntaxes.get(numericOID);
         if (element != null) {
-            removeSyntax(element);
+            removeSyntax(element, null);
             return true;
         }
         return false;
@@ -2145,6 +2145,29 @@
         return this;
     }
 
+    private static final class NamesMapping {
+        final Map<String, MatchingRule> name2MatchingRules;
+        final Map<String, MatchingRuleUse> name2MatchingRuleUses;
+        final Map<String, AttributeType> name2AttributeTypes;
+        final Map<String, ObjectClass> name2ObjectClasses;
+        final Map<String, NameForm> name2NameForms;
+        final Map<String, DITContentRule> name2ContentRules;
+        final Map<String, DITStructureRule> name2StructureRules;
+
+        NamesMapping(Map<String, MatchingRule> name2MatchingRules, Map<String, MatchingRuleUse> name2MatchingRuleUses,
+                Map<String, AttributeType> name2AttributeTypes, Map<String, ObjectClass> name2ObjectClasses,
+                Map<String, NameForm> name2NameForms, Map<String, DITContentRule> name2ContentRules,
+                Map<String, DITStructureRule> name2StructureRules) {
+            this.name2MatchingRules = name2MatchingRules;
+            this.name2MatchingRuleUses = name2MatchingRuleUses;
+            this.name2AttributeTypes = name2AttributeTypes;
+            this.name2ObjectClasses = name2ObjectClasses;
+            this.name2NameForms = name2NameForms;
+            this.name2ContentRules = name2ContentRules;
+            this.name2StructureRules = name2StructureRules;
+        }
+    }
+
     /**
      * Returns a strict {@code Schema} containing all of the schema elements
      * contained in this schema builder as well as the same set of schema
@@ -2185,24 +2208,21 @@
             defaultMatchingRule = Schema.getCoreSchema().getDefaultMatchingRule();
         }
 
-        removeDuplicateMatchingRulesNames();
-        removeDuplicateMatchingRuleUsesNames();
-        removeDuplicateAttributeTypesNames();
-        removeDuplicateObjectClassesNames();
-        removeDuplicateNameFormsNames();
-        removeDuplicateDITContentRulesNames();
-        removeDuplicateDITStructureRulesNames();
+        NamesMapping names = new NamesMapping(removeDuplicateMatchingRulesNames(),
+                removeDuplicateMatchingRuleUsesNames(), removeDuplicateAttributeTypesNames(),
+                removeDuplicateObjectClassesNames(), removeDuplicateNameFormsNames(),
+                removeDuplicateDITContentRulesNames(), removeDuplicateDITStructureRulesNames());
 
         final Schema schema =
                 new Schema.StrictImpl(localSchemaName, options,
                         defaultSyntax, defaultMatchingRule, numericOID2Syntaxes,
                         numericOID2MatchingRules, numericOID2MatchingRuleUses,
                         numericOID2AttributeTypes, numericOID2ObjectClasses, numericOID2NameForms,
-                        numericOID2ContentRules, id2StructureRules, name2MatchingRules,
-                        name2MatchingRuleUses, name2AttributeTypes, name2ObjectClasses,
-                        name2NameForms, name2ContentRules, name2StructureRules,
+                        numericOID2ContentRules, id2StructureRules, names.name2MatchingRules,
+                        names.name2MatchingRuleUses, names.name2AttributeTypes, names.name2ObjectClasses,
+                        names.name2NameForms, names.name2ContentRules, names.name2StructureRules,
                         objectClass2NameForms, nameForm2StructureRules, warnings).asStrictSchema();
-        validate(schema);
+        validate(schema, names);
 
         // Re-init this builder so that it can continue to be used afterwards.
         preLazyInitBuilder(schemaName, schema);
@@ -2220,7 +2240,7 @@
                                 attribute.getOID(), conflictingAttribute.getNameOrOID());
                 throw new ConflictingSchemaElementException(message);
             }
-            removeAttributeType(conflictingAttribute);
+            removeAttributeType(conflictingAttribute, null);
         }
 
         numericOID2AttributeTypes.put(attribute.getOID(), attribute);
@@ -2251,7 +2271,7 @@
                                 .getStructuralClassOID(), conflictingRule.getNameOrOID());
                 throw new ConflictingSchemaElementException(message);
             }
-            removeDITContentRule(conflictingRule);
+            removeDITContentRule(conflictingRule, null);
         }
 
         numericOID2ContentRules.put(rule.getStructuralClassOID(), rule);
@@ -2282,7 +2302,7 @@
                                 rule.getRuleID(), conflictingRule.getNameOrRuleID());
                 throw new ConflictingSchemaElementException(message);
             }
-            removeDITStructureRule(conflictingRule);
+            removeDITStructureRule(conflictingRule, null);
         }
 
         id2StructureRules.put(rule.getRuleID(), rule);
@@ -2313,7 +2333,7 @@
                                 .getMatchingRuleOID(), conflictingUse.getNameOrOID());
                 throw new ConflictingSchemaElementException(message);
             }
-            removeMatchingRuleUse(conflictingUse);
+            removeMatchingRuleUse(conflictingUse, null);
         }
 
         numericOID2MatchingRuleUses.put(use.getMatchingRuleOID(), use);
@@ -2346,7 +2366,7 @@
                                 conflictingRule.getNameOrOID());
                 throw new ConflictingSchemaElementException(message);
             }
-            removeMatchingRule(conflictingRule);
+            removeMatchingRule(conflictingRule, null);
         }
 
         numericOID2MatchingRules.put(rule.getOID(), rule);
@@ -2376,7 +2396,7 @@
                                 form.getOID(), conflictingForm.getNameOrOID());
                 throw new ConflictingSchemaElementException(message);
             }
-            removeNameForm(conflictingForm);
+            removeNameForm(conflictingForm, null);
         }
 
         numericOID2NameForms.put(form.getOID(), form);
@@ -2406,7 +2426,7 @@
                                 conflictingOC.getNameOrOID());
                 throw new ConflictingSchemaElementException(message);
             }
-            removeObjectClass(conflictingOC);
+            removeObjectClass(conflictingOC, null);
         }
 
         numericOID2ObjectClasses.put(oc.getOID(), oc);
@@ -2475,7 +2495,7 @@
                         syntax.getOID(), conflictingSyntax.getOID());
                 throw new ConflictingSchemaElementException(message);
             }
-            removeSyntax(conflictingSyntax);
+            removeSyntax(conflictingSyntax, null);
         }
 
         numericOID2Syntaxes.put(syntax.getOID(), syntax);
@@ -2545,7 +2565,7 @@
         this.warnings = null;
     }
 
-    private void removeAttributeType(final AttributeType attributeType) {
+    private void removeAttributeType(final AttributeType attributeType, NamesMapping names) {
         numericOID2AttributeTypes.remove(attributeType.getOID());
         for (final String name : attributeType.getNames()) {
             final String lowerName = StaticUtils.toLowerCase(name);
@@ -2557,10 +2577,13 @@
                     attributes.remove(attributeType);
                 }
             }
+            if (names != null) {
+                names.name2AttributeTypes.remove(lowerName);
+            }
         }
     }
 
-    private void removeDITContentRule(final DITContentRule rule) {
+    private void removeDITContentRule(final DITContentRule rule, NamesMapping names) {
         numericOID2ContentRules.remove(rule.getStructuralClassOID());
         for (final String name : rule.getNames()) {
             final String lowerName = StaticUtils.toLowerCase(name);
@@ -2572,10 +2595,13 @@
                     rules.remove(rule);
                 }
             }
+            if (names != null) {
+                names.name2ContentRules.remove(lowerName);
+            }
         }
     }
 
-    private void removeDITStructureRule(final DITStructureRule rule) {
+    private void removeDITStructureRule(final DITStructureRule rule, NamesMapping names) {
         id2StructureRules.remove(rule.getRuleID());
         for (final String name : rule.getNames()) {
             final String lowerName = StaticUtils.toLowerCase(name);
@@ -2587,10 +2613,13 @@
                     rules.remove(rule);
                 }
             }
+            if (names != null) {
+                names.name2StructureRules.remove(lowerName);
+            }
         }
     }
 
-    private void removeMatchingRule(final MatchingRule rule) {
+    private void removeMatchingRule(final MatchingRule rule, NamesMapping names) {
         numericOID2MatchingRules.remove(rule.getOID());
         for (final String name : rule.getNames()) {
             final String lowerName = StaticUtils.toLowerCase(name);
@@ -2602,10 +2631,13 @@
                     rules.remove(rule);
                 }
             }
+            if (names != null) {
+                names.name2MatchingRules.remove(lowerName);
+            }
         }
     }
 
-    private void removeMatchingRuleUse(final MatchingRuleUse use) {
+    private void removeMatchingRuleUse(final MatchingRuleUse use, NamesMapping names) {
         numericOID2MatchingRuleUses.remove(use.getMatchingRuleOID());
         for (final String name : use.getNames()) {
             final String lowerName = StaticUtils.toLowerCase(name);
@@ -2617,10 +2649,13 @@
                     uses.remove(use);
                 }
             }
+            if (names != null) {
+                names.name2MatchingRuleUses.remove(lowerName);
+            }
         }
     }
 
-    private void removeNameForm(final NameForm form) {
+    private void removeNameForm(final NameForm form, NamesMapping names) {
         numericOID2NameForms.remove(form.getOID());
         name2NameForms.remove(form.getOID());
         for (final String name : form.getNames()) {
@@ -2633,10 +2668,13 @@
                     forms.remove(form);
                 }
             }
+            if (names != null) {
+                names.name2NameForms.remove(lowerName);
+            }
         }
     }
 
-    private void removeObjectClass(final ObjectClass oc) {
+    private void removeObjectClass(final ObjectClass oc, NamesMapping names) {
         numericOID2ObjectClasses.remove(oc.getOID());
         name2ObjectClasses.remove(oc.getOID());
         for (final String name : oc.getNames()) {
@@ -2649,10 +2687,13 @@
                     classes.remove(oc);
                 }
             }
+            if (names != null) {
+                names.name2ObjectClasses.remove(lowerName);
+            }
         }
     }
 
-    private void removeSyntax(final Syntax syntax) {
+    private void removeSyntax(final Syntax syntax, NamesMapping names) {
         for (Map.Entry<String, List<String>> property : syntax.getExtraProperties().entrySet()) {
             if ("x-enum".equalsIgnoreCase(property.getKey())) {
                 removeMatchingRule(OMR_OID_GENERIC_ENUM + "." + syntax.getOID());
@@ -2662,14 +2703,14 @@
         numericOID2Syntaxes.remove(syntax.getOID());
     }
 
-    private void validate(final Schema schema) {
+    private void validate(final Schema schema, NamesMapping names) {
         // Verify all references in all elements
         for (final Syntax syntax : numericOID2Syntaxes.values().toArray(
                 new Syntax[numericOID2Syntaxes.values().size()])) {
             try {
                 syntax.validate(schema, warnings);
             } catch (final SchemaException e) {
-                removeSyntax(syntax);
+                removeSyntax(syntax, names);
                 warnings.add(ERR_SYNTAX_VALIDATION_FAIL
                         .get(syntax.toString(), e.getMessageObject()));
             }
@@ -2680,7 +2721,7 @@
             try {
                 rule.validate(schema, warnings);
             } catch (final SchemaException e) {
-                removeMatchingRule(rule);
+                removeMatchingRule(rule, names);
                 warnings.add(ERR_MR_VALIDATION_FAIL.get(rule.toString(), e.getMessageObject()));
             }
         }
@@ -2693,7 +2734,7 @@
         }
 
         for (final AttributeType attributeType : invalidAttributeTypes) {
-            removeAttributeType(attributeType);
+            removeAttributeType(attributeType, names);
         }
 
         // Object classes need special processing because they have hierarchical
@@ -2704,7 +2745,7 @@
         }
 
         for (final ObjectClass objectClass : invalidObjectClasses) {
-            removeObjectClass(objectClass);
+            removeObjectClass(objectClass, names);
         }
 
         for (final MatchingRuleUse use : numericOID2MatchingRuleUses.values().toArray(
@@ -2712,7 +2753,7 @@
             try {
                 use.validate(schema, warnings);
             } catch (final SchemaException e) {
-                removeMatchingRuleUse(use);
+                removeMatchingRuleUse(use, names);
                 warnings.add(ERR_MRU_VALIDATION_FAIL.get(use.toString(), e.getMessageObject()));
             }
         }
@@ -2735,7 +2776,7 @@
                     forms.add(form);
                 }
             } catch (final SchemaException e) {
-                removeNameForm(form);
+                removeNameForm(form, names);
                 warnings.add(ERR_NAMEFORM_VALIDATION_FAIL
                         .get(form.toString(), e.getMessageObject()));
             }
@@ -2746,7 +2787,7 @@
             try {
                 rule.validate(schema, warnings);
             } catch (final SchemaException e) {
-                removeDITContentRule(rule);
+                removeDITContentRule(rule, names);
                 warnings.add(ERR_DCR_VALIDATION_FAIL.get(rule.toString(), e.getMessageObject()));
             }
         }
@@ -2759,7 +2800,7 @@
         }
 
         for (final DITStructureRule rule : invalidStructureRules) {
-            removeDITStructureRule(rule);
+            removeDITStructureRule(rule, names);
         }
 
         for (final DITStructureRule rule : id2StructureRules.values()) {
@@ -2778,8 +2819,9 @@
         }
     }
 
-    private void removeDuplicateMatchingRulesNames() {
-        for (final java.util.Map.Entry<String, List<MatchingRule>> entry : name2MatchingRules.entrySet()) {
+    private Map<String, MatchingRule> removeDuplicateMatchingRulesNames() {
+        final Map<String, MatchingRule> names = newMap(name2MatchingRules.size());
+        for (final Map.Entry<String, List<MatchingRule>> entry : name2MatchingRules.entrySet()) {
             List<MatchingRule> rules = entry.getValue();
             if (rules.size() > 1) {
                 StringBuilder oids = new StringBuilder();
@@ -2791,14 +2833,17 @@
                 }
                 String name = entry.getKey();
                 warnings.add(WARN_MATCHING_RULES_DUPLICATED_NAME.get(oids, name, name, rules.get(0).getOID()));
-                // keep only the first value
-                rules.subList(1, rules.size()).clear();
+            }
+            if (!rules.isEmpty()) {
+                names.put(entry.getKey(), rules.get(0));
             }
         }
+        return names;
     }
 
-    private void removeDuplicateMatchingRuleUsesNames() {
-        for (final java.util.Map.Entry<String, List<MatchingRuleUse>> entry : name2MatchingRuleUses.entrySet()) {
+    private Map<String, MatchingRuleUse> removeDuplicateMatchingRuleUsesNames() {
+        final Map<String, MatchingRuleUse> names = newMap(name2MatchingRuleUses.size());
+        for (final Map.Entry<String, List<MatchingRuleUse>> entry : name2MatchingRuleUses.entrySet()) {
             List<MatchingRuleUse> uses = entry.getValue();
             if (uses.size() > 1) {
                 StringBuilder oids = new StringBuilder();
@@ -2811,16 +2856,19 @@
                 String name = entry.getKey();
                 warnings.add(WARN_MATCHING_RULE_USES_DUPLICATED_NAME.get(oids, name, name,
                         uses.get(0).getMatchingRuleOID()));
-                // keep only the first value
-                uses.subList(1, uses.size()).clear();
+            }
+            if (!uses.isEmpty()) {
+                names.put(entry.getKey(), uses.get(0));
             }
         }
+        return names;
     }
 
-    private void removeDuplicateAttributeTypesNames() {
-        for (final java.util.Map.Entry<String, List<AttributeType>> entry : name2AttributeTypes.entrySet()) {
+    private Map<String, AttributeType> removeDuplicateAttributeTypesNames() {
+        final Map<String, AttributeType> names = newMap(name2AttributeTypes.size());
+        for (final Map.Entry<String, List<AttributeType>> entry : name2AttributeTypes.entrySet()) {
             List<AttributeType> types = entry.getValue();
-            if (entry.getValue().size() > 1) {
+            if (types.size() > 1) {
                 StringBuilder oids = new StringBuilder();
                 for (AttributeType attr : types) {
                     if (oids.length() > 0) {
@@ -2830,16 +2878,19 @@
                 }
                 String name = entry.getKey();
                 warnings.add(WARN_ATTR_TYPES_DUPLICATED_NAME.get(oids, name, name, types.get(0).getOID()));
-                // keep only the first value
-                types.subList(1, types.size()).clear();
+            }
+            if (!types.isEmpty()) {
+                names.put(entry.getKey(), types.get(0));
             }
         }
+        return names;
     }
 
-    private void removeDuplicateObjectClassesNames() {
-        for (final java.util.Map.Entry<String, List<ObjectClass>> entry : name2ObjectClasses.entrySet()) {
+    private Map<String, ObjectClass> removeDuplicateObjectClassesNames() {
+        final Map<String, ObjectClass> names = newMap(name2ObjectClasses.size());
+        for (final Map.Entry<String, List<ObjectClass>> entry : name2ObjectClasses.entrySet()) {
             List<ObjectClass> classes = entry.getValue();
-            if (entry.getValue().size() > 1) {
+            if (classes.size() > 1) {
                 StringBuilder oids = new StringBuilder();
                 for (ObjectClass attr : classes) {
                     if (oids.length() > 0) {
@@ -2849,16 +2900,19 @@
                 }
                 String name = entry.getKey();
                 warnings.add(WARN_CLASSES_DUPLICATED_NAME.get(oids, name, name, classes.get(0).getOID()));
-                // keep only the first value
-                classes.subList(1, classes.size()).clear();
+            }
+            if (!classes.isEmpty()) {
+                names.put(entry.getKey(), classes.get(0));
             }
         }
+        return names;
     }
 
-    private void removeDuplicateNameFormsNames() {
-        for (final java.util.Map.Entry<String, List<NameForm>> entry : name2NameForms.entrySet()) {
+    private Map<String, NameForm> removeDuplicateNameFormsNames() {
+        final Map<String, NameForm> names = newMap(name2NameForms.size());
+        for (final Map.Entry<String, List<NameForm>> entry : name2NameForms.entrySet()) {
             List<NameForm> forms = entry.getValue();
-            if (entry.getValue().size() > 1) {
+            if (forms.size() > 1) {
                 StringBuilder oids = new StringBuilder();
                 for (NameForm attr : forms) {
                     if (oids.length() > 0) {
@@ -2868,16 +2922,19 @@
                 }
                 String name = entry.getKey();
                 warnings.add(WARN_NAME_FORMS_DUPLICATED_NAME.get(oids, name, name, forms.get(0).getOID()));
-                // keep only the first value
-                forms.subList(1, forms.size()).clear();
+            }
+            if (!forms.isEmpty()) {
+                names.put(entry.getKey(), forms.get(0));
             }
         }
+        return names;
     }
 
-    private void removeDuplicateDITStructureRulesNames() {
-        for (final java.util.Map.Entry<String, List<DITStructureRule>> entry : name2StructureRules.entrySet()) {
+    private Map<String, DITStructureRule> removeDuplicateDITStructureRulesNames() {
+        final Map<String, DITStructureRule> names = newMap(name2StructureRules.size());
+        for (final Map.Entry<String, List<DITStructureRule>> entry : name2StructureRules.entrySet()) {
             List<DITStructureRule> rules = entry.getValue();
-            if (entry.getValue().size() > 1) {
+            if (rules.size() > 1) {
                 StringBuilder ids = new StringBuilder();
                 for (DITStructureRule attr : rules) {
                     if (ids.length() > 0) {
@@ -2887,16 +2944,19 @@
                 }
                 String name = entry.getKey();
                 warnings.add(WARN_DIT_SR_DUPLICATED_NAME.get(ids, name, name, rules.get(0).getRuleID()));
-                // keep only the first value
-                rules.subList(1, rules.size()).clear();
+            }
+            if (!rules.isEmpty()) {
+                names.put(entry.getKey(), rules.get(0));
             }
         }
+        return names;
     }
 
-    private void removeDuplicateDITContentRulesNames() {
-        for (final java.util.Map.Entry<String, List<DITContentRule>> entry : name2ContentRules.entrySet()) {
+    private Map<String, DITContentRule> removeDuplicateDITContentRulesNames() {
+        final Map<String, DITContentRule> names = newMap(name2ContentRules.size());
+        for (final Map.Entry<String, List<DITContentRule>> entry : name2ContentRules.entrySet()) {
             List<DITContentRule> rules = entry.getValue();
-            if (entry.getValue().size() > 1) {
+            if (rules.size() > 1) {
                 StringBuilder ids = new StringBuilder();
                 for (DITContentRule attr : rules) {
                     if (ids.length() > 0) {
@@ -2906,9 +2966,15 @@
                 }
                 String name = entry.getKey();
                 warnings.add(WARN_DIT_CR_DUPLICATED_NAME.get(ids, name, name, rules.get(0).getStructuralClassOID()));
-                // keep only the first value
-                rules.subList(1, rules.size()).clear();
+            }
+            if (!rules.isEmpty()) {
+                names.put(entry.getKey(), rules.get(0));
             }
         }
+        return names;
+    }
+
+    private <T extends SchemaElement> Map<String, T> newMap(int size) {
+        return new HashMap<String, T>((int) ((size) / 0.75 + 1));
     }
 }

--
Gitblit v1.10.0