From 48dfaad29e7758526f1c107ed7b7ee2a0697c0a5 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Thu, 24 Mar 2016 13:15:06 +0000
Subject: [PATCH] Replaced server's SortKey and SortOrder by SDK's SortKey + List<SortKey>

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java            |  100 +++++++-----
 /dev/null                                                                                        |  180 ----------------------
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java      |   16 +-
 opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java    |   25 +-
 opendj-server-legacy/src/main/java/org/opends/server/controls/ServerSideSortRequestControl.java  |   85 +++++-----
 opendj-server-legacy/src/test/java/org/opends/server/controls/ServerSideSortControlTestCase.java |   43 +---
 6 files changed, 132 insertions(+), 317 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
index 4fab79c..eb574fa 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
@@ -51,6 +51,7 @@
 import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.SortKey;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.util.Pair;
 import org.opends.messages.CoreMessages;
@@ -97,7 +98,6 @@
 import org.opends.server.types.Operation;
 import org.opends.server.types.Privilege;
 import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SortOrder;
 import org.opends.server.types.VirtualAttributeRule;
 import org.opends.server.util.ServerConstants;
 import org.opends.server.util.StaticUtils;
@@ -771,8 +771,8 @@
               // this sort key was not found in the user entry.
               try
               {
-                SortOrder sortOrder = sortRequest.getSortOrder();
-                reorderedCandidateEntryIDs = sort(txn, candidateEntryIDs, searchOperation, sortOrder, vlvRequest);
+                List<SortKey> sortKeys = sortRequest.getSortKeys();
+                reorderedCandidateEntryIDs = sort(txn, candidateEntryIDs, searchOperation, sortKeys, vlvRequest);
               }
               catch (DirectoryException de)
               {
@@ -2499,7 +2499,7 @@
   }
 
   private long[] sort(ReadableTransaction txn, EntryIDSet entryIDSet, SearchOperation searchOperation,
-      SortOrder sortOrder, VLVRequestControl vlvRequest) throws DirectoryException
+      List<SortKey> sortKeys, VLVRequestControl vlvRequest) throws DirectoryException
   {
     if (!entryIDSet.isDefined())
     {
@@ -2518,7 +2518,7 @@
         Entry e = getEntry(txn, id);
         if (e.matchesBaseAndScope(baseDN, scope) && filter.matchesEntry(e))
         {
-          sortMap.put(encodeVLVKey(sortOrder, e, id.longValue()), id);
+          sortMap.put(encodeVLVKey(sortKeys, e, id.longValue()), id);
         }
       }
       catch (Exception e)
@@ -2539,7 +2539,7 @@
     {
       return sortByOffset(searchOperation, vlvRequest, sortMap);
     }
-    return sortByGreaterThanOrEqualAssertion(searchOperation, vlvRequest, sortOrder, sortMap);
+    return sortByGreaterThanOrEqualAssertion(searchOperation, vlvRequest, sortKeys, sortMap);
   }
 
   private static final long[] toArray(Collection<EntryID> entryIDs)
@@ -2554,12 +2554,12 @@
   }
 
   private static final long[] sortByGreaterThanOrEqualAssertion(SearchOperation searchOperation,
-      VLVRequestControl vlvRequest, SortOrder sortOrder, final TreeMap<ByteString, EntryID> sortMap)
+      VLVRequestControl vlvRequest, List<SortKey> sortKeys, final TreeMap<ByteString, EntryID> sortMap)
       throws DirectoryException
   {
     ByteString assertionValue = vlvRequest.getGreaterThanOrEqualAssertion();
     ByteSequence encodedTargetAssertion =
-        encodeTargetAssertion(sortOrder, assertionValue, searchOperation, sortMap.size());
+        encodeTargetAssertion(sortKeys, assertionValue, searchOperation, sortMap.size());
 
     boolean targetFound = false;
     int index = 0;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java
index 145993c..499c063 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java
@@ -20,9 +20,11 @@
 import static org.opends.messages.ProtocolMessages.*;
 import static org.opends.server.backends.pluggable.EntryIDSet.*;
 import static org.opends.server.backends.pluggable.IndexFilter.*;
+import static org.opends.server.core.DirectoryServer.*;
 import static org.opends.server.util.StaticUtils.*;
 
 import java.io.Closeable;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
@@ -34,12 +36,15 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
+import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.SortKey;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
 import org.forgerock.util.Reject;
@@ -62,13 +67,10 @@
 import org.opends.server.core.SearchOperation;
 import org.opends.server.protocols.ldap.LDAPResultCode;
 import org.opends.server.types.Attribute;
-import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
 import org.opends.server.types.Modification;
 import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SortKey;
-import org.opends.server.types.SortOrder;
 import org.opends.server.util.StaticUtils;
 
 /**
@@ -96,7 +98,7 @@
   private DN baseDN;
   private SearchScope scope;
   private SearchFilter filter;
-  private SortOrder sortOrder;
+  private List<SortKey> sortKeys;
 
   /** The storage associated with this index. */
   private final Storage storage;
@@ -120,7 +122,7 @@
 
     final ConfigChangeResult ccr = new ConfigChangeResult();
     this.filter = parseSearchFilter(config, getName().toString(), ccr);
-    this.sortOrder = new SortOrder(parseSortKeys(config.getSortOrder(), ccr));
+    this.sortKeys = parseSortKeys(config.getSortOrder(), ccr);
     if (!ccr.getMessages().isEmpty())
     {
       throw new ConfigException(ccr.getMessages().get(0));
@@ -263,7 +265,7 @@
     // Update the sort order only if changed
     if (!config.getSortOrder().equals(cfg.getSortOrder()))
     {
-      this.sortOrder = new SortOrder(parseSortKeys(cfg.getSortOrder(), ccr));
+      this.sortKeys = parseSortKeys(cfg.getSortOrder(), ccr);
       ccr.setAdminActionRequired(true);
     }
 
@@ -285,22 +287,21 @@
     this.config = cfg;
   }
 
-  private SortKey[] parseSortKeys(final String sortOrder, ConfigChangeResult ccr)
+  private List<SortKey> parseSortKeys(final String sortOrder, ConfigChangeResult ccr)
   {
     return parseSortKeys(sortOrder, ccr, getName().toString());
   }
 
-  private static SortKey[] parseSortKeys(final String sortOrder, ConfigChangeResult ccr, String indexName)
+  private static List<SortKey> parseSortKeys(final String sortOrder, ConfigChangeResult ccr, String indexName)
   {
     final String[] sortAttrs = sortOrder.split(" ");
-    final SortKey[] sortKeys = new SortKey[sortAttrs.length];
-    for (int i = 0; i < sortAttrs.length; i++)
+    final List<SortKey> sortKeys = new ArrayList<>(sortAttrs.length);
+    for (String sortAttr : sortAttrs)
     {
-      String sortAttr = sortAttrs[i];
-      final boolean ascending;
+      final boolean isReverseOrder;
       try
       {
-        ascending = !sortAttr.startsWith("-");
+        isReverseOrder = sortAttr.startsWith("-");
 
         if (sortAttr.startsWith("-") || sortAttr.startsWith("+"))
         {
@@ -311,23 +312,24 @@
       {
         ccr.setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
         ccr.addMessage(ERR_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortAttr, indexName));
-        return null;
+        return Collections.emptyList();
       }
 
-      final AttributeType attrType = DirectoryServer.getAttributeType(sortAttr);
+      final AttributeDescription attrDesc = AttributeDescription.valueOf(sortAttr);
+      final AttributeType attrType = attrDesc.getAttributeType();
       if (attrType.isPlaceHolder())
       {
         ccr.setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
         ccr.addMessage(ERR_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortAttr, indexName));
-        return null;
+        return Collections.emptyList();
       }
       if (attrType.getOrderingMatchingRule() == null)
       {
         ccr.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
         ccr.addMessage(INFO_SORTREQ_CONTROL_NO_ORDERING_RULE_FOR_ATTR.get(attrType.getNameOrOID()));
-        return null;
+        return Collections.emptyList();
       }
-      sortKeys[i] = new SortKey(attrType, ascending);
+      sortKeys.add(new SortKey(sortAttr, isReverseOrder));
     }
     return sortKeys;
   }
@@ -411,9 +413,10 @@
 
   private boolean isSortAttributeModified(final List<Modification> mods)
   {
-    for (final SortKey sortKey : sortOrder.getSortKeys())
+    for (final SortKey sortKey : sortKeys)
     {
-      final AttributeType attributeType = sortKey.getAttributeType();
+      final AttributeDescription attrDesc = AttributeDescription.valueOf(sortKey.getAttributeDescription());
+      final AttributeType attributeType = attrDesc.getAttributeType();
       final List<AttributeType> subTypes = DirectoryServer.getSchema().getSubTypes(attributeType);
       for (final Modification mod : mods)
       {
@@ -486,7 +489,7 @@
         !searchOperation.getBaseDN().equals(baseDN) ||
         !searchOperation.getScope().equals(scope) ||
         !searchOperation.getFilter().equals(filter) ||
-        !sortControl.getSortOrder().equals(sortOrder))
+        !sortControl.getSortKeys().equals(sortKeys))
     {
       return null;
     }
@@ -547,7 +550,7 @@
     final int afterCount = vlvRequest.getAfterCount();
     final ByteString assertion = vlvRequest.getGreaterThanOrEqualAssertion();
     final ByteSequence encodedTargetAssertion =
-        encodeTargetAssertion(sortOrder, assertion, searchOperation, currentCount);
+        encodeTargetAssertion(sortKeys, assertion, searchOperation, currentCount);
     try (Cursor<ByteString, ByteString> cursor = txn.openCursor(getName()))
     {
       final LinkedList<Long> selectedIDs = new LinkedList<>();
@@ -616,10 +619,10 @@
   }
 
   /** Normalize the assertion using the primary key's ordering matching rule. */
-  static ByteSequence encodeTargetAssertion(final SortOrder sortOrder, final ByteString assertion,
+  static ByteSequence encodeTargetAssertion(final List<SortKey> sortKeys, final ByteString assertion,
       final SearchOperation searchOperation, final int resultSetSize) throws DirectoryException
   {
-    final SortKey primarySortKey = sortOrder.getSortKeys()[0];
+    final SortKey primarySortKey = sortKeys.get(0);
     try
     {
       /*
@@ -628,16 +631,16 @@
        * include some escaped bytes as well. 10 extra bytes should accommodate most inputs.
        */
       final ByteStringBuilder encodedPrimaryKey = new ByteStringBuilder(assertion.length() + 10);
-      final MatchingRule matchingRule = primarySortKey.getEffectiveOrderingRule();
+      final MatchingRule matchingRule = getEffectiveOrderingRule(primarySortKey);
       final ByteString normalizedAttributeValue = matchingRule.normalizeAttributeValue(assertion);
-      encodeVLVKeyValue(normalizedAttributeValue, encodedPrimaryKey, primarySortKey.ascending());
+      encodeVLVKeyValue(normalizedAttributeValue, encodedPrimaryKey, primarySortKey.isReverseOrder());
       return encodedPrimaryKey;
     }
     catch (final DecodeException e)
     {
       addVLVResponseControl(searchOperation, 0, resultSetSize, LDAPResultCode.OFFSET_RANGE_ERROR);
-      final String attributeName = primarySortKey.getAttributeType().getNameOrOID();
-      throw new DirectoryException(ResultCode.VIRTUAL_LIST_VIEW_ERROR, ERR_VLV_BAD_ASSERTION.get(attributeName));
+      final String attrDesc = primarySortKey.getAttributeDescription();
+      throw new DirectoryException(ResultCode.VIRTUAL_LIST_VIEW_ERROR, ERR_VLV_BAD_ASSERTION.get(attrDesc));
     }
   }
 
@@ -779,23 +782,23 @@
 
   private ByteString encodeVLVKey(final Entry entry, final long entryID)
   {
-    return encodeVLVKey(sortOrder, entry, entryID);
+    return encodeVLVKey(sortKeys, entry, entryID);
   }
 
-  static ByteString encodeVLVKey(final SortOrder sortOrder, final Entry entry, final long entryID)
+  static ByteString encodeVLVKey(final List<SortKey> sortKeys, final Entry entry, final long entryID)
   {
     final ByteStringBuilder builder = new ByteStringBuilder();
-    encodeVLVKey0(sortOrder, entry, builder);
+    encodeVLVKey0(sortKeys, entry, builder);
     builder.appendLong(entryID);
     return builder.toByteString();
   }
 
-  private static void encodeVLVKey0(final SortOrder sortOrder, final Entry entry, final ByteStringBuilder builder)
+  private static void encodeVLVKey0(final List<SortKey> sortKeys, final Entry entry, final ByteStringBuilder builder)
   {
-    for (final SortKey sortKey : sortOrder.getSortKeys())
+    for (final SortKey sortKey : sortKeys)
     {
       ByteString sortValue = getLowestAttributeValue(entry, sortKey);
-      encodeVLVKeyValue(sortValue, builder, sortKey.ascending());
+      encodeVLVKeyValue(sortValue, builder, sortKey.isReverseOrder());
     }
   }
 
@@ -805,10 +808,10 @@
    */
   private static ByteString getLowestAttributeValue(final Entry entry, final SortKey sortKey)
   {
-    final AttributeType attributeType = sortKey.getAttributeType();
-    final MatchingRule matchingRule = sortKey.getEffectiveOrderingRule();
+    final AttributeDescription attrDesc = AttributeDescription.valueOf(sortKey.getAttributeDescription());
+    final MatchingRule matchingRule = getEffectiveOrderingRule(sortKey);
     ByteString sortValue = null;
-    for (Attribute a : entry.getAttribute(attributeType))
+    for (Attribute a : entry.getAttribute(attrDesc.getAttributeType()))
     {
       for (ByteString v : a)
       {
@@ -833,6 +836,21 @@
     return sortValue;
   }
 
+  private static MatchingRule getEffectiveOrderingRule(SortKey sortKey)
+  {
+    String mrOid = sortKey.getOrderingMatchingRule();
+    if (mrOid != null)
+    {
+      MatchingRule orderingRule = getMatchingRule(mrOid);
+      if (orderingRule != null)
+      {
+        return orderingRule;
+      }
+    }
+    AttributeDescription attrDesc = AttributeDescription.valueOf(sortKey.getAttributeDescription());
+    return attrDesc.getAttributeType().getOrderingMatchingRule();
+  }
+
   /**
    * Package private for testing.
    * <p>
@@ -853,12 +871,12 @@
    * </ul>
    */
   static void encodeVLVKeyValue(final ByteString keyBytes, final ByteStringBuilder builder,
-      final boolean ascending)
+      final boolean isReverseOrder)
   {
-    final byte separator = ascending ? (byte) 0x00 : (byte) 0xff;
+    final byte separator = !isReverseOrder ? (byte) 0x00 : (byte) 0xff;
     if (keyBytes != null)
     {
-      final byte escape = ascending ? (byte) 0x01 : (byte) 0xfe;
+      final byte escape = !isReverseOrder ? (byte) 0x01 : (byte) 0xfe;
       final byte sortOrderMask = separator;
       final int length = keyBytes.length();
       for (int i = 0; i < length; i++)
@@ -884,7 +902,7 @@
     else
     {
       // Ensure that null keys sort after (ascending) or before (descending) all other keys.
-      builder.appendByte(ascending ? 0xFF : 0x00);
+      builder.appendByte(!isReverseOrder ? 0xFF : 0x00);
     }
     builder.appendByte(separator);
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/controls/ServerSideSortRequestControl.java b/opendj-server-legacy/src/main/java/org/opends/server/controls/ServerSideSortRequestControl.java
index 05366ee..29cf785 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/controls/ServerSideSortRequestControl.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/controls/ServerSideSortRequestControl.java
@@ -16,25 +16,30 @@
  */
 package org.opends.server.controls;
 
+import static org.opends.messages.ProtocolMessages.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
+
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.StringTokenizer;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.opendj.io.ASN1;
 import org.forgerock.opendj.io.ASN1Reader;
 import org.forgerock.opendj.io.ASN1Writer;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.SortKey;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.protocols.ldap.LDAPResultCode;
-import org.opends.server.types.*;
-
-import static org.opends.messages.ProtocolMessages.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
+import org.opends.server.types.Control;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.LDAPException;
 
 /**
  * This class implements the server-side sort request control as defined in RFC
@@ -104,12 +109,11 @@
           {
             //This attribute is not defined in the schema. There is no point
             //iterating over the next attribute and return a partially sorted result.
-            return new ServerSideSortRequestControl(isCritical,
-            new SortOrder(sortKeys.toArray(new SortKey[0])));
+            return new ServerSideSortRequestControl(isCritical, sortKeys);
           }
 
           MatchingRule orderingRule = null;
-          boolean ascending = true;
+          boolean isReverseOrder = false;
           if(reader.hasNextElement() &&
               reader.peekType() == TYPE_ORDERING_RULE_ID)
           {
@@ -129,7 +133,7 @@
           if(reader.hasNextElement() &&
               reader.peekType() == TYPE_REVERSE_ORDER)
           {
-            ascending = ! reader.readBoolean();
+            isReverseOrder = reader.readBoolean();
           }
           reader.readEndSequence();
 
@@ -140,12 +144,11 @@
             throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
           }
 
-          sortKeys.add(new SortKey(attrType, ascending, orderingRule));
+          sortKeys.add(new SortKey(AttributeDescription.create(attrType), isReverseOrder, orderingRule));
         }
         reader.readEndSequence();
 
-        return new ServerSideSortRequestControl(isCritical,
-            new SortOrder(sortKeys.toArray(new SortKey[0])));
+        return new ServerSideSortRequestControl(isCritical, sortKeys);
       }
       catch (DirectoryException de)
       {
@@ -175,10 +178,9 @@
       new Decoder();
 
   /** The sort order associated with this control represented by strings. */
-  private ArrayList<String[]> decodedKeyList;
-
+  private List<String[]> decodedKeyList;
   /** The sort order associated with this control. */
-  private SortOrder sortOrder;
+  private List<SortKey> sortKeys;
 
   /**
    * Creates a new server-side sort request control based on the definition in
@@ -289,11 +291,11 @@
    * Creates a new server-side sort request control based on the provided sort
    * order.
    *
-   * @param  sortOrder  The sort order to use for this control.
+   * @param  sortKeys  The sort order to use for this control.
    */
-  public ServerSideSortRequestControl(SortOrder sortOrder)
+  public ServerSideSortRequestControl(List<SortKey> sortKeys)
   {
-    this(false, sortOrder);
+    this(false, sortKeys);
   }
 
   /**
@@ -302,14 +304,14 @@
    *
    * @param  isCritical    Indicates whether support for this control should be
    *                       considered a critical part of the server processing.
-   * @param  sortOrder     sort order associated with this server-side sort
+   * @param  sortKeys     sort order associated with this server-side sort
    *                       control.
    */
-  public ServerSideSortRequestControl(boolean isCritical, SortOrder sortOrder)
+  public ServerSideSortRequestControl(boolean isCritical, List<SortKey> sortKeys)
   {
     super(OID_SERVER_SIDE_SORT_REQUEST_CONTROL, isCritical);
 
-    this.sortOrder = sortOrder;
+    this.sortKeys = sortKeys;
   }
 
 
@@ -317,17 +319,15 @@
    * Retrieves the sort order for this server-side sort request control.
    *
    * @return  The sort order for this server-side sort request control.
-   * @throws  DirectoryException if an error occurs while retriving the
-   *          sort order.
+   * @throws  DirectoryException if an error occurs while retrieving the sort order.
    */
-  public SortOrder getSortOrder() throws DirectoryException
+  public List<SortKey> getSortKeys() throws DirectoryException
   {
-    if(sortOrder == null)
+    if (sortKeys == null)
     {
-      sortOrder = decodeSortOrderFromString();
+      sortKeys = decodeSortKeysFromString();
     }
-
-    return sortOrder;
+    return sortKeys;
   }
 
   /**
@@ -344,7 +344,7 @@
    */
   public boolean  containsSortKeys() throws DirectoryException
   {
-    return getSortOrder().getSortKeys().length!=0;
+    return !getSortKeys().isEmpty();
   }
 
   /**
@@ -381,7 +381,7 @@
   public void toString(StringBuilder buffer)
   {
     buffer.append("ServerSideSortRequestControl(");
-    if(sortOrder == null)
+    if (sortKeys == null)
     {
       buffer.append("SortOrder(");
 
@@ -399,7 +399,7 @@
     }
     else
     {
-      buffer.append(sortOrder);
+      buffer.append(sortKeys);
     }
     buffer.append(")");
   }
@@ -426,9 +426,9 @@
     buffer.append(")");
   }
 
-  private SortOrder decodeSortOrderFromString() throws DirectoryException
+  private List<SortKey> decodeSortKeysFromString() throws DirectoryException
   {
-    ArrayList<SortKey> sortKeys = new ArrayList<>();
+    List<SortKey> sortKeys = new ArrayList<>();
     for(String[] decodedKey : decodedKeyList)
     {
       AttributeType attrType = DirectoryServer.getAttributeType(decodedKey[0]);
@@ -436,7 +436,7 @@
       {
         //This attribute is not defined in the schema. There is no point
         //iterating over the next attribute and return a partially sorted result.
-        return new SortOrder(sortKeys.toArray(new SortKey[0]));
+        return sortKeys;
       }
 
       MatchingRule orderingRule = null;
@@ -451,7 +451,7 @@
       }
 
       String decodedKey2 = decodedKey[2];
-      boolean ascending = decodedKey2 == null || !decodedKey2.equals("r");
+      boolean isReverseOrder = decodedKey2 != null && decodedKey2.equals("r");
       if (orderingRule == null
           && attrType.getOrderingMatchingRule() == null)
       {
@@ -459,10 +459,10 @@
             INFO_SORTREQ_CONTROL_NO_ORDERING_RULE_FOR_ATTR.get(decodedKey[0]));
       }
 
-      sortKeys.add(new SortKey(attrType, ascending, orderingRule));
+      sortKeys.add(new SortKey(AttributeDescription.create(attrType), isReverseOrder, orderingRule));
     }
 
-    return new SortOrder(sortKeys.toArray(new SortKey[0]));
+    return sortKeys;
   }
 
   private void writeValueFromString(ASN1Writer writer) throws IOException
@@ -497,18 +497,17 @@
     writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE);
 
     writer.writeStartSequence();
-    for (SortKey sortKey : sortOrder.getSortKeys())
+    for (SortKey sortKey : sortKeys)
     {
       writer.writeStartSequence();
-      writer.writeOctetString(sortKey.getAttributeType().getNameOrOID());
+      writer.writeOctetString(sortKey.getAttributeDescription());
 
-      if (sortKey.getOrderingRule() != null)
+      if (sortKey.getOrderingMatchingRule() != null)
       {
-        writer.writeOctetString(TYPE_ORDERING_RULE_ID,
-            sortKey.getOrderingRule().getNameOrOID());
+        writer.writeOctetString(TYPE_ORDERING_RULE_ID, sortKey.getOrderingMatchingRule());
       }
 
-      if (! sortKey.ascending())
+      if (sortKey.isReverseOrder())
       {
         writer.writeBoolean(TYPE_REVERSE_ORDER, true);
       }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/SortKey.java b/opendj-server-legacy/src/main/java/org/opends/server/types/SortKey.java
deleted file mode 100644
index 4b1ff95..0000000
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/SortKey.java
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * The contents of this file are subject to the terms of the Common Development and
- * Distribution License (the License). You may not use this file except in compliance with the
- * License.
- *
- * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
- * specific language governing permission and limitations under the License.
- *
- * When distributing Covered Software, include this CDDL Header Notice in each file and include
- * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
- * Header, with the fields enclosed by brackets [] replaced by your own identifying
- * information: "Portions Copyright [year] [name of copyright owner]".
- *
- * Copyright 2008 Sun Microsystems, Inc.
- * Portions Copyright 2014-2016 ForgeRock AS.
- */
-package org.opends.server.types;
-
-import org.forgerock.opendj.ldap.schema.AttributeType;
-
-import org.forgerock.i18n.slf4j.LocalizedLogger;
-import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.schema.MatchingRule;
-
-/**
- * This class defines a data structure that may be used as a sort key.
- * It includes an attribute type and a boolean value that indicates
- * whether the sort should be ascending or descending.  It may also
- * contain a specific ordering matching rule that should be used for
- * the sorting process, although if none is provided it will use the
- * default ordering matching rule for the attribute type.
- * <p>
- * FIXME: replace with the equivalent SDK type.
- */
-@org.opends.server.types.PublicAPI(
-     stability=org.opends.server.types.StabilityLevel.VOLATILE,
-     mayInstantiate=true,
-     mayExtend=false,
-     mayInvoke=true)
-public final class SortKey
-{
-  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
-
-  /** The attribute type for this sort key. */
-  private AttributeType attributeType;
-  /** The indication of whether the sort should be ascending. */
-  private boolean ascending;
-  /** The ordering matching rule to use with this sort key. */
-  private MatchingRule orderingRule;
-
-
-
-  /**
-   * Creates a new sort key with the provided information.
-   *
-   * @param  attributeType  The attribute type for this sort key.
-   * @param  ascending      Indicates whether the sort should be in
-   *                        ascending order rather than descending.
-   */
-  public SortKey(AttributeType attributeType, boolean ascending)
-  {
-    this(attributeType, ascending, null);
-  }
-
-
-
-  /**
-   * Creates a new sort key with the provided information.
-   *
-   * @param  attributeType  The attribute type for this sort key.
-   * @param  ascending      Indicates whether the sort should be in
-   *                        ascending order rather than descending.
-   * @param  orderingRule   The ordering matching rule to use with
-   *                        this sort key.
-   */
-  public SortKey(AttributeType attributeType, boolean ascending, MatchingRule orderingRule)
-  {
-    this.attributeType = attributeType;
-    this.ascending     = ascending;
-    this.orderingRule  = orderingRule;
-  }
-
-
-
-  /**
-   * Retrieves the attribute type for this sort key.
-   *
-   * @return  The attribute type for this sort key.
-   */
-  public AttributeType getAttributeType()
-  {
-    return attributeType;
-  }
-
-
-
-  /**
-   * Indicates whether the specified attribute should be sorted in
-   * ascending order.
-   *
-   * @return  {@code true} if the attribute should be sorted in
-   *          ascending order, or {@code false} if it should be sorted
-   *          in descending order.
-   */
-  public boolean ascending()
-  {
-    return ascending;
-  }
-
-
-
-  /**
-   * Retrieves the ordering matching rule to use with this sort key.
-   *
-   * @return  The ordering matching rule to use with this sort key.
-   */
-  public MatchingRule getOrderingRule()
-  {
-    return orderingRule;
-  }
-
-  /**
-   * Retrieves the ordering matching rule to use with this sort key.
-   *
-   * @return The ordering matching rule to use with this sort key.
-   */
-  public MatchingRule getEffectiveOrderingRule()
-  {
-    return orderingRule != null ? orderingRule : attributeType.getOrderingMatchingRule();
-  }
-
-  /**
-   * Compares the provided values using this sort key.
-   *
-   * @param  value1  The first value to be compared.
-   * @param  value2  The second value to be compared.
-   *
-   * @return  A negative value if the first value should come before
-   *          the second in a sorted list, a positive value if the
-   *          first value should come after the second in a sorted
-   *          list, or zero if there is no relative difference between
-   *          the values.
-   */
-  public int compareValues(ByteString value1, ByteString value2)
-  {
-    // A null value will always come after a non-null value.
-    if (value1 == null)
-    {
-      if (value2 == null)
-      {
-        return 0;
-      }
-      else
-      {
-        return 1;
-      }
-    }
-    else if (value2 == null)
-    {
-      return -1;
-    }
-
-
-    // Use the ordering matching rule if one is provided.
-    // Otherwise, fall back on the default ordering rule for the attribute type.
-    if (orderingRule != null)
-    {
-      return compareValues(orderingRule, value1, value2);
-    }
-    final MatchingRule rule = attributeType.getOrderingMatchingRule();
-    if (rule != null)
-    {
-      return compareValues(rule, value1, value2);
-    }
-    return 0;
-  }
-
-  private int compareValues(MatchingRule rule, ByteString value1,
-      ByteString value2)
-  {
-    try
-    {
-      final ByteString val1 = rule.normalizeAttributeValue(value1);
-      final ByteString val2 = rule.normalizeAttributeValue(value2);
-      return ascending ? val1.compareTo(val2) : val2.compareTo(val1);
-    }
-    catch (Exception e)
-    {
-      logger.traceException(e);
-      return 0;
-    }
-  }
-
-
-
-  /**
-   * Retrieves a string representation of this sort key.
-   *
-   * @return  A string representation of this sort key.
-   */
-  @Override
-  public String toString()
-  {
-    StringBuilder buffer = new StringBuilder();
-    toString(buffer);
-    return buffer.toString();
-  }
-
-
-
-  /**
-   * Appends a string representation of this sort key to the
-   * provided buffer.
-   *
-   * @param  buffer  The buffer to which the information should be
-   *                 appended.
-   */
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("SortKey(");
-    if (ascending)
-    {
-      buffer.append("+");
-    }
-    else
-    {
-      buffer.append("-");
-    }
-    buffer.append(attributeType.getNameOrOID());
-
-    if (orderingRule != null)
-    {
-      buffer.append(":");
-      buffer.append(orderingRule.getNameOrOID());
-    }
-
-    buffer.append(")");
-  }
-
-  /**
-   * Retrieves the hash code for this sort key.
-   *
-   * @return  The hash code for this sort key.
-   */
-  @Override
-  public int hashCode()
-  {
-    int hashCode = 0;
-
-    if(ascending)
-    {
-      hashCode += 1;
-    }
-
-    hashCode += attributeType.hashCode();
-
-    if(orderingRule != null)
-    {
-      hashCode += orderingRule.hashCode();
-    }
-
-    return hashCode;
-  }
-
-  /**
-   * Indicates whether this sort key is equal to the provided
-   * object.
-   *
-   * @param  o  The object for which to make the determination.
-   *
-   * @return  <CODE>true</CODE> if the provide object is equal to this
-   *          sort key, or <CODE>false</CODE> if it is not.
-   */
-  @Override
-  public boolean equals(Object o)
-  {
-    if(o == null)
-    {
-      return false;
-    }
-
-    if (o == this)
-    {
-      return true;
-    }
-
-    if (! (o instanceof SortKey))
-    {
-      return false;
-    }
-
-    SortKey s = (SortKey) o;
-
-    if(ascending != s.ascending)
-    {
-      return false;
-    }
-
-    if(!attributeType.equals(s.attributeType))
-    {
-      return false;
-    }
-
-    if(orderingRule != null)
-    {
-      if(s.orderingRule != null)
-      {
-        if(!orderingRule.equals(s.orderingRule))
-        {
-          return false;
-        }
-      }
-      else if(!orderingRule.equals(
-          s.attributeType.getOrderingMatchingRule()))
-      {
-        return false;
-      }
-    }
-    else if(s.orderingRule != null)
-    {
-      if(!attributeType.getOrderingMatchingRule().equals(
-          s.orderingRule))
-      {
-        return false;
-      }
-    }
-
-    return true;
-  }
-}
-
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/SortOrder.java b/opendj-server-legacy/src/main/java/org/opends/server/types/SortOrder.java
deleted file mode 100644
index 4320153..0000000
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/SortOrder.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * The contents of this file are subject to the terms of the Common Development and
- * Distribution License (the License). You may not use this file except in compliance with the
- * License.
- *
- * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
- * specific language governing permission and limitations under the License.
- *
- * When distributing Covered Software, include this CDDL Header Notice in each file and include
- * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
- * Header, with the fields enclosed by brackets [] replaced by your own identifying
- * information: "Portions Copyright [year] [name of copyright owner]".
- *
- * Copyright 2008 Sun Microsystems, Inc.
- * Portions Copyright 2014 ForgeRock AS.
- */
-package org.opends.server.types;
-
-/**
- * This class defines a data structure that defines a set of sort
- * criteria that may be used to order entries in a set of search
- * results.  The sort order object is comprised of one or more sort
- * keys, which indicate which attribute types should be used to
- * perform the sort and information about the ordering to use for
- * those attributes.  If the sort order has multiple sort keys, then
- * the first sort key will be used as the primary sort criteria, and
- * the second will only be used in cases where the values of the
- * attribute associated with the first sort key are equal, the third
- * will only be used if the first and second values are equal, etc.
- * If all of the sort key attributes for two entries are identical,
- * then the relative order for those entries is undefined.
- * <p>
- * FIXME: replace with the SDK's SortKey?
- */
-@org.opends.server.types.PublicAPI(
-     stability=org.opends.server.types.StabilityLevel.VOLATILE,
-     mayInstantiate=true,
-     mayExtend=false,
-     mayInvoke=true)
-public final class SortOrder
-{
-  /** The set of sort keys in this sort order. */
-  private SortKey[] sortKeys;
-
-  /**
-   * Creates a new sort order with a single key.
-   *
-   * @param  sortKey  The sort key to use in this sort order.
-   */
-  public SortOrder(SortKey sortKey)
-  {
-    this.sortKeys = new SortKey[] { sortKey };
-  }
-
-
-
-  /**
-   * Creates a new sort order with the provided set of sort keys.
-   *
-   * @param  sortKeys  The set of sort keys to use for this sort
-   *                   order.
-   */
-  public SortOrder(SortKey... sortKeys)
-  {
-    this.sortKeys = new SortKey[sortKeys.length];
-    System.arraycopy(sortKeys, 0, this.sortKeys, 0, sortKeys.length);
-  }
-
-
-
-  /**
-   * Retrieves the sort keys for this sort order.
-   *
-   * @return  The sort keys for this sort order.
-   */
-  public SortKey[] getSortKeys()
-  {
-    return sortKeys;
-  }
-
-
-
-  /**
-   * Retrieves a string representation of this sort order.
-   *
-   * @return  A string representation of this sort order.
-   */
-  @Override
-  public String toString()
-  {
-    StringBuilder buffer = new StringBuilder();
-    toString(buffer);
-    return buffer.toString();
-  }
-
-
-
-  /**
-   * Appends a string representation of this sort order to the
-   * provided buffer.
-   *
-   * @param  buffer  The buffer to which the information should be
-   *                 appended.
-   */
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("SortOrder(");
-
-    if (sortKeys.length > 0)
-    {
-      sortKeys[0].toString(buffer);
-
-      for (int i=1; i < sortKeys.length; i++)
-      {
-        buffer.append(",");
-        sortKeys[i].toString(buffer);
-      }
-    }
-
-    buffer.append(")");
-  }
-
-  /**
-   * Retrieves the hash code for this sort order.
-   *
-   * @return  The hash code for this sort order.
-   */
-  @Override
-  public int hashCode()
-  {
-    int hashCode = 0;
-    for(SortKey sortKey : sortKeys)
-    {
-      hashCode += sortKey.hashCode();
-    }
-    return hashCode;
-  }
-
-  /**
-   * Indicates whether this sort order is equal to the provided
-   * object.
-   *
-   * @param  o  The object for which to make the determination.
-   *
-   * @return  <CODE>true</CODE> if the provide object is equal to this
-   *          sort order, or <CODE>false</CODE> if it is not.
-   */
-  @Override
-  public boolean equals(Object o)
-  {
-    if(o == null)
-    {
-      return false;
-    }
-    if (o == this)
-    {
-      return true;
-    }
-    if (! (o instanceof SortOrder))
-    {
-      return false;
-    }
-
-    SortOrder s = (SortOrder) o;
-    if(sortKeys.length != s.sortKeys.length)
-    {
-      return false;
-    }
-
-    for(int i = 0; i < sortKeys.length; i++)
-    {
-      if(!sortKeys[i].equals(s.sortKeys[i]))
-      {
-        return false;
-      }
-    }
-    return true;
-  }
-}
-
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java
index b7a70e4..4a8135f 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java
@@ -33,6 +33,7 @@
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
+import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
 import org.opends.server.DirectoryServerTestCase;
@@ -52,7 +53,6 @@
 import org.opends.server.protocols.ldap.LDAPControl;
 import org.opends.server.protocols.ldap.LDAPResultCode;
 import org.opends.server.types.Control;
-import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
 import org.opends.server.types.SearchResultEntry;
@@ -207,31 +207,28 @@
   @Test(dataProvider = "encodedKeyDataProvider")
   public void vlvKeyEncodingGenerateCorrectAscendingSortOrder(String key1, String key2, int expectedCompareResult)
   {
-    ByteString bytes1 = key1 != null ? ByteString.valueOfHex(key1) : null;
-    ByteStringBuilder encodedBytes1 = new ByteStringBuilder();
-    VLVIndex.encodeVLVKeyValue(bytes1, encodedBytes1, true);
-
-    ByteString bytes2 = key2 != null ? ByteString.valueOfHex(key2) : null;
-    ByteStringBuilder encodedBytes2 = new ByteStringBuilder();
-    VLVIndex.encodeVLVKeyValue(bytes2, encodedBytes2, true);
-
-    int actualResult = Math.min(Math.max(encodedBytes1.compareTo(encodedBytes2), -1), 1);
-    assertThat(actualResult).isEqualTo(expectedCompareResult);
+    vlvKeyEncodingGenerateCorrectSortOrder(key1, key2, expectedCompareResult, false);
   }
 
   @Test(dataProvider = "encodedKeyDataProvider")
   public void vlvKeyEncodingGenerateCorrectDescendingSortOrder(String key1, String key2, int expectedCompareResult)
   {
+    vlvKeyEncodingGenerateCorrectSortOrder(key1, key2, expectedCompareResult, true);
+  }
+
+  private void vlvKeyEncodingGenerateCorrectSortOrder(String key1, String key2, int expectedCompareResult,
+      boolean isReverseOrder)
+  {
     ByteString bytes1 = key1 != null ? ByteString.valueOfHex(key1) : null;
     ByteStringBuilder encodedBytes1 = new ByteStringBuilder();
-    VLVIndex.encodeVLVKeyValue(bytes1, encodedBytes1, false);
+    VLVIndex.encodeVLVKeyValue(bytes1, encodedBytes1, isReverseOrder);
 
     ByteString bytes2 = key2 != null ? ByteString.valueOfHex(key2) : null;
     ByteStringBuilder encodedBytes2 = new ByteStringBuilder();
-    VLVIndex.encodeVLVKeyValue(bytes2, encodedBytes2, false);
+    VLVIndex.encodeVLVKeyValue(bytes2, encodedBytes2, isReverseOrder);
 
     int actualResult = Math.min(Math.max(encodedBytes1.compareTo(encodedBytes2), -1), 1);
-    assertThat(actualResult).isEqualTo(-expectedCompareResult);
+    assertThat(actualResult).isEqualTo(isReverseOrder ? -expectedCompareResult : expectedCompareResult);
   }
 
   @DataProvider
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/controls/ServerSideSortControlTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/controls/ServerSideSortControlTestCase.java
index 53c824c..a1cda21 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/controls/ServerSideSortControlTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/controls/ServerSideSortControlTestCase.java
@@ -21,21 +21,18 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.SortKey;
 import org.opends.server.TestCaseUtils;
-import org.opends.server.core.DirectoryServer;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.SearchRequest;
 import org.opends.server.protocols.ldap.LDAPControl;
-import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.types.Control;
-import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
 import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SortKey;
-import org.opends.server.types.SortOrder;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -51,11 +48,6 @@
 public class ServerSideSortControlTestCase
     extends ControlsTestCase
 {
-  /** The givenName attribute type. */
-  private AttributeType givenNameType;
-  /** The sn attribute type. */
-  private AttributeType snType;
-
   /** The DN for "Aaccf Johnson". */
   DN aaccfJohnsonDN;
   /** The DN for "Aaron Zimmerman". */
@@ -87,12 +79,6 @@
   {
     TestCaseUtils.startServer();
 
-    givenNameType = DirectoryServer.getAttributeType("givenname");
-    assertNotNull(givenNameType);
-
-    snType = DirectoryServer.getAttributeType("sn");
-    assertNotNull(snType);
-
     aaccfJohnsonDN    = DN.valueOf("uid=aaccf.johnson,dc=example,dc=com");
     aaronZimmermanDN  = DN.valueOf("uid=aaron.zimmerman,dc=example,dc=com");
     albertSmithDN     = DN.valueOf("uid=albert.smith,dc=example,dc=com");
@@ -221,23 +207,18 @@
   @Test
   public void testRequestConstructor1() throws Exception
   {
-    SortKey sortKey = new SortKey(givenNameType, true);
-    SortOrder sortOrder = new SortOrder(sortKey);
-    new ServerSideSortRequestControl(sortOrder).toString();
-    sortKey.toString();
-    sortOrder.toString();
+    SortKey sortKey = new SortKey("givenName", false);
+    List<SortKey> sortKeys = Arrays.asList(sortKey);
+    new ServerSideSortRequestControl(sortKeys).toString();
 
-    sortKey = new SortKey(givenNameType, false);
-    sortOrder = new SortOrder(sortKey);
-    new ServerSideSortRequestControl(sortOrder).toString();
-    sortKey.toString();
-    sortOrder.toString();
+    sortKey = new SortKey("givenName", true);
+    sortKeys = Arrays.asList(sortKey);
+    new ServerSideSortRequestControl(sortKeys).toString();
 
-    sortOrder = new SortOrder(
-      new SortKey(snType, true),
-      new SortKey(givenNameType, true));
-    new ServerSideSortRequestControl(sortOrder).toString();
-    sortOrder.toString();
+    sortKeys = Arrays.asList(
+      new SortKey("sn", false),
+      new SortKey("givenName", false));
+    new ServerSideSortRequestControl(sortKeys).toString();
   }
 
 

--
Gitblit v1.10.0