mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
17.54.2014 094f3cede311d8554aff0d4ce0a9c2bdaca49535
OPENDJ-1368 Remove AttributeValue

Code review: Matthew Swift


Removing the last calls to AttributeValue.getNormalizedValue().


SortValues.java:
Added types field + getter.

SortValuesSet.java:
In add(), remove(), binarySearch() and attributeValuesToDatabase(), passed in AttributeType array as a parameter.

VLVIndex.java:
In getSortValuesSet(), containsValues() and encodeKey(), passed in AttributeType array as a parameter.
Added getSortTypes() and encodeKey().

VLVKeyComparator.java:
In compare(), passed in AttributeType array as a parameter.

VerifyJob.java, TestVerifyJob.java, TestVLVIndex.java:
Consequence of the changes above.

TestVLVIndex.java:
Extracted method getSortValuesSet().

StringPrepProfileTestCase.java:
Removed unused import.
8 files modified
448 ■■■■■ changed files
opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValues.java 44 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java 101 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java 154 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java 31 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java 8 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java 67 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java 22 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/StringPrepProfileTestCase.java 21 ●●●●● patch | view | raw | blame | history
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.
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();
  }
}
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);
  }
  /**
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.
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())
            {
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);
          }
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);
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