From d45f3ef4848972f83705fede48872b8d91d68349 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Thu, 03 Apr 2014 13:53:49 +0000
Subject: [PATCH] Checkpoint commit for OPENDJ-1308 Migrate schema support

---
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java                                     |   29 
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java |  184 ++----
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java      |   11 
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/EqualityMatchingRule.java                             |   41 +
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/CertificateExactMatchingRule.java                  |    9 
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java                                   |  131 +--
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java |   14 
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java                            |   66 --
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/AbstractOrderingMatchingRule.java                  |   53 +
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/ApproximateMatchingRule.java                          |   28 
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java                          |  855 +++++-----------------------
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQuery.java                              |   23 
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexFilter.java                             |  109 ---
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQueryFactoryImpl.java                   |   94 ++-
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java                             |   68 ++
 15 files changed, 564 insertions(+), 1,151 deletions(-)

diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java
index c377a94..1a871cc 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java
@@ -52,6 +52,65 @@
 public abstract class AbstractMatchingRule implements MatchingRule
 {
 
+  /**
+   * Default implementation of assertion.
+   */
+  public static final class DefaultAssertion implements Assertion
+  {
+    /** The ID of the DB index to use with this assertion. */
+    private final String indexID;
+    private final ByteSequence normalizedAssertionValue;
+
+    /**
+     * Returns the equality assertion.
+     *
+     * @param normalizedAssertionValue
+     *          The value on which the assertion is built.
+     * @return the equality assertion
+     */
+    public static DefaultAssertion equality(final ByteSequence normalizedAssertionValue)
+    {
+      return new DefaultAssertion("equality", normalizedAssertionValue);
+    }
+
+    /**
+     * Returns the approximate assertion.
+     *
+     * @param normalizedAssertionValue
+     *          The value on which the assertion is built.
+     * @return the approximate assertion
+     */
+    static DefaultAssertion approximate(final ByteSequence normalizedAssertionValue)
+    {
+      return new DefaultAssertion("approximate", normalizedAssertionValue);
+    }
+
+    private DefaultAssertion(final String indexID, final ByteSequence normalizedAssertionValue)
+    {
+      this.indexID = indexID;
+      this.normalizedAssertionValue = normalizedAssertionValue;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ConditionResult matches(final ByteSequence normalizedAttributeValue)
+    {
+      return ConditionResult.valueOf(normalizedAssertionValue.equals(normalizedAttributeValue));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public <T> T createIndexQuery(IndexQueryFactory<T> factory)
+        throws DecodeException
+    {
+      return factory.createExactMatchQuery(indexID, normalizedAssertionValue);
+    }
+  }
+
   private static final Assertion UNDEFINED_ASSERTION = new Assertion()
   {
     @Override
@@ -71,9 +130,14 @@
   };
 
   /**
-   * {@inheritDoc}
+   * Returns the normalized form of the assertion value.
+   *
+   * @param value
+   *            The assertion value to normalize.
+   * @return the normalized value
+   * @throws DecodeException
+   *            If a problem occurs.
    */
-  @Override
   public ByteString normalizeAssertionValue(ByteSequence value)
       throws DecodeException
   {
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/ApproximateMatchingRule.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/ApproximateMatchingRule.java
index 1c530a3..93e114e 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/ApproximateMatchingRule.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/ApproximateMatchingRule.java
@@ -26,8 +26,12 @@
  */
 package org.opends.server.api;
 
+import org.forgerock.opendj.ldap.Assertion;
 import org.forgerock.opendj.ldap.ByteSequence;
+import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 
 /**
  * This class defines the set of methods and structures that must be
@@ -86,5 +90,29 @@
     return ConditionResult.valueOf(
         approximatelyMatch(attributeValue, assertionValue));
   }
+
+  /** {@inheritDoc} */
+  @Override
+  public Assertion getAssertion(ByteSequence assertionValue) throws DecodeException
+  {
+    final ByteString normAssertionValue = normalizeAttributeValue(assertionValue);
+    final DefaultAssertion approxAssertion = DefaultAssertion.approximate(normAssertionValue);
+    return new Assertion()
+    {
+      @Override
+      public ConditionResult matches(ByteSequence normalizedAttributeValue)
+      {
+        return valuesMatch(normalizedAttributeValue, normAssertionValue);
+      }
+
+      @Override
+      public <T> T createIndexQuery(IndexQueryFactory<T> factory)
+          throws DecodeException
+      {
+       return approxAssertion.createIndexQuery(factory);
+      }
+    };
+  }
+
 }
 
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/EqualityMatchingRule.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/EqualityMatchingRule.java
index 05a364e..81251f7 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/EqualityMatchingRule.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/EqualityMatchingRule.java
@@ -26,8 +26,13 @@
  */
 package org.opends.server.api;
 
+import org.forgerock.opendj.ldap.Assertion;
 import org.forgerock.opendj.ldap.ByteSequence;
+import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
+import org.opends.server.api.AbstractMatchingRule.DefaultAssertion;
 
 /**
  * This class defines the set of methods and structures that must be
@@ -108,5 +113,41 @@
   {
     return attributeValue.hashCode();
   }
+
+  /** {@inheritDoc} */
+  @Override
+  public Assertion getAssertion(ByteSequence assertionValue) throws DecodeException
+  {
+    final ByteString normAssertionValue = normalizeAttributeValue(assertionValue);
+    return getEqualityAssertion(normAssertionValue);
+  }
+
+  /**
+   * Return the equality assertion for the matching rule.
+   *
+   * @param normAssertionValue
+   *            The normalized assertion value.
+   * @return the assertion
+   */
+  protected Assertion getEqualityAssertion(final ByteString normAssertionValue)
+  {
+    final DefaultAssertion eqAssertion = DefaultAssertion.equality(normAssertionValue);
+    return new Assertion()
+    {
+      @Override
+      public ConditionResult matches(ByteSequence normalizedAttributeValue)
+      {
+        return valuesMatch(normalizedAttributeValue, normAssertionValue);
+      }
+
+      @Override
+      public <T> T createIndexQuery(IndexQueryFactory<T> factory)
+          throws DecodeException
+      {
+       return eqAssertion.createIndexQuery(factory);
+      }
+    };
+  }
+
 }
 
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java
index 0d3c9ee..e0aeb2a 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java
@@ -64,25 +64,6 @@
    */
   String getOID();
 
-
-
-  /**
-   * Retrieves the normalized form of the provided assertion value,
-   * which is best suite for efficiently performing matching
-   * operations on that value.
-   *
-   * @param value
-   *          The assertion value to be normalized.
-   * @return The normalized version of the provided value.
-   * @throws DecodeException
-   *           If the provided value is invalid according to the
-   *           associated attribute syntax.
-   */
-  ByteString normalizeAssertionValue(ByteSequence value)
-      throws DecodeException;
-
-
-
   /**
    * Retrieves the name or OID for this matching rule. If it has a
    * name, then it will be returned. Otherwise, the OID will be
@@ -118,7 +99,7 @@
    * @throws DecodeException
    *           if problem
    */
-  Assertion getAssertion(final ByteSequence assertionValue) throws DecodeException;
+  Assertion getAssertion(ByteSequence assertionValue) throws DecodeException;
 
   /**
    * Returns the normalized form of the provided assertion value, which is
@@ -132,7 +113,7 @@
    * @throws DecodeException
    *             if the syntax of the value is not valid.
    */
-  public Assertion getGreaterOrEqualAssertion(final ByteSequence assertionValue) throws DecodeException;
+  Assertion getGreaterOrEqualAssertion(ByteSequence assertionValue) throws DecodeException;
 
   /**
    * Returns the normalized form of the provided assertion value, which is
@@ -146,7 +127,7 @@
    * @throws DecodeException
    *             if the syntax of the value is not valid.
    */
-  public Assertion getLessOrEqualAssertion(final ByteSequence assertionValue) throws DecodeException;
+  Assertion getLessOrEqualAssertion(ByteSequence assertionValue) throws DecodeException;
 
   /**
    * Returns the normalized form of the provided assertion substring values,
@@ -166,8 +147,8 @@
    * @throws DecodeException
    *             if the syntax of the value is not valid.
    */
-  public Assertion getSubstringAssertion(final ByteSequence subInitial,
-      final List<? extends ByteSequence> subAnyElements, final ByteSequence subFinal) throws DecodeException;
+  Assertion getSubstringAssertion(ByteSequence subInitial, List<? extends ByteSequence> subAnyElements,
+      ByteSequence subFinal) throws DecodeException;
 
   /**
    * Indicates whether this matching rule is declared "OBSOLETE". The
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java
index b3d84fb..8eaec37 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java
@@ -345,72 +345,6 @@
           }
       }
 
-      // TODO : reminder : should add this method in the SDK
-      /** {@inheritDoc} */
-      @Override
-    public int hashCode()
-    {
-      int hashCode = 0;
-      if (normInitial != null)
-      {
-        hashCode += normInitial.hashCode();
-      }
-      if (normAnys != null)
-      {
-        for (ByteString any : normAnys)
-        {
-          hashCode += any.hashCode();
-        }
-      }
-      if (normFinal != null)
-      {
-        hashCode += normFinal.hashCode();
-      }
-      return hashCode;
-    }
-
-      // TODO : reminder : should add this method in the SDK
-      /** {@inheritDoc} */
-      @Override
-      public boolean equals(Object obj)
-      {
-        if (obj == this)
-        {
-          return true;
-        }
-        if (! (obj instanceof DefaultSubstringAssertion))
-        {
-          return false;
-        }
-        DefaultSubstringAssertion other = (DefaultSubstringAssertion) obj;
-        boolean initialCheck = normInitial == null ? other.normInitial == null : normInitial.equals(other.normInitial);
-        if (!initialCheck)
-        {
-          return false;
-        }
-        boolean finalCheck = normFinal == null ? other.normFinal == null : normFinal.equals(other.normFinal);
-        if (!finalCheck)
-        {
-          return false;
-        }
-        boolean anyCheck = normAnys == null ? other.normAnys == null : normAnys.length == other.normAnys.length;
-        if (!anyCheck)
-        {
-          return false;
-        }
-        if (normAnys != null)
-        {
-          for (int i = 0; i < normAnys.length; i++)
-          {
-            if (! normAnys[i].equals(other.normAnys[i]))
-            {
-              return false;
-            }
-          }
-        }
-        return true;
-      }
-
   }
 
   /** {@inheritDoc} */
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
index cb1e32d..fb3a6a8 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
@@ -31,8 +31,10 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizableMessageBuilder;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.Assertion;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.ResultCode;
@@ -41,11 +43,11 @@
 import org.forgerock.util.Utils;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn;
+import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType;
 import org.opends.server.admin.std.server.LocalDBIndexCfg;
 import org.opends.server.api.ExtensibleIndexer;
 import org.opends.server.api.ExtensibleMatchingRule;
 import org.opends.server.api.MatchingRule;
-import org.opends.server.api.SubstringMatchingRule;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.monitors.DatabaseEnvironmentMonitor;
 import org.opends.server.types.*;
@@ -119,6 +121,11 @@
    */
   Index approximateIndex = null;
 
+  /** The mapping from names to indexes. */
+  private Map<String, Index> nameToIndexes;
+
+  private IndexQueryFactory<IndexQuery> indexQueryFactory;
+
   /**
    * The ExtensibleMatchingRuleIndex instance for ExtensibleMatchingRule
    * indexes.
@@ -131,6 +138,7 @@
 
   /**
    * Create a new attribute index object.
+   *
    * @param entryContainer The entryContainer of this attribute index.
    * @param state The state database to persist index state info.
    * @param env The JE environment handle.
@@ -139,71 +147,73 @@
    * @throws ConfigException if a configuration related error occurs.
    */
   public AttributeIndex(LocalDBIndexCfg indexConfig, State state,
-                        Environment env,
-                        EntryContainer entryContainer)
+                        Environment env, EntryContainer entryContainer)
       throws DatabaseException, ConfigException
   {
     this.entryContainer = entryContainer;
     this.env = env;
     this.indexConfig = indexConfig;
     this.state = state;
+    nameToIndexes = new HashMap<String, Index>();
 
     AttributeType attrType = indexConfig.getAttribute();
-    String name =
-        entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID();
+    String name = entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID();
     final JEIndexConfig config = new JEIndexConfig(indexConfig.getSubstringLength());
 
-    if (indexConfig.getIndexType().contains(
-            LocalDBIndexCfgDefn.IndexType.EQUALITY))
+    if (indexConfig.getIndexType().contains(IndexType.EQUALITY))
     {
       this.equalityIndex = buildExtIndex(
           name, attrType, attrType.getEqualityMatchingRule(), new EqualityIndexer(attrType));
+      nameToIndexes.put(IndexType.EQUALITY.toString(), equalityIndex);
     }
 
-    if (indexConfig.getIndexType().contains(
-            LocalDBIndexCfgDefn.IndexType.PRESENCE))
+    if (indexConfig.getIndexType().contains(IndexType.PRESENCE))
     {
       this.presenceIndex = newIndex(name + ".presence",
           new PresenceIndexer(attrType), indexConfig.getIndexEntryLimit());
+      nameToIndexes.put(IndexType.PRESENCE.toString(), presenceIndex);
     }
 
-    if (indexConfig.getIndexType().contains(
-            LocalDBIndexCfgDefn.IndexType.SUBSTRING))
+    if (indexConfig.getIndexType().contains(IndexType.SUBSTRING))
     {
       this.substringIndex = buildExtIndex(
           name, attrType, attrType.getSubstringMatchingRule(), new SubstringIndexer(attrType, config));
+      //nameToIndexes.put(IndexType.SUBSTRING.toString(), substringIndex);
     }
 
-    if (indexConfig.getIndexType().contains(
-            LocalDBIndexCfgDefn.IndexType.ORDERING))
+    if (indexConfig.getIndexType().contains(IndexType.ORDERING))
     {
       this.orderingIndex = buildExtIndex(
           name, attrType, attrType.getOrderingMatchingRule(), new OrderingIndexer(attrType));
+      nameToIndexes.put(IndexType.ORDERING.toString(), orderingIndex);
     }
-    if (indexConfig.getIndexType().contains(
-        LocalDBIndexCfgDefn.IndexType.APPROXIMATE))
+
+    if (indexConfig.getIndexType().contains(IndexType.APPROXIMATE))
     {
       this.approximateIndex = buildExtIndex(
           name, attrType, attrType.getApproximateMatchingRule(), new ApproximateIndexer(attrType));
+      nameToIndexes.put(IndexType.APPROXIMATE.toString(), approximateIndex);
     }
-    if (indexConfig.getIndexType().contains(
-        LocalDBIndexCfgDefn.IndexType.EXTENSIBLE))
+
+    indexQueryFactory = new IndexQueryFactoryImpl(nameToIndexes, config);
+
+    if (indexConfig.getIndexType().contains(IndexType.EXTENSIBLE))
     {
-      Set<String> extensibleRules =
-              indexConfig.getIndexExtensibleMatchingRule();
+      Set<String> extensibleRules = indexConfig.getIndexExtensibleMatchingRule();
       if(extensibleRules == null || extensibleRules.isEmpty())
       {
         throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "extensible"));
       }
       extensibleIndexes = new ExtensibleMatchingRuleIndex();
-      //Iterate through the Set and create the index only if necessary.
-      //Collation equality and Ordering matching rules share the same
-      //indexer and index. A Collation substring matching rule is treated
-      // differently as it uses a separate indexer and index.
+
+      // Iterate through the Set and create the index only if necessary.
+      // Collation equality and Ordering matching rules share the same
+      // indexer and index.
+      // A Collation substring matching rule is treated differently
+      // as it uses a separate indexer and index.
       for(String ruleName:extensibleRules)
       {
-        ExtensibleMatchingRule rule =
-            DirectoryServer.getExtensibleMatchingRule(toLowerCase(ruleName));
+        ExtensibleMatchingRule rule = DirectoryServer.getExtensibleMatchingRule(toLowerCase(ruleName));
         if(rule == null)
         {
           logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
@@ -221,11 +231,9 @@
             extensibleIndexes.addIndex(extIndex, indexID);
           }
           extensibleIndexes.addRule(indexID, rule);
-          indexMap.put(indexer.getExtensibleIndexID(),
-              extensibleIndexes.getIndex(indexID));
+          indexMap.put(indexer.getExtensibleIndexID(), extensibleIndexes.getIndex(indexID));
         }
-        IndexQueryFactory<IndexQuery> factory =
-            new IndexQueryFactoryImpl(indexMap, config);
+        IndexQueryFactory<IndexQuery> factory = new IndexQueryFactoryImpl(indexMap, config);
         extensibleIndexes.addQueryFactory(rule, factory);
       }
     }
@@ -637,127 +645,47 @@
   }
 
   /**
-   * Retrieve the entry IDs that might contain a given substring.
-   * @param bytes A normalized substring of an attribute value.
-   * @return The candidate entry IDs.
+   * Retrieve the entry IDs that might match the provided assertion.
+   *
+   * @param indexQuery
+   *            The query used to retrieve entries.
+   * @param indexName
+   *            The name of index used to retrieve entries.
+   * @param filter
+   *          The filter on entries.
+   * @param debugBuffer
+   *          If not null, a diagnostic string will be written which will help
+   *          determine how the indexes contributed to this search.
+   * @param monitor
+   *          The database environment monitor provider that will keep index
+   *          filter usage statistics.
+   * @return The candidate entry IDs that might contain the filter assertion
+   *         value.
    */
-  private EntryIDSet matchSubstring(byte[] bytes)
-  { // FIXME replace this code with SDK's
-    // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.createIndexQuery()
+  private EntryIDSet evaluateIndexQuery(IndexQuery indexQuery, String indexName, SearchFilter filter,
+      StringBuilder debugBuffer, DatabaseEnvironmentMonitor monitor)
+  {
+    LocalizableMessageBuilder debugMessage = monitor.isFilterUseEnabled() ? new LocalizableMessageBuilder() : null;
+    EntryIDSet results = indexQuery.evaluate(debugMessage);
 
-    int substrLength = indexConfig.getSubstringLength();
-
-    // There are two cases, depending on whether the user-provided
-    // substring is smaller than the configured index substring length or not.
-    if (bytes.length < substrLength)
+    if (debugBuffer != null)
     {
-      // Iterate through all the keys that have this value as the prefix.
-
-      // Set the lower bound for a range search.
-      byte[] lower = makeSubstringKey(bytes, 0, bytes.length);
-
-      // Set the upper bound for a range search.
-      // We need a key for the upper bound that is of equal length
-      // but slightly greater than the lower bound.
-      byte[] upper = makeSubstringKey(bytes, 0, bytes.length);
-      for (int i = upper.length-1; i >= 0; i--)
-      {
-        if (upper[i] == 0xFF)
-        {
-          // We have to carry the overflow to the more significant byte.
-          upper[i] = 0;
-        }
-        else
-        {
-          // No overflow, we can stop.
-          upper[i] = (byte) (upper[i] + 1);
-          break;
-        }
-      }
-
-      // Read the range: lower <= keys < upper.
-      return substringIndex.readRange(lower, upper, true, false);
+      debugBuffer.append("[INDEX:").append(indexConfig.getAttribute().getNameOrOID())
+        .append(".").append(indexName).append("]");
     }
-    else
+
+    if (monitor.isFilterUseEnabled())
     {
-      // Break the value up into fragments of length equal to the
-      // index substring length, and read those keys.
-
-      // Eliminate duplicates by putting the keys into a set.
-      Set<byte[]> set =
-          new TreeSet<byte[]>(substringIndex.indexer.getComparator());
-
-      // Example: The value is ABCDE and the substring length is 3.
-      // We produce the keys ABC BCD CDE.
-      for (int first = 0, last = substrLength;
-           last <= bytes.length; first++, last++)
+      if (results.isDefined())
       {
-        set.add(makeSubstringKey(bytes, first, substrLength));
-      }
-
-      EntryIDSet results = new EntryIDSet();
-      DatabaseEntry key = new DatabaseEntry();
-      for (byte[] keyBytes : set)
-      {
-        // Read the key.
-        key.setData(keyBytes);
-        EntryIDSet list = substringIndex.readKey(key, null, LockMode.DEFAULT);
-
-        // Incorporate them into the results.
-        results.retainAll(list);
-
-        // We may have reached the point of diminishing returns where
-        // it is quicker to stop now and process the current small number of
-        // candidates.
-        if (results.isDefined() &&
-             results.size() <= IndexFilter.FILTER_CANDIDATE_THRESHOLD)
-        {
-          break;
-        }
-      }
-
-      return results;
-    }
-  }
-
-  /**
-   * Uses an equality index to retrieve the entry IDs that might contain a
-   * given initial substring.
-   * @param bytes A normalized initial substring of an attribute value.
-   * @return The candidate entry IDs.
-   */
-  private EntryIDSet matchInitialSubstring(byte[] bytes)
-  { // FIXME replace this code with SDK's
-    // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.createIndexQuery()
-
-    // Iterate through all the keys that have this value as the prefix.
-
-    // Set the lower bound for a range search.
-    byte[] lower = bytes;
-
-    // Set the upper bound for a range search.
-    // We need a key for the upper bound that is of equal length
-    // but slightly greater than the lower bound.
-    byte[] upper = new byte[bytes.length];
-    System.arraycopy(bytes,0, upper, 0, bytes.length);
-
-    for (int i = upper.length-1; i >= 0; i--)
-    {
-      if (upper[i] == 0xFF)
-      {
-        // We have to carry the overflow to the more significant byte.
-        upper[i] = 0;
+        monitor.updateStats(filter, results.size());
       }
       else
       {
-        // No overflow, we can stop.
-        upper[i] = (byte) (upper[i] + 1);
-        break;
+        monitor.updateStats(filter, debugMessage.toMessage());
       }
     }
-
-    // Read the range: lower <= keys < upper.
-    return equalityIndex.readRange(lower, upper, true, false);
+    return results;
   }
 
   /**
@@ -776,62 +704,11 @@
                                            StringBuilder debugBuffer,
                                            DatabaseEnvironmentMonitor monitor)
   {
-    if (equalityIndex == null)
-    {
-      if(monitor.isFilterUseEnabled())
-      {
-        monitor.updateStats(equalityFilter,
-            INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("equality",
-                indexConfig.getAttribute().getNameOrOID()));
-      }
-      return new EntryIDSet();
-    }
-
-    try
-    {
-      // Make a key from the normalized assertion value.
-      MatchingRule equalityRule = equalityFilter.getAttributeType().
-        getEqualityMatchingRule();
-      byte[] keyBytes = equalityRule.normalizeAssertionValue(
-          equalityFilter.getAssertionValue()).toByteArray();
-      DatabaseEntry key = new DatabaseEntry(keyBytes);
-
-      if(debugBuffer != null)
-      {
-        debugBuffer.append("[INDEX:");
-        debugBuffer.append(indexConfig.getAttribute().getNameOrOID());
-        debugBuffer.append(".");
-        debugBuffer.append("equality]");
-      }
-
-      // Read the key.
-      EntryIDSet idSet = equalityIndex.readKey(key, null, LockMode.DEFAULT);
-      if(monitor.isFilterUseEnabled())
-      {
-        if(idSet.isDefined())
-        {
-          monitor.updateStats(equalityFilter, idSet.size());
-        }
-        else if(!equalityIndex.isTrusted())
-        {
-          monitor.updateStats(equalityFilter,
-              INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                  equalityIndex.getName()));
-        }
-        else if(equalityIndex.isRebuildRunning())
-        {
-          monitor.updateStats(equalityFilter,
-              INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                  equalityIndex.getName()));
-        }
-        else
-        {
-          monitor.updateStats(equalityFilter,
-              INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                  equalityIndex.getName()));
-        }
-      }
-      return idSet;
+    try {
+      final MatchingRule matchRule = equalityFilter.getAttributeType().getEqualityMatchingRule();
+      final IndexQuery indexQuery = matchRule.getAssertion(equalityFilter.getAssertionValue())
+          .createIndexQuery(indexQueryFactory);
+      return evaluateIndexQuery(indexQuery, "equality", equalityFilter, debugBuffer, monitor);
     }
     catch (DecodeException e)
     {
@@ -856,54 +733,8 @@
                                            StringBuilder debugBuffer,
                                            DatabaseEnvironmentMonitor monitor)
   {
-    if (presenceIndex == null)
-    {
-      if(monitor.isFilterUseEnabled())
-      {
-        monitor.updateStats(filter,
-            INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("presence",
-                indexConfig.getAttribute().getNameOrOID()));
-      }
-      return new EntryIDSet();
-    }
-
-    if(debugBuffer != null)
-    {
-      debugBuffer.append("[INDEX:");
-      debugBuffer.append(indexConfig.getAttribute().getNameOrOID());
-      debugBuffer.append(".");
-      debugBuffer.append("presence]");
-    }
-
-    // Read the presence key
-    EntryIDSet idSet =
-        presenceIndex.readKey(presenceKey, null, LockMode.DEFAULT);
-    if(monitor.isFilterUseEnabled())
-    {
-      if(idSet.isDefined())
-      {
-        monitor.updateStats(filter, idSet.size());
-      }
-      else if(!presenceIndex.isTrusted())
-      {
-        monitor.updateStats(filter,
-            INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                  presenceIndex.getName()));
-      }
-      else if(presenceIndex.isRebuildRunning())
-      {
-        monitor.updateStats(filter,
-            INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                  presenceIndex.getName()));
-      }
-      else
-      {
-        monitor.updateStats(filter,
-            INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                  presenceIndex.getName()));
-      }
-    }
-    return idSet;
+    final IndexQuery indexQuery = indexQueryFactory.createMatchAllQuery();
+    return evaluateIndexQuery(indexQuery, "presence", filter, debugBuffer, monitor);
   }
 
   /**
@@ -938,88 +769,22 @@
    * @return The candidate entry IDs that might contain a value
    *         less than or equal to the filter assertion value.
    */
-  public EntryIDSet evaluateLessOrEqualFilter(SearchFilter filter,
-                                              StringBuilder debugBuffer,
-                                             DatabaseEnvironmentMonitor monitor)
+  public EntryIDSet evaluateLessOrEqualFilter(SearchFilter filter, StringBuilder debugBuffer,
+      DatabaseEnvironmentMonitor monitor)
   {
     return evaluateOrderingFilter(filter, false, debugBuffer, monitor);
   }
 
-  private EntryIDSet evaluateOrderingFilter(SearchFilter filter,
-      boolean greater, StringBuilder debugBuffer,
+  private EntryIDSet evaluateOrderingFilter(SearchFilter filter, boolean greater, StringBuilder debugBuffer,
       DatabaseEnvironmentMonitor monitor)
   {
-
-    if (orderingIndex == null)
-    {
-      if(monitor.isFilterUseEnabled())
-      {
-        monitor.updateStats(filter,
-            INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("ordering",
-                indexConfig.getAttribute().getNameOrOID()));
-      }
-      return new EntryIDSet();
-    }
-
-    try
-    {
-      // Use the ordering matching rule to normalize the value.
-      MatchingRule orderingRule = filter.getAttributeType().getOrderingMatchingRule();
-      byte[] normalizedValue = orderingRule.normalizeAssertionValue(
-          filter.getAssertionValue()).toByteArray();
-
-      // Set the lower and upper bounds for a range search.
-      byte[] lower;
-      byte[] upper;
-      if (greater)
-      {
-        // Set upper bound to 0 to search all keys greater than the lower bound.
-        lower = normalizedValue;
-        upper = new byte[0];
-      }
-      else
-      {
-        // Set lower bound to 0 to start the range search from the smallest key.
-        lower = new byte[0];
-        upper = normalizedValue;
-      }
-
-      if(debugBuffer != null)
-      {
-        debugBuffer.append("[INDEX:");
-        debugBuffer.append(indexConfig.getAttribute().getNameOrOID());
-        debugBuffer.append(".");
-        debugBuffer.append("ordering]");
-      }
-
-      // Read the range: lower <= keys < upper OR lower < keys <= upper
-      EntryIDSet idSet = orderingIndex.readRange(lower, upper, greater, !greater);
-      if(monitor.isFilterUseEnabled())
-      {
-        if(idSet.isDefined())
-        {
-          monitor.updateStats(filter, idSet.size());
-        }
-        else if(!orderingIndex.isTrusted())
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                  orderingIndex.getName()));
-        }
-        else if(orderingIndex.isRebuildRunning())
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                  orderingIndex.getName()));
-        }
-        else
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                  orderingIndex.getName()));
-        }
-      }
-      return idSet;
+    try {
+      final MatchingRule matchRule = filter.getAttributeType().getOrderingMatchingRule();
+      final Assertion assertion = greater ?
+          matchRule.getGreaterOrEqualAssertion(filter.getAssertionValue()) :
+          matchRule.getLessOrEqualAssertion(filter.getAssertionValue());
+      final IndexQuery indexQuery = assertion.createIndexQuery(indexQueryFactory);
+      return evaluateIndexQuery(indexQuery, "ordering", filter, debugBuffer, monitor);
     }
     catch (DecodeException e)
     {
@@ -1044,165 +809,12 @@
                                             StringBuilder debugBuffer,
                                             DatabaseEnvironmentMonitor monitor)
   {
-    SubstringMatchingRule matchRule =
-         filter.getAttributeType().getSubstringMatchingRule();
-
-    try
-    {
-      ArrayList<ByteString> elements = new ArrayList<ByteString>();
-      EntryIDSet results = new EntryIDSet();
-
-      if (filter.getSubInitialElement() != null)
-      {
-        // Use the equality index for initial substrings if possible.
-        if (equalityIndex != null && matchRule != null)
-        {
-          ByteString normValue =
-               matchRule.normalizeSubstring(filter.getSubInitialElement());
-          byte[] normBytes = normValue.toByteArray();
-
-          EntryIDSet list = matchInitialSubstring(normBytes);
-          results.retainAll(list);
-
-          if (results.isDefined() &&
-               results.size() <= IndexFilter.FILTER_CANDIDATE_THRESHOLD)
-          {
-            if(debugBuffer != null)
-            {
-              debugBuffer.append("[INDEX:");
-              debugBuffer.append(indexConfig.getAttribute().
-                  getNameOrOID());
-              debugBuffer.append(".");
-              debugBuffer.append("equality]");
-            }
-
-            if(monitor.isFilterUseEnabled())
-            {
-              monitor.updateStats(filter, results.size());
-            }
-            return results;
-          }
-        }
-        else
-        {
-          elements.add(filter.getSubInitialElement());
-        }
-      }
-
-      if (substringIndex == null)
-      {
-        if(monitor.isFilterUseEnabled())
-        {
-          if(!results.isDefined())
-          {
-            if(filter.getSubInitialElement() != null)
-            {
-              if(equalityIndex == null)
-              {
-                monitor.updateStats(filter,
-                    INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("equality",
-                        indexConfig.getAttribute().getNameOrOID()));
-              }
-              else if(!equalityIndex.isTrusted())
-              {
-                monitor.updateStats(filter,
-                    INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                        equalityIndex.getName()));
-              }
-              else if(equalityIndex.isRebuildRunning())
-              {
-                monitor.updateStats(filter,
-                    INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                        equalityIndex.getName()));
-              }
-              else
-              {
-                monitor.updateStats(filter,
-                    INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                        equalityIndex.getName()));
-              }
-            }
-            else
-            {
-              monitor.updateStats(filter,
-                  INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("substring",
-                      indexConfig.getAttribute().getNameOrOID()));
-            }
-          }
-          else
-          {
-            monitor.updateStats(filter, results.size());
-          }
-        }
-        return results;
-      }
-
-      // We do not distinguish between sub and final elements
-      // in the substring index. Put all the elements into a single list.
-      elements.addAll(filter.getSubAnyElements());
-      if (filter.getSubFinalElement() != null)
-      {
-        elements.add(filter.getSubFinalElement());
-      }
-
-      // Iterate through each substring element.
-      for (ByteString element : elements)
-      {
-        // Normalize the substring according to the substring matching rule.
-        ByteString normValue = matchRule.normalizeSubstring(element);
-        byte[] normBytes = normValue.toByteArray();
-
-        // Get the candidate entry IDs from the index.
-        EntryIDSet list = matchSubstring(normBytes);
-
-        // Incorporate them into the results.
-        results.retainAll(list);
-
-        // We may have reached the point of diminishing returns where
-        // it is quicker to stop now and process the current small number of
-        // candidates.
-        if (results.isDefined() &&
-             results.size() <= IndexFilter.FILTER_CANDIDATE_THRESHOLD)
-        {
-          break;
-        }
-      }
-
-      if(debugBuffer != null)
-      {
-        debugBuffer.append("[INDEX:");
-        debugBuffer.append(indexConfig.getAttribute().getNameOrOID());
-        debugBuffer.append(".");
-        debugBuffer.append("substring]");
-      }
-
-      if(monitor.isFilterUseEnabled())
-      {
-        if(results.isDefined())
-        {
-          monitor.updateStats(filter, results.size());
-        }
-        else if(!substringIndex.isTrusted())
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                  substringIndex.getName()));
-        }
-        else if(substringIndex.isRebuildRunning())
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                  substringIndex.getName()));
-        }
-        else
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                  substringIndex.getName()));
-        }
-      }
-
-      return results;
+    try {
+      final MatchingRule matchRule = filter.getAttributeType().getSubstringMatchingRule();
+      final IndexQuery indexQuery = matchRule.getSubstringAssertion(
+          filter.getSubInitialElement(), filter.getSubAnyElements(), filter.getSubFinalElement())
+          .createIndexQuery(indexQueryFactory);
+      return evaluateIndexQuery(indexQuery, "substring", filter, debugBuffer, monitor);
     }
     catch (DecodeException e)
     {
@@ -1212,36 +824,41 @@
   }
 
   /**
-   * Retrieve the entry IDs that might have a value greater than or
-   * equal to the lower bound value, and less than or equal to the
-   * upper bound value.
+   * Retrieve the entry IDs that might match two filters that restrict a value
+   * to both a lower bound and an upper bound.
    *
-   * @param lowerValue The lower bound assertion value
-   * @param upperValue The upper bound assertion value
-   * @return The candidate entry IDs.
+   * @param filter1
+   *          The first filter, that is either a less-or-equal filter or a
+   *          greater-or-equal filter.
+   * @param filter2
+   *          The second filter, that is either a less-or-equal filter or a
+   *          greater-or-equal filter. It must not be of the same type than the
+   *          first filter.
+   * @param debugBuffer
+   *          If not null, a diagnostic string will be written which will help
+   *          determine how the indexes contributed to this search.
+   * @param monitor
+   *          The database environment monitor provider that will keep index
+   *          filter usage statistics.
+   * @return The candidate entry IDs that might contain match both filters.
    */
-  public EntryIDSet evaluateBoundedRange(ByteString lowerValue, ByteString upperValue)
+  public EntryIDSet evaluateBoundedRange(SearchFilter filter1, SearchFilter filter2, StringBuilder debugBuffer,
+      DatabaseEnvironmentMonitor monitor)
   {
-    if (orderingIndex == null)
-    {
-      return new EntryIDSet();
-    }
-
-    try
-    {
-      // Set the lower and upper bounds for a range search.
-      MatchingRule orderingRule = getAttributeType().getOrderingMatchingRule();
-      byte[] lower = orderingRule.normalizeAssertionValue(lowerValue).toByteArray();
-      byte[] upper = orderingRule.normalizeAssertionValue(upperValue).toByteArray();
-
-      // Read the range: lower <= keys <= upper.
-      return orderingIndex.readRange(lower, upper, true, true);
-    }
-    catch (DecodeException e)
-    {
-      logger.traceException(e);
-      return new EntryIDSet();
-    }
+    // TODO : this implementation is not optimal
+    // as it implies two separate evaluations instead of a single one,
+    // thus defeating the purpose of the optimisation done
+    // in IndexFilter#evaluateLogicalAndFilter method.
+    // One solution could be to implement a boundedRangeAssertion that combine
+    // the two operations in one.
+    EntryIDSet results = filter1.getFilterType() == FilterType.LESS_OR_EQUAL ?
+        evaluateLessOrEqualFilter(filter1, debugBuffer, monitor) :
+        evaluateGreaterOrEqualFilter(filter1, debugBuffer, monitor);
+    EntryIDSet results2 = filter2.getFilterType() == FilterType.LESS_OR_EQUAL ?
+        evaluateLessOrEqualFilter(filter2, debugBuffer, monitor) :
+        evaluateGreaterOrEqualFilter(filter2, debugBuffer, monitor);
+    results.retainAll(results2);
+    return results;
   }
 
   /**
@@ -1356,66 +973,14 @@
    * @return The candidate entry IDs that might contain the filter
    *         assertion value.
    */
-  public EntryIDSet evaluateApproximateFilter(SearchFilter approximateFilter,
-                                              StringBuilder debugBuffer,
-                                             DatabaseEnvironmentMonitor monitor)
+  public EntryIDSet evaluateApproximateFilter(SearchFilter approximateFilter, StringBuilder debugBuffer,
+      DatabaseEnvironmentMonitor monitor)
   {
-    if (approximateIndex == null)
-    {
-      if(monitor.isFilterUseEnabled())
-      {
-        monitor.updateStats(approximateFilter,
-            INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("approximate",
-                indexConfig.getAttribute().getNameOrOID()));
-      }
-      return new EntryIDSet();
-    }
-
-    try
-    {
-      MatchingRule approximateMatchingRule =
-          approximateFilter.getAttributeType().getApproximateMatchingRule();
-      // Make a key from the normalized assertion value.
-      byte[] keyBytes = approximateMatchingRule.normalizeAssertionValue(
-          approximateFilter.getAssertionValue()).toByteArray();
-      DatabaseEntry key = new DatabaseEntry(keyBytes);
-
-      if(debugBuffer != null)
-      {
-        debugBuffer.append("[INDEX:");
-        debugBuffer.append(indexConfig.getAttribute().getNameOrOID());
-        debugBuffer.append(".");
-        debugBuffer.append("approximate]");
-      }
-
-      // Read the key.
-      EntryIDSet idSet = approximateIndex.readKey(key, null, LockMode.DEFAULT);
-      if(monitor.isFilterUseEnabled())
-      {
-        if(idSet.isDefined())
-        {
-          monitor.updateStats(approximateFilter, idSet.size());
-        }
-        else if(!approximateIndex.isTrusted())
-        {
-          monitor.updateStats(approximateFilter,
-              INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                  approximateIndex.getName()));
-        }
-        else if(approximateIndex.isRebuildRunning())
-        {
-          monitor.updateStats(approximateFilter,
-              INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                  approximateIndex.getName()));
-        }
-        else
-        {
-          monitor.updateStats(approximateFilter,
-              INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                  approximateIndex.getName()));
-        }
-      }
-      return idSet;
+    try {
+      MatchingRule matchRule = approximateFilter.getAttributeType().getApproximateMatchingRule();
+      IndexQuery indexQuery = matchRule.getAssertion(approximateFilter.getAssertionValue())
+          .createIndexQuery(indexQueryFactory);
+      return evaluateIndexQuery(indexQuery, "approximate", approximateFilter, debugBuffer, monitor);
     }
     catch (DecodeException e)
     {
@@ -1609,8 +1174,7 @@
     try
     {
       AttributeType attrType = cfg.getAttribute();
-      String name =
-        entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID();
+      String name = entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID();
       final int indexEntryLimit = cfg.getIndexEntryLimit();
       final JEIndexConfig config = new JEIndexConfig(cfg.getSubstringLength());
 
@@ -1620,6 +1184,7 @@
         {
           equalityIndex = openNewIndex(name, attrType,
               new EqualityIndexer(attrType), adminActionRequired, messages);
+          nameToIndexes.put(LocalDBIndexCfgDefn.IndexType.EQUALITY.toString(), equalityIndex);
         }
         else
         {
@@ -1627,8 +1192,7 @@
           if(this.equalityIndex.setIndexEntryLimit(indexEntryLimit))
           {
             adminActionRequired.set(true);
-            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
-                .get(equalityIndex.getName()));
+            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(equalityIndex.getName()));
             this.equalityIndex.setIndexEntryLimit(indexEntryLimit);
           }
         }
@@ -1640,6 +1204,7 @@
           entryContainer.exclusiveLock.lock();
           try
           {
+            nameToIndexes.remove(LocalDBIndexCfgDefn.IndexType.EQUALITY.toString());
             entryContainer.deleteDatabase(equalityIndex);
             equalityIndex = null;
           }
@@ -1657,6 +1222,7 @@
           Indexer presenceIndexer = new PresenceIndexer(attrType);
           presenceIndex = newIndex(name + ".presence", presenceIndexer, indexEntryLimit);
           openIndex(presenceIndex, adminActionRequired, messages);
+          nameToIndexes.put(LocalDBIndexCfgDefn.IndexType.PRESENCE.toString(), presenceIndex);
         }
         else
         {
@@ -1664,8 +1230,7 @@
           if(this.presenceIndex.setIndexEntryLimit(indexEntryLimit))
           {
             adminActionRequired.set(true);
-            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
-                .get(presenceIndex.getName()));
+            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(presenceIndex.getName()));
           }
         }
       }
@@ -1676,6 +1241,7 @@
           entryContainer.exclusiveLock.lock();
           try
           {
+            nameToIndexes.remove(LocalDBIndexCfgDefn.IndexType.PRESENCE.toString());
             entryContainer.deleteDatabase(presenceIndex);
             presenceIndex = null;
           }
@@ -1695,6 +1261,7 @@
           Index index = newIndex(name + "." + indexer.getExtensibleIndexID(),
               extIndexer, indexEntryLimit);
           substringIndex = openIndex(index, adminActionRequired, messages);
+          nameToIndexes.put(LocalDBIndexCfgDefn.IndexType.SUBSTRING.toString(), substringIndex);
         }
         else
         {
@@ -1702,8 +1269,7 @@
           if(this.substringIndex.setIndexEntryLimit(indexEntryLimit))
           {
             adminActionRequired.set(true);
-            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
-                .get(substringIndex.getName()));
+            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(substringIndex.getName()));
           }
 
           if (indexConfig.getSubstringLength() != cfg.getSubstringLength())
@@ -1719,6 +1285,7 @@
           entryContainer.exclusiveLock.lock();
           try
           {
+            nameToIndexes.remove(LocalDBIndexCfgDefn.IndexType.SUBSTRING.toString());
             entryContainer.deleteDatabase(substringIndex);
             substringIndex = null;
           }
@@ -1735,6 +1302,7 @@
         {
           orderingIndex = openNewIndex(name, attrType,
               new OrderingIndexer(attrType), adminActionRequired, messages);
+          nameToIndexes.put(LocalDBIndexCfgDefn.IndexType.ORDERING.toString(), orderingIndex);
         }
         else
         {
@@ -1742,8 +1310,7 @@
           if(this.orderingIndex.setIndexEntryLimit(indexEntryLimit))
           {
             adminActionRequired.set(true);
-            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
-                .get(orderingIndex.getName()));
+            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(orderingIndex.getName()));
           }
         }
       }
@@ -1754,6 +1321,7 @@
           entryContainer.exclusiveLock.lock();
           try
           {
+            nameToIndexes.remove(LocalDBIndexCfgDefn.IndexType.ORDERING.toString());
             entryContainer.deleteDatabase(orderingIndex);
             orderingIndex = null;
           }
@@ -1764,13 +1332,13 @@
         }
       }
 
-      if (cfg.getIndexType().contains(
-              LocalDBIndexCfgDefn.IndexType.APPROXIMATE))
+      if (cfg.getIndexType().contains(LocalDBIndexCfgDefn.IndexType.APPROXIMATE))
       {
         if(approximateIndex == null)
         {
           approximateIndex = openNewIndex(name, attrType,
               new ApproximateIndexer(attrType), adminActionRequired, messages);
+          nameToIndexes.put(LocalDBIndexCfgDefn.IndexType.APPROXIMATE.toString(), approximateIndex);
         }
         else
         {
@@ -1778,8 +1346,7 @@
           if(this.approximateIndex.setIndexEntryLimit(indexEntryLimit))
           {
             adminActionRequired.set(true);
-            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
-                .get(approximateIndex.getName()));
+            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(approximateIndex.getName()));
           }
         }
       }
@@ -1790,6 +1357,7 @@
           entryContainer.exclusiveLock.lock();
           try
           {
+            nameToIndexes.remove(LocalDBIndexCfgDefn.IndexType.APPROXIMATE.toString());
             entryContainer.deleteDatabase(approximateIndex);
             approximateIndex = null;
           }
@@ -1800,22 +1368,18 @@
         }
       }
 
-      if (cfg.getIndexType().contains(
-              LocalDBIndexCfgDefn.IndexType.EXTENSIBLE))
+      if (cfg.getIndexType().contains(LocalDBIndexCfgDefn.IndexType.EXTENSIBLE))
       {
-        Set<String> extensibleRules =
-            cfg.getIndexExtensibleMatchingRule();
-        Set<ExtensibleMatchingRule> validRules =
-                                      new HashSet<ExtensibleMatchingRule>();
+        Set<String> extensibleRules = cfg.getIndexExtensibleMatchingRule();
+        Set<ExtensibleMatchingRule> validRules = new HashSet<ExtensibleMatchingRule>();
         if(extensibleIndexes == null)
         {
           extensibleIndexes = new ExtensibleMatchingRuleIndex();
         }
         for(String ruleName:extensibleRules)
         {
-          ExtensibleMatchingRule rule =
-              DirectoryServer.getExtensibleMatchingRule(toLowerCase(ruleName));
-           if(rule == null)
+          ExtensibleMatchingRule rule = DirectoryServer.getExtensibleMatchingRule(toLowerCase(ruleName));
+          if(rule == null)
           {
             logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
             continue;
@@ -1838,8 +1402,7 @@
               if(extensibleIndex.setIndexEntryLimit(indexEntryLimit))
               {
                 adminActionRequired.set(true);
-                messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
-                    .get(extensibleIndex.getName()));
+                messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(extensibleIndex.getName()));
               }
               if (indexConfig.getSubstringLength() != cfg.getSubstringLength())
               {
@@ -1850,8 +1413,7 @@
             extensibleIndexes.addRule(indexID, rule);
             indexMap.put(indexer.getExtensibleIndexID(), extensibleIndexes.getIndex(indexID));
           }
-          final IndexQueryFactory<IndexQuery> factory =
-              new IndexQueryFactoryImpl(indexMap, config);
+          IndexQueryFactory<IndexQuery> factory = new IndexQueryFactoryImpl(indexMap, config);
           extensibleIndexes.addQueryFactory(rule, factory);
         }
         //Some rules might have been removed from the configuration.
@@ -1928,8 +1490,7 @@
 
       indexConfig = cfg;
 
-      return new ConfigChangeResult(
-          ResultCode.SUCCESS, adminActionRequired.get(), messages);
+      return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired.get(), messages);
     }
     catch(Exception e)
     {
@@ -2168,101 +1729,37 @@
                                              DatabaseEnvironmentMonitor monitor)
   {
     //Get the Matching Rule OID of the filter.
-    String nOID  = extensibleFilter.getMatchingRuleID();
+    String matchRuleOID  = extensibleFilter.getMatchingRuleID();
     /**
      * Use the default equality index in two conditions:
      * 1. There is no matching rule provided
      * 2. The matching rule specified is actually the default equality.
      */
-    MatchingRule eqRule =
-            indexConfig.getAttribute().getEqualityMatchingRule();
-    if (nOID == null
-        || nOID.equals(eqRule.getOID())
-        || nOID.equalsIgnoreCase(eqRule.getNameOrOID()))
+    MatchingRule eqRule = indexConfig.getAttribute().getEqualityMatchingRule();
+    if (matchRuleOID == null
+        || matchRuleOID.equals(eqRule.getOID())
+        || matchRuleOID.equalsIgnoreCase(eqRule.getNameOrOID()))
     {
       //No matching rule is defined; use the default equality matching rule.
-      if(equalityIndex == null)
-      {
-        // There is no index on this matching rule.
-        if(monitor.isFilterUseEnabled())
-        {
-          monitor.updateStats(extensibleFilter,
-              INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("equality",
-                  indexConfig.getAttribute().getNameOrOID()));
-        }
-        return IndexQuery.createNullIndexQuery().evaluate(null);
-      }
-      try
-      {
-        // Make a key from the normalized assertion value.
-        MatchingRule rule =
-            extensibleFilter.getAttributeType().getEqualityMatchingRule();
-        ByteString value = extensibleFilter.getAssertionValue();
-        byte[] keyBytes = rule.normalizeAssertionValue(value).toByteArray();
-        DatabaseEntry key = new DatabaseEntry(keyBytes);
-
-        if(debugBuffer != null)
-        {
-          debugBuffer.append("[INDEX:");
-          debugBuffer.append(indexConfig.getAttribute().getNameOrOID());
-          debugBuffer.append(".");
-          debugBuffer.append("equality]");
-        }
-
-        // Read the key.
-        EntryIDSet idSet = equalityIndex.readKey(key, null, LockMode.DEFAULT);
-        if(monitor.isFilterUseEnabled())
-        {
-          if(idSet.isDefined())
-          {
-            monitor.updateStats(extensibleFilter, idSet.size());
-          }
-          else if(!equalityIndex.isTrusted())
-          {
-            monitor.updateStats(extensibleFilter,
-                INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                  equalityIndex.getName()));
-          }
-          else if(equalityIndex.isRebuildRunning())
-          {
-            monitor.updateStats(extensibleFilter,
-                INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                  equalityIndex.getName()));
-          }
-          else
-          {
-            monitor.updateStats(extensibleFilter,
-                INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                  equalityIndex.getName()));
-          }
-        }
-        return idSet;
-      }
-      catch (DecodeException e)
-      {
-        logger.traceException(e);
-        return IndexQuery.createNullIndexQuery().evaluate(null);
-      }
+      return evaluateEqualityFilter(extensibleFilter, debugBuffer, monitor);
     }
-    ExtensibleMatchingRule rule =
-            DirectoryServer.getExtensibleMatchingRule(nOID);
+
+    ExtensibleMatchingRule rule = DirectoryServer.getExtensibleMatchingRule(matchRuleOID);
     IndexQueryFactory<IndexQuery> factory = null;
-    if(extensibleIndexes == null
-            || (factory = extensibleIndexes.getQueryFactory(rule))==null)
+    if (extensibleIndexes == null || (factory = extensibleIndexes.getQueryFactory(rule)) == null)
     {
       // There is no index on this matching rule.
-      if(monitor.isFilterUseEnabled())
+      if (monitor.isFilterUseEnabled())
       {
-        monitor.updateStats(extensibleFilter,
-            INFO_JEB_INDEX_FILTER_MATCHING_RULE_NOT_INDEXED.get(nOID,
-                indexConfig.getAttribute().getNameOrOID()));
+        monitor.updateStats(extensibleFilter, INFO_JEB_INDEX_FILTER_MATCHING_RULE_NOT_INDEXED.get(
+            matchRuleOID, indexConfig.getAttribute().getNameOrOID()));
       }
       return IndexQuery.createNullIndexQuery().evaluate(null);
     }
 
     try
     {
-      if(debugBuffer != null)
+      if (debugBuffer != null)
       {
         debugBuffer.append("[INDEX:");
         for (ExtensibleIndexer indexer : rule.getIndexers())
@@ -2276,25 +1773,17 @@
       }
       ByteString assertionValue = extensibleFilter.getAssertionValue();
       IndexQuery expression = rule.createIndexQuery(assertionValue, factory);
-      List<LocalizableMessage> debugMessages =
-          monitor.isFilterUseEnabled() ? new ArrayList<LocalizableMessage>() : null;
-      EntryIDSet idSet = expression.evaluate(debugMessages);
-      if(monitor.isFilterUseEnabled())
+      LocalizableMessageBuilder debugMessage = monitor.isFilterUseEnabled() ? new LocalizableMessageBuilder() : null;
+      EntryIDSet idSet = expression.evaluate(debugMessage);
+      if (monitor.isFilterUseEnabled())
       {
-        if(idSet.isDefined())
+        if (idSet.isDefined())
         {
           monitor.updateStats(extensibleFilter, idSet.size());
         }
         else
         {
-          if(debugMessages != null && !debugMessages.isEmpty())
-          {
-            monitor.updateStats(extensibleFilter, debugMessages.get(0));
-          }
-          else
-          {
-            monitor.updateStats(extensibleFilter, LocalizableMessage.EMPTY);
-          }
+          monitor.updateStats(extensibleFilter, debugMessage.toMessage());
         }
       }
       return idSet;
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexFilter.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexFilter.java
index 11485a3..dd3119d 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexFilter.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexFilter.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions copyright 2011 ForgeRock AS
+ *      Portions copyright 2011-2014 ForgeRock AS
  *
  */
 package org.opends.server.backends.jeb;
@@ -298,11 +298,10 @@
       ArrayList<SearchFilter> rangeList = rangeEntry.getValue();
       if (rangeList.size() == 2)
       {
-        SearchFilter a = rangeList.get(0);
-        SearchFilter b = rangeList.get(1);
+        SearchFilter filter1 = rangeList.get(0);
+        SearchFilter filter2 = rangeList.get(1);
 
-        AttributeIndex attributeIndex =
-             entryContainer.getAttributeIndex(rangeEntry.getKey());
+        AttributeIndex attributeIndex = entryContainer.getAttributeIndex(rangeEntry.getKey());
         if (attributeIndex == null)
         {
           if(monitor.isFilterUseEnabled())
@@ -313,104 +312,18 @@
           }
           continue;
         }
+        EntryIDSet set = attributeIndex.evaluateBoundedRange(filter1, filter2, buffer, monitor);
 
-        if (a.getFilterType() == FilterType.GREATER_OR_EQUAL &&
-             b.getFilterType() == FilterType.LESS_OR_EQUAL)
+        if(monitor.isFilterUseEnabled() && set.isDefined())
         {
-          // Like (cn>=A)(cn<=B).
-          EntryIDSet set;
-          set = attributeIndex.evaluateBoundedRange(a.getAssertionValue(),
-                                                     b.getAssertionValue());
-
-          if (buffer != null)
-          {
-            a.toString(buffer);
-            b.toString(buffer);
-            set.toString(buffer);
-          }
-
-          if(monitor.isFilterUseEnabled())
-          {
-            if(set.isDefined())
-            {
-              monitor.updateStats(SearchFilter.createANDFilter(rangeList),
-                  set.size());
-            }
-            else if(!attributeIndex.orderingIndex.isTrusted())
-            {
-              monitor.updateStats(SearchFilter.createANDFilter(rangeList),
-                  INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                      attributeIndex.orderingIndex.getName()));
-            }
-            else if(attributeIndex.orderingIndex.isRebuildRunning())
-            {
-              monitor.updateStats(SearchFilter.createANDFilter(rangeList),
-                  INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                      attributeIndex.orderingIndex.getName()));
-            }
-            else
-            {
-              monitor.updateStats(SearchFilter.createANDFilter(rangeList),
-                  INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                      attributeIndex.orderingIndex.getName()));
-            }
-          }
-
-          if (retainAll(results, set))
-          {
-            return results;
-          }
-          continue;
+          monitor.updateStats(SearchFilter.createANDFilter(rangeList), set.size());
         }
-        else if (a.getFilterType() == FilterType.LESS_OR_EQUAL &&
-             b.getFilterType() == FilterType.GREATER_OR_EQUAL)
+
+        if (retainAll(results, set))
         {
-          // Like (cn<=A)(cn>=B).
-          EntryIDSet set;
-          set = attributeIndex.evaluateBoundedRange(b.getAssertionValue(),
-                                                     a.getAssertionValue());
-
-          if (buffer != null)
-          {
-            a.toString(buffer);
-            b.toString(buffer);
-            set.toString(buffer);
-          }
-
-          if(monitor.isFilterUseEnabled())
-          {
-            if(set.isDefined())
-            {
-              monitor.updateStats(SearchFilter.createANDFilter(rangeList),
-                  set.size());
-            }
-            else if(!attributeIndex.orderingIndex.isTrusted())
-            {
-              monitor.updateStats(SearchFilter.createANDFilter(rangeList),
-                  INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                      attributeIndex.orderingIndex.getName()));
-            }
-            else if(attributeIndex.orderingIndex.isRebuildRunning())
-            {
-              monitor.updateStats(SearchFilter.createANDFilter(rangeList),
-                  INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                      attributeIndex.orderingIndex.getName()));
-            }
-            else
-            {
-              monitor.updateStats(SearchFilter.createANDFilter(rangeList),
-                  INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                      attributeIndex.orderingIndex.getName()));
-            }
-          }
-
-
-          if (retainAll(results, set))
-          {
-            return results;
-          }
-          continue;
+          return results;
         }
+        continue;
       }
 
       // Add to the remaining range components to be processed.
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQuery.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQuery.java
index acd6c4b..c15aa73 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQuery.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQuery.java
@@ -29,10 +29,9 @@
 
 
 
-import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizableMessageBuilder;
 
 import java.util.Collection;
-import java.util.List;
 
 import static org.opends.server.backends.jeb.IndexFilter.*;
 
@@ -51,12 +50,12 @@
   /**
    * Evaluates the index query and returns the EntryIDSet.
    *
-   * @param debugMessages If not null, diagnostic messages will be written
+   * @param debugMessage If not null, diagnostic message will be written
    *                      which will help to determine why the returned
    *                      EntryIDSet is not defined.
-   * @return The EntryIDSet as a result of evaulation of this query.
+   * @return The EntryIDSet as a result of evaluation of this query.
    */
-  public abstract EntryIDSet evaluate(List<LocalizableMessage> debugMessages);
+  public abstract EntryIDSet evaluate(LocalizableMessageBuilder debugMessage);
 
 
 
@@ -117,7 +116,7 @@
      * @param debugMessages
      */
     @Override
-    public EntryIDSet evaluate(List<LocalizableMessage> debugMessages)
+    public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage)
     {
       return new EntryIDSet();
     }
@@ -154,18 +153,18 @@
      * @param debugMessages
      */
     @Override
-    public EntryIDSet evaluate(List<LocalizableMessage> debugMessages)
+    public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage)
     {
       EntryIDSet entryIDs = null;
       for (IndexQuery query : subIndexQueries)
       {
         if (entryIDs == null)
         {
-          entryIDs = query.evaluate(debugMessages);
+          entryIDs = query.evaluate(debugMessage);
         }
         else
         {
-          entryIDs.retainAll(query.evaluate(debugMessages));
+          entryIDs.retainAll(query.evaluate(debugMessage));
         }
         if (entryIDs.isDefined()
             && entryIDs.size() <= FILTER_CANDIDATE_THRESHOLD)
@@ -207,18 +206,18 @@
      * @param debugMessages
      */
     @Override
-    public EntryIDSet evaluate(List<LocalizableMessage> debugMessages)
+    public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage)
     {
       EntryIDSet entryIDs = null;
       for (IndexQuery query : subIndexQueries)
       {
         if (entryIDs == null)
         {
-          entryIDs = query.evaluate(debugMessages);
+          entryIDs = query.evaluate(debugMessage);
         }
         else
         {
-          entryIDs.addAll(query.evaluate(debugMessages));
+          entryIDs.addAll(query.evaluate(debugMessage));
         }
         if (entryIDs.isDefined()
             && entryIDs.size() <= FILTER_CANDIDATE_THRESHOLD)
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQueryFactoryImpl.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQueryFactoryImpl.java
index ffcdca7..92386d9 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQueryFactoryImpl.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexQueryFactoryImpl.java
@@ -27,10 +27,9 @@
 package org.opends.server.backends.jeb;
 
 import java.util.Collection;
-import java.util.List;
 import java.util.Map;
 
-import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizableMessageBuilder;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 import org.forgerock.opendj.ldap.spi.IndexingOptions;
@@ -48,6 +47,8 @@
     IndexQueryFactory<IndexQuery>
 {
 
+  private static final String PRESENCE_INDEX_KEY = "presence";
+
   /**
    * The Map containing the string type identifier and the corresponding index.
    */
@@ -79,34 +80,35 @@
       {
 
         @Override
-        public EntryIDSet evaluate(List<LocalizableMessage> debugMessages)
+        public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage)
         {
           // Read the database and get Record for the key.
           DatabaseEntry key = new DatabaseEntry(value.toByteArray());
 
           // Select the right index to be used.
           Index index = indexMap.get(indexID);
-          EntryIDSet entrySet =
-              index.readKey(key, null, LockMode.DEFAULT);
-          if(debugMessages != null && !entrySet.isDefined())
+          if (index == null)
+          {
+            if(debugMessage != null)
+            {
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get(indexID, ""));
+            }
+            return createMatchAllQuery().evaluate(debugMessage);
+          }
+          EntryIDSet entrySet = index.readKey(key, null, LockMode.DEFAULT);
+          if(debugMessage != null && !entrySet.isDefined())
           {
             if(!index.isTrusted())
             {
-              debugMessages.add(
-                  INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                      index.getName()));
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(index.getName()));
             }
             else if(index.isRebuildRunning())
             {
-              debugMessages.add(
-                  INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                      index.getName()));
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(index.getName()));
             }
             else
             {
-              debugMessages.add(
-                  INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                      index.getName()));
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(index.getName()));
             }
           }
           return entrySet;
@@ -126,32 +128,33 @@
       {
 
         @Override
-        public EntryIDSet evaluate(List<LocalizableMessage> debugMessages)
+        public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage)
         {
           // Find the right index.
           Index index = indexMap.get(indexID);
-          EntryIDSet entrySet =
-              index.readRange(lowerBound.toByteArray(), upperBound
-                  .toByteArray(), includeLowerBound, includeUpperBound);
-          if(debugMessages != null && !entrySet.isDefined())
+          if (index == null)
+          {
+            if(debugMessage != null)
+            {
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get(indexID, ""));
+            }
+            return createMatchAllQuery().evaluate(debugMessage);
+          }
+          EntryIDSet entrySet = index.readRange(lowerBound.toByteArray(), upperBound.toByteArray(),
+              includeLowerBound, includeUpperBound);
+          if(debugMessage != null && !entrySet.isDefined())
           {
             if(!index.isTrusted())
             {
-              debugMessages.add(
-                  INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                      index.getName()));
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(index.getName()));
             }
             else if(index.isRebuildRunning())
             {
-              debugMessages.add(
-                  INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                      index.getName()));
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(index.getName()));
             }
             else
             {
-              debugMessages.add(
-                  INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                      index.getName()));
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(index.getName()));
             }
           }
           return entrySet;
@@ -191,11 +194,38 @@
   {
     return new IndexQuery()
       {
-
         @Override
-        public EntryIDSet evaluate(List<LocalizableMessage> debugMessages)
+        public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage)
         {
-          return new EntryIDSet();
+          Index index = indexMap.get(PRESENCE_INDEX_KEY);
+          if (index == null)
+          {
+            if(debugMessage != null)
+            {
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get(index.getName(), ""));
+            }
+            return new EntryIDSet();
+          }
+
+          EntryIDSet entrySet = index.readKey(AttributeIndex.presenceKey, null, LockMode.DEFAULT);
+
+          if (debugMessage != null && !entrySet.isDefined())
+          {
+            if (!index.isTrusted())
+            {
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(index.getName()));
+            }
+            else if (index.isRebuildRunning())
+            {
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(index.getName()));
+            }
+            else
+            {
+              debugMessage.append(INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(index.getName()));
+            }
+          }
+
+          return entrySet;
         }
       };
   }
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/AbstractOrderingMatchingRule.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/AbstractOrderingMatchingRule.java
index 7ff209b..df653d9 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/AbstractOrderingMatchingRule.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/AbstractOrderingMatchingRule.java
@@ -28,8 +28,8 @@
 import java.util.Comparator;
 
 import org.forgerock.opendj.ldap.*;
+import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 import org.opends.server.api.AbstractMatchingRule;
-import org.opends.server.api.NotImplementedAssertion;
 import org.opends.server.api.OrderingMatchingRule;
 
 /**
@@ -57,46 +57,61 @@
 
   /** {@inheritDoc} */
   @Override
-  public Assertion getAssertion(final ByteSequence value)
-      throws DecodeException
+  public Assertion getAssertion(final ByteSequence assertionValue) throws DecodeException
   {
-    final ByteString assertionValue = normalizeAssertionValue(value);
-    return new NotImplementedAssertion()
+    final ByteString normAssertionValue = normalizeAttributeValue(assertionValue);
+    return new Assertion()
     {
       @Override
-      public ConditionResult matches(ByteSequence attributeValue)
+      public ConditionResult matches(final ByteSequence attributeValue)
       {
-        return ConditionResult.valueOf(compareValues(attributeValue, assertionValue) < 0);
+        return ConditionResult.valueOf(compareValues(attributeValue, normAssertionValue) < 0);
+      }
+
+      @Override
+      public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException
+      {
+        return factory.createRangeMatchQuery("ordering", ByteString.empty(), normAssertionValue, false, false);
       }
     };
   }
 
   /** {@inheritDoc} */
   @Override
-  public Assertion getGreaterOrEqualAssertion(ByteSequence value) throws DecodeException
+  public Assertion getGreaterOrEqualAssertion(final ByteSequence assertionValue) throws DecodeException
   {
-    final ByteString normAssertion = normalizeAssertionValue(value);
-    return new NotImplementedAssertion()
+    final ByteString normAssertionValue = normalizeAttributeValue(assertionValue);
+    return new Assertion()
     {
-      @Override
-      public ConditionResult matches(final ByteSequence normalizedAttributeValue)
-      {
-        return ConditionResult.valueOf(compareValues(normalizedAttributeValue, normAssertion) >= 0);
-      }
+        @Override
+        public ConditionResult matches(final ByteSequence normalizedAttributeValue) {
+          return ConditionResult.valueOf(compareValues(normalizedAttributeValue, normAssertionValue) >= 0);
+        }
+
+        @Override
+        public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException {
+            return factory.createRangeMatchQuery("ordering", normAssertionValue, ByteString.empty(), true, false);
+        }
     };
   }
 
   /** {@inheritDoc} */
   @Override
-  public Assertion getLessOrEqualAssertion(ByteSequence value) throws DecodeException
+  public Assertion getLessOrEqualAssertion(final ByteSequence assertionValue) throws DecodeException
   {
-    final ByteString normAssertion = normalizeAssertionValue(value);
-    return new NotImplementedAssertion()
+    final ByteString normAssertionValue = normalizeAttributeValue(assertionValue);
+    return new Assertion()
     {
       @Override
       public ConditionResult matches(final ByteSequence normalizedAttributeValue)
       {
-        return ConditionResult.valueOf(compareValues(normalizedAttributeValue, normAssertion) <= 0);
+        return ConditionResult.valueOf(compareValues(normalizedAttributeValue, normAssertionValue) <= 0);
+      }
+
+      @Override
+      public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException
+      {
+        return factory.createRangeMatchQuery("ordering", ByteString.empty(), normAssertionValue, false, true);
       }
     };
   }
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/CertificateExactMatchingRule.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/CertificateExactMatchingRule.java
index a85513e..6d2b537 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/CertificateExactMatchingRule.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/CertificateExactMatchingRule.java
@@ -42,6 +42,7 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.Assertion;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
@@ -369,5 +370,13 @@
     return builder.toByteString();
   }
 
+  /** {@inheritDoc} */
+  @Override
+  public Assertion getAssertion(ByteSequence assertionValue) throws DecodeException
+  {
+    final ByteString normAssertionValue = normalizeAssertionValue(assertionValue);
+    return getEqualityAssertion(normAssertionValue);
+  }
+
 }
 
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java
index c7c4f52..d6bcb26 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java
@@ -42,7 +42,6 @@
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
 import org.forgerock.opendj.ldap.ConditionResult;
-import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.api.MatchingRule;
 import org.opends.server.api.SubstringMatchingRule;
@@ -2146,42 +2145,6 @@
     return assertionValue;
   }
 
-  private ByteString getNormalizedAssertionValue() throws DecodeException
-  {
-    if (normalizedAssertionValue == null)
-    {
-      return normalizedAssertionValue = normalizeAssertionValue();
-    }
-    return normalizedAssertionValue;
-  }
-
-  private ByteString normalizeAssertionValue() throws DecodeException
-  {
-    switch (filterType)
-    {
-    case EQUALITY:
-      return attributeType.getEqualityMatchingRule()
-          .normalizeAssertionValue(assertionValue);
-    case GREATER_OR_EQUAL:
-    case LESS_OR_EQUAL:
-      return attributeType.getOrderingMatchingRule()
-          .normalizeAssertionValue(assertionValue);
-    case APPROXIMATE_MATCH:
-      return attributeType.getApproximateMatchingRule()
-          .normalizeAssertionValue(assertionValue);
-    case AND:
-    case OR:
-    case NOT:
-    case PRESENT:
-    case SUBSTRING:
-    case EXTENSIBLE_MATCH:
-    default:
-      return null;
-    }
-  }
-
-
-
   /**
    * Retrieves the subInitial element for this substring filter.
    *
@@ -3610,7 +3573,7 @@
       case APPROXIMATE_MATCH:
         return typeAndOptionsAndAssertionEqual(f);
       case EXTENSIBLE_MATCH:
-        return equalsExtensible(f);
+        return extensibleEqual(f);
       default:
         return false;
     }
@@ -3641,23 +3604,15 @@
 
   private boolean typeAndOptionsAndAssertionEqual(SearchFilter f)
   {
-    final boolean tmp =
-        attributeType.equals(f.attributeType)
-            && optionsEqual(attributeOptions, f.attributeOptions);
-    try
-    {
-      return tmp && getNormalizedAssertionValue().equals(f.getNormalizedAssertionValue());
-    }
-    catch (DecodeException e)
-    {
-      return tmp && assertionValue.equals(f.assertionValue);
-    }
+    return attributeType.equals(f.attributeType)
+        && optionsEqual(attributeOptions, f.attributeOptions)
+        && assertionValue.equals(f.assertionValue);
   }
 
 
-  private boolean substringEqual(SearchFilter f)
+  private boolean substringEqual(SearchFilter other)
   {
-    if (! attributeType.equals(f.attributeType))
+    if (! attributeType.equals(other.attributeType))
     {
       return false;
     }
@@ -3667,20 +3622,43 @@
     {
       return false;
     }
-    try
-    {
-      Assertion thisAssertion = rule.getSubstringAssertion(subInitialElement, subAnyElements, subFinalElement);
-      Assertion thatAssertion = rule.getSubstringAssertion(f.subInitialElement, f.subAnyElements, f.subFinalElement);
-      return thisAssertion.equals(thatAssertion);
-    }
-    catch (DecodeException e)
+    if (! optionsEqual(attributeOptions, other.attributeOptions))
     {
       return false;
     }
+
+    boolean initialCheck = subInitialElement == null ?
+        other.subInitialElement == null : subInitialElement.equals(other.subInitialElement);
+    if (!initialCheck)
+    {
+      return false;
+    }
+    boolean finalCheck = subFinalElement == null ?
+        other.subFinalElement == null : subFinalElement.equals(other.subFinalElement);
+    if (!finalCheck)
+    {
+      return false;
+    }
+    boolean anyCheck = subAnyElements == null ?
+        other.subAnyElements == null : subAnyElements.size() == other.subAnyElements.size();
+    if (!anyCheck)
+    {
+      return false;
+    }
+    if (subAnyElements != null)
+    {
+      for (int i = 0; i < subAnyElements.size(); i++)
+      {
+        if (! subAnyElements.get(i).equals(other.subAnyElements.get(i)))
+        {
+          return false;
+        }
+      }
+    }
+    return true;
   }
 
-
-  private boolean equalsExtensible(SearchFilter f)
+  private boolean extensibleEqual(SearchFilter f)
   {
     if (attributeType == null)
     {
@@ -3886,41 +3864,28 @@
 
   private int typeAndAssertionHashCode()
   {
-    final int hashCode = attributeType.hashCode();
-    try
-    {
-      return hashCode + getNormalizedAssertionValue().hashCode();
-    }
-    catch (DecodeException e)
-    {
-      return hashCode + assertionValue.hashCode();
-    }
+    return attributeType.hashCode() + assertionValue.hashCode();
   }
 
   /** Returns hash code to use for substring filter. */
   private int substringHashCode()
   {
     int hashCode = attributeType.hashCode();
-    final MatchingRule rule = attributeType.getSubstringMatchingRule();
-    if (rule != null)
+    if (subInitialElement != null)
     {
-      try
+      hashCode += subInitialElement.hashCode();
+    }
+    if (subAnyElements != null)
+    {
+      for (ByteString e : subAnyElements)
       {
-        return hashCode + rule.getSubstringAssertion(subInitialElement, subAnyElements, subFinalElement).hashCode();
-      }
-      catch (DecodeException e)
-      {
-        logger.traceException(e);
+        hashCode += e.hashCode();
       }
     }
-
-    // Fallback to hash code based on elements
-    hashCode += subInitialElement.hashCode();
-    for (ByteString e : subAnyElements)
+    if (subFinalElement != null)
     {
-      hashCode += e.hashCode();
+      hashCode += subFinalElement.hashCode();
     }
-    hashCode += subFinalElement.hashCode();
     return hashCode;
   }
 
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
index 47b5dbd..0a1b9a0 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
@@ -32,12 +32,10 @@
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
 import org.opends.server.api.ClientConnection;
-import org.opends.server.api.MatchingRule;
 import org.opends.server.api.plugin.PluginResult;
 import org.opends.server.config.ConfigConstants;
 import org.opends.server.controls.*;
@@ -1247,17 +1245,7 @@
   private static int extractChangeNumber(SearchFilter sf)
       throws DirectoryException
   {
-    try
-    {
-      MatchingRule rule = sf.getAttributeType().getEqualityMatchingRule();
-      ByteString normValue = rule.normalizeAssertionValue(sf.getAssertionValue());
-      return Integer.decode(normValue.toString());
-    }
-    catch (DecodeException e)
-    {
-      throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, e
-          .getMessageObject(), e);
-    }
+    return Integer.decode(sf.getAssertionValue().toString());
   }
 
   private static boolean matches(SearchFilter sf, FilterType filterType,
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
index 3cff6ed..a4539be6 100644
--- a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
@@ -47,12 +47,6 @@
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.ldap.LDAPFilter;
 import org.opends.server.types.*;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
-import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
-import org.opends.server.types.Modification;
-import org.opends.server.types.RDN;
 import org.opends.server.util.Base64;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
@@ -647,15 +641,75 @@
 
   @Test(dependsOnMethods = "testAdd")
   public void testSearchIndex() throws Exception {
-    InternalClientConnection conn =
-        InternalClientConnection.getRootConnection();
+    InternalClientConnection conn = InternalClientConnection.getRootConnection();
     Set<String> attribs = new LinkedHashSet<String>();
-
     String debugString;
-    int finalStartPos;
-    int finalEndPos;
-    int finalCount;
+    List<SearchResultEntry> result;
 
+    // search 1
+    result = doSubtreeSearch(conn, "(&(cn=Aaccf Amar)(cn=Ardyth Bainton))", attribs);
+    assertEquals(result.size(), 0);
+
+    // Adding a debug search attribute for next searches
+    attribs.add(ATTR_DEBUG_SEARCH_INDEX);
+
+    // search 2
+    result = doSubtreeSearch(conn, "(&(cn=Aaccf Amar)(employeeNumber=222))", attribs);
+
+    // Only one index should be used because it is below the FILTER_CANDIDATE
+    debugString = getDebugString(result);
+    assertTrue(debugString.split("cn").length <= 3);
+    assertResultsCountIs(1, debugString);
+
+    // search 3
+    result = doSubtreeSearch(conn, "(|(cn=Aaccf Amar)(cn=Ardyth Bainton))", attribs);
+
+    debugString = getDebugString(result);
+    assertFalse(debugString.contains("NOT-INDEXED"));
+    assertResultsCountIs(2, debugString);
+
+    // search 4
+    result = doSubtreeSearch(conn, "(&(employeeNumber=*)(cn=A*)(employeeNumber>=0)(employeeNumber<=z))", attribs);
+
+    debugString = getDebugString(result);
+    assertFalse(debugString.contains("NOT-INDEXED"));
+    assertResultsCountIs(12, debugString);
+
+    // search 5
+    result = doSubtreeSearch(conn,
+        "(&(employeeNumber<=z)(cn<=Abbey Abbie)(cn>=0)(|(cn>=Abahri Abazari)(employeeNumber<=9)))", attribs);
+
+
+    debugString = getDebugString(result);
+    assertFalse(debugString.contains("NOT-INDEXED"));
+    assertResultsCountIs(11, debugString);
+
+    // search 6
+    result = doSubtreeSearch(conn, "(cn~=Aartjan)", attribs);
+
+    debugString = getDebugString(result);
+    assertFalse(debugString.contains("NOT-INDEXED"));
+    assertResultsCountIs(1, debugString);
+  }
+
+  private void assertResultsCountIs(int expectedCount, String debugString)
+  {
+    int finalStartPos = debugString.indexOf("final=") + 13;
+    int finalEndPos = debugString.indexOf("]", finalStartPos);
+    int finalCount = Integer.valueOf(debugString.substring(finalStartPos, finalEndPos));
+    assertEquals(finalCount, expectedCount);
+  }
+
+  /** Returns the debug string from a search result. */
+  private String getDebugString(List<SearchResultEntry> result)
+  {
+    return result.get(0).getAttribute("debugsearchindex").get(0).toString();
+  }
+
+  /** Returns the results of subtree search on provided connection with provided filter. */
+  private List<SearchResultEntry> doSubtreeSearch(InternalClientConnection conn, String filter,
+      Set<String> attribs) throws Exception
+  {
     InternalSearchOperation search =
         conn.processSearch(DN.valueOf("dc=test,dc=com"),
             SearchScope.WHOLE_SUBTREE,
@@ -663,111 +717,9 @@
             0,
             0,
             false,
-            LDAPFilter.decode("(&(cn=Aaccf Amar)(cn=Ardyth Bainton))").toSearchFilter(),
+            LDAPFilter.decode(filter).toSearchFilter(),
             attribs);
-
-    List<SearchResultEntry> result = search.getSearchEntries();
-    assertEquals(result.size(), 0);
-
-    attribs.add(ATTR_DEBUG_SEARCH_INDEX);
-
-    search = conn.processSearch(DN.valueOf("dc=test,dc=com"),
-        SearchScope.WHOLE_SUBTREE,
-        DereferenceAliasesPolicy.NEVER,
-        0,
-        0,
-        false,
-        LDAPFilter.decode("(&(cn=Aaccf Amar)(employeeNumber=222))").toSearchFilter(),
-        attribs);
-
-    result = search.getSearchEntries();
-
-    //Only one index should be used because it is below the FILTER_CANDIDATEassertEquals(ec.getDN2URI().)_THRESHOLD.
-    debugString =
-        result.get(0).getAttribute("debugsearchindex").get(0).toString();
-    assertTrue(debugString.split("cn").length <= 3);
-    finalStartPos = debugString.indexOf("final=") + 13;
-    finalEndPos = debugString.indexOf("]", finalStartPos);
-    finalCount = Integer.valueOf(debugString.substring(finalStartPos,
-        finalEndPos));
-    assertEquals(finalCount, 1);
-
-    search = conn.processSearch(DN.valueOf("dc=test,dc=com"),
-        SearchScope.WHOLE_SUBTREE,
-        DereferenceAliasesPolicy.NEVER,
-        0,
-        0,
-        false,
-        LDAPFilter.decode("(|(cn=Aaccf Amar)(cn=Ardyth Bainton))").toSearchFilter(),
-        attribs);
-
-    result = search.getSearchEntries();
-
-    debugString =
-        result.get(0).getAttribute("debugsearchindex").get(0).toString();
-    assertTrue(!debugString.contains("NOT-INDEXED"));
-    finalStartPos = debugString.indexOf("final=") + 13;
-    finalEndPos = debugString.indexOf("]", finalStartPos);
-    finalCount = Integer.valueOf(debugString.substring(finalStartPos,
-        finalEndPos));
-    assertEquals(finalCount, 2);
-
-    search = conn.processSearch(DN.valueOf("dc=test,dc=com"),
-        SearchScope.WHOLE_SUBTREE,
-        DereferenceAliasesPolicy.NEVER,
-        0,
-        0,
-        false,
-        LDAPFilter.decode("(&(employeeNumber=*)(cn=A*)(employeeNumber>=0)(employeeNumber<=z))").toSearchFilter(),
-        attribs);
-    result = search.getSearchEntries();
-
-    debugString =
-        result.get(0).getAttribute("debugsearchindex").get(0).toString();
-    assertTrue(!debugString.contains("NOT-INDEXED"));
-    finalStartPos = debugString.indexOf("final=") + 13;
-    finalEndPos = debugString.indexOf("]", finalStartPos);
-    finalCount = Integer.valueOf(debugString.substring(finalStartPos,
-        finalEndPos));
-    assertEquals(finalCount, 12);
-
-    search = conn.processSearch(DN.valueOf("dc=test,dc=com"),
-        SearchScope.WHOLE_SUBTREE,
-        DereferenceAliasesPolicy.NEVER,
-        0,
-        0,
-        false,
-        LDAPFilter.decode("(&(employeeNumber<=z)(cn<=Abbey Abbie)(cn>=0)(|(cn>=Abahri Abazari)(employeeNumber<=9)))").toSearchFilter(),
-        attribs);
-    result = search.getSearchEntries();
-
-    debugString =
-        result.get(0).getAttribute("debugsearchindex").get(0).toString();
-    assertTrue(!debugString.contains("NOT-INDEXED"));
-    finalStartPos = debugString.indexOf("final=") + 13;
-    finalEndPos = debugString.indexOf("]", finalStartPos);
-    finalCount = Integer.valueOf(debugString.substring(finalStartPos,
-        finalEndPos));
-    assertEquals(finalCount, 11);
-
-    search = conn.processSearch(DN.valueOf("dc=test,dc=com"),
-        SearchScope.WHOLE_SUBTREE,
-        DereferenceAliasesPolicy.NEVER,
-        0,
-        0,
-        false,
-        LDAPFilter.decode("(cn~=Aartjan)").toSearchFilter(),
-        attribs);
-    result = search.getSearchEntries();
-
-    debugString =
-        result.get(0).getAttribute("debugsearchindex").get(0).toString();
-    assertTrue(!debugString.contains("NOT-INDEXED"));
-    finalStartPos = debugString.indexOf("final=") + 13;
-    finalEndPos = debugString.indexOf("]", finalStartPos);
-    finalCount = Integer.valueOf(debugString.substring(finalStartPos,
-        finalEndPos));
-    assertEquals(finalCount, 1);
+    return search.getSearchEntries();
   }
 
   @Test(dependsOnMethods = {"testAdd", "testSearchIndex",
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java
index 3b2d643..b278826 100644
--- a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java
@@ -918,9 +918,12 @@
 
           // These should be case insensitive
           {"(SN=Smith)", "(sn=Smith)", true, true},
-          {"(sn=smith)", "(sn=Smith)", true, false},
           {"(SN=S*th)", "(sn=S*th)", true, true},
 
+          // We no longer normalize assertion values,
+          // so these filters are not equal
+          {"(sn=smith)", "(sn=Smith)", false, false},
+
           {"(sn:caseExactMatch:=Smith)", "(sn:caseExactMatch:=Smith)", true, true},
 
           // This demonstrates bug 704.
@@ -939,8 +942,10 @@
           {"(sn;lang-en=Smith)", "(sn=Smith)", false, false},
 
 
-          // This demonstrates bug 705.
-          {"(sn=s*t*h)", "(sn=S*T*H)", true, false},
+          // This was initially to demonstrates bug 705.
+          // But we reverted back to old behavior,
+          // because we no longer normalize assertion values.
+          {"(sn=s*t*h)", "(sn=S*T*H)", false, false},
 
           // These should be case sensitive
           {"(labeledURI=http://opends.org)", "(labeledURI=http://OpenDS.org)", false, false},

--
Gitblit v1.10.0