From 0dad0bb4e877952cb0f631585f9bb733500f42ed Mon Sep 17 00:00:00 2001
From: sin <sin@localhost>
Date: Tue, 17 Feb 2009 16:11:27 +0000
Subject: [PATCH] issue# 3774: Sort control doesn't work for collation matching rules

---
 opendj-sdk/opends/src/server/org/opends/server/api/ExtensibleMatchingRule.java                               |   10 
 opendj-sdk/opends/src/server/org/opends/server/schema/IntegerOrderingMatchingRule.java                       |    7 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/CollationMatchingRuleTest.java |  170 +++++++++++
 opendj-sdk/opends/src/server/org/opends/server/schema/GeneralizedTimeOrderingMatchingRule.java               |    9 
 opendj-sdk/opends/src/server/org/opends/server/types/Schema.java                                             |    8 
 opendj-sdk/opends/src/server/org/opends/server/schema/UUIDOrderingMatchingRule.java                          |   11 
 opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java     |    7 
 opendj-sdk/opends/src/server/org/opends/server/api/ApproximateMatchingRule.java                              |    6 
 opendj-sdk/opends/src/server/org/opends/server/api/EqualityMatchingRule.java                                 |    6 
 opendj-sdk/opends/src/server/org/opends/server/api/AbstractMatchingRule.java                                 |  249 ++++++++++++++++
 opendj-sdk/opends/src/server/org/opends/server/schema/CaseExactOrderingMatchingRule.java                     |    9 
 opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java                                         |    1 
 opendj-sdk/opends/src/server/org/opends/server/api/OrderingMatchingRule.java                                 |   53 ---
 opendj-sdk/opends/src/server/org/opends/server/schema/CaseIgnoreOrderingMatchingRule.java                    |    9 
 opendj-sdk/opends/src/server/org/opends/server/schema/NumericStringOrderingMatchingRule.java                 |   11 
 opendj-sdk/opends/src/server/org/opends/server/schema/OctetStringOrderingMatchingRule.java                   |   11 
 opendj-sdk/opends/src/server/org/opends/server/api/SubstringMatchingRule.java                                |   35 --
 opendj-sdk/opends/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java                      |  123 +++++++
 opendj-sdk/opends/src/server/org/opends/server/api/MatchingRule.java                                         |  149 +--------
 19 files changed, 614 insertions(+), 270 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/AbstractMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/api/AbstractMatchingRule.java
new file mode 100644
index 0000000..fc1d178
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/AbstractMatchingRule.java
@@ -0,0 +1,249 @@
+/*
+ * 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
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+package org.opends.server.api;
+
+
+
+import java.util.Collection;
+
+import org.opends.server.types.ByteSequence;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ConditionResult;
+import org.opends.server.types.DirectoryException;
+
+
+
+/**
+ * This class provides default implementation of MatchingRule. A
+ * matching rule implemented by a Directory Server module must extend
+ * this class.
+ */
+@org.opends.server.types.PublicAPI(
+    stability = org.opends.server.types.StabilityLevel.VOLATILE,
+    mayInstantiate = false,
+    mayExtend = true,
+    mayInvoke = false)
+public abstract class AbstractMatchingRule implements MatchingRule
+{
+  /**
+   * {@inheritDoc}
+   */
+  public abstract String getName();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public abstract Collection<String> getAllNames();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public abstract String getOID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString normalizeAssertionValue(ByteSequence value)
+      throws DirectoryException
+  {
+    // Default implementation is to use attribute value normalization.
+    return normalizeValue(value);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final String getNameOrOID()
+  {
+    String name = getName();
+    if ((name == null) || (name.length() == 0))
+    {
+      return getOID();
+    }
+    else
+    {
+      return name;
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public abstract String getDescription();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public abstract String getSyntaxOID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isObsolete()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public abstract ByteString normalizeValue(ByteSequence value)
+      throws DirectoryException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ConditionResult valuesMatch(
+      ByteSequence attributeValue, ByteSequence assertionValue)
+  {
+    //Default implementation of most rule types.
+    return ConditionResult.UNDEFINED;
+  }
+
+
+
+  /**
+   * Retrieves the hash code for this matching rule. It will be
+   * calculated as the sum of the characters in the OID.
+   *
+   * @return The hash code for this matching rule.
+   */
+  @Override
+  public final int hashCode()
+  {
+    int hashCode = 0;
+
+    String oidString = getOID();
+    int oidLength = oidString.length();
+    for (int i = 0; i < oidLength; i++)
+    {
+      hashCode += oidString.charAt(i);
+    }
+
+    return hashCode;
+  }
+
+
+
+  /**
+   * Indicates whether the provided object is equal to this matching
+   * rule. The provided object will be considered equal to this
+   * matching rule only if it is a matching rule with the same OID.
+   *
+   * @param o
+   *          The object for which to make the determination.
+   * @return {@code true} if the provided object is equal to this
+   *         matching rule, or {@code false} if it is not.
+   */
+  @Override
+  public final boolean equals(Object o)
+  {
+    if (o == null)
+    {
+      return false;
+    }
+
+    if (this == o)
+    {
+      return true;
+    }
+
+    if (!(o instanceof MatchingRule))
+    {
+      return false;
+    }
+
+    return getOID().equals(((MatchingRule) o).getOID());
+  }
+
+
+
+  /**
+   * Retrieves a string representation of this matching rule in the
+   * format defined in RFC 2252.
+   *
+   * @return A string representation of this matching rule in the
+   *         format defined in RFC 2252.
+   */
+  @Override
+  public final String toString()
+  {
+    StringBuilder buffer = new StringBuilder();
+    toString(buffer);
+    return buffer.toString();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final void toString(StringBuilder buffer)
+  {
+    buffer.append("( ");
+    buffer.append(getOID());
+    buffer.append(" NAME '");
+    buffer.append(getName());
+
+    String description = getDescription();
+    if ((description != null) && (description.length() > 0))
+    {
+      buffer.append("' DESC '");
+      buffer.append(description);
+    }
+
+    if (isObsolete())
+    {
+      buffer.append("' OBSOLETE SYNTAX ");
+    }
+    else
+    {
+      buffer.append("' SYNTAX ");
+    }
+
+    buffer.append(getSyntaxOID());
+    buffer.append(" )");
+  }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/ApproximateMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/api/ApproximateMatchingRule.java
index 2017afb..48f9958 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/ApproximateMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/ApproximateMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.api;
 
@@ -43,7 +43,8 @@
      mayExtend=true,
      mayInvoke=false)
 public abstract class ApproximateMatchingRule
-       extends MatchingRule
+       extends AbstractMatchingRule
+       implements MatchingRule
 {
   /**
    * Indicates whether the two provided normalized values are
@@ -81,6 +82,7 @@
    *          if it does not match, or {@code UNDEFINED} if the result
    *          is undefined.
    */
+  @Override
   public ConditionResult valuesMatch(ByteSequence attributeValue,
                                      ByteSequence assertionValue)
   {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/EqualityMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/api/EqualityMatchingRule.java
index 9a0fb1b..73d7022 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/EqualityMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/EqualityMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.api;
 
@@ -42,7 +42,9 @@
      mayInstantiate=false,
      mayExtend=true,
      mayInvoke=false)
-public abstract class EqualityMatchingRule extends MatchingRule
+public abstract class EqualityMatchingRule
+        extends AbstractMatchingRule
+        implements MatchingRule
 {
   /**
    * Indicates whether the two provided normalized values are equal to
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/ExtensibleMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/api/ExtensibleMatchingRule.java
index 4c54a99..2f586b2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/ExtensibleMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/ExtensibleMatchingRule.java
@@ -37,7 +37,7 @@
 
 
 /**
- * This class defines the set of methods and structures that must be
+ * This interface defines the set of methods that must be
  * implemented by a Directory Server module that implements an
  * Extensible matching rule.
  */
@@ -46,7 +46,7 @@
     mayInstantiate = false,
     mayExtend = true,
     mayInvoke = false)
-public abstract class ExtensibleMatchingRule extends MatchingRule
+public interface ExtensibleMatchingRule extends MatchingRule
 {
   /**
    * Returns a collection of extensible indexers associated with this
@@ -58,7 +58,7 @@
    * @return The collection of extensible indexers associated with
    *         this matching rule.
    */
-  public abstract Collection<ExtensibleIndexer> getIndexers(
+  Collection<ExtensibleIndexer> getIndexers(
       IndexConfig config);
 
 
@@ -79,6 +79,6 @@
    * @throws DirectoryException
    *           If an error occurs while generating the index query.
    */
-  public abstract <T> T createIndexQuery(ByteSequence assertionValue,
+  <T> T createIndexQuery(ByteSequence assertionValue,
       IndexQueryFactory<T> factory) throws DirectoryException;
-}
\ No newline at end of file
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/MatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/api/MatchingRule.java
index 47f06a1..c2dff58 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/MatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/MatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.api;
 
@@ -38,16 +38,15 @@
 
 
 /**
- * This class defines the set of methods and structures that must be
- * implemented by a Directory Server module that implements a matching
- * rule.
+ * This interface defines the set of methods that must be implemented
+ * by a Directory Server module that implements a matching rule.
  */
 @org.opends.server.types.PublicAPI(
     stability = org.opends.server.types.StabilityLevel.VOLATILE,
     mayInstantiate = false,
     mayExtend = true,
     mayInvoke = false)
-public abstract class MatchingRule
+public interface MatchingRule
 {
   /**
    * Retrieves the common name for this matching rule.
@@ -55,7 +54,7 @@
    * @return The common name for this matching rule, or {@code null}
    *         if it does not have a name.
    */
-  public abstract String getName();
+  String getName();
 
 
 
@@ -64,7 +63,7 @@
    *
    * @return All names for this matching rule.
    */
-  public abstract Collection<String> getAllNames();
+  Collection<String> getAllNames();
 
 
 
@@ -73,7 +72,7 @@
    *
    * @return The OID for this matching rule.
    */
-  public abstract String getOID();
+  String getOID();
 
 
 
@@ -89,12 +88,8 @@
    *           If the provided value is invalid according to the
    *           associated attribute syntax.
    */
-  public ByteString normalizeAssertionValue(ByteSequence value)
-      throws DirectoryException
-  {
-    // Default implementation is to use attribute value normalization.
-    return normalizeValue(value);
-  }
+  ByteString normalizeAssertionValue(ByteSequence value)
+      throws DirectoryException;
 
 
 
@@ -105,18 +100,7 @@
    *
    * @return The name or OID for this matching rule.
    */
-  public final String getNameOrOID()
-  {
-    String name = getName();
-    if ((name == null) || (name.length() == 0))
-    {
-      return getOID();
-    }
-    else
-    {
-      return name;
-    }
-  }
+  String getNameOrOID();
 
 
 
@@ -126,7 +110,7 @@
    * @return The description for this matching rule, or {@code null}
    *         if there is none.
    */
-  public abstract String getDescription();
+  String getDescription();
 
 
 
@@ -137,7 +121,7 @@
    * @return The OID of the syntax with which this matching rule is
    *         associated.
    */
-  public abstract String getSyntaxOID();
+  String getSyntaxOID();
 
 
 
@@ -151,10 +135,7 @@
    * @return {@code true} if this matching rule is declared
    *         "OBSOLETE", or {@code false} if not.
    */
-  public boolean isObsolete()
-  {
-    return false;
-  }
+  boolean isObsolete();
 
 
 
@@ -170,7 +151,7 @@
    *           If the provided value is invalid according to the
    *           associated attribute syntax.
    */
-  public abstract ByteString normalizeValue(ByteSequence value)
+  ByteString normalizeValue(ByteSequence value)
       throws DirectoryException;
 
 
@@ -193,115 +174,17 @@
    *         if it does not match, or {@code UNDEFINED} if the result
    *         is undefined.
    */
-  public abstract ConditionResult valuesMatch(
+  ConditionResult valuesMatch(
       ByteSequence attributeValue, ByteSequence assertionValue);
 
 
 
   /**
-   * Retrieves the hash code for this matching rule. It will be
-   * calculated as the sum of the characters in the OID.
-   *
-   * @return The hash code for this matching rule.
-   */
-  @Override
-  public final int hashCode()
-  {
-    int hashCode = 0;
-
-    String oidString = getOID();
-    int oidLength = oidString.length();
-    for (int i = 0; i < oidLength; i++)
-    {
-      hashCode += oidString.charAt(i);
-    }
-
-    return hashCode;
-  }
-
-
-
-  /**
-   * Indicates whether the provided object is equal to this matching
-   * rule. The provided object will be considered equal to this
-   * matching rule only if it is a matching rule with the same OID.
-   *
-   * @param o
-   *          The object for which to make the determination.
-   * @return {@code true} if the provided object is equal to this
-   *         matching rule, or {@code false} if it is not.
-   */
-  @Override
-  public final boolean equals(Object o)
-  {
-    if (o == null)
-    {
-      return false;
-    }
-
-    if (this == o)
-    {
-      return true;
-    }
-
-    if (!(o instanceof MatchingRule))
-    {
-      return false;
-    }
-
-    return getOID().equals(((MatchingRule) o).getOID());
-  }
-
-
-
-  /**
-   * Retrieves a string representation of this matching rule in the
-   * format defined in RFC 2252.
-   *
-   * @return A string representation of this matching rule in the
-   *         format defined in RFC 2252.
-   */
-  @Override
-  public final String toString()
-  {
-    StringBuilder buffer = new StringBuilder();
-    toString(buffer);
-    return buffer.toString();
-  }
-
-
-
-  /**
    * Appends a string representation of this matching rule in the
    * format defined in RFC 2252 to the provided buffer.
    *
    * @param buffer
    *          The buffer to which the information should be appended.
    */
-  public final void toString(StringBuilder buffer)
-  {
-    buffer.append("( ");
-    buffer.append(getOID());
-    buffer.append(" NAME '");
-    buffer.append(getName());
-
-    String description = getDescription();
-    if ((description != null) && (description.length() > 0))
-    {
-      buffer.append("' DESC '");
-      buffer.append(description);
-    }
-
-    if (isObsolete())
-    {
-      buffer.append("' OBSOLETE SYNTAX ");
-    }
-    else
-    {
-      buffer.append("' SYNTAX ");
-    }
-
-    buffer.append(getSyntaxOID());
-    buffer.append(" )");
-  }
+  void toString(StringBuilder buffer);
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/OrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/api/OrderingMatchingRule.java
index 7c561bf..a7ec634 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/OrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/OrderingMatchingRule.java
@@ -30,14 +30,13 @@
 
 import java.io.Serializable;
 import java.util.Comparator;
-
-import org.opends.server.types.ConditionResult;
 import org.opends.server.types.ByteSequence;
 
 
+
 /**
- * This class defines the set of methods and structures that must be
- * implemented by a Directory Server module that implements a matching
+ * This interface defines the set of methods that must be implemented
+ * by a Directory Server module that implements a matching
  * rule used for determining the correct order of values when sorting
  * or processing range filters.
  */
@@ -46,21 +45,10 @@
      mayInstantiate=false,
      mayExtend=true,
      mayInvoke=false)
-public abstract class OrderingMatchingRule
-       extends MatchingRule
-       implements Comparator<byte[]>, Serializable
+public interface OrderingMatchingRule
+        extends MatchingRule,Comparator<byte[]>,Serializable
 {
   /**
-   * The serial version identifier required to satisfy the compiler
-   * because this class implements the {@code java.io.Serializable}
-   * interface.  This value was generated using the {@code serialver}
-   * command-line utility included with the Java SDK.
-   */
-  private static final long serialVersionUID = -5322529685787024597L;
-
-
-
-  /**
    * Compares the first value to the second and returns a value that
    * indicates their relative order.
    *
@@ -77,35 +65,4 @@
    */
   public abstract int compareValues(ByteSequence value1,
                                     ByteSequence value2);
-
-
-
-  /**
-   * Indicates whether the provided attribute value should be
-   * considered a match for the given assertion value.  This will only
-   * be used for the purpose of extensible matching.
-   * <BR><BR>
-   * Note that ordering matching rules by default do not support
-   * extensible matching, and therefore this method will always return
-   * {@code UNDEFINED}.  If an ordering matching rule does support
-   * extensible matching operations, then it should override this
-   * method and provide an appropriate implementation.
-   *
-   * @param  attributeValue  The attribute value in a form that has
-   *                         been normalized according to this
-   *                         matching rule.
-   * @param  assertionValue  The assertion value in a form that has
-   *                         been normalized according to this
-   *                         matching rule.
-   *
-   * @return  {@code true} if the attribute value should be considered
-   *          a match for the provided assertion value, or
-   *          {@code false} if not.
-   */
-  public ConditionResult valuesMatch(ByteSequence attributeValue,
-                                     ByteSequence assertionValue)
-  {
-    return ConditionResult.UNDEFINED;
-  }
 }
-
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/SubstringMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/api/SubstringMatchingRule.java
index 978ac53..93d9b8d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/SubstringMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/SubstringMatchingRule.java
@@ -43,7 +43,9 @@
      mayInstantiate=false,
      mayExtend=true,
      mayInvoke=false)
-public abstract class SubstringMatchingRule extends MatchingRule
+public abstract class SubstringMatchingRule
+        extends AbstractMatchingRule
+        implements MatchingRule
 {
   /**
    * Normalizes the provided value fragment into a form that can be
@@ -174,36 +176,5 @@
 
     return true;
   }
-
-
-
-  /**
-   * Indicates whether the provided attribute value should be
-   * considered a match for the given assertion value.  This will only
-   * be used for the purpose of extensible matching.
-   * <BR><BR>
-   * Note that substring matching rules by default do not support
-   * extensible matching, and therefore this method will always return
-   * {@code UNDEFINED}.  If a substring matching rule does support
-   * extensible matching operations, then it should override this
-   * method and provide an appropriate implementation.
-   *
-   * @param  attributeValue  The attribute value in a form that has
-   *                         been normalized according to this
-   *                         matching rule.
-   * @param  assertionValue  The assertion value in a form that has
-   *                         been normalized according to this
-   *                         matching rule.
-   *
-   * @return  {@code true} if the attribute value should be considered
-   *          a match for the provided assertion value, or
-   *          {@code false} if not.
-   */
-  @Override
-  public ConditionResult valuesMatch(ByteSequence attributeValue,
-                                     ByteSequence assertionValue)
-  {
-    return ConditionResult.UNDEFINED;
-  }
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java
index 7566869..cdad536 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRule.java
@@ -22,12 +22,13 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.replication.plugin;
 
 import java.util.Collection;
 import java.util.Collections;
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.types.ByteString;
 import org.opends.server.types.ByteSequence;
@@ -36,7 +37,8 @@
  * Used to establish an order between historical information and index them.
  */
 public class HistoricalCsnOrderingMatchingRule
-       extends OrderingMatchingRule
+       extends AbstractMatchingRule
+       implements OrderingMatchingRule
 {
   /**
    * The serial version identifier required to satisfy the compiler because this
@@ -63,7 +65,6 @@
    * @param value2 second value to compare
    * @return 0 when equals, -1 or 1 to establish order
    */
-  @Override
   public int compareValues(ByteSequence value1, ByteSequence value2)
   {
     String[] token1 = value1.toString().split(":", 3);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/CaseExactOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/schema/CaseExactOrderingMatchingRule.java
index af478c7..66bc8fe 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/CaseExactOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/schema/CaseExactOrderingMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.schema;
 
@@ -33,6 +33,7 @@
 import java.util.Collection;
 import java.util.Collections;
 
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.types.ByteSequence;
 import org.opends.server.types.ByteString;
@@ -47,7 +48,8 @@
  * and referenced in RFC 4519.
  */
 class CaseExactOrderingMatchingRule
-       extends OrderingMatchingRule
+       extends AbstractMatchingRule
+       implements OrderingMatchingRule
 {
   /**
    * The serial version identifier required to satisfy the compiler because this
@@ -201,10 +203,9 @@
    *          ascending order, or zero if there is no difference between the
    *          values with regard to ordering.
    */
-  @Override
   public int compareValues(ByteSequence value1, ByteSequence value2)
   {
-    return StaticUtils.compare(value1, value2);
+    return value1.compareTo(value2);
   }
 
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/CaseIgnoreOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/schema/CaseIgnoreOrderingMatchingRule.java
index 2286476..dbb3a54 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/CaseIgnoreOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/schema/CaseIgnoreOrderingMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.schema;
 
@@ -34,6 +34,7 @@
 import java.util.Collection;
 import java.util.Collections;
 
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.types.ByteSequence;
 import org.opends.server.types.ByteString;
@@ -48,7 +49,8 @@
  * and referenced in RFC 2252.
  */
 public class CaseIgnoreOrderingMatchingRule
-       extends OrderingMatchingRule
+       extends AbstractMatchingRule
+       implements OrderingMatchingRule
 {
   /**
    * The serial version identifier required to satisfy the compiler because this
@@ -202,10 +204,9 @@
    *          ascending order, or zero if there is no difference between the
    *          values with regard to ordering.
    */
-  @Override
   public int compareValues(ByteSequence value1, ByteSequence value2)
   {
-    return StaticUtils.compare(value1, value2);
+    return value1.compareTo(value2);
   }
 
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java b/opendj-sdk/opends/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java
index 8e9995a..f0247d3 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java
@@ -58,11 +58,13 @@
 import org.opends.server.admin.std.meta.
   CollationMatchingRuleCfgDefn.MatchingRuleType;
 import org.opends.server.admin.std.server.CollationMatchingRuleCfg;
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.ExtensibleIndexer;
 import org.opends.server.api.ExtensibleMatchingRule;
 import org.opends.server.api.IndexQueryFactory;
 import org.opends.server.api.MatchingRule;
 import org.opends.server.api.MatchingRuleFactory;
+import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.backends.jeb.AttributeIndex;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
@@ -75,6 +77,7 @@
 import org.opends.server.types.IndexConfig;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
+import org.opends.server.util.StaticUtils;
 
 
 
@@ -721,8 +724,9 @@
   /**
    * Collation Extensible matching rule.
    */
-  private abstract class CollationMatchingRule extends
-      ExtensibleMatchingRule
+  private abstract class CollationMatchingRule
+          extends AbstractMatchingRule
+          implements ExtensibleMatchingRule
   {
     // Names for this class.
     private final Collection<String> names;
@@ -857,7 +861,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public Collection<ExtensibleIndexer> getIndexers(IndexConfig config)
     {
       if (indexer == null)
@@ -873,9 +876,21 @@
   /**
    * Collation rule for Equality matching rule.
    */
-  private final class CollationEqualityMatchingRule extends
-      CollationMatchingRule
+  private final class CollationEqualityMatchingRule
+          extends CollationMatchingRule
+          implements OrderingMatchingRule
   {
+
+    /**
+     * The serial version identifier required to satisfy the compiler because
+     * this class implements the <CODE>java.io.Serializable</CODE> interface.
+     * This value was generated using the <CODE>serialver</CODE> command-line
+     * utility included with the Java SDK.
+     */
+    private static final long serialVersionUID = 3990778178484159862L;
+
+
+
     /**
      * Constructs a new CollationEqualityMatchingRule.
      *
@@ -929,7 +944,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public <T> T createIndexQuery(ByteSequence assertionValue,
         IndexQueryFactory<T> factory) throws DirectoryException
     {
@@ -937,6 +951,26 @@
       return factory.createExactMatchQuery(indexer
           .getExtensibleIndexID(), normalizeValue(assertionValue));
     }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compare(byte[] arg0, byte[] arg1)
+    {
+      return StaticUtils.compare(arg0, arg1);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareValues(ByteSequence value1, ByteSequence value2)
+    {
+      return value1.compareTo(value2);
+    }
   }
 
   /**
@@ -1645,7 +1679,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public <T> T createIndexQuery(ByteSequence assertionValue,
         IndexQueryFactory<T> factory) throws DirectoryException
     {
@@ -1690,9 +1723,21 @@
   /**
    * An abstract Collation rule for Ordering matching rule.
    */
-  private abstract class CollationOrderingMatchingRule extends
-      CollationMatchingRule
+  private abstract class CollationOrderingMatchingRule
+          extends CollationMatchingRule
+          implements OrderingMatchingRule
   {
+
+    /**
+     * The serial version identifier required to satisfy the compiler because
+     * this class implements the <CODE>java.io.Serializable</CODE> interface.
+     * This value was generated using the <CODE>serialver</CODE> command-line
+     * utility included with the Java SDK.
+     */
+    private static final long serialVersionUID = 7354051060508436941L;
+
+
+
     /**
      * Constructs a new CollationOrderingMatchingRule.
      *
@@ -1721,6 +1766,26 @@
       CollationKey key = collator.getCollationKey(value.toString());
       return ByteString.wrap(key.toByteArray());
     }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compare(byte[] arg0, byte[] arg1)
+    {
+      return StaticUtils.compare(arg0, arg1);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareValues(ByteSequence value1, ByteSequence value2)
+    {
+      return value1.compareTo(value2);
+    }
   }
 
   /**
@@ -1729,6 +1794,15 @@
   private final class CollationLessThanMatchingRule extends
       CollationOrderingMatchingRule
   {
+    /**
+     * The serial version identifier required to satisfy the compiler because
+     * this class implements the <CODE>java.io.Serializable</CODE> interface.
+     * This value was generated using the <CODE>serialver</CODE> command-line
+     * utility included with the Java SDK.
+     */
+    private static final long serialVersionUID = -7578406829946732713L;
+
+
 
     /**
      * Constructs a new CollationLessThanMatchingRule.
@@ -1772,7 +1846,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public <T> T createIndexQuery(ByteSequence assertionValue,
         IndexQueryFactory<T> factory) throws DirectoryException
     {
@@ -1788,6 +1861,15 @@
   private final class CollationLessThanOrEqualToMatchingRule extends
       CollationOrderingMatchingRule
   {
+    /**
+     * The serial version identifier required to satisfy the compiler because
+     * this class implements the <CODE>java.io.Serializable</CODE> interface.
+     * This value was generated using the <CODE>serialver</CODE> command-line
+     * utility included with the Java SDK.
+     */
+    private static final long serialVersionUID = 7222067708233629974L;
+
+
 
     /**
      * Constructs a new CollationLessThanOrEqualToMatchingRule.
@@ -1831,7 +1913,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public <T> T createIndexQuery(ByteSequence assertionValue,
         IndexQueryFactory<T> factory) throws DirectoryException
     {
@@ -1848,6 +1929,15 @@
   private final class CollationGreaterThanMatchingRule extends
       CollationOrderingMatchingRule
   {
+    /**
+     * The serial version identifier required to satisfy the compiler because
+     * this class implements the <CODE>java.io.Serializable</CODE> interface.
+     * This value was generated using the <CODE>serialver</CODE> command-line
+     * utility included with the Java SDK.
+     */
+    private static final long serialVersionUID = 1204368277332957024L;
+
+
 
     /**
      * Constructs a new CollationGreaterThanMatchingRule.
@@ -1891,7 +1981,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public <T> T createIndexQuery(ByteSequence assertionValue,
         IndexQueryFactory<T> factory) throws DirectoryException
     {
@@ -1907,6 +1996,15 @@
   private final class CollationGreaterThanOrEqualToMatchingRule extends
       CollationOrderingMatchingRule
   {
+    /**
+     * The serial version identifier required to satisfy the compiler because
+     * this class implements the <CODE>java.io.Serializable</CODE> interface.
+     * This value was generated using the <CODE>serialver</CODE> command-line
+     * utility included with the Java SDK.
+     */
+    private static final long serialVersionUID = -5212358378014047933L;
+
+
 
     /**
      * Constructs a new CollationGreaterThanOrEqualToMatchingRule.
@@ -1950,7 +2048,6 @@
     /**
      * {@inheritDoc}
      */
-    @Override
     public <T> T createIndexQuery(ByteSequence assertionValue,
         IndexQueryFactory<T> factory) throws DirectoryException
     {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/GeneralizedTimeOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/schema/GeneralizedTimeOrderingMatchingRule.java
index 01c02e0..63ace4b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/GeneralizedTimeOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/schema/GeneralizedTimeOrderingMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.schema;
 
@@ -35,6 +35,7 @@
 import java.util.Collection;
 import java.util.Collections;
 
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.loggers.debug.DebugTracer;
@@ -50,7 +51,8 @@
  * X.520 and referenced in RFC 2252.
  */
 class GeneralizedTimeOrderingMatchingRule
-       extends OrderingMatchingRule
+       extends AbstractMatchingRule
+       implements OrderingMatchingRule
 {
   /**
    * The tracer object for the debug logger.
@@ -203,7 +205,6 @@
    *          ascending order, or zero if there is no difference between the
    *          values with regard to ordering.
    */
-  @Override
   public int compareValues(ByteSequence value1, ByteSequence value2)
   {
     try
@@ -253,6 +254,6 @@
   public int compare(byte[] b1, byte[] b2)
   {
     return compareValues(ByteString.wrap(b1), ByteString.wrap(b2));
-  }
+}
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/IntegerOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/schema/IntegerOrderingMatchingRule.java
index a05e469..61c7384 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/IntegerOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/schema/IntegerOrderingMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.schema;
 
@@ -36,6 +36,7 @@
 import java.util.Collections;
 
 import org.opends.messages.Message;
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.ByteSequence;
@@ -50,7 +51,8 @@
  * and referenced in RFC 4519.
  */
 class IntegerOrderingMatchingRule
-       extends OrderingMatchingRule
+       extends AbstractMatchingRule
+       implements OrderingMatchingRule
 {
   /**
    * The serial version identifier required to satisfy the compiler because this
@@ -374,7 +376,6 @@
    *          ascending order, or zero if there is no difference between the
    *          values with regard to ordering.
    */
-  @Override
   public int compareValues(ByteSequence value1, ByteSequence value2)
   {
     int b1Length = value1.length();
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/NumericStringOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/schema/NumericStringOrderingMatchingRule.java
index 6134cfb..e0a022a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/NumericStringOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/schema/NumericStringOrderingMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.schema;
 
@@ -36,6 +36,7 @@
 import java.util.Collections;
 
 import org.opends.messages.Message;
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.loggers.ErrorLogger;
@@ -52,7 +53,8 @@
  * in X.520 and referenced in RFC 2252.
  */
 class NumericStringOrderingMatchingRule
-       extends OrderingMatchingRule
+       extends AbstractMatchingRule
+       implements OrderingMatchingRule
 {
   /**
    * The serial version identifier required to satisfy the compiler because this
@@ -208,10 +210,9 @@
    *          ascending order, or zero if there is no difference between the
    *          values with regard to ordering.
    */
-  @Override
   public int compareValues(ByteSequence value1, ByteSequence value2)
   {
-    return StaticUtils.compare(value1, value2);
+    return value1.compareTo(value2);
   }
 
 
@@ -232,6 +233,6 @@
   public int compare(byte[] b1, byte[] b2)
   {
     return StaticUtils.compare(b1, b2);
-  }
+}
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/OctetStringOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/schema/OctetStringOrderingMatchingRule.java
index 7f02b59..f831724 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/OctetStringOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/schema/OctetStringOrderingMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.schema;
 
@@ -33,6 +33,7 @@
 import java.util.Collection;
 import java.util.Collections;
 
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.types.ByteSequence;
 import org.opends.server.types.ByteString;
@@ -47,7 +48,8 @@
  * octet string syntaxes.
  */
 class OctetStringOrderingMatchingRule
-       extends OrderingMatchingRule
+       extends AbstractMatchingRule
+       implements OrderingMatchingRule
 {
   /**
    * The serial version identifier required to satisfy the compiler because this
@@ -169,10 +171,9 @@
    *          ascending order, or zero if there is no difference between the
    *          values with regard to ordering.
    */
-  @Override
   public int compareValues(ByteSequence value1, ByteSequence value2)
   {
-    return StaticUtils.compare(value1, value2);
+    return value1.compareTo(value2);
   }
 
 
@@ -193,6 +194,6 @@
   public int compare(byte[] b1, byte[] b2)
   {
     return StaticUtils.compare(b1, b2);
-  }
+}
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/schema/UUIDOrderingMatchingRule.java b/opendj-sdk/opends/src/server/org/opends/server/schema/UUIDOrderingMatchingRule.java
index 543b70e..0b4ec37 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/schema/UUIDOrderingMatchingRule.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/schema/UUIDOrderingMatchingRule.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2009 Sun Microsystems, Inc.
  */
 package org.opends.server.schema;
 
@@ -35,6 +35,7 @@
 import java.util.Collections;
 
 import org.opends.messages.Message;
+import org.opends.server.api.AbstractMatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.loggers.ErrorLogger;
@@ -51,7 +52,8 @@
  * This will be the default ordering matching rule for the UUID syntax.
  */
 class UUIDOrderingMatchingRule
-       extends OrderingMatchingRule
+       extends AbstractMatchingRule
+       implements OrderingMatchingRule
 {
   /**
    * The serial version identifier required to satisfy the compiler because this
@@ -279,10 +281,9 @@
    *          ascending order, or zero if there is no difference between the
    *          values with regard to ordering.
    */
-  @Override
   public int compareValues(ByteSequence value1, ByteSequence value2)
   {
-    return StaticUtils.compare(value1, value2);
+    return value1.compareTo(value2);
   }
 
 
@@ -303,6 +304,6 @@
   public int compare(byte[] b1, byte[] b2)
   {
     return StaticUtils.compare(b1, b2);
-  }
+}
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/Schema.java b/opendj-sdk/opends/src/server/org/opends/server/types/Schema.java
index 92c0511..f69cc44 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/Schema.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/types/Schema.java
@@ -1876,7 +1876,13 @@
   public ExtensibleMatchingRule getExtensibleMatchingRule(
                                       String lowerName)
   {
-    return extensibleMatchingRules.get(lowerName);
+    //An ExtensibleMatchingRule can be of multiple types.
+    MatchingRule rule = matchingRules.get(lowerName);
+    if(rule instanceof ExtensibleMatchingRule)
+    {
+      return (ExtensibleMatchingRule)rule;
+    }
+    return null;
   }
 
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java b/opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java
index c14119b..b2311aa 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/StaticUtils.java
@@ -1415,6 +1415,7 @@
    *         if the first byte array is less than, equal to, or greater
    *         than the second.
    */
+  @Deprecated
   public static int compare(ByteSequence a, ByteSequence a2) {
     if (a == a2) {
       return 0;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/CollationMatchingRuleTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/CollationMatchingRuleTest.java
index ba958db..daf2750 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/CollationMatchingRuleTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/schema/CollationMatchingRuleTest.java
@@ -22,24 +22,31 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 
 
 package org.opends.server.schema;
 
+import java.util.ArrayList;
 import static org.testng.Assert.*;
 
 import java.util.List;
 
 import org.opends.server.TestCaseUtils;
+import org.opends.server.controls.ServerSideSortRequestControl;
+import org.opends.server.controls.VLVRequestControl;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.ldap.LDAPFilter;
 import org.opends.server.tools.LDAPModify;
 import org.opends.server.types.ByteString;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
 import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.Entry;
 import org.opends.server.types.ResultCode;
+import org.opends.server.types.SearchFilter;
 import org.opends.server.types.SearchResultEntry;
 import org.opends.server.types.SearchScope;
 import org.testng.annotations.BeforeClass;
@@ -65,6 +72,10 @@
   {
     TestCaseUtils.startServer();
     TestCaseUtils.initializeTestBackend(true);
+    user1 = DN.decode("cn=user1,dc=example,dc=com");
+    user2 = DN.decode("cn=user2,dc=example,dc=com");
+    user3 = DN.decode("cn=user3,dc=example,dc=com");
+    user4 = DN.decode("cn=user4,dc=example,dc=com");
   }
 
 
@@ -363,4 +374,161 @@
     //An entry must be returned for sn=quebec.
     assertNotNull(e);
   }
+
+  private DN user1;
+  private DN user2 ;
+  private DN user3;
+  private DN user4;
+
+
+  /**
+   * Test to verify the Sort control works well with the Collation
+   * Less-than-equal-to matching rule and French Locale.
+   */
+  @Test()
+  public void testSortControlLTERule() throws Exception
+  {
+    ArrayList<DN> expectedDNOrder = new ArrayList<DN>();
+    expectedDNOrder.add(user4);
+    expectedDNOrder.add(user3);
+    expectedDNOrder.add(user2);
+    expectedDNOrder.add(user1);
+    ArrayList<Control> requestControls = new ArrayList<Control>();
+    requestControls.add(new ServerSideSortRequestControl("displayname:fr"));
+    ValidateSortControl(expectedDNOrder,
+            requestControls,
+            "displayname:fr-FR.6:=A*");
+  }
+
+
+  /**
+   * Test to verify the Sort control works with Collation equality
+   * matching rule and Spanish locale.
+   */
+  @Test()
+  public void testSortControlEQRule() throws Exception
+  {
+    ArrayList<DN> expectedDNOrder = new ArrayList<DN>();
+    expectedDNOrder.add(user4);
+    expectedDNOrder.add(user3);
+    expectedDNOrder.add(user2);
+    expectedDNOrder.add(user1);
+    ArrayList<Control> requestControls = new ArrayList<Control>();
+    requestControls.add(new ServerSideSortRequestControl("displayname:es"));
+    ValidateSortControl(expectedDNOrder,
+            requestControls,
+            "displayname:es.6:=A*");
+  }
+
+
+  /**
+   * Test to verify the Sort control works with Collation greater
+   * than matching rule and English locale in a descending order.
+   */
+  @Test()
+  public void testSortControlGTRule() throws Exception
+  {
+    ArrayList<DN> expectedDNOrder = new ArrayList<DN>();
+    expectedDNOrder.add(user1);
+    expectedDNOrder.add(user2);
+    expectedDNOrder.add(user3);
+    expectedDNOrder.add(user4);
+    ArrayList<Control> requestControls = new ArrayList<Control>();
+    requestControls.add(new ServerSideSortRequestControl("-displayname:en"));
+    ValidateSortControl(expectedDNOrder,
+            requestControls,
+            "displayname:en-US.6:=A*");
+  }
+
+
+
+  /**
+   * Tests the Sort control with the VLV control using a collation equality
+   * matching rule.
+   */
+  @Test()
+  public void testVLVSortControl() throws Exception
+  {
+    ArrayList<DN> expectedDNOrder = new ArrayList<DN>();
+    expectedDNOrder.add(user4);
+    expectedDNOrder.add(user3);
+    expectedDNOrder.add(user2);
+    expectedDNOrder.add(user1);
+    ArrayList<Control> requestControls = new ArrayList<Control>();
+    requestControls.add(new ServerSideSortRequestControl("displayname:fr"));
+    requestControls.add(new VLVRequestControl(0, 4, 1, 0));
+    ValidateSortControl(expectedDNOrder,
+            requestControls,
+            "objectclass=inetOrgPerson");
+  }
+
+
+
+  private void ValidateSortControl(ArrayList<DN> expectedDNOrder,
+          ArrayList<Control> requestControls,
+          String searchFilter) throws Exception
+  {
+    try
+    {
+      populateEntriesForControl();
+      InternalClientConnection conn =
+         InternalClientConnection.getRootConnection();
+
+      InternalSearchOperation internalSearch =
+         new InternalSearchOperation(conn, InternalClientConnection.nextOperationID(),
+                  InternalClientConnection.nextMessageID(), requestControls,
+                  DN.decode("dc=example,dc=com"), SearchScope.WHOLE_SUBTREE,
+                  DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+                  SearchFilter.createFilterFromString(searchFilter),
+                  null, null);
+
+      internalSearch.run();
+      assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
+      ArrayList<DN> returnedDNOrder = new ArrayList<DN>();
+      for (Entry e : internalSearch.getSearchEntries())
+      {
+        returnedDNOrder.add(e.getDN());
+      }
+     assertEquals(returnedDNOrder, expectedDNOrder);
+    }
+    finally
+    {
+      TestCaseUtils.clearJEBackend(false, "userRoot", "dc=example,dc=com");
+    }
+  }
+
+
+  private void populateEntriesForControl() throws Exception
+  {
+    TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+    TestCaseUtils.addEntries(
+      "dn: cn=user1,dc=example,dc=com",
+      "objectclass: inetorgperson",
+      "cn: user1",
+      "sn: user1",
+      "uid: user1",
+      "displayname:: QXVy4oiawqlsaWVuNA==",
+      "",
+      "dn: cn=user2,dc=example,dc=com",
+      "objectclass: inetorgperson",
+      "cn: user2",
+      "sn: user2",
+      "uid: user2",
+      "displayname:: QXVy4oiawqlsaWVuMw==",
+      "",
+      "dn: cn=user3,dc=example,dc=com",
+      "objectclass: inetorgperson",
+      "cn: user3",
+      "sn: user3",
+      "uid: user3",
+      "displayname:: QXVy4oiawqlsaWVuMg==",
+      "",
+      "dn: cn=user4,dc=example,dc=com",
+      "objectclass: inetorgperson",
+      "cn: user4",
+      "sn: user4",
+      "uid: user4",
+      "displayname:: QXVy4oiawqlsaWVuMQ=="
+    );
+  }
 }

--
Gitblit v1.10.0