From 1f5e18cc0adb4ca85c69257c7ee95ce9718d1eba Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 17 Mar 2014 09:54:42 +0000
Subject: [PATCH] OPENDJ-1368 Remove AttributeValue

---
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java       |   22 +-
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java                               |  101 +++++++-----
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValues.java                                  |   44 ++++-
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java                            |   31 ++-
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java        |   67 +++----
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java                                   |    8 
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/StringPrepProfileTestCase.java |   21 +-
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java                                    |  154 +++++++++++-------
 8 files changed, 267 insertions(+), 181 deletions(-)

diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValues.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValues.java
index 7c9bc37..a9436f1 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValues.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValues.java
@@ -22,11 +22,10 @@
  *
  *
  *      Copyright 2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2014 ForgeRock AS
  */
 package org.opends.server.backends.jeb;
 
-
-
 import java.util.List;
 
 import org.opends.server.types.Attribute;
@@ -36,7 +35,6 @@
 import org.opends.server.types.SortKey;
 import org.opends.server.types.SortOrder;
 
-
 /**
  * This class defines a data structure that holds a set of attribute values that
  * are associated with a sort order for a given entry.  Any or all of the
@@ -46,17 +44,25 @@
  * This class implements the {@code Comparable} interface and may therefore be
  * used to order the elements in components like {@code TreeMap} and
  * {@code TreeSet}.
+ * <p>
+ * FIXME: replace with the SDK's SortKey?
  */
 public class SortValues
        implements Comparable<SortValues>
 {
-  // The set of sort keys in this sort order.
+  /** The set of sort keys (attribute values) in this sort order. */
   private AttributeValue[] values;
+  /**
+   * The types of sort keys.
+   *
+   * @see #values
+   */
+  private AttributeType[] types;
 
-  // The entry ID for the entry associated with this sort values.
+  /** The entry ID for the entry associated with this sort values. */
   private EntryID entryID;
 
-  // The sort order for this set of sort values.
+  /** The sort order for this set of sort values. */
   private SortOrder sortOrder;
 
 
@@ -75,6 +81,13 @@
     this.entryID = entryID;
     this.sortOrder = sortOrder;
     this.values = values;
+
+    final SortKey[] sortKeys = sortOrder.getSortKeys();
+    this.types = new AttributeType[sortKeys.length];
+    for (int i = 0; i < sortKeys.length; i++)
+    {
+      types[i] = sortKeys[i].getAttributeType();
+    }
   }
 
   /**
@@ -92,12 +105,13 @@
     this.sortOrder = sortOrder;
 
     SortKey[] sortKeys = sortOrder.getSortKeys();
-    values = new AttributeValue[sortKeys.length];
+    this.values = new AttributeValue[sortKeys.length];
+    this.types = new AttributeType[sortKeys.length];
     for (int i=0; i < sortKeys.length; i++)
     {
       SortKey sortKey = sortKeys[i];
-      AttributeType attrType = sortKey.getAttributeType();
-      List<Attribute> attrList = entry.getAttribute(attrType);
+      types[i] = sortKey.getAttributeType();
+      List<Attribute> attrList = entry.getAttribute(types[i]);
       if (attrList != null)
       {
         AttributeValue sortValue = null;
@@ -145,6 +159,7 @@
    *          list, or zero if there is no significant difference in their
    *          relative order.
    */
+  @Override
   public int compareTo(SortValues sortValues)
   {
     SortKey[] sortKeys = sortOrder.getSortKeys();
@@ -205,6 +220,7 @@
    *
    * @return  A string representation of this sort values object.
    */
+  @Override
   public String toString()
   {
     StringBuilder buffer = new StringBuilder();
@@ -269,6 +285,16 @@
   }
 
   /**
+   * Retrieve the type of the attribute values in this sort values.
+   *
+   * @return The array of type of the attribute values for this sort values.
+   */
+  public AttributeType[] getTypes()
+  {
+    return types;
+  }
+
+  /**
    * Retrieve the entry ID in this sort values.
    *
    * @return The entry ID for this sort values.
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java
index 482914e..c324444 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java
@@ -26,9 +26,13 @@
  */
 package org.opends.server.backends.jeb;
 
-import org.opends.server.types.*;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.opends.server.api.MatchingRule;
+import org.opends.server.types.*;
+
 import com.sleepycat.je.DatabaseException;
 
 /**
@@ -40,7 +44,6 @@
   private long[] entryIDs;
 
   private int[] valuesBytesOffsets;
-
   private byte[] valuesBytes;
 
   private byte[] keyBytes;
@@ -95,13 +98,14 @@
    *
    * @param entryID The entry ID to add.
    * @param values The values to add.
+   * @param types The types of the values to add.
    * @return True if the information was successfully added or False
    * otherwise.
    * @throws DirectoryException If a Directory Server error occurs.
    * @throws DatabaseException If an error occurs in the JE database.
    */
-  public boolean add(long entryID, AttributeValue[] values)
-      throws DatabaseException, DirectoryException
+  public boolean add(long entryID, AttributeValue[] values,
+      AttributeType[] types) throws DatabaseException, DirectoryException
   {
     if(values == null)
     {
@@ -110,24 +114,22 @@
 
     if(entryIDs == null || entryIDs.length == 0)
     {
-      entryIDs = new long[1];
-      entryIDs[0] = entryID;
-      valuesBytes = attributeValuesToDatabase(values);
+      entryIDs = new long[] { entryID };
+      valuesBytes = attributeValuesToDatabase(values, types);
       if(valuesBytesOffsets != null)
       {
-        valuesBytesOffsets = new int[1];
-        valuesBytesOffsets[0] = 0;
+        valuesBytesOffsets = new int[] { 0 };
       }
       return true;
     }
-    if(vlvIndex.comparator.compare(this, entryIDs.length - 1, entryID,
-                                              values) < 0)
+    if (vlvIndex.comparator.compare(
+        this, entryIDs.length - 1, entryID, values, types) < 0)
     {
       long[] updatedEntryIDs = new long[entryIDs.length + 1];
       System.arraycopy(entryIDs, 0, updatedEntryIDs, 0, entryIDs.length);
       updatedEntryIDs[entryIDs.length] = entryID;
 
-      byte[] newValuesBytes = attributeValuesToDatabase(values);
+      byte[] newValuesBytes = attributeValuesToDatabase(values, types);
       byte[] updatedValuesBytes = new byte[valuesBytes.length +
           newValuesBytes.length];
       System.arraycopy(valuesBytes, 0, updatedValuesBytes, 0,
@@ -153,7 +155,7 @@
     }
     else
     {
-      int pos = binarySearch(entryID, values);
+      int pos = binarySearch(entryID, values, types);
       if(pos >= 0)
       {
         if(entryIDs[pos] == entryID)
@@ -176,7 +178,7 @@
                        entryIDs.length-pos);
       updatedEntryIDs[pos] = entryID;
 
-      byte[] newValuesBytes = attributeValuesToDatabase(values);
+      byte[] newValuesBytes = attributeValuesToDatabase(values, types);
       // BUG valuesBytesOffsets might be null ? If not why testing below ?
       int valuesPos = valuesBytesOffsets[pos];
       byte[] updatedValuesBytes = new byte[valuesBytes.length +
@@ -216,12 +218,13 @@
    *
    * @param entryID The entry ID to remove.
    * @param values The values to remove.
+   * @param types The types of the values to remove.
    * @return True if the information was successfully removed or False
    * otherwise.
    * @throws DirectoryException If a Directory Server error occurs.
    * @throws DatabaseException If an error occurs in the JE database.
    */
-  public boolean remove(long entryID, AttributeValue[] values)
+  public boolean remove(long entryID, AttributeValue[] values, AttributeType[] types)
       throws DatabaseException, DirectoryException
   {
     if(entryIDs == null || entryIDs.length == 0)
@@ -234,7 +237,7 @@
       updateValuesBytesOffsets();
     }
 
-    int pos = binarySearch(entryID, values);
+    int pos = binarySearch(entryID, values, types);
     if(pos < 0)
     {
       // Not found.
@@ -408,12 +411,13 @@
    *
    * @param entryID The entry ID to match or -1 if not matching on entry ID.
    * @param values The values to match.
+   * @param types The types of the values to match.
    * @return Index of the entry matching the values and optionally the entry ID
    * if it is found or a negative index if its not found.
    * @throws DirectoryException If a Directory Server error occurs.
    * @throws DatabaseException If an error occurs in the JE database.
    */
-  int binarySearch(long entryID, AttributeValue[] values)
+  int binarySearch(long entryID, AttributeValue[] values, AttributeType[] types)
       throws DatabaseException, DirectoryException
   {
     if(entryIDs == null || entryIDs.length == 0)
@@ -425,14 +429,19 @@
     for(int j = entryIDs.length - 1; i <= j;)
     {
       int k = i + j >> 1;
-      int l = vlvIndex.comparator.compare(this, k, entryID, values);
-      if(l < 0)
+      int l = vlvIndex.comparator.compare(this, k, entryID, values, types);
+      if (l < 0)
+      {
         i = k + 1;
-      else
-      if(l > 0)
+      }
+      else if (l > 0)
+      {
         j = k - 1;
+      }
       else
+      {
         return k;
+      }
     }
 
     return -(i + 1);
@@ -463,26 +472,37 @@
     return entryIDs;
   }
 
-  private byte[] attributeValuesToDatabase(AttributeValue[] values)
-      throws DirectoryException
+  private byte[] attributeValuesToDatabase(AttributeValue[] values,
+      AttributeType[] types) throws DirectoryException
   {
-    ByteStringBuilder builder = new ByteStringBuilder();
-
-    for (AttributeValue v : values)
+    try
     {
-      if(v == null)
-      {
-        builder.appendBERLength(0);
-      }
-      else
-      {
-        builder.appendBERLength(v.getNormalizedValue().length());
-        builder.append(v.getNormalizedValue());
-      }
-    }
-    builder.trimToSize();
+      final ByteStringBuilder builder = new ByteStringBuilder();
 
-    return builder.getBackingArray();
+      for (int i = 0; i < values.length; i++)
+      {
+        final AttributeValue v = values[i];
+        if (v == null)
+        {
+          builder.appendBERLength(0);
+        }
+        else
+        {
+          final MatchingRule eqRule = types[i].getEqualityMatchingRule();
+          final ByteString nv = eqRule.normalizeAttributeValue(v.getValue());
+          builder.appendBERLength(nv.length());
+          builder.append(nv);
+        }
+      }
+      builder.trimToSize();
+
+      return builder.getBackingArray();
+    }
+    catch (DecodeException e)
+    {
+      throw new DirectoryException(
+          ResultCode.INVALID_ATTRIBUTE_SYNTAX, e.getMessageObject(), e);
+    }
   }
 
   /**
@@ -583,8 +603,7 @@
     EntryID id = new EntryID(entryIDs[index]);
     SortKey[] sortKeys = vlvIndex.sortOrder.getSortKeys();
     int numValues = sortKeys.length;
-    AttributeValue[] values =
-        new AttributeValue[numValues];
+    AttributeValue[] values = new AttributeValue[numValues];
     for (int i = index * numValues, j = 0;
          i < (index + 1) * numValues;
          i++, j++)
@@ -683,6 +702,6 @@
         vBytesPos += valueLength;
       }
     }
-    return ByteString.wrap(new byte[0]);
+    return ByteString.empty();
   }
 }
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java
index bf649b2..bc27de4 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java
@@ -31,16 +31,19 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
 import org.forgerock.opendj.ldap.ByteSequence;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope.Enum;
 import org.forgerock.opendj.ldap.SearchScope;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.meta.LocalDBVLVIndexCfgDefn.Scope;
 import org.opends.server.admin.std.server.LocalDBVLVIndexCfg;
+import org.opends.server.api.MatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
-import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.controls.ServerSideSortRequestControl;
 import org.opends.server.controls.VLVRequestControl;
 import org.opends.server.controls.VLVResponseControl;
@@ -48,7 +51,11 @@
 import org.opends.server.core.SearchOperation;
 import org.opends.server.protocols.ldap.LDAPResultCode;
 import org.opends.server.types.*;
-import org.forgerock.opendj.ldap.ResultCode;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.Modification;
+import org.opends.server.types.SortKey;
 import org.opends.server.util.StaticUtils;
 
 import com.sleepycat.je.*;
@@ -649,6 +656,7 @@
    *            not required.
    * @param entryID The entry ID to use.
    * @param values The values to use.
+   * @param types The types of the values to use.
    * @return The SortValuesSet that should contain the entry with the given
    *         information.
    * @throws DatabaseException If an error occurs during an operation on a
@@ -656,8 +664,8 @@
    * @throws DirectoryException If a Directory Server error occurs.
    */
   public SortValuesSet getSortValuesSet(Transaction txn, long entryID,
-                                        AttributeValue[] values)
-      throws DatabaseException, DirectoryException
+      AttributeValue[] values, AttributeType[] types) throws DatabaseException,
+      DirectoryException
   {
     SortValuesSet sortValuesSet = null;
     DatabaseEntry key = new DatabaseEntry();
@@ -669,7 +677,7 @@
 
     try
     {
-      key.setData(encodeKey(entryID, values));
+      key.setData(encodeKey(entryID, values, types));
       status = cursor.getSearchKeyRange(key, data,lockMode);
 
       if(status != OperationStatus.SUCCESS)
@@ -715,6 +723,7 @@
    * @param txn The JE transaction to use for database updates.
    * @param entryID The entry ID to search for.
    * @param values The values to search for.
+   * @param types The types of the values to search for.
    * @return The index of the entry ID matching the values or -1 if its not
    * found.
    * @throws DatabaseException If an error occurs during an operation on a
@@ -724,34 +733,28 @@
    * @throws DirectoryException If a Directory Server error occurs.
    */
   public boolean containsValues(Transaction txn, long entryID,
-                             AttributeValue[] values)
-      throws JebException, DatabaseException, DirectoryException
+      AttributeValue[] values, AttributeType[] types) throws JebException,
+      DatabaseException, DirectoryException
   {
-    SortValuesSet valuesSet = getSortValuesSet(txn, entryID, values);
-    int pos = valuesSet.binarySearch(entryID, values);
-    if(pos < 0)
-    {
-      return false;
-    }
-    return true;
+    SortValuesSet valuesSet = getSortValuesSet(txn, entryID, values, types);
+    int pos = valuesSet.binarySearch(entryID, values, types);
+    return pos >= 0;
   }
 
   private boolean insertValues(Transaction txn, long entryID, Entry entry)
       throws JebException, DatabaseException, DirectoryException
   {
-    SortValuesSet sortValuesSet;
     AttributeValue[] values = getSortValues(entry);
+    AttributeType[] types = getSortTypes();
     DatabaseEntry key = new DatabaseEntry();
     OperationStatus status;
     LockMode lockMode = LockMode.RMW;
     DatabaseEntry data = new DatabaseEntry();
-    boolean success = true;
 
     Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
-
     try
     {
-      key.setData(encodeKey(entryID, values));
+      key.setData(encodeKey(entryID, values, types));
       status = cursor.getSearchKeyRange(key, data,lockMode);
     }
     finally
@@ -759,6 +762,7 @@
       cursor.close();
     }
 
+    SortValuesSet sortValuesSet;
     if(status != OperationStatus.SUCCESS)
     {
       // There are no records in the database
@@ -791,7 +795,7 @@
 
 
 
-    success = sortValuesSet.add(entryID, values);
+    boolean success = sortValuesSet.add(entryID, values, types);
 
     int newSize = sortValuesSet.size();
     if(newSize >= sortedSetCapacity)
@@ -831,11 +835,29 @@
     return success;
   }
 
+  /**
+   * Gets the types of the attribute values to sort.
+   *
+   * @return The types of the attribute values to sort on.
+   */
+  AttributeType[] getSortTypes()
+  {
+    SortKey[] sortKeys = sortOrder.getSortKeys();
+    AttributeType[] types = new AttributeType[sortKeys.length];
+    for (int i = 0; i < sortKeys.length; i++)
+    {
+      SortKey sortKey = sortKeys[i];
+      types[i] = sortKey.getAttributeType();
+    }
+    return types;
+  }
+
   private boolean removeValues(Transaction txn, long entryID, Entry entry)
       throws JebException, DatabaseException, DirectoryException
   {
     SortValuesSet sortValuesSet;
     AttributeValue[] values = getSortValues(entry);
+    AttributeType[] types = getSortTypes();
     DatabaseEntry key = new DatabaseEntry();
     OperationStatus status;
     LockMode lockMode = LockMode.RMW;
@@ -845,7 +867,7 @@
 
     try
     {
-      key.setData(encodeKey(entryID, values));
+      key.setData(encodeKey(entryID, values, types));
       status = cursor.getSearchKeyRange(key, data,lockMode);
     }
     finally
@@ -869,7 +891,7 @@
       }
       sortValuesSet = new SortValuesSet(key.getData(), data.getData(),
                                         this);
-      boolean success = sortValuesSet.remove(entryID, values);
+      boolean success = sortValuesSet.remove(entryID, values, types);
       byte[] after = sortValuesSet.toDatabase();
 
       if(after == null)
@@ -889,10 +911,7 @@
 
       return success;
     }
-    else
-    {
-      return false;
-    }
+    return false;
   }
 
   /**
@@ -948,21 +967,21 @@
           // Start from the smallest values from either set.
           if(av.compareTo(dv) < 0)
           {
-            key.setData(encodeKey(av.getEntryID(), av.getValues()));
+            key.setData(encodeKey(av));
           }
           else
           {
-            key.setData(encodeKey(dv.getEntryID(), dv.getValues()));
+            key.setData(encodeKey(dv));
           }
         }
         else
         {
-          key.setData(encodeKey(av.getEntryID(), av.getValues()));
+          key.setData(encodeKey(av));
         }
       }
       else if(dv != null)
       {
-        key.setData(encodeKey(dv.getEntryID(), dv.getValues()));
+        key.setData(encodeKey(dv));
       }
       else
       {
@@ -1015,7 +1034,7 @@
         // This is the last unbounded set.
         while(av != null)
         {
-          sortValuesSet.add(av.getEntryID(), av.getValues());
+          sortValuesSet.add(av.getEntryID(), av.getValues(), av.getTypes());
           aValues.remove();
           if(aValues.hasNext())
           {
@@ -1029,7 +1048,7 @@
 
         while(dv != null)
         {
-          sortValuesSet.remove(dv.getEntryID(), dv.getValues());
+          sortValuesSet.remove(dv.getEntryID(), dv.getValues(), dv.getTypes());
           dValues.remove();
           if(dValues.hasNext())
           {
@@ -1047,7 +1066,7 @@
 
         while(av != null && av.compareTo(maxValues) <= 0)
         {
-          sortValuesSet.add(av.getEntryID(), av.getValues());
+          sortValuesSet.add(av.getEntryID(), av.getValues(), av.getTypes());
           aValues.remove();
           if(aValues.hasNext())
           {
@@ -1061,7 +1080,7 @@
 
         while(dv != null && dv.compareTo(maxValues) <= 0)
         {
-          sortValuesSet.remove(dv.getEntryID(), dv.getValues());
+          sortValuesSet.remove(dv.getEntryID(), dv.getValues(), dv.getTypes());
           dValues.remove();
           if(dValues.hasNext())
           {
@@ -1111,6 +1130,11 @@
     }
   }
 
+  private byte[] encodeKey(SortValues sv) throws DirectoryException
+  {
+    return encodeKey(sv.getEntryID(), sv.getValues(), sv.getTypes());
+  }
+
   /**
    * Evaluate a search with sort control using this VLV index.
    *
@@ -1326,14 +1350,15 @@
             }
             SortValuesSet sortValuesSet =
                 new SortValuesSet(key.getData(), data.getData(), this);
-            AttributeValue[] assertionValue = new AttributeValue[1];
-            assertionValue[0] =
+            AttributeType type = sortOrder.getSortKeys()[0].getAttributeType();
+            AttributeValue[] assertionValue = new AttributeValue[] {
                 AttributeValues.create(
-                    sortOrder.getSortKeys()[0].getAttributeType(),
-                        vlvRequest.getGreaterThanOrEqualAssertion());
+                    type, vlvRequest.getGreaterThanOrEqualAssertion())
+            };
+            AttributeType[] assertionType = new AttributeType[] { type };
 
             int adjustedTargetOffset =
-                sortValuesSet.binarySearch(-1, assertionValue);
+                sortValuesSet.binarySearch(-1, assertionValue, assertionType);
             if(adjustedTargetOffset < 0)
             {
               // For a negative return value r, the vlvIndex -(r+1) gives the
@@ -1580,30 +1605,42 @@
    *
    * @param entryID The entry ID to encode.
    * @param values The values to encode.
+   * @param types The types of the values to encode.
    * @return The encoded bytes.
    * @throws DirectoryException If a Directory Server error occurs.
    */
-  byte[] encodeKey(long entryID, AttributeValue[] values)
+  byte[] encodeKey(long entryID, AttributeValue[] values, AttributeType[] types)
       throws DirectoryException
   {
-    ByteStringBuilder builder = new ByteStringBuilder();
-
-    for (AttributeValue v : values)
+    try
     {
-      if(v == null)
-      {
-        builder.appendBERLength(0);
-      }
-      else
-      {
-        builder.appendBERLength(v.getNormalizedValue().length());
-        builder.append(v.getNormalizedValue());
-      }
-    }
-    builder.append(entryID);
-    builder.trimToSize();
+      final ByteStringBuilder builder = new ByteStringBuilder();
 
-    return builder.getBackingArray();
+      for (int i = 0; i < values.length; i++)
+      {
+        final AttributeValue v = values[i];
+        if (v == null)
+        {
+          builder.appendBERLength(0);
+        }
+        else
+        {
+          final MatchingRule eqRule = types[i].getEqualityMatchingRule();
+          final ByteString nv = eqRule.normalizeAttributeValue(v.getValue());
+          builder.appendBERLength(nv.length());
+          builder.append(nv);
+        }
+      }
+      builder.append(entryID);
+      builder.trimToSize();
+
+      return builder.getBackingArray();
+    }
+    catch (DecodeException e)
+    {
+      throw new DirectoryException(
+          ResultCode.INVALID_ATTRIBUTE_SYNTAX, e.getMessageObject(), e);
+    }
   }
 
   /**
@@ -1688,11 +1725,8 @@
   public boolean shouldInclude(Entry entry) throws DirectoryException
   {
     DN entryDN = entry.getName();
-    if(entryDN.matchesBaseAndScope(baseDN, scope) && filter.matchesEntry(entry))
-    {
-      return true;
-    }
-    return false;
+    return entryDN.matchesBaseAndScope(baseDN, scope)
+        && filter.matchesEntry(entry);
   }
 
   /**
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java
index 35b4454..9b1926e 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java
@@ -26,13 +26,17 @@
  */
 package org.opends.server.backends.jeb;
 
+import java.io.Serializable;
+import java.util.Comparator;
+
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.opends.server.api.MatchingRule;
 import org.opends.server.api.OrderingMatchingRule;
+import org.opends.server.types.AttributeType;
 import org.opends.server.types.AttributeValue;
 import org.opends.server.types.DirectoryException;
-import org.forgerock.opendj.ldap.ByteString;
-
-import java.util.Comparator;
-import java.io.Serializable;
 
 import com.sleepycat.je.DatabaseException;
 
@@ -94,6 +98,7 @@
    *          order, or zero if there is no difference between the values with
    *          regard to ordering.
    */
+  @Override
   public int compare(byte[] b1, byte[] b2)
   {
     // A 0 length byte array is a special key used for the unbound max
@@ -259,6 +264,7 @@
    * @param  index The index of the values in the set.
    * @param  entryID The entry ID to use in the comparasion.
    * @param  values The values to use in the comparasion.
+   * @param  types The types of the values to use in the comparasion.
    *
    * @return  A negative integer if the values in the set should come before
    *          the given values in ascending order, a positive integer if
@@ -272,9 +278,9 @@
    *                              not acceptable for use with the
    *                              associated equality matching rule).
    */
-  public int compare(SortValuesSet set, int index,
-                                long entryID, AttributeValue[] values)
-      throws DatabaseException, DirectoryException
+  public int compare(SortValuesSet set, int index, long entryID,
+      AttributeValue[] values, AttributeType[] types) throws DatabaseException,
+      DirectoryException
   {
     for (int j=0; j < orderingRules.length; j++)
     {
@@ -288,7 +294,16 @@
 
       if(values[j] != null)
       {
-        b2Bytes = values[j].getNormalizedValue();
+        try
+        {
+          final MatchingRule eqRule = types[j].getEqualityMatchingRule();
+          b2Bytes = eqRule.normalizeAttributeValue(values[j].getValue());
+        }
+        catch (DecodeException e)
+        {
+          throw new DirectoryException(
+              ResultCode.INVALID_ATTRIBUTE_SYNTAX, e.getMessageObject(), e);
+        }
       }
 
       // A null value will always come after a non-null value.
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java
index 394d630..f4da2d5 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java
@@ -995,8 +995,8 @@
           {
             // If this is the last one in a bounded set, make sure it is the
             // same as the database key.
-            byte[] encodedKey = vlvIndex.encodeKey(values.getEntryID(),
-                                                   values.getValues());
+            byte[] encodedKey = vlvIndex.encodeKey(
+                values.getEntryID(), values.getValues(), values.getTypes());
             if(!Arrays.equals(key.getData(), encodedKey))
             {
               if(logger.isTraceEnabled())
@@ -1548,8 +1548,8 @@
       {
         if(vlvIndex.shouldInclude(entry))
         {
-          if(!vlvIndex.containsValues(null, entryID.longValue(),
-                                  vlvIndex.getSortValues(entry)))
+          if (!vlvIndex.containsValues(null, entryID.longValue(),
+              vlvIndex.getSortValues(entry), vlvIndex.getSortTypes()))
           {
             if(logger.isTraceEnabled())
             {
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java
index c6e54c9..7fbc6c3 100644
--- a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java
@@ -32,9 +32,11 @@
 
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DereferenceAliasesPolicy;
+import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
 import org.opends.server.DirectoryServerTestCase;
 import org.opends.server.TestCaseUtils;
+import org.opends.server.api.MatchingRule;
 import org.opends.server.controls.ServerSideSortRequestControl;
 import org.opends.server.controls.ServerSideSortResponseControl;
 import org.opends.server.controls.VLVRequestControl;
@@ -45,7 +47,6 @@
 import org.opends.server.protocols.ldap.LDAPControl;
 import org.opends.server.protocols.ldap.LDAPResultCode;
 import org.opends.server.types.*;
-import org.forgerock.opendj.ldap.ResultCode;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -260,18 +261,12 @@
     {
       if(vlvIndex.getName().contains("testvlvindex"))
       {
-        SortValuesSet svs1 =
-            vlvIndex.getSortValuesSet(null, 0,
-                                      expectedSortedValues.first().getValues());
-
-        assertNotNull(svs1);
+        SortValues sv1 = expectedSortedValues.first();
+        SortValuesSet svs1 = getSortValuesSet(vlvIndex, sv1);
         assertEquals(svs1.size(), 3);
 
-        SortValuesSet svs2 =
-            vlvIndex.getSortValuesSet(null, 0,
-                                      expectedSortedValues.last().getValues());
-
-        assertNotNull(svs2);
+        SortValues sv2 = expectedSortedValues.last();
+        SortValuesSet svs2 = getSortValuesSet(vlvIndex, sv2);
         assertEquals(svs2.size(), 5);
       }
     }
@@ -287,25 +282,28 @@
     {
       if(vlvIndex.getName().contains("testvlvindex"))
       {
-        SortValuesSet svs1 =
-            vlvIndex.getSortValuesSet(null, 0,
-                                      expectedSortedValues.first().getValues());
-
-        assertNotNull(svs1);
+        SortValues sv1 = expectedSortedValues.first();
+        SortValuesSet svs1 = getSortValuesSet(vlvIndex, sv1);
         assertEquals(svs1.size(), 0);
         assertNull(svs1.getKeyBytes());
 
-        SortValuesSet svs2 =
-            vlvIndex.getSortValuesSet(null, 0,
-                                      expectedSortedValues.last().getValues());
-
-        assertNotNull(svs2);
-        assertEquals(svs1.size(), 0);
-        assertNull(svs1.getKeyBytes());
+        SortValues sv2 = expectedSortedValues.last();
+        SortValuesSet svs2 = getSortValuesSet(vlvIndex, sv2);
+        assertEquals(svs2.size(), 0);
+        assertNull(svs2.getKeyBytes());
       }
     }
   }
 
+  private SortValuesSet getSortValuesSet(VLVIndex vlvIndex, SortValues sv)
+      throws DirectoryException
+  {
+    SortValuesSet result =
+        vlvIndex.getSortValuesSet(null, 0, sv.getValues(), sv.getTypes());
+    assertNotNull(result);
+    return result;
+  }
+
   @Test( dependsOnMethods = { "testDel" } )
   public void testAdd() throws Exception
   {
@@ -319,24 +317,20 @@
     {
       if(vlvIndex.getName().contains("testvlvindex"))
       {
-        SortValuesSet svs1 =
-            vlvIndex.getSortValuesSet(null, 0,
-                                      expectedSortedValues.first().getValues());
-
-        assertNotNull(svs1);
+        SortValues sv1 = expectedSortedValues.first();
+        SortValuesSet svs1 = getSortValuesSet(vlvIndex, sv1);
         assertEquals(svs1.size(), 4);
 
-        SortValuesSet svs2 =
-            vlvIndex.getSortValuesSet(null, 0,
-                                      expectedSortedValues.last().getValues());
-
-        assertNotNull(svs2);
+        SortValues sv2 = expectedSortedValues.last();
+        SortValuesSet svs2 = getSortValuesSet(vlvIndex, sv2);
         assertEquals(svs2.size(), 6);
 
         int i = 0;
         for(SortValues values : expectedSortedValues)
         {
-          for(int j = 0; j < values.getValues().length; j++)
+          AttributeValue[] attrValues = values.getValues();
+          AttributeType[] attrTypes = values.getTypes();
+          for(int j = 0; j < attrValues.length; j++)
           {
             ByteString value;
             if(i < 4)
@@ -348,9 +342,10 @@
               value = svs2.getValue((i - 4) * 3 + j);
             }
             ByteString oValue = null;
-            if(values.getValues()[j] != null)
+            if(attrValues[j] != null)
             {
-              oValue = values.getValues()[j].getNormalizedValue();
+              MatchingRule eqRule = attrTypes[j].getEqualityMatchingRule();
+              oValue = eqRule.normalizeAttributeValue(attrValues[j].getValue());
             }
             assertEquals(value, oValue);
           }
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
index c41b16b..202c1f0 100644
--- a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
@@ -387,18 +387,19 @@
     try
     {
       VLVIndex vlvIndex = eContainer.getVLVIndex(indexName);
+      AttributeType[] types = vlvIndex.getSortTypes();
 
       // Add an incorrectly ordered values.
       SortValuesSet svs =
-          vlvIndex.getSortValuesSet(null, 0, new AttributeValue[3]);
+          vlvIndex.getSortValuesSet(null, 0, new AttributeValue[3], new AttributeType[3]);
       long id = svs.getEntryIDs()[0];
       Entry entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
 
       SortValuesSet svs2 = svs.split(2);
-      svs2.add(id, vlvIndex.getSortValues(entry));
+      svs2.add(id, vlvIndex.getSortValues(entry), types);
 
       // Add an invalid ID
-      svs2.add(1000, vlvIndex.getSortValues(entry));
+      svs2.add(1000, vlvIndex.getSortValues(entry), types);
 
       // Muck up the values of another ID
       id = svs.getEntryIDs()[0];
@@ -407,8 +408,8 @@
       AttributeValue[] badValues = new AttributeValue[values.length];
       System.arraycopy(values, 1, badValues, 0, values.length - 1);
       badValues[badValues.length-1] = values[0];
-      svs.remove(id, values);
-      svs.add(id, badValues);
+      svs.remove(id, values, types);
+      svs.add(id, badValues, types);
 
       vlvIndex.putSortValuesSet(null, svs);
       vlvIndex.putSortValuesSet(null, svs2);
@@ -690,17 +691,18 @@
     try
     {
       VLVIndex vlvIndex = eContainer.getVLVIndex(indexName);
+      AttributeType[] types = vlvIndex.getSortTypes();
 
       // Remove an ID
       SortValuesSet svs =
-          vlvIndex.getSortValuesSet(null, 0, new AttributeValue[3]);
+          vlvIndex.getSortValuesSet(null, 0, new AttributeValue[3], types);
       long id = svs.getEntryIDs()[0];
       Entry entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
-      svs.remove(id, vlvIndex.getSortValues(entry));
+      svs.remove(id, vlvIndex.getSortValues(entry), types);
 
       // Add an incorrectly ordered values.
       SortValuesSet svs2 = svs.split(2);
-      svs2.add(1000, vlvIndex.getSortValues(entry));
+      svs2.add(1000, vlvIndex.getSortValues(entry), types);
 
       // Muck up the values of another ID
       id = svs.getEntryIDs()[0];
@@ -709,8 +711,8 @@
       AttributeValue[] badValues = new AttributeValue[values.length];
       System.arraycopy(values, 1, badValues, 0, values.length - 1);
       badValues[badValues.length-1] = values[0];
-      svs.remove(id, values);
-      svs.add(id, badValues);
+      svs.remove(id, values, types);
+      svs.add(id, badValues, types);
 
       vlvIndex.putSortValuesSet(null, svs);
       vlvIndex.putSortValuesSet(null, svs2);
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/StringPrepProfileTestCase.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/StringPrepProfileTestCase.java
index 0b383d9..ea98dc8 100644
--- a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/StringPrepProfileTestCase.java
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/StringPrepProfileTestCase.java
@@ -24,32 +24,27 @@
  *      Copyright 2008-2009 Sun Microsystems, Inc.
  *      Portions Copyright 2014 ForgeRock AS
  */
-
-
 package org.opends.server.schema;
 
-import org.opends.server.api.MatchingRule;
-import org.opends.server.api.MatchingRule;
-
-import static org.testng.Assert.*;
-
 import java.util.List;
 
-import org.opends.server.TestCaseUtils;
-import org.opends.server.protocols.internal.InternalClientConnection;
-import org.opends.server.protocols.internal.InternalSearchOperation;
-import org.opends.server.protocols.ldap.LDAPFilter;
 import org.forgerock.opendj.ldap.Assertion;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.DereferenceAliasesPolicy;
 import org.forgerock.opendj.ldap.ResultCode;
-import org.opends.server.types.SearchResultEntry;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.opends.server.TestCaseUtils;
+import org.opends.server.api.MatchingRule;
+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.types.SearchResultEntry;
 import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
+import static org.testng.Assert.*;
 
 /**
  * This Test Class tests various matching rules for their compatibility

--
Gitblit v1.10.0