From a1d57e5fa800648c2308a3daf2ea528a1504c646 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Thu, 11 Jan 2007 20:17:46 +0000
Subject: [PATCH] Update the attribute type syntax so that it is possible to specify an approximate matching rule for that attribute type using the X-APPROX extension. This will be more standards-compliant than the way we were previously handling it, by using an APPROX keyword (which was not in-line with the LDAP specification).

---
 opends/src/server/org/opends/server/schema/AttributeTypeSyntax.java                                        |   50 +++++-----
 opends/tests/unit-tests-testng/src/server/org/opends/server/schema/EqualLengthApproximateMatchingRule.java |  170 ++++++++++++++++++++++++++++++++++
 opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AttributeTypeSyntaxTest.java            |   60 +++++++++++
 opends/src/server/org/opends/server/util/ServerConstants.java                                              |    8 +
 4 files changed, 261 insertions(+), 27 deletions(-)

diff --git a/opends/src/server/org/opends/server/schema/AttributeTypeSyntax.java b/opends/src/server/org/opends/server/schema/AttributeTypeSyntax.java
index d692564..6ed5126 100644
--- a/opends/src/server/org/opends/server/schema/AttributeTypeSyntax.java
+++ b/opends/src/server/org/opends/server/schema/AttributeTypeSyntax.java
@@ -55,6 +55,7 @@
 import static org.opends.server.messages.MessageHandler.*;
 import static org.opends.server.messages.SchemaMessages.*;
 import static org.opends.server.schema.SchemaConstants.*;
+import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
 
 
@@ -628,31 +629,6 @@
         isNoUserModification    = superiorType.isNoUserModification();
         attributeUsage          = superiorType.getUsage();
       }
-      else if (lowerTokenName.equals("approx") ||
-               lowerTokenName.equals("approximate"))
-      {
-        // This specifies the name or OID of the approximate matching rule to
-        // use for this attribute type.
-        StringBuilder woidBuffer = new StringBuilder();
-        pos = readWOID(lowerStr, woidBuffer, pos);
-        ApproximateMatchingRule amr =
-             schema.getApproximateMatchingRule(woidBuffer.toString());
-        if (amr == null)
-        {
-          // This is bad because we have no idea what the approximate matching
-          // rule should be.  Log a message and go with the default matching
-          // rule for the associated syntax.
-          int    msgID   = MSGID_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_APPROXIMATE_MR;
-          String message = getMessage(msgID, String.valueOf(oid),
-                                      String.valueOf(woidBuffer));
-          logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING,
-                   message, msgID);
-        }
-        else
-        {
-          approximateMatchingRule = amr;
-        }
-      }
       else if (lowerTokenName.equals("equality"))
       {
         // This specifies the name or OID of the equality matching rule to use
@@ -925,6 +901,30 @@
       }
     }
 
+    List<String> approxRules = extraProperties.get(SCHEMA_PROPERTY_APPROX_RULE);
+    if ((approxRules != null) && (! approxRules.isEmpty()))
+    {
+      String ruleName  = approxRules.get(0);
+      String lowerName = toLowerCase(ruleName);
+      ApproximateMatchingRule amr =
+           schema.getApproximateMatchingRule(lowerName);
+      if (amr == null)
+      {
+        // This is bad because we have no idea what the approximate matching
+        // rule should be.  Log a message and go with the default matching
+        // rule for the associated syntax.
+        int    msgID   = MSGID_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_APPROXIMATE_MR;
+        String message = getMessage(msgID, String.valueOf(oid),
+                                    String.valueOf(ruleName));
+        logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING,
+                 message, msgID);
+      }
+      else
+      {
+        approximateMatchingRule = amr;
+      }
+    }
+
 
     return new AttributeType(value.stringValue(), primaryName, typeNames, oid,
                              description, superiorType, syntax,
diff --git a/opends/src/server/org/opends/server/util/ServerConstants.java b/opends/src/server/org/opends/server/util/ServerConstants.java
index 5db76e1..df94036 100644
--- a/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -1909,6 +1909,14 @@
 
 
   /**
+   * The name of the schema extension that will be used to specify the
+   * approximate matching rule that should be used for a given attribute type.
+   */
+  public static final String SCHEMA_PROPERTY_APPROX_RULE = "X-APPROX";
+
+
+
+  /**
    * The name of the schema property that will be used to specify the path to
    * the schema file from which the schema element was loaded.
    */
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AttributeTypeSyntaxTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AttributeTypeSyntaxTest.java
index 983d966..4c69a52 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AttributeTypeSyntaxTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AttributeTypeSyntaxTest.java
@@ -26,8 +26,17 @@
  */
 package org.opends.server.schema;
 
-import org.opends.server.api.AttributeSyntax;
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import org.opends.server.api.ApproximateMatchingRule;
+import org.opends.server.api.AttributeSyntax;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringFactory;
+
+import static org.testng.Assert.*;
 
 /**
  * Test the AttributeTypeSyntax.
@@ -55,7 +64,7 @@
         {"(1.2.8.5 NAME 'testtype' DESC 'full type' OBSOLETE SUP 1.2" +
           " EQUALITY 2.3 ORDERING 5.6 SUBSTR 7.8 SYNTAX 9.1 SINGLE-VALUE" +
           " COLLECTIVE NO-USER-MODIFICATION USAGE directoryOperations )",
-          true},        
+          true},
         {"(1.2.8.5 NAME 'testtype' DESC 'full type')",
               true},
         {"(1.2.8.5 USAGE directoryOperations )",
@@ -63,4 +72,51 @@
     };
   }
 
+
+
+  /**
+   * Tests the use of the "X-APPROX" extension to specify a particular
+   * approximate matching rule.
+   *
+   * @throws  Exception  If an unexpected problem occurs.
+   */
+  @Test()
+  public void testXAPPROXExtension()
+         throws Exception
+  {
+    // Create and register the approximate matching rule for testing purposes.
+    EqualLengthApproximateMatchingRule testApproxRule =
+         new EqualLengthApproximateMatchingRule();
+    testApproxRule.initializeMatchingRule(null);
+    DirectoryServer.registerApproximateMatchingRule(testApproxRule, false);
+
+
+    // Get a reference to the attribute type syntax implementation in the
+    // server.
+    AttributeTypeSyntax attrTypeSyntax =
+      (AttributeTypeSyntax)
+      DirectoryServer.getAttributeSyntax("1.3.6.1.4.1.1466.115.121.1.3", false);
+    assertNotNull(attrTypeSyntax);
+
+
+    // Create an attribute type definition and verify that it is acceptable.
+    ByteString definition = ByteStringFactory.create(
+      "( testxapproxtype-oid NAME 'testXApproxType' " +
+           "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 " +
+           "X-APPROX 'equalLengthApproximateMatch' )");
+    StringBuilder invalidReason = new StringBuilder();
+    assertTrue(attrTypeSyntax.valueIsAcceptable(definition, invalidReason),
+               invalidReason.toString());
+
+
+    // Verify that we can decode the attribute type and that it has the
+    // correct approximate matching rule.
+    AttributeType attrType =
+         AttributeTypeSyntax.decodeAttributeType(definition,
+                                                 DirectoryServer.getSchema());
+    assertNotNull(attrType);
+    assertNotNull(attrType.getApproximateMatchingRule());
+    assertEquals(attrType.getApproximateMatchingRule(), testApproxRule);
+  }
 }
+
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/EqualLengthApproximateMatchingRule.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/EqualLengthApproximateMatchingRule.java
new file mode 100644
index 0000000..c45cd36
--- /dev/null
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/EqualLengthApproximateMatchingRule.java
@@ -0,0 +1,170 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.server.schema;
+
+
+
+import org.opends.server.api.ApproximateMatchingRule;
+import org.opends.server.config.ConfigEntry;
+import org.opends.server.config.ConfigException;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringFactory;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.InitializationException;
+
+import static org.opends.server.schema.SchemaConstants.*;
+
+
+
+/**
+ * This class implements an extremely simple approximate matching rule that will
+ * consider two values approximately equal only if they have the same length.
+ * It is intended purely for testing purposes.
+ */
+public class EqualLengthApproximateMatchingRule
+       extends ApproximateMatchingRule
+{
+  /**
+   * Creates a new instance of this equal length approximate matching rule.
+   */
+  public EqualLengthApproximateMatchingRule()
+  {
+    super();
+  }
+
+
+
+  /**
+   * Initializes this matching rule based on the information in the provided
+   * configuration entry.
+   *
+   * @param  configEntry  The configuration entry that contains the information
+   *                      to use to initialize this matching rule.
+   *
+   * @throws  ConfigException  If an unrecoverable problem arises in the
+   *                           process of performing the initialization.
+   *
+   * @throws  InitializationException  If a problem that is not
+   *                                   configuration-related occurs during
+   *                                   initialization.
+   */
+  public void initializeMatchingRule(ConfigEntry configEntry)
+         throws ConfigException, InitializationException
+  {
+    // No initialization is required.
+  }
+
+
+
+  /**
+   * Retrieves the common name for this matching rule.
+   *
+   * @return  The common name for this matching rule, or <CODE>null</CODE> if
+   * it does not have a name.
+   */
+  public String getName()
+  {
+    return "equalLengthApproximateMatch";
+  }
+
+
+
+  /**
+   * Retrieves the OID for this matching rule.
+   *
+   * @return  The OID for this matching rule.
+   */
+  public String getOID()
+  {
+    return "equallengthapproximatematch-oid";
+  }
+
+
+
+  /**
+   * Retrieves the description for this matching rule.
+   *
+   * @return  The description for this matching rule, or <CODE>null</CODE> if
+   *          there is none.
+   */
+  public String getDescription()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * Retrieves the OID of the syntax with which this matching rule is
+   * associated.
+   *
+   * @return  The OID of the syntax with which this matching rule is associated.
+   */
+  public String getSyntaxOID()
+  {
+    return SYNTAX_DIRECTORY_STRING_OID;
+  }
+
+
+
+  /**
+   * Retrieves the normalized form of the provided value, which is best suited
+   * for efficiently performing matching operations on that value.
+   *
+   * @param  value  The value to be normalized.
+   *
+   * @return  The normalized version of the provided value.
+   *
+   * @throws  DirectoryException  If the provided value is invalid according to
+   *                              the associated attribute syntax.
+   */
+  public ByteString normalizeValue(ByteString value)
+         throws DirectoryException
+  {
+    // Any value is acceptable, so we can just return a copy of the
+    // value.
+    return ByteStringFactory.create(value.value());
+  }
+
+
+
+  /**
+   * Indicates whether the two provided normalized values are approximately
+   * equal to each other.
+   *
+   * @param  value1  The normalized form of the first value to compare.
+   * @param  value2  The normalized form of the second value to compare.
+   *
+   * @return  <CODE>true</CODE> if the provided values are approximately equal,
+   *          or <CODE>false</CODE> if not.
+   */
+  public boolean approximatelyMatch(ByteString value1, ByteString value2)
+  {
+    return (value1.value().length == value2.value().length);
+  }
+}
+

--
Gitblit v1.10.0