From 026e3e427926d1de7ff1e6697c4c9634b6b80cd1 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Tue, 26 Apr 2016 13:01:17 +0000
Subject: [PATCH] OPENDJ-2797 Switch server classes to SDK MatchingRuleUse class

---
 opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java           |   20 +
 opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java         |  141 +++++++---------
 opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java             |    6 
 opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java          |    5 
 opendj-server-legacy/src/main/java/org/opends/server/core/MatchingRuleConfigManager.java |    8 
 opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java                   |  198 ++++++++++++++++--------
 opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java       |   33 ---
 opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java |   14 
 opendj-server-legacy/src/messages/org/opends/messages/schema.properties                  |    2 
 9 files changed, 225 insertions(+), 202 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
index a8b82a9..cef2067 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
@@ -64,6 +64,7 @@
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.CoreSchema;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
+import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
 import org.forgerock.opendj.ldap.schema.ObjectClassType;
 import org.forgerock.opendj.server.config.server.SchemaBackendCfg;
 import org.opends.server.api.AlertGenerator;
@@ -82,9 +83,9 @@
 import org.opends.server.schema.DITContentRuleSyntax;
 import org.opends.server.schema.DITStructureRuleSyntax;
 import org.opends.server.schema.GeneralizedTimeSyntax;
-import org.opends.server.schema.MatchingRuleUseSyntax;
 import org.opends.server.schema.NameFormSyntax;
 import org.opends.server.schema.ObjectClassSyntax;
+import org.opends.server.schema.ServerSchemaElement;
 import org.opends.server.schema.SomeSchemaElement;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeBuilder;
@@ -103,7 +104,6 @@
 import org.opends.server.types.LDIFExportConfig;
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.LDIFImportResult;
-import org.opends.server.types.MatchingRuleUse;
 import org.opends.server.types.Modification;
 import org.opends.server.types.NameForm;
 import org.opends.server.types.ObjectClass;
@@ -593,7 +593,7 @@
         operationalAttrs, ditContentRulesType, includeSchemaFile, false, true);
     buildSchemaAttribute(schema.getDITStructureRulesByID().values(), userAttrs,
         operationalAttrs, ditStructureRulesType, includeSchemaFile, false, true);
-    buildSchemaAttribute(schema.getMatchingRuleUses().values(), userAttrs,
+    buildSchemaAttribute(schema.getMatchingRuleUses(), userAttrs,
         operationalAttrs, matchingRuleUsesType, includeSchemaFile, false, true);
 
     // Add the lastmod attributes.
@@ -856,21 +856,7 @@
           {
             for (ByteString v : a)
             {
-              MatchingRuleUse mru;
-              try
-              {
-                mru = MatchingRuleUseSyntax.decodeMatchingRuleUse(v, newSchema, false);
-              }
-              catch (DirectoryException de)
-              {
-                logger.traceException(de);
-
-                LocalizableMessage message = ERR_SCHEMA_MODIFY_CANNOT_DECODE_MR_USE.get(
-                    v, de.getMessageObject());
-                throw new DirectoryException(
-                    ResultCode.INVALID_ATTRIBUTE_SYNTAX, message, de);
-              }
-
+              MatchingRuleUse mru = newSchema.parseMatchingRuleUse(v.toString());
               addMatchingRuleUse(mru, newSchema, modifiedSchemaFiles);
             }
           }
@@ -1009,21 +995,7 @@
           {
             for (ByteString v : a)
             {
-              MatchingRuleUse mru;
-              try
-              {
-                mru = MatchingRuleUseSyntax.decodeMatchingRuleUse(v, newSchema, false);
-              }
-              catch (DirectoryException de)
-              {
-                logger.traceException(de);
-
-                LocalizableMessage message = ERR_SCHEMA_MODIFY_CANNOT_DECODE_MR_USE.get(
-                    v, de.getMessageObject());
-                throw new DirectoryException(
-                    ResultCode.INVALID_ATTRIBUTE_SYNTAX, message, de);
-              }
-
+              MatchingRuleUse mru = newSchema.parseMatchingRuleUse(v.toString());
               removeMatchingRuleUse(mru, newSchema, modifiedSchemaFiles);
             }
           }
@@ -1261,6 +1233,18 @@
     return schemaFile == null ? finalFile : null;
   }
 
+  /**
+   * Update list of modified files and return the schema file to use for the
+   * added element (may be null).
+   */
+  private String addNewSchemaElement(Set<String> modifiedSchemaFiles, ServerSchemaElement elem)
+  {
+    String schemaFile = elem.getSchemaFile();
+    String finalFile = schemaFile != null ? schemaFile : FILE_USER_SCHEMA_ELEMENTS;
+    modifiedSchemaFiles.add(finalFile);
+    return schemaFile == null ? finalFile : null;
+  }
+
   private <T extends SchemaFileElement> void replaceExistingSchemaElement(
       Set<String> modifiedSchemaFiles, T newElem, T existingElem)
   {
@@ -1315,6 +1299,36 @@
   }
 
   /**
+   * Update list of modified files and return the schema file to use for the new
+   * element (may be null).
+   */
+  private String replaceExistingSchemaElement(Set<String> modifiedSchemaFiles, ServerSchemaElement newElem,
+      ServerSchemaElement existingElem)
+  {
+    String newSchemaFile = newElem.getSchemaFile();
+    String oldSchemaFile = existingElem.getSchemaFile();
+    if (newSchemaFile == null)
+    {
+      if (oldSchemaFile == null)
+      {
+        oldSchemaFile = FILE_USER_SCHEMA_ELEMENTS;
+      }
+      modifiedSchemaFiles.add(oldSchemaFile);
+      return oldSchemaFile;
+    }
+    else if (oldSchemaFile == null || oldSchemaFile.equals(newSchemaFile))
+    {
+      modifiedSchemaFiles.add(newSchemaFile);
+    }
+    else
+    {
+      modifiedSchemaFiles.add(newSchemaFile);
+      modifiedSchemaFiles.add(oldSchemaFile);
+    }
+    return null;
+  }
+
+  /**
    * Handles all processing required to remove the provided attribute type from
    * the server schema, ensuring all other metadata is properly updated.  Note
    * that this method will first check to see whether the same attribute type
@@ -1412,9 +1426,8 @@
       }
     }
 
-    // Make sure that the attribute type isn't referenced by any matching rule
-    // use.
-    for (MatchingRuleUse mru : schema.getMatchingRuleUses().values())
+    // Make sure that the attribute type isn't referenced by any matching rule use.
+    for (MatchingRuleUse mru : schema.getMatchingRuleUses())
     {
       if (mru.getAttributes().contains(removeType))
       {
@@ -2391,9 +2404,9 @@
     // be more than one match (although if there is, then we'll refuse the
     // operation).
     MatchingRuleUse existingMRU = null;
-    for (MatchingRuleUse mru : schema.getMatchingRuleUses().values())
+    for (MatchingRuleUse mru : schema.getMatchingRuleUses())
     {
-      for (String name : matchingRuleUse.getNames().keySet())
+      for (String name : matchingRuleUse.getNames())
       {
         if (mru.hasName(name))
         {
@@ -2402,36 +2415,15 @@
             existingMRU = mru;
             break;
           }
-          else
-          {
-            LocalizableMessage message =
-                    ERR_SCHEMA_MODIFY_MULTIPLE_CONFLICTS_FOR_ADD_MR_USE.get(
-                            matchingRuleUse.getNameOrOID(),
-                            existingMRU.getNameOrOID(),
-                            mru.getNameOrOID());
-            throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
-                                         message);
-          }
+          LocalizableMessage message = ERR_SCHEMA_MODIFY_MULTIPLE_CONFLICTS_FOR_ADD_MR_USE.get(
+              matchingRuleUse.getNameOrOID(), existingMRU.getNameOrOID(), mru.getNameOrOID());
+          throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
         }
       }
     }
 
-    // Get the matching rule for the new matching rule use and see if there's
-    // already an existing matching rule use that is associated with that
-    // matching rule.  If there is, then it will only be acceptable if it's the
-    // matching rule use that we are replacing (in which case we really do want
-    // to use the "!=" operator).
+    // Obsolete matching rule and attribute types are not checked by the SDK
     MatchingRule matchingRule = matchingRuleUse.getMatchingRule();
-    MatchingRuleUse existingMRUForRule =
-         schema.getMatchingRuleUse(matchingRule);
-    if (existingMRUForRule != null && existingMRUForRule != existingMRU)
-    {
-      LocalizableMessage message = ERR_SCHEMA_MODIFY_MR_CONFLICT_FOR_ADD_MR_USE.
-          get(matchingRuleUse.getNameOrOID(), matchingRule.getNameOrOID(),
-              existingMRUForRule.getNameOrOID());
-      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
-    }
-
     if (matchingRule.isObsolete())
     {
       LocalizableMessage message = ERR_SCHEMA_MODIFY_MRU_OBSOLETE_MR.get(
@@ -2439,17 +2431,9 @@
       throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
     }
 
-    // Make sure that the new matching rule use doesn't reference an undefined
-    // attribute type.
     for (AttributeType at : matchingRuleUse.getAttributes())
     {
-      if (! schema.hasAttributeType(at.getOID()))
-      {
-        LocalizableMessage message = ERR_SCHEMA_MODIFY_MRU_UNDEFINED_ATTR.get(
-            matchingRuleUse.getNameOrOID(), at.getNameOrOID());
-        throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
-      }
-      else if (at.isObsolete())
+      if (at.isObsolete())
       {
         LocalizableMessage message = ERR_SCHEMA_MODIFY_MRU_OBSOLETE_ATTR.get(
             matchingRuleUse.getNameOrOID(), matchingRule.getNameOrOID());
@@ -2462,15 +2446,14 @@
     if (existingMRU == null)
     {
       schema.registerMatchingRuleUse(matchingRuleUse, false);
-      addNewSchemaElement(modifiedSchemaFiles, matchingRuleUse);
+      addNewSchemaElement(modifiedSchemaFiles, new ServerSchemaElement(matchingRuleUse));
     }
     else
     {
       schema.deregisterMatchingRuleUse(existingMRU);
       schema.registerMatchingRuleUse(matchingRuleUse, false);
-      schema.rebuildDependentElements(existingMRU);
-      replaceExistingSchemaElement(modifiedSchemaFiles, matchingRuleUse,
-          existingMRU);
+      replaceExistingSchemaElement(modifiedSchemaFiles, new ServerSchemaElement(matchingRuleUse),
+          new ServerSchemaElement(existingMRU));
     }
   }
 
@@ -2517,7 +2500,7 @@
     // just remove the DIT content rule now, and if it is added back later then
     // there still won't be any conflict.
     schema.deregisterMatchingRuleUse(removeMRU);
-    String schemaFile = getSchemaFile(removeMRU);
+    String schemaFile = new ServerSchemaElement(removeMRU).getSchemaFile();
     if (schemaFile != null)
     {
       modifiedSchemaFiles.add(schemaFile);
@@ -2798,9 +2781,9 @@
     // there is no hierarchical relationship between matching rule uses, we
     // don't need to worry about ordering.
     values = new LinkedHashSet<>();
-    for (MatchingRuleUse mru : schema.getMatchingRuleUses().values())
+    for (MatchingRuleUse mru : schema.getMatchingRuleUses())
     {
-      if (schemaFile.equals(getSchemaFile(mru)))
+      if (schemaFile.equals(new ServerSchemaElement(mru).getSchemaFile()))
       {
         values.add(ByteString.valueOfUtf8(mru.toString()));
       }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
index 9a84ed4..af36ec0 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -17,7 +17,6 @@
 package org.opends.server.core;
 
 import static com.forgerock.opendj.cli.CommonArguments.*;
-
 import static org.forgerock.util.Reject.*;
 import static org.opends.messages.CoreMessages.*;
 import static org.opends.messages.ToolMessages.*;
@@ -75,6 +74,7 @@
 import org.forgerock.opendj.ldap.schema.MatchingRule;
 import org.forgerock.opendj.ldap.schema.ObjectClassType;
 import org.forgerock.opendj.ldap.schema.Syntax;
+import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException;
 import org.forgerock.opendj.server.config.server.AlertHandlerCfg;
 import org.forgerock.opendj.server.config.server.ConnectionHandlerCfg;
 import org.forgerock.opendj.server.config.server.CryptoManagerCfg;
@@ -155,7 +155,7 @@
 import org.opends.server.types.LDIFExportConfig;
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.LockManager;
-import org.opends.server.types.MatchingRuleUse;
+import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
 import org.opends.server.types.Modification;
 import org.opends.server.types.NameForm;
 import org.opends.server.types.ObjectClass;
@@ -2685,8 +2685,7 @@
    *
    * @return  The set of matching rule uses defined in the Directory Server.
    */
-  public static ConcurrentMap<MatchingRule, MatchingRuleUse>
-                     getMatchingRuleUses()
+  public static Collection<MatchingRuleUse> getMatchingRuleUses()
   {
     return directoryServer.schema.getMatchingRuleUses();
   }
@@ -2702,7 +2701,14 @@
    */
   public static MatchingRuleUse getMatchingRuleUse(MatchingRule matchingRule)
   {
-    return directoryServer.schema.getMatchingRuleUse(matchingRule);
+    try
+    {
+      return directoryServer.schema.getMatchingRuleUse(matchingRule);
+    }
+    catch (UnknownSchemaElementException e)
+    {
+      return null;
+    }
   }
 
   /**
@@ -2732,8 +2738,10 @@
    *
    * @param  matchingRuleUse  The matching rule use to deregister with the
    *                          server.
+   * @throws DirectoryException
+   *            If the resulting schema contains warning.
    */
-  public static void deregisterMatchingRuleUse(MatchingRuleUse matchingRuleUse)
+  public static void deregisterMatchingRuleUse(MatchingRuleUse matchingRuleUse) throws DirectoryException
   {
     directoryServer.schema.deregisterMatchingRuleUse(matchingRuleUse);
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/MatchingRuleConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/MatchingRuleConfigManager.java
index 9818288..2399771 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/MatchingRuleConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/MatchingRuleConfigManager.java
@@ -42,7 +42,7 @@
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.InitializationException;
-import org.opends.server.types.MatchingRuleUse;
+import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
 
 /**
  * This class defines a utility that will be used to manage the set of matching
@@ -222,8 +222,7 @@
         }
 
         final String oid = matchingRule.getOID();
-        for (MatchingRuleUse mru :
-                DirectoryServer.getMatchingRuleUses().values())
+        for (MatchingRuleUse mru : DirectoryServer.getMatchingRuleUses())
         {
           if (oid.equals(mru.getMatchingRule().getOID()))
           {
@@ -327,8 +326,7 @@
           }
 
           final String oid = matchingRule.getOID();
-          for (MatchingRuleUse mru :
-               DirectoryServer.getMatchingRuleUses().values())
+          for (MatchingRuleUse mru : DirectoryServer.getMatchingRuleUses())
           {
             if (oid.equals(mru.getMatchingRule().getOID()))
             {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
index 27196e1..b37f141 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
@@ -34,7 +34,6 @@
 import org.forgerock.opendj.ldap.schema.Syntax;
 import org.opends.server.schema.DITContentRuleSyntax;
 import org.opends.server.schema.DITStructureRuleSyntax;
-import org.opends.server.schema.MatchingRuleUseSyntax;
 import org.opends.server.schema.NameFormSyntax;
 import org.opends.server.schema.ObjectClassSyntax;
 import org.opends.server.types.Attribute;
@@ -44,7 +43,6 @@
 import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.LDIFImportConfig;
-import org.opends.server.types.MatchingRuleUse;
 import org.opends.server.types.Modification;
 import org.opends.server.types.NameForm;
 import org.opends.server.types.ObjectClass;
@@ -952,39 +950,12 @@
       {
         for (ByteString v : a)
         {
-          // Parse the matching rule use definition.
-          MatchingRuleUse mru;
-          try
-          {
-            mru = MatchingRuleUseSyntax.decodeMatchingRuleUse(v, schema, false);
-            mru.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME);
-            setSchemaFile(mru, schemaFile);
-          }
-          catch (DirectoryException de)
-          {
-            logger.traceException(de);
-
-            LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_MRU.get(
-                    schemaFile, de.getMessageObject());
-            reportError(failOnError, de, message);
-            continue;
-          }
-          catch (Exception e)
-          {
-            logger.traceException(e);
-
-            LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_MRU.get(
-                    schemaFile, v + ":  " + getExceptionMessage(e));
-            reportError(failOnError, e, message);
-            continue;
-          }
-
           // Register it with the schema.  We will allow duplicates, with the
           // later definition overriding any earlier definition, but we want
           // to trap them and log a warning.
           try
           {
-            schema.registerMatchingRuleUse(mru, failOnError);
+            schema.registerMatchingRuleUse(v.toString(), schemaFile, failOnError);
           }
           catch (DirectoryException de)
           {
@@ -994,7 +965,7 @@
 
             try
             {
-              schema.registerMatchingRuleUse(mru, true);
+              schema.registerMatchingRuleUse(v.toString(), schemaFile, true);
             }
             catch (Exception e)
             {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java b/opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java
index b3e69f6..f7a94e1 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java
@@ -18,7 +18,6 @@
 
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import org.forgerock.i18n.LocalizableMessage;
@@ -26,6 +25,7 @@
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
+import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
 import org.forgerock.opendj.ldap.schema.Syntax;
 import org.opends.server.api.AlertGenerator;
 import org.opends.server.api.ExtendedOperationHandler;
@@ -365,8 +365,7 @@
    * @return  The set of matching rule uses defined in the Directory
    *          Server.
    */
-  public static Map<MatchingRule,MatchingRuleUse>
-       getMatchingRuleUses()
+  public static Collection<MatchingRuleUse> getMatchingRuleUses()
   {
     return DirectoryServer.getMatchingRuleUses();
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
index 60c7bf0..fe9812b 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
@@ -16,6 +16,8 @@
  */
 package org.opends.server.types;
 
+import static org.opends.messages.SchemaMessages.ERR_ATTR_SYNTAX_MRUSE_EMPTY_VALUE;
+
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
@@ -51,7 +53,10 @@
 import org.forgerock.opendj.ldap.schema.ConflictingSchemaElementException;
 import org.forgerock.opendj.ldap.schema.CoreSchema;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
+import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
+import org.forgerock.opendj.ldap.schema.MatchingRuleUse.Builder;
 import org.forgerock.opendj.ldap.schema.SchemaBuilder;
+import org.forgerock.opendj.ldap.schema.SchemaElement;
 import org.forgerock.opendj.ldap.schema.Syntax;
 import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException;
 import org.forgerock.util.Option;
@@ -60,7 +65,6 @@
 import org.opends.server.core.SchemaConfigManager;
 import org.opends.server.schema.DITContentRuleSyntax;
 import org.opends.server.schema.DITStructureRuleSyntax;
-import org.opends.server.schema.MatchingRuleUseSyntax;
 import org.opends.server.schema.NameFormSyntax;
 import org.opends.server.schema.ObjectClassSyntax;
 import org.opends.server.schema.SomeSchemaElement;
@@ -116,13 +120,6 @@
   private ConcurrentHashMap<String,ObjectClass> objectClasses;
 
   /**
-   * The set of matching rule uses for this schema, mapped between the matching
-   * rule for the definition and the matching rule use itself.
-   */
-  private ConcurrentHashMap<MatchingRule,MatchingRuleUse>
-               matchingRuleUses;
-
-  /**
    * The set of DIT content rules for this schema, mapped between the structural
    * objectclass for the definition and the DIT content rule itself.
    */
@@ -202,7 +199,6 @@
     switchSchema(schemaNG);
 
     objectClasses = new ConcurrentHashMap<String,ObjectClass>();
-    matchingRuleUses = new ConcurrentHashMap<MatchingRule,MatchingRuleUse>();
     ditContentRules = new ConcurrentHashMap<ObjectClass,DITContentRule>();
     ditStructureRulesByID = new ConcurrentHashMap<Integer,DITStructureRule>();
     ditStructureRulesByNameForm = new ConcurrentHashMap<NameForm,DITStructureRule>();
@@ -322,6 +318,36 @@
   }
 
   /**
+   * Parses a matching rule use from its provided definition.
+   *
+   * @param definition
+   *          The definition of the matching rule use
+   * @return the matching rule use
+   * @throws DirectoryException
+   *            If an error occurs
+   */
+  public MatchingRuleUse parseMatchingRuleUse(final String definition) throws DirectoryException
+  {
+    try
+    {
+      SchemaBuilder builder = new SchemaBuilder(schemaNG);
+      builder.addMatchingRuleUse(definition, true);
+      org.forgerock.opendj.ldap.schema.Schema newSchema = builder.toSchema();
+      rejectSchemaWithWarnings(newSchema);
+      return newSchema.getMatchingRuleUse(parseMatchingRuleUseOID(definition));
+    }
+    catch (UnknownSchemaElementException e)
+    {
+      LocalizableMessage msg = ERR_MATCHING_RULE_USE_CANNOT_REGISTER.get(definition);
+      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, msg, e);
+    }
+    catch (LocalizedIllegalArgumentException e)
+    {
+      throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, e.getMessageObject(), e);
+    }
+  }
+
+  /**
    * Registers a list of attribute types from their provided definitions.
    * <p>
    * This method allows to do only one schema change for multiple definitions,
@@ -346,8 +372,7 @@
       SchemaBuilder builder = new SchemaBuilder(schemaNG);
       for (String definition : definitions)
       {
-        String defWithFile = schemaFile != null ?
-            addSchemaFileToElementDefinitionIfAbsent(definition, schemaFile) : definition;
+        String defWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
         builder.addAttributeType(defWithFile, overwrite);
       }
       switchSchema(builder.toSchema());
@@ -464,14 +489,19 @@
     return parseOID(definition, ResultCode.INVALID_ATTRIBUTE_SYNTAX, ERR_ATTR_SYNTAX_ATTRTYPE_EMPTY_VALUE);
   }
 
+  private String parseMatchingRuleUseOID(String definition) throws DirectoryException
+  {
+    return parseOID(definition, ResultCode.INVALID_ATTRIBUTE_SYNTAX, ERR_ATTR_SYNTAX_MRUSE_EMPTY_VALUE);
+  }
+
   /**
-   * Returns the OID from the provided attribute type definition, assuming the
+   * Returns the OID from the provided schema element definition, assuming the
    * definition is valid.
    * <p>
    * This method does not perform any check.
    *
    * @param definition
-   *          The definition, assumed to be valid
+   *          The definition of a schema element, assumed to be valid
    * @param parsingErrorResultCode the result code to use if a problem occurs while parsing the definition
    * @param parsingErrorMsg the message to use if a problem occurs while parsing the definition
    * @return the OID, which is never {@code null}
@@ -1039,7 +1069,18 @@
     return schemaNG.hasMatchingRule(nameOrOid);
   }
 
-
+  /**
+   * Indicates whether this schema definition includes a matching rule use
+   * with the provided name or OID.
+   *
+   * @param  nameOrOid  The name or OID for which to make the determination, ignoring case considerations
+   * @return  {@code true} if this schema contains a matching rule use
+   *          with the provided name or OID, or {@code false} if not.
+   */
+  public boolean hasMatchingRuleUse(String nameOrOid)
+  {
+    return schemaNG.hasMatchingRuleUse(nameOrOid);
+  }
 
   /**
    * Retrieves the matching rule definition with the specified name or OID.
@@ -1120,7 +1161,7 @@
    * @param matchingRule
    *          The matching rule to deregister with this schema.
    * @throws DirectoryException
-   *           If the matching rule is referenced by another schema element.
+   *           If the schema has constraints violations.
    */
   public void deregisterMatchingRule(final MatchingRule matchingRule) throws DirectoryException
   {
@@ -1148,10 +1189,9 @@
    *
    * @return  The matching rule use definitions for this schema.
    */
-  public ConcurrentHashMap<MatchingRule,MatchingRuleUse>
-              getMatchingRuleUses()
+  public Collection<MatchingRuleUse> getMatchingRuleUses()
   {
-    return matchingRuleUses;
+    return schemaNG.getMatchingRuleUses();
   }
 
 
@@ -1168,7 +1208,7 @@
    */
   public MatchingRuleUse getMatchingRuleUse(MatchingRule matchingRule)
   {
-    return matchingRuleUses.get(matchingRule);
+    return schemaNG.getMatchingRuleUse(matchingRule);
   }
 
 
@@ -1188,46 +1228,87 @@
    *                              <CODE>overwriteExisting</CODE> flag
    *                              is set to <CODE>false</CODE>
    */
-  public void registerMatchingRuleUse(MatchingRuleUse matchingRuleUse,
-                                      boolean overwriteExisting)
+  public void registerMatchingRuleUse(MatchingRuleUse matchingRuleUse, boolean overwriteExisting)
          throws DirectoryException
   {
-    synchronized (matchingRuleUses)
+    exclusiveLock.lock();
+    try
     {
-      MatchingRule matchingRule = matchingRuleUse.getMatchingRule();
-
-      if (!overwriteExisting && matchingRuleUses.containsKey(matchingRule))
+      SchemaBuilder builder = new SchemaBuilder(schemaNG);
+      Builder mruBuilder = builder.buildMatchingRuleUse(matchingRuleUse);
+      if (overwriteExisting)
       {
-        MatchingRuleUse conflictingUse = matchingRuleUses.get(matchingRule);
-
-        LocalizableMessage message = ERR_SCHEMA_CONFLICTING_MATCHING_RULE_USE.
-            get(matchingRuleUse.getNameOrOID(),
-                matchingRule.getNameOrOID(),
-                conflictingUse.getNameOrOID());
-        throw new DirectoryException(
-                       ResultCode.CONSTRAINT_VIOLATION, message);
+        mruBuilder.addToSchemaOverwrite();
       }
-
-      matchingRuleUses.put(matchingRule, matchingRuleUse);
+      else
+      {
+        mruBuilder.addToSchema();
+      }
+      switchSchema(builder.toSchema());
+    }
+    finally
+    {
+      exclusiveLock.unlock();
     }
   }
 
+  /**
+   * Registers the provided matching rule use definition with this schema.
+   *
+   * @param definition
+   *          The matching rule use definition to register.
+   * @param schemaFile
+   *          The schema file where this definition belongs, maybe {@code null}
+   * @param overwriteExisting
+   *          Indicates whether to overwrite an existing mapping if there are any conflicts (i.e.,
+   *          another matching rule use with the same matching rule).
+   * @throws DirectoryException
+   *           If a conflict is encountered and the <CODE>overwriteExisting</CODE> flag is set to
+   *           <CODE>false</CODE>
+   */
+  public void registerMatchingRuleUse(String definition, String schemaFile, boolean overwriteExisting)
+      throws DirectoryException
+  {
+    exclusiveLock.lock();
+    try
+    {
+      String definitionWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
+      switchSchema(new SchemaBuilder(schemaNG)
+        .addMatchingRuleUse(definitionWithFile, overwriteExisting)
+        .toSchema());
+    }
+    finally
+    {
+      exclusiveLock.unlock();
+    }
+  }
 
+  private String getDefinitionWithSchemaFile(String definition, String schemaFile)
+  {
+    return schemaFile != null ? addSchemaFileToElementDefinitionIfAbsent(definition, schemaFile) : definition;
+  }
 
   /**
-   * Deregisters the provided matching rule use definition with this
-   * schema.
+   * Deregisters the provided matching rule use definition with this schema.
    *
-   * @param  matchingRuleUse  The matching rule use to deregister with
-   *                          this schema.
+   * @param matchingRuleUse
+   *          The matching rule use to deregister with this schema.
+   * @throws DirectoryException
+   *            If the schema has constraints violations.
    */
-  public void deregisterMatchingRuleUse(
-                   MatchingRuleUse matchingRuleUse)
+  public void deregisterMatchingRuleUse(org.forgerock.opendj.ldap.schema.MatchingRuleUse matchingRuleUse)
+      throws DirectoryException
   {
-    synchronized (matchingRuleUses)
+    exclusiveLock.lock();
+    try
     {
-      matchingRuleUses.remove(matchingRuleUse.getMatchingRule(),
-                              matchingRuleUse);
+      SchemaBuilder builder = new SchemaBuilder(schemaNG);
+      builder.removeMatchingRuleUse(matchingRuleUse.getNameOrOID());
+      switchSchema(builder.toSchema());
+    }
+    finally
+    {
+      exclusiveLock.unlock();
     }
   }
 
@@ -1886,13 +1967,12 @@
       }
     }
 
-    for (MatchingRuleUse mru : matchingRuleUses.values())
+    for (MatchingRuleUse mru : schemaNG.getMatchingRuleUses())
     {
       if (mru.getAttributes().contains(type))
       {
-        MatchingRuleUse newMRU = recreateFromDefinition(mru);
         deregisterMatchingRuleUse(mru);
-        registerMatchingRuleUse(newMRU, true);
+        registerMatchingRuleUse(mru.toString(), getSchemaFileName(mru), true);
       }
     }
   }
@@ -1965,9 +2045,9 @@
     }
   }
 
-  private String getSchemaFileName(AttributeType attributeType)
+  private String getSchemaFileName(SchemaElement element)
   {
-    List<String> values = attributeType.getExtraProperties().get(ServerConstants.SCHEMA_PROPERTY_FILENAME);
+    List<String> values = element.getExtraProperties().get(ServerConstants.SCHEMA_PROPERTY_FILENAME);
     return values != null && ! values.isEmpty() ? values.get(0) : null;
   }
 
@@ -1991,16 +2071,6 @@
     return copy;
   }
 
-  private MatchingRuleUse recreateFromDefinition(MatchingRuleUse mru)
-      throws DirectoryException
-  {
-    ByteString value = ByteString.valueOfUtf8(mru.toString());
-    MatchingRuleUse copy =
-        MatchingRuleUseSyntax.decodeMatchingRuleUse(value, this, false);
-    setSchemaFile(copy, getSchemaFile(mru));
-    return copy;
-  }
-
   private NameForm recreateFromDefinition(NameForm nf)
       throws DirectoryException
   {
@@ -2040,11 +2110,9 @@
 
     dupSchema.subordinateTypes.putAll(subordinateTypes);
     dupSchema.objectClasses.putAll(objectClasses);
-    dupSchema.matchingRuleUses.putAll(matchingRuleUses);
     dupSchema.ditContentRules.putAll(ditContentRules);
     dupSchema.ditStructureRulesByID.putAll(ditStructureRulesByID);
-    dupSchema.ditStructureRulesByNameForm.putAll(
-         ditStructureRulesByNameForm);
+    dupSchema.ditStructureRulesByNameForm.putAll(ditStructureRulesByNameForm);
     dupSchema.nameFormsByOC.putAll(nameFormsByOC);
     dupSchema.nameFormsByName.putAll(nameFormsByName);
     dupSchema.ldapSyntaxDescriptions.putAll(ldapSyntaxDescriptions);
@@ -2493,12 +2561,6 @@
       ditStructureRulesByNameForm = null;
     }
 
-    if (matchingRuleUses != null)
-    {
-      matchingRuleUses.clear();
-      matchingRuleUses = null;
-    }
-
     if (nameFormsByName != null)
     {
       nameFormsByName.clear();
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java b/opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java
index abb1966..a6435d3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java
@@ -42,6 +42,7 @@
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
+import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
 import org.opends.server.core.DirectoryServer;
 
 /**
@@ -3224,9 +3225,8 @@
     // determine if it allows that attribute type.
     if (attributeType != null)
     {
-      MatchingRuleUse mru =
-           DirectoryServer.getMatchingRuleUse(matchingRule);
-      if (mru != null && !mru.appliesToAttribute(attributeType))
+      MatchingRuleUse mru = DirectoryServer.getMatchingRuleUse(matchingRule);
+      if (mru != null && !mru.hasAttribute(attributeType))
       {
         if (logger.isTraceEnabled())
         {
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/schema.properties b/opendj-server-legacy/src/messages/org/opends/messages/schema.properties
index 5ca96f5..1ba08c8 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/schema.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/schema.properties
@@ -498,3 +498,5 @@
 ERR_ATTR_TYPE_CANNOT_REGISTER_340=Attribute type could not be registered from definition: %s
 ERR_SCHEMA_HAS_WARNINGS_341=There should be no warnings on the schema, \
  but instead got %d warnings: %s
+ERR_MATCHING_RULE_USE_CANNOT_REGISTER_342=Matching rule use could not be \
+ registered from definition: %s
\ No newline at end of file
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
index f88b042..6d12435 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
@@ -28,6 +28,7 @@
 import java.io.File;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -60,7 +61,7 @@
 import org.opends.server.types.LDIFExportConfig;
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.LDIFImportResult;
-import org.opends.server.types.MatchingRuleUse;
+import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
 import org.opends.server.types.ObjectClass;
 import org.opends.server.types.SearchFilter;
 import org.opends.server.util.CollectionUtils;
@@ -3845,7 +3846,10 @@
 
   private void assertSchemaDoesNotHaveMatchingRuleUse(MatchingRule matchingRule)
   {
-    assertFalse(DirectoryServer.getSchema().getMatchingRuleUses().containsKey(matchingRule));
+    for (MatchingRuleUse matchingRuleUse : DirectoryServer.getSchema().getMatchingRuleUses())
+    {
+      assertFalse(matchingRuleUse.getMatchingRule().equals(matchingRule));
+    }
   }
 
   /**
@@ -3958,12 +3962,8 @@
               "X-ORIGIN 'SchemaBackendTestCase' )");
 
     assertSchemaDoesNotHaveMatchingRuleUse(matchingRule);
-
     assertEquals(runModify(argsNotPermissive(), ldif, System.err), 0);
-
-    MatchingRuleUse mru =
-         DirectoryServer.getSchema().getMatchingRuleUse(matchingRule);
-    assertNull(mru);
+    assertSchemaDoesNotHaveMatchingRuleUse(matchingRule);
   }
 
   /**

--
Gitblit v1.10.0