From 6e92d4259d25e53c653e646c3e393b1a74a064ee Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <yannick.lecaillez@forgerock.com>
Date: Mon, 18 May 2015 13:52:40 +0000
Subject: [PATCH] OPENDJ-1864: Ordering matching rules should reuse equality indexes where possible

---
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java              |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java                   |    8 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java          |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java  |   10 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Suffix.java                                          |   25 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java                           |    8 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRuleSyntaxImpl.java                               |    4 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListSubstringMatchingRuleImpl.java                |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java                             |   22 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractApproximateMatchingRuleImpl.java                    |   18 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerOrderingMatchingRuleImpl.java                        |    6 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractMatchingRuleImpl.java                               |   32 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/EqualityIndexer.java                                 |    7 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactSubstringMatchingRuleImpl.java                     |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java                                           |    9 
 opendj-sdk/opendj-core/clirr-ignored-api-changes.xml                                                                              |    6 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BitStringEqualityMatchingRuleImpl.java                      |    9 
 opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeGreaterThanMatchingRuleTest.java                |    6 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactOrderingMatchingRuleImpl.java                      |   10 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java                           |    8 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java                                  |    2 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java              |    8 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeOrderingMatchingRuleImpl.java                |   10 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/KeywordEqualityMatchingRuleImpl.java                        |   11 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java                       |   11 
 opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestBackendImpl.java                                 |  210 +++-
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java                |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreOrderingMatchingRuleImpl.java                     |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java               |    8 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VerifyJob.java                                 |   12 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java                 |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringEqualityMatchingRuleImpl.java                  |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringOrderingMatchingRuleImpl.java                    |    9 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DefaultIndex.java                              |   17 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2CIndexer.java                                     |    7 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java                      |   31 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringSubstringMatchingRuleImpl.java                   |    8 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Indexer.java                                         |   10 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5EqualityMatchingRuleImpl.java                   |    9 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CollationMatchingRulesImpl.java                             |   18 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java |    7 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java                                  |   28 
 opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaTestMatchingRuleImpl.java                          |   10 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactEqualityMatchingRuleImpl.java                      |    8 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndexer.java                                |   29 
 opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestVerifyJob.java                                   |   27 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringEqualityMatchingRuleImpl.java                    |    9 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java                            |  508 +++++-------
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreEqualityMatchingRuleImpl.java                     |    8 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/PresenceIndexer.java                                 |    5 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeEqualityMatchingRuleImpl.java                |    9 
 opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/PartialDateAndTimeMatchingRuleTestCase.java                 |    7 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringOrderingMatchingRuleImpl.java                  |   10 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRuleImpl.java     |   14 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ProtocolInformationEqualityMatchingRuleImpl.java            |    8 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Index.java                                           |   30 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java             |    8 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringSubstringMatchingRuleImpl.java                 |    9 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/NullIndex.java                                       |    9 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AbstractTree.java                              |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/schema/AbstractPasswordEqualityMatchingRuleImpl.java              |   15 
 opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeLessThanMatchingRuleTest.java                   |    5 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/EnumOrderingMatchingRule.java                               |    4 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreSubstringMatchingRuleImpl.java                    |    9 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Importer.java                                        |  150 --
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5SubstringMatchingRuleImpl.java                  |    8 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BooleanEqualityMatchingRuleImpl.java                        |    9 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/VerifyJob.java                                       |  106 --
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java               |    5 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerEqualityMatchingRuleImpl.java                        |    6 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractOrderingMatchingRuleImpl.java                       |   37 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java                            |   21 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleImpl.java                                       |   14 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractEqualityMatchingRuleImpl.java                       |   20 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/Indexer.java                                                   |    7 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListEqualityMatchingRuleImpl.java                 |   10 
 opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImplTest.java                  |   35 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2SIndexer.java                                     |    7 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PresentationAddressEqualityMatchingRuleImpl.java            |    8 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java              |   10 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndex.java                                  |  568 ++++---------
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java                  |    8 
 82 files changed, 1,132 insertions(+), 1,316 deletions(-)

diff --git a/opendj-sdk/opendj-core/clirr-ignored-api-changes.xml b/opendj-sdk/opendj-core/clirr-ignored-api-changes.xml
index 4bc7588..4f61db9 100644
--- a/opendj-sdk/opendj-core/clirr-ignored-api-changes.xml
+++ b/opendj-sdk/opendj-core/clirr-ignored-api-changes.xml
@@ -421,6 +421,12 @@
     <justification>OPENDJ-1689 method has been removed because all matching rules should support the default comparator</justification>
   </difference>
   <difference>
+    <className>org/forgerock/opendj/ldap/schema/MatchingRuleImpl</className>
+    <differenceType>7012</differenceType>
+    <method>java.util.Collection createIndexers(org.forgerock.opendj.ldap.spi.IndexingOptions)</method>
+    <justification>Doesn't really seem correct to call createKeys() with different options each time.</justification>
+  </difference>
+  <difference>
     <className>org/forgerock/opendj/ldap/ByteSequence</className>
     <differenceType>7012</differenceType>
     <method>boolean startsWith(org.forgerock.opendj.ldap.ByteSequence)</method>
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractApproximateMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractApproximateMatchingRuleImpl.java
index bd35c91..057d321 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractApproximateMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractApproximateMatchingRuleImpl.java
@@ -21,7 +21,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2014 ForgeRock AS
+ *      Copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -32,6 +32,7 @@
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 /**
  * This class implements an approximate matching rule that matches normalized
@@ -39,22 +40,21 @@
  */
 abstract class AbstractApproximateMatchingRuleImpl extends AbstractMatchingRuleImpl {
 
-    private final Collection<? extends Indexer> indexers =
-            Collections.singleton(new DefaultIndexer("approximate"));
+    private final Indexer indexer;
 
-    AbstractApproximateMatchingRuleImpl() {
-        // Nothing to do.
+    AbstractApproximateMatchingRuleImpl(String indexID) {
+        indexer = new DefaultIndexer(indexID);
     }
 
     @Override
-    public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
+    public final Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
             throws DecodeException {
-        return DefaultAssertion.approximate(normalizeAttributeValue(schema, assertionValue));
+        return named(indexer.getIndexID(), normalizeAttributeValue(schema, assertionValue));
     }
 
     /** {@inheritDoc} */
     @Override
-    public Collection<? extends Indexer> getIndexers() {
-        return indexers;
+    public final Collection<? extends Indexer> createIndexers(IndexingOptions options) {
+        return Collections.singleton(indexer);
     }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractEqualityMatchingRuleImpl.java
index 0ccc622..a521bf6 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractEqualityMatchingRuleImpl.java
@@ -21,7 +21,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2014 ForgeRock AS
+ *      Copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -32,6 +32,7 @@
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 /**
  * This class implements an equality matching rule that matches normalized
@@ -39,21 +40,26 @@
  */
 abstract class AbstractEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl {
 
-    private final Collection<? extends Indexer> indexers = Collections.singleton(new DefaultIndexer("equality"));
+    private final Indexer indexer;
 
-    AbstractEqualityMatchingRuleImpl() {
-        // Nothing to do.
+    AbstractEqualityMatchingRuleImpl(String indexID) {
+        this.indexer = new DefaultIndexer(indexID);
     }
 
     @Override
     public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
             throws DecodeException {
-        return DefaultAssertion.equality(normalizeAttributeValue(schema, assertionValue));
+        return defaultAssertion(normalizeAttributeValue(schema, assertionValue));
     }
 
     /** {@inheritDoc} */
     @Override
-    public Collection<? extends Indexer> getIndexers() {
-        return indexers;
+    public Collection<? extends Indexer> createIndexers(IndexingOptions options) {
+        return Collections.singleton(indexer);
     }
+
+    Assertion defaultAssertion(final ByteSequence normalizedAssertionValue) {
+        return named(indexer.getIndexID(), normalizedAssertionValue);
+    }
+
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractMatchingRuleImpl.java
index 69233fc..dbf1dca 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractMatchingRuleImpl.java
@@ -36,7 +36,6 @@
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 import org.forgerock.opendj.ldap.spi.Indexer;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 import static org.forgerock.opendj.ldap.Assertion.*;
 
@@ -46,23 +45,15 @@
  */
 abstract class AbstractMatchingRuleImpl implements MatchingRuleImpl {
 
-    static final class DefaultAssertion implements Assertion {
+    static DefaultAssertion named(final String indexID, final ByteSequence normalizedAssertionValue) {
+        return new DefaultAssertion(indexID, normalizedAssertionValue);
+    }
+
+    private 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;
 
-        static DefaultAssertion equality(final ByteSequence normalizedAssertionValue) {
-            return named("equality", normalizedAssertionValue);
-        }
-
-        static DefaultAssertion approximate(final ByteSequence normalizedAssertionValue) {
-            return named("approximate", normalizedAssertionValue);
-        }
-
-        static DefaultAssertion named(final String indexID, final ByteSequence normalizedAssertionValue) {
-            return new DefaultAssertion(indexID, normalizedAssertionValue);
-        }
-
         private DefaultAssertion(final String indexID, final ByteSequence normalizedAssertionValue) {
             this.indexID = indexID;
             this.normalizedAssertionValue = normalizedAssertionValue;
@@ -88,8 +79,7 @@
         }
 
         @Override
-        public void createKeys(Schema schema, ByteSequence value, IndexingOptions options, Collection<ByteString> keys)
-                throws DecodeException {
+        public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) throws DecodeException {
             keys.add(normalizeAttributeValue(schema, value));
         }
 
@@ -99,10 +89,6 @@
         }
     }
 
-    AbstractMatchingRuleImpl() {
-        // Nothing to do.
-    }
-
     @Override
     public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
             throws DecodeException {
@@ -127,10 +113,4 @@
             throws DecodeException {
         return UNDEFINED_ASSERTION;
     }
-
-    @Override
-    public boolean isIndexingSupported() {
-        return !getIndexers().isEmpty();
-    }
-
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractOrderingMatchingRuleImpl.java
index 7bf58c5..d3ef2bc 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractOrderingMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -36,6 +36,7 @@
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 /**
  * This class implements a default ordering matching rule that matches
@@ -46,23 +47,16 @@
  * this assumption does not hold true.
  */
 abstract class AbstractOrderingMatchingRuleImpl extends AbstractMatchingRuleImpl {
-    private final Collection<? extends Indexer> indexers;
-    private final String indexId;
-
-    /** Constructor for default matching rules. */
-    AbstractOrderingMatchingRuleImpl() {
-        this("ordering");
-    }
+    private final Indexer indexer;
 
     /** Constructor for non-default matching rules. */
     AbstractOrderingMatchingRuleImpl(String indexId) {
-        this.indexId = indexId;
-        this.indexers = Collections.singleton(new DefaultIndexer(indexId));
+        this.indexer = new DefaultIndexer(indexId);
     }
 
     /** {@inheritDoc} */
     @Override
-    public Assertion getAssertion(final Schema schema, final ByteSequence value)
+    public final Assertion getAssertion(final Schema schema, final ByteSequence value)
             throws DecodeException {
         final ByteString normAssertion = normalizeAttributeValue(schema, value);
         return new Assertion() {
@@ -73,14 +67,16 @@
 
             @Override
             public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException {
-                return factory.createRangeMatchQuery(indexId, ByteString.empty(), normAssertion, false, false);
+                return factory.createRangeMatchQuery(indexer.getIndexID(), ByteString.empty(), normAssertion, false,
+                        false);
             }
         };
     }
 
     /** {@inheritDoc} */
     @Override
-    public Assertion getGreaterOrEqualAssertion(final Schema schema, final ByteSequence value) throws DecodeException {
+    public final Assertion getGreaterOrEqualAssertion(final Schema schema, final ByteSequence value)
+            throws DecodeException {
         final ByteString normAssertion = normalizeAttributeValue(schema, value);
         return new Assertion() {
             @Override
@@ -90,14 +86,15 @@
 
             @Override
             public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException {
-                return factory.createRangeMatchQuery(indexId, normAssertion, ByteString.empty(), true, false);
+                return factory.createRangeMatchQuery(indexer.getIndexID(), normAssertion, ByteString.empty(), true,
+                        false);
             }
         };
     }
 
     /** {@inheritDoc} */
     @Override
-    public Assertion getLessOrEqualAssertion(final Schema schema, final ByteSequence value)
+    public final Assertion getLessOrEqualAssertion(final Schema schema, final ByteSequence value)
             throws DecodeException {
         final ByteString normAssertion = normalizeAttributeValue(schema, value);
         return new Assertion() {
@@ -108,18 +105,16 @@
 
             @Override
             public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException {
-                return factory.createRangeMatchQuery(indexId, ByteString.empty(), normAssertion, false, true);
+                return factory.createRangeMatchQuery(indexer.getIndexID(), ByteString.empty(), normAssertion, false,
+                        true);
             }
         };
     }
 
     /** {@inheritDoc} */
     @Override
-    public Collection<? extends Indexer> getIndexers() {
-        return indexers;
+    public final Collection<? extends Indexer> createIndexers(IndexingOptions options) {
+        return Collections.singleton(indexer);
     }
 
-    final String getIndexId() {
-        return indexId;
-    }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java
index d85cfe2..39d8769 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java
@@ -225,14 +225,20 @@
 
     }
 
-    final class SubstringIndexer implements Indexer {
+    private final class SubstringIndexer implements Indexer {
+
+        private final String indexID;
+        private final int substringKeySize;
+
+        private SubstringIndexer(int substringKeySize) {
+            this.substringKeySize = substringKeySize;
+            this.indexID = substringIndexId + ":" + this.substringKeySize;
+        }
 
         /** {@inheritDoc} */
         @Override
-        public void createKeys(Schema schema, ByteSequence value, IndexingOptions options, Collection<ByteString> keys)
-                throws DecodeException {
+        public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) throws DecodeException {
             final ByteString normValue = normalizeAttributeValue(schema, value);
-            final int substringKeySize = options.substringKeySize();
 
             // Example: The value is ABCDE and the substring length is 3.
             // We produce the keys ABC BCD CDE DE E
@@ -248,23 +254,16 @@
         /** {@inheritDoc} */
         @Override
         public String getIndexID() {
-            return substringIndexId;
+            return indexID;
         }
     }
 
-    private final Collection<? extends Indexer> indexers = Collections.singleton(new SubstringIndexer());
-
     /** Identifier of the substring index. */
     private final String substringIndexId;
 
     /** Identifier of the equality index. */
     private final String equalityIndexId;
 
-    /** Constructor for default matching rules. */
-    AbstractSubstringMatchingRuleImpl() {
-        this("substring", "equality");
-    }
-
     /** Constructor for non-default matching rules. */
     AbstractSubstringMatchingRuleImpl(String substringIndexId, String equalityIndexId) {
         this.substringIndexId = substringIndexId;
@@ -273,7 +272,7 @@
 
     /** {@inheritDoc} */
     @Override
-    public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
+    public final Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
             throws DecodeException {
         if (assertionValue.length() == 0) {
             throw DecodeException.error(WARN_ATTR_SYNTAX_SUBSTRING_EMPTY.get());
@@ -323,7 +322,7 @@
 
     /** {@inheritDoc} */
     @Override
-    public Assertion getSubstringAssertion(final Schema schema, final ByteSequence subInitial,
+    public final Assertion getSubstringAssertion(final Schema schema, final ByteSequence subInitial,
             final List<? extends ByteSequence> subAnyElements, final ByteSequence subFinal)
             throws DecodeException {
         final ByteString normInitial =
@@ -543,8 +542,8 @@
 
     /** {@inheritDoc} */
     @Override
-    public Collection<? extends Indexer> getIndexers() {
-        return indexers;
+    public final Collection<? extends Indexer> createIndexers(IndexingOptions options) {
+        return Collections.singleton(new SubstringIndexer(options.substringKeySize()));
     }
 
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
index a41fa75..071d8ed 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
@@ -35,6 +37,12 @@
  * 3112.
  */
 final class AuthPasswordExactEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    AuthPasswordExactEqualityMatchingRuleImpl() {
+        super(EMR_AUTH_PASSWORD_EXACT_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         final StringBuilder[] authPWComponents =
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BitStringEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BitStringEqualityMatchingRuleImpl.java
index 278a099..cac2efb 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BitStringEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BitStringEqualityMatchingRuleImpl.java
@@ -22,13 +22,14 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_BIT_STRING_INVALID_BIT;
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_BIT_STRING_NOT_QUOTED;
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_BIT_STRING_TOO_SHORT;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.opendj.ldap.ByteSequence;
@@ -40,6 +41,12 @@
  * referenced in RFC 2252.
  */
 final class BitStringEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    BitStringEqualityMatchingRuleImpl() {
+        super(EMR_BIT_STRING_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         final String valueString = value.toString().toUpperCase();
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BooleanEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BooleanEqualityMatchingRuleImpl.java
index 7e1317b..dfa15d7 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BooleanEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BooleanEqualityMatchingRuleImpl.java
@@ -22,11 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_ILLEGAL_BOOLEAN;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
@@ -37,6 +38,12 @@
  * referenced in RFC 4519.
  */
 final class BooleanEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    BooleanEqualityMatchingRuleImpl() {
+        super(EMR_BOOLEAN_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         final String valueString = value.toString().toUpperCase();
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactEqualityMatchingRuleImpl.java
index 6b8fa44..d3e48c7 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactEqualityMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -30,12 +30,18 @@
 import org.forgerock.opendj.ldap.ByteString;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class defines the caseExactMatch matching rule defined in X.520 and
  * referenced in RFC 4519.
  */
 final class CaseExactEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    CaseExactEqualityMatchingRuleImpl() {
+        super(EMR_CASE_EXACT_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeStringAttributeValue(value, TRIM, NO_CASE_FOLD);
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5EqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5EqualityMatchingRuleImpl.java
index 4aa9163..eec5651 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5EqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5EqualityMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -31,12 +31,19 @@
 import org.forgerock.opendj.ldap.DecodeException;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the caseExactIA5Match matching rule defined in RFC
  * 2252.
  */
 final class CaseExactIA5EqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    CaseExactIA5EqualityMatchingRuleImpl() {
+        super(EMR_CASE_EXACT_IA5_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         return SchemaUtils.normalizeIA5StringAttributeValue(value, TRIM, NO_CASE_FOLD);
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5SubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5SubstringMatchingRuleImpl.java
index 9af57d0..16ae03e 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5SubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5SubstringMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -31,6 +31,7 @@
 import org.forgerock.opendj.ldap.DecodeException;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the caseExactIA5SubstringsMatch matching rule. This
@@ -39,6 +40,11 @@
  * private namespace.
  */
 final class CaseExactIA5SubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
+
+    CaseExactIA5SubstringMatchingRuleImpl() {
+        super(SMR_CASE_EXACT_IA5_NAME, EMR_CASE_EXACT_IA5_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactOrderingMatchingRuleImpl.java
index b96f83a..ea7084d 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactOrderingMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -30,12 +30,20 @@
 import org.forgerock.opendj.ldap.ByteString;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class defines the caseExactOrderingMatch matching rule defined in X.520
  * and referenced in RFC 4519.
  */
 final class CaseExactOrderingMatchingRuleImpl extends AbstractOrderingMatchingRuleImpl {
+
+    public CaseExactOrderingMatchingRuleImpl() {
+        // Reusing equality index since OPENDJ-1864
+        super(EMR_CASE_EXACT_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeStringAttributeValue(value, TRIM, NO_CASE_FOLD);
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactSubstringMatchingRuleImpl.java
index 8d16777..e8b6910 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactSubstringMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -31,12 +31,19 @@
 import org.forgerock.opendj.ldap.DecodeException;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class defines the caseExactSubstringsMatch matching rule defined in
  * X.520 and referenced in RFC 2252.
  */
 final class CaseExactSubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
+
+    CaseExactSubstringMatchingRuleImpl() {
+        super(SMR_CASE_EXACT_NAME, EMR_CASE_EXACT_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return normalize(TRIM, value);
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreEqualityMatchingRuleImpl.java
index e90369d..71602f4 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreEqualityMatchingRuleImpl.java
@@ -22,11 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
@@ -36,6 +37,11 @@
  * referenced in RFC 2252.
  */
 final class CaseIgnoreEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    CaseIgnoreEqualityMatchingRuleImpl() {
+        super(EMR_CASE_IGNORE_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeStringAttributeValue(value, TRIM, CASE_FOLD);
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java
index 5c3f861..03ee6a1 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -31,12 +31,18 @@
 import org.forgerock.opendj.ldap.DecodeException;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the caseIgnoreIA5Match matching rule defined in RFC
  * 2252.
  */
 final class CaseIgnoreIA5EqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    CaseIgnoreIA5EqualityMatchingRuleImpl() {
+        super(EMR_CASE_IGNORE_IA5_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java
index 8dfe213..bb04024 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -31,12 +31,19 @@
 import org.forgerock.opendj.ldap.DecodeException;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the caseIgnoreIA5SubstringsMatch matching rule defined
  * in RFC 2252.
  */
 final class CaseIgnoreIA5SubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
+
+    CaseIgnoreIA5SubstringMatchingRuleImpl() {
+        super(SMR_CASE_IGNORE_IA5_NAME, EMR_CASE_IGNORE_IA5_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         return normalize(TRIM, value);
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListEqualityMatchingRuleImpl.java
index 55d7809..fbec644 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListEqualityMatchingRuleImpl.java
@@ -22,21 +22,29 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.util.StringPrepProfile.CASE_FOLD;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the caseIgnoreListMatch matching rule defined in X.520
  * and referenced in RFC 2252.
  */
 final class CaseIgnoreListEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    CaseIgnoreListEqualityMatchingRuleImpl() {
+        super(EMR_CASE_IGNORE_LIST_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeStringListAttributeValue(value, TRIM, CASE_FOLD);
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListSubstringMatchingRuleImpl.java
index bf2ebc8..4c95a67 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListSubstringMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -31,12 +31,19 @@
 import org.forgerock.opendj.ldap.DecodeException;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the caseIgnoreListSubstringsMatch matching rule defined
  * in X.520 and referenced in RFC 2252.
  */
 final class CaseIgnoreListSubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
+
+    CaseIgnoreListSubstringMatchingRuleImpl() {
+        super(SMR_CASE_IGNORE_LIST_NAME, EMR_CASE_IGNORE_LIST_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeStringListAttributeValue(value, TRIM, CASE_FOLD);
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreOrderingMatchingRuleImpl.java
index b295d10..dae024d 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreOrderingMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -30,12 +30,19 @@
 import org.forgerock.opendj.ldap.ByteString;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class defines the caseIgnoreOrderingMatch matching rule defined in X.520
  * and referenced in RFC 2252.
  */
 final class CaseIgnoreOrderingMatchingRuleImpl extends AbstractOrderingMatchingRuleImpl {
+
+    public CaseIgnoreOrderingMatchingRuleImpl() {
+        // Reusing equality index since OPENDJ-1864
+        super(EMR_CASE_IGNORE_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeStringAttributeValue(value, TRIM, CASE_FOLD);
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreSubstringMatchingRuleImpl.java
index aff7f7d..5474035 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreSubstringMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -31,12 +31,19 @@
 import org.forgerock.opendj.ldap.DecodeException;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class defines the caseIgnoreSubstringsMatch matching rule defined in
  * X.520 and referenced in RFC 2252.
  */
 final class CaseIgnoreSubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
+
+    CaseIgnoreSubstringMatchingRuleImpl() {
+        super(SMR_CASE_IGNORE_NAME, EMR_CASE_IGNORE_NAME);
+    }
+
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return normalize(TRIM, value);
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java
index 1e023e6..3441f94 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java
@@ -23,7 +23,7 @@
  *
  *      Copyright 2006-2009 Sun Microsystems, Inc.
  *      Portions Copyright 2013-2014 Manuel Gaupp
- *      Copyright 2014 ForgeRock AS
+ *      Copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -49,6 +49,7 @@
 import com.forgerock.opendj.util.StaticUtils;
 
 import static com.forgerock.opendj.ldap.CoreMessages.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the certificateExactMatch matching rule defined in
@@ -74,6 +75,10 @@
      */
     private static final String GSER_ID_RDNSEQUENCE = "rdnSequence";
 
+    CertificateExactMatchingRuleImpl() {
+        super(EMR_CERTIFICATE_EXACT_NAME);
+    }
+
     /**
      * Retrieves the normalized form of the provided value, which is best suited
      * for efficiently performing matching operations on that value.
@@ -129,7 +134,7 @@
             // Assume the assertion value is a certificate and parse issuer and
             // serial number. If the value is not even a certificate then the
             // raw bytes will be returned.
-            return DefaultAssertion.equality(normalizeAttributeValue(schema, value));
+            return defaultAssertion(normalizeAttributeValue(schema, value));
         }
 
         final BigInteger serialNumber;
@@ -181,7 +186,7 @@
         }
 
         final ByteString certificateIssuer = normalizeDN(schema, dnstring);
-        return DefaultAssertion.equality(createEncodedValue(serialNumber, certificateIssuer));
+        return defaultAssertion(createEncodedValue(serialNumber, certificateIssuer));
     }
 
     private ByteString normalizeDN(final Schema schema, final String dnstring) throws DecodeException {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CollationMatchingRulesImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CollationMatchingRulesImpl.java
index 4542d34..e01bf68 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CollationMatchingRulesImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CollationMatchingRulesImpl.java
@@ -21,12 +21,12 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2014 ForgeRock AS.
+ *      Copyright 2014-2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
 import java.text.Collator;
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -40,6 +40,7 @@
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 /**
  * Implementations of collation matching rules. Each matching rule is created
@@ -183,7 +184,7 @@
 
         /** {@inheritDoc} */
         @Override
-        public Collection<? extends Indexer> getIndexers() {
+        public Collection<? extends Indexer> createIndexers(IndexingOptions options) {
             return Collections.singletonList(indexer);
         }
 
@@ -219,7 +220,7 @@
         @Override
         public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
                 throws DecodeException {
-            return DefaultAssertion.named(indexName, normalizeAttributeValue(schema, assertionValue));
+            return named(indexName, normalizeAttributeValue(schema, assertionValue));
         }
 
     }
@@ -230,7 +231,6 @@
     private static final class CollationSubstringMatchingRuleImpl extends AbstractCollationMatchingRuleImpl {
 
         private final AbstractSubstringMatchingRuleImpl substringMatchingRule;
-        private final Indexer subIndexer;
 
         /**
          * Creates the matching rule with the provided locale.
@@ -248,8 +248,6 @@
                     return CollationSubstringMatchingRuleImpl.this.normalizeAttributeValue(schema, value);
                 }
             };
-            // default substring matching rule has exactly one indexer
-            subIndexer = substringMatchingRule.getIndexers().iterator().next();
         }
 
         @Override
@@ -266,8 +264,10 @@
 
         /** {@inheritDoc} */
         @Override
-        public final Collection<? extends Indexer> getIndexers() {
-            return Arrays.asList(subIndexer, indexer);
+        public final Collection<? extends Indexer> createIndexers(IndexingOptions options) {
+            final Collection<Indexer> indexers = new ArrayList<>(substringMatchingRule.createIndexers(options));
+            indexers.add(indexer);
+            return indexers;
         }
     }
 
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRuleSyntaxImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRuleSyntaxImpl.java
index 9881561..4288c96 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRuleSyntaxImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRuleSyntaxImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2011-2014 ForgeRock AS
+ *      Portions copyright 2011-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -50,7 +50,7 @@
 
     @Override
     public String getEqualityMatchingRule() {
-        return EMR_OID_FIRST_COMPONENT_OID;
+        return EMR_OID_FIRST_COMPONENT_NAME;
     }
 
     public String getName() {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java
index 509c8b4..3f1ac61 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -30,6 +30,7 @@
 import static com.forgerock.opendj.util.StringPrepProfile.TRIM;
 import static com.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_EMPTY_VALUE;
 import static com.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.EMR_DIRECTORY_STRING_FIRST_COMPONENT_NAME;
 
 import org.forgerock.opendj.ldap.Assertion;
 import org.forgerock.opendj.ldap.ByteSequence;
@@ -48,9 +49,14 @@
  */
 final class DirectoryStringFirstComponentEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
 
+    DirectoryStringFirstComponentEqualityMatchingRuleImpl() {
+      super(EMR_DIRECTORY_STRING_FIRST_COMPONENT_NAME);
+    }
+
     @Override
     public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue) {
-        return DefaultAssertion.equality(SchemaUtils.normalizeStringAttributeValue(assertionValue, TRIM, CASE_FOLD));
+        return named(EMR_DIRECTORY_STRING_FIRST_COMPONENT_NAME,
+                SchemaUtils.normalizeStringAttributeValue(assertionValue, TRIM, CASE_FOLD));
     }
 
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java
index d8381a3..861cf0e 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions copyright 2011-2014 ForgeRock AS.
+ *      Portions copyright 2011-2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
@@ -38,6 +40,10 @@
  */
 final class DistinguishedNameEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
 
+    DistinguishedNameEqualityMatchingRuleImpl() {
+        super(EMR_DN_NAME);
+    }
+
     /** {@inheritDoc} */
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
index cc76e22..6c8169e 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.ByteSequence;
@@ -53,6 +55,10 @@
 
     private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
+    DoubleMetaphoneApproximateMatchingRuleImpl() {
+      super(AMR_DOUBLE_METAPHONE_NAME);
+    }
+
     /** {@inheritDoc} */
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         String valueString = value.toString();
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/EnumOrderingMatchingRule.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/EnumOrderingMatchingRule.java
index 0d1b390..a39d1bd 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/EnumOrderingMatchingRule.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/EnumOrderingMatchingRule.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
+ *      Portions Copyright 2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_INVALID_VALUE;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
@@ -42,10 +44,12 @@
     private final EnumSyntaxImpl syntax;
 
     EnumOrderingMatchingRule(final EnumSyntaxImpl syntax) {
+        super(OMR_GENERIC_ENUM_NAME);
         Reject.ifNull(syntax);
         this.syntax = syntax;
     }
 
+    @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         final int index = syntax.indexOf(value);
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeEqualityMatchingRuleImpl.java
index d681293..7b9dbc5 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeEqualityMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2012-2014 ForgeRock AS.
+ *      Portions copyright 2012-2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
@@ -37,6 +39,11 @@
  * and referenced in RFC 2252.
  */
 final class GeneralizedTimeEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    GeneralizedTimeEqualityMatchingRuleImpl() {
+        super(EMR_GENERALIZED_TIME_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         try {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeOrderingMatchingRuleImpl.java
index f28821e..9ca261d 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeOrderingMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2012 ForgeRock AS.
+ *      Portions copyright 2012-2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
@@ -37,6 +39,12 @@
  * X.520 and referenced in RFC 2252.
  */
 final class GeneralizedTimeOrderingMatchingRuleImpl extends AbstractOrderingMatchingRuleImpl {
+
+    GeneralizedTimeOrderingMatchingRuleImpl() {
+        // Reusing equality index since OPENDJ-1864
+        super(EMR_GENERALIZED_TIME_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         try {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerEqualityMatchingRuleImpl.java
index 4b9e608..d31f610 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerEqualityMatchingRuleImpl.java
@@ -27,6 +27,7 @@
 package org.forgerock.opendj.ldap.schema;
 
 import static org.forgerock.opendj.ldap.schema.IntegerOrderingMatchingRuleImpl.normalizeValueAndEncode;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
@@ -39,6 +40,11 @@
  * potentially share the same index.
  */
 final class IntegerEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    IntegerEqualityMatchingRuleImpl() {
+        super(EMR_INTEGER_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java
index 030ad88..f9dfe66 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java
@@ -22,11 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2013-2014 ForgeRock AS
+ *      Portions copyright 2013-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.ldap.CoreMessages.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
@@ -48,6 +49,10 @@
 
     private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
+    IntegerFirstComponentEqualityMatchingRuleImpl() {
+        super(EMR_INTEGER_FIRST_COMPONENT_NAME);
+    }
+
     @Override
     public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
             throws DecodeException {
@@ -55,7 +60,7 @@
             final String definition = assertionValue.toString();
             final SubstringReader reader = new SubstringReader(definition);
             final int intValue = SchemaUtils.readRuleID(reader);
-            return DefaultAssertion.equality(ByteString.valueOf(intValue));
+            return defaultAssertion(ByteString.valueOf(intValue));
         } catch (final Exception e) {
             logger.debug(LocalizableMessage.raw("%s", e));
 
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerOrderingMatchingRuleImpl.java
index b484194..d475173 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerOrderingMatchingRuleImpl.java
@@ -27,6 +27,7 @@
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_ILLEGAL_INTEGER;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import java.math.BigInteger;
 
@@ -136,6 +137,11 @@
         }
     }
 
+    public IntegerOrderingMatchingRuleImpl() {
+        // Reusing equality index since OPENDJ-1864
+        super(EMR_INTEGER_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/KeywordEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/KeywordEqualityMatchingRuleImpl.java
index dbceb6f..6762f68 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/KeywordEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/KeywordEqualityMatchingRuleImpl.java
@@ -22,12 +22,13 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.util.StringPrepProfile.CASE_FOLD;
 import static com.forgerock.opendj.util.StringPrepProfile.TRIM;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -39,6 +40,7 @@
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 /**
  * This class implements the keywordMatch matching rule defined in X.520. That
@@ -60,6 +62,11 @@
  * </UL>
  */
 final class KeywordEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    KeywordEqualityMatchingRuleImpl() {
+        super(EMR_KEYWORD_NAME);
+    }
+
     @Override
     public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue)
             throws DecodeException {
@@ -122,7 +129,7 @@
 
     /** {@inheritDoc} */
     @Override
-    public Collection<? extends Indexer> getIndexers() {
+    public Collection<? extends Indexer> createIndexers(IndexingOptions options) {
         return Collections.emptySet();
     }
 
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java
index b9f1ea5..c282e42 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java
@@ -41,6 +41,7 @@
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 /**
  * This class defines a data structure for storing and interacting with matching
@@ -348,12 +349,14 @@
     }
 
     /**
-     * Returns the indexers for this matching rule.
+     * Returns the indexers for this matching rule configured using the provided indexing options.
      *
+     * @param options
+     *            The indexing options
      * @return the collection of indexers for this matching rule.
      */
-    public Collection<? extends Indexer> getIndexers() {
-        return impl.getIndexers();
+    public Collection<? extends Indexer> createIndexers(IndexingOptions options) {
+        return impl.createIndexers(options);
     }
 
     /**
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleImpl.java
index 3ca11b8..98f1fad 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleImpl.java
@@ -34,6 +34,7 @@
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 /**
  * This interface defines the set of methods that must be implemented to define
@@ -133,16 +134,9 @@
 
     /**
      * Returns the indexers for this matching rule.
-     *
+     * @param options
+     *          The indexing options
      * @return a non null collection of indexers for this matching rule.
      */
-    Collection<? extends Indexer> getIndexers();
-
-    /**
-     * Returns whether a backend can build an index for this matching rule.
-     *
-     * @return true a backend can build an index for this matching rule,
-     *         false otherwise.
-     */
-    boolean isIndexingSupported();
+    Collection<? extends Indexer> createIndexers(IndexingOptions options);
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringEqualityMatchingRuleImpl.java
index 98f5836..33d1c3d 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringEqualityMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
@@ -35,6 +37,11 @@
  * spaces, but ignores spaces when performing matching.
  */
 final class NumericStringEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    NumericStringEqualityMatchingRuleImpl() {
+        super(EMR_NUMERIC_STRING_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeNumericStringAttributeValue(value);
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringOrderingMatchingRuleImpl.java
index 7152afa..2b9bc3f 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringOrderingMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
@@ -34,6 +36,12 @@
  * in X.520 and referenced in RFC 2252.
  */
 final class NumericStringOrderingMatchingRuleImpl extends AbstractOrderingMatchingRuleImpl {
+
+    NumericStringOrderingMatchingRuleImpl() {
+        // Reusing equality index since OPENDJ-1864
+        super(EMR_NUMERIC_STRING_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeNumericStringAttributeValue(value);
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringSubstringMatchingRuleImpl.java
index fc3f636..2d06bf4 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringSubstringMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
@@ -34,6 +36,11 @@
  * in X.520 and referenced in RFC 2252.
  */
 final class NumericStringSubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
+
+    NumericStringSubstringMatchingRuleImpl() {
+        super(SMR_NUMERIC_STRING_NAME, EMR_NUMERIC_STRING_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeNumericStringAttributeValue(value);
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
index fc074d6..b5000c5 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
@@ -26,6 +26,7 @@
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 import static org.forgerock.opendj.ldap.schema.SchemaOptions.*;
 import static org.forgerock.opendj.ldap.schema.SchemaUtils.*;
 
@@ -44,6 +45,10 @@
  */
 final class ObjectIdentifierEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
 
+    ObjectIdentifierEqualityMatchingRuleImpl() {
+        super(EMR_OID_NAME);
+    }
+
     static String resolveNames(final Schema schema, final String oid) {
         if (!StaticUtils.isDigit(oid.charAt(0))) {
             // Do an best effort attempt to normalize names to OIDs.
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java
index 50cf1a9..4b7914c 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java
@@ -29,6 +29,7 @@
 import static com.forgerock.opendj.ldap.CoreMessages.*;
 
 import static org.forgerock.opendj.ldap.schema.ObjectIdentifierEqualityMatchingRuleImpl.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 import static org.forgerock.opendj.ldap.schema.SchemaOptions.*;
 import static org.forgerock.opendj.ldap.schema.SchemaUtils.*;
 
@@ -50,9 +51,13 @@
  */
 final class ObjectIdentifierFirstComponentEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
 
+    ObjectIdentifierFirstComponentEqualityMatchingRuleImpl() {
+        super(EMR_OID_FIRST_COMPONENT_NAME);
+    }
+
     @Override
     public Assertion getAssertion(final Schema schema, final ByteSequence assertionValue) throws DecodeException {
-        return DefaultAssertion.equality(normalizeAttributeValuePrivate(schema, assertionValue));
+        return defaultAssertion(normalizeAttributeValuePrivate(schema, assertionValue));
     }
 
     @Override
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringEqualityMatchingRuleImpl.java
index 410815b..5e0e02a 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringEqualityMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
@@ -35,6 +37,11 @@
  * string syntaxes.
  */
 final class OctetStringEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    OctetStringEqualityMatchingRuleImpl() {
+        super(EMR_OCTET_STRING_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return value.toByteString();
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringOrderingMatchingRuleImpl.java
index c4a9b99..f0e9c9f 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringOrderingMatchingRuleImpl.java
@@ -22,9 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
+ *      Portions copyright 2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
@@ -34,6 +37,12 @@
  * octet string syntaxes.
  */
 final class OctetStringOrderingMatchingRuleImpl extends AbstractOrderingMatchingRuleImpl {
+
+    OctetStringOrderingMatchingRuleImpl() {
+        // Reusing equality index since OPENDJ-1864
+        super(EMR_OCTET_STRING_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return value.toByteString();
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringSubstringMatchingRuleImpl.java
index b37690e..5778d06 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringSubstringMatchingRuleImpl.java
@@ -22,9 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
+ *      Portions Copyright 2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
@@ -34,6 +37,11 @@
  * and octet string syntaxes.
  */
 final class OctetStringSubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
+
+    OctetStringSubstringMatchingRuleImpl() {
+        super(SMR_OCTET_STRING_NAME, EMR_OCTET_STRING_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return value.toByteString();
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PresentationAddressEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PresentationAddressEqualityMatchingRuleImpl.java
index 026d8f5..44dfda1 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PresentationAddressEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PresentationAddressEqualityMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -30,6 +30,7 @@
 import org.forgerock.opendj.ldap.ByteString;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the presentationAddressMatch matching rule defined in
@@ -38,6 +39,11 @@
  * like the caseIgnoreMatch rule.
  */
 final class PresentationAddressEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    PresentationAddressEqualityMatchingRuleImpl() {
+        super(EMR_PRESENTATION_ADDRESS_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeStringAttributeValue(value, TRIM, CASE_FOLD);
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ProtocolInformationEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ProtocolInformationEqualityMatchingRuleImpl.java
index a5c70ba..b457f6b 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ProtocolInformationEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ProtocolInformationEqualityMatchingRuleImpl.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -30,6 +30,7 @@
 import org.forgerock.opendj.ldap.ByteString;
 
 import static com.forgerock.opendj.util.StringPrepProfile.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * This class implements the protocolInformationMatch matching rule defined in
@@ -38,6 +39,11 @@
  * like the caseIgnoreMatch rule.
  */
 final class ProtocolInformationEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    ProtocolInformationEqualityMatchingRuleImpl() {
+        super(EMR_PROTOCOL_INFORMATION_NAME);
+    }
+
     @Override
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         return SchemaUtils.normalizeStringAttributeValue(value, TRIM, CASE_FOLD);
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java
index 78f5604..40b17c4 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
@@ -38,6 +40,11 @@
  * only numeric digits and strip out everything else.
  */
 final class TelephoneNumberEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    TelephoneNumberEqualityMatchingRuleImpl() {
+        super(EMR_TELEPHONE_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         final String valueString = value.toString();
         final int valueLength = valueString.length();
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java
index 413eb55..b72de8f 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java
@@ -22,9 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
+ *      Portions Copyright 2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 
@@ -37,6 +40,11 @@
  * this matching will compare only numeric digits and strip out everything else.
  */
 final class TelephoneNumberSubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
+
+    TelephoneNumberSubstringMatchingRuleImpl() {
+        super(SMR_TELEPHONE_NAME, EMR_TELEPHONE_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) {
         final String valueString = value.toString();
         final int valueLength = valueString.length();
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java
index 9adec0c..e273f0e 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java
@@ -46,23 +46,18 @@
 import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 import org.forgerock.opendj.ldap.spi.Indexer;
 import org.forgerock.opendj.ldap.spi.IndexingOptions;
-
 import org.forgerock.util.time.TimeService;
 
 import static com.forgerock.opendj.ldap.CoreMessages.*;
 import static com.forgerock.opendj.util.StaticUtils.*;
-
 import static org.forgerock.opendj.ldap.DecodeException.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 /**
  * Implementations of time-based matching rules.
  */
 final class TimeBasedMatchingRulesImpl {
 
-    private static final String RELATIVE_TIME_INDEX_ID = "rt";
-    private static final String PARTIAL_DATE_TIME_INDEX_ID = "pdt";
-    private static final String EXTENSIBLE_INDEX_ID = "ext";
-
     private static final TimeZone TIME_ZONE_UTC = TimeZone.getTimeZone("UTC");
 
     /** Constants for generating keys. */
@@ -114,7 +109,7 @@
 
         /** {@inheritDoc} */
         @Override
-        public ByteString normalizeAttributeValue(Schema schema, ByteSequence value) throws DecodeException {
+        public final ByteString normalizeAttributeValue(Schema schema, ByteSequence value) throws DecodeException {
             try {
                 return ByteString.valueOf(GeneralizedTime.valueOf(value.toString()).getTimeInMillis());
             } catch (final LocalizedIllegalArgumentException e) {
@@ -133,11 +128,11 @@
      */
     private static abstract class RelativeTimeOrderingMatchingRuleImpl extends TimeBasedMatchingRuleImpl {
 
-        final Indexer indexer = new DefaultIndexer(RELATIVE_TIME_INDEX_ID + "." + EXTENSIBLE_INDEX_ID);
+        final Indexer indexer = new DefaultIndexer(EMR_GENERALIZED_TIME_NAME);
 
         /** {@inheritDoc} */
         @Override
-        public Collection<? extends Indexer> getIndexers() {
+        public Collection<? extends Indexer> createIndexers(IndexingOptions options) {
             return Collections.singletonList(indexer);
         }
 
@@ -291,11 +286,11 @@
      */
     private static final class PartialDateAndTimeMatchingRuleImpl extends TimeBasedMatchingRuleImpl {
 
-        final Indexer indexer = new PartialDateAndTimeIndexer(this);
+        private final Indexer indexer = new PartialDateAndTimeIndexer(this);
 
         /** {@inheritDoc} */
         @Override
-        public Collection<? extends Indexer> getIndexers() {
+        public Collection<? extends Indexer> createIndexers(IndexingOptions options) {
             return Collections.singletonList(indexer);
         }
 
@@ -585,15 +580,14 @@
 
         /** {@inheritDoc} */
         @Override
-        public void createKeys(Schema schema, ByteSequence value, IndexingOptions options,
-                Collection<ByteString> keys) {
+        public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) {
             matchingRule.timeKeys(value, keys);
         }
 
         /** {@inheritDoc} */
         @Override
         public String getIndexID() {
-            return PARTIAL_DATE_TIME_INDEX_ID + "." + EXTENSIBLE_INDEX_ID;
+            return MR_PARTIAL_DATE_AND_TIME_NAME;
         }
     }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java
index cc7e1e9..727eb00 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java
@@ -22,13 +22,14 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH;
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX;
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.opendj.ldap.ByteSequence;
@@ -40,6 +41,11 @@
  * be used as the default equality matching rule for the UUID syntax.
  */
 final class UUIDEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    UUIDEqualityMatchingRuleImpl() {
+        super(EMR_UUID_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         if (value.length() != 36) {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java
index 9082007..427b5de 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java
@@ -22,12 +22,14 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
+ *      Portions copyright 2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH;
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX;
 import static com.forgerock.opendj.ldap.CoreMessages.WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.opendj.ldap.ByteSequence;
@@ -39,6 +41,12 @@
  * This will be the default ordering matching rule for the UUID syntax.
  */
 final class UUIDOrderingMatchingRuleImpl extends AbstractOrderingMatchingRuleImpl {
+
+    UUIDOrderingMatchingRuleImpl() {
+        // Reusing equality index since OPENDJ-1864
+        super(EMR_UUID_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         if (value.length() != 36) {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java
index 951cf84..35dc895 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
@@ -41,6 +43,10 @@
  */
 final class UniqueMemberEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
 
+    UniqueMemberEqualityMatchingRuleImpl() {
+        super(EMR_UNIQUE_MEMBER_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value) throws DecodeException {
         // Separate value into normalized DN and "optional uid" portion.
         final String stringValue = value.toString().trim();
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java
index 04df0f2..1922c45 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java
@@ -22,10 +22,12 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.schema;
 
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
+
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
@@ -38,6 +40,11 @@
  * equal to each other.
  */
 final class UserPasswordExactEqualityMatchingRuleImpl extends AbstractEqualityMatchingRuleImpl {
+
+    UserPasswordExactEqualityMatchingRuleImpl() {
+        super(EMR_USER_PASSWORD_EXACT_NAME);
+    }
+
     public ByteString normalizeAttributeValue(final Schema schema, final ByteSequence value)
             throws DecodeException {
         // The normalized form of this matching rule is exactly equal to the
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/Indexer.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/Indexer.java
index 8be2333..ca401e1 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/Indexer.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/Indexer.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2014 ForgeRock AS
+ *      Portions copyright 2014-2015 ForgeRock AS
  */
 package org.forgerock.opendj.ldap.spi;
 
@@ -58,13 +58,10 @@
      *          The schema in which the associated matching rule is defined.
      * @param value
      *          The attribute value for which keys are required.
-     * @param options
-     *          The indexing options
      * @param keys
      *          A collection where to add the created keys.
      * @throws DecodeException if an error occurs while normalizing the value
      */
-    void createKeys(Schema schema, ByteSequence value, IndexingOptions options,
-            Collection<ByteString> keys) throws DecodeException;
+    void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) throws DecodeException;
 
 }
diff --git a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImplTest.java b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImplTest.java
index 47c6ca1..7d6850f 100644
--- a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImplTest.java
+++ b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImplTest.java
@@ -43,6 +43,7 @@
 import org.testng.annotations.Test;
 
 import static org.forgerock.opendj.ldap.ByteString.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 import static org.mockito.Mockito.*;
 import static org.testng.Assert.*;
 
@@ -54,6 +55,10 @@
 
     private static class FakeSubstringMatchingRuleImpl extends AbstractSubstringMatchingRuleImpl {
 
+        FakeSubstringMatchingRuleImpl() {
+            super(SMR_CASE_EXACT_OID, EMR_CASE_EXACT_OID);
+        }
+
         /** {@inheritDoc} */
         @Override
         public ByteString normalizeAttributeValue(Schema schema, ByteSequence value) throws DecodeException {
@@ -210,8 +215,8 @@
         assertEquals(
             assertion.createIndexQuery(new FakeIndexQueryFactory(newIndexingOptions())),
             "intersect["
-                    + "exactMatch(substring, value=='his'), "
-                    + "exactMatch(substring, value=='thi')"
+                    + "exactMatch(" + SMR_CASE_EXACT_OID + ", value=='his'), "
+                    + "exactMatch(" + SMR_CASE_EXACT_OID + ", value=='thi')"
                     + "]");
     }
 
@@ -223,11 +228,11 @@
         assertEquals(
             assertion.createIndexQuery(new FakeIndexQueryFactory(newIndexingOptions())),
             "intersect["
-                    + "rangeMatch(equality, 'abc' <= value < 'abd'), "
-                    + "exactMatch(substring, value=='def'), "
-                    + "exactMatch(substring, value=='ghi'), "
-                    + "exactMatch(substring, value=='jkl'), "
-                    + "exactMatch(substring, value=='abc')"
+                    + "rangeMatch(" + EMR_CASE_EXACT_OID + ", 'abc' <= value < 'abd'), "
+                    + "exactMatch(" + SMR_CASE_EXACT_OID + ", value=='def'), "
+                    + "exactMatch(" + SMR_CASE_EXACT_OID + ", value=='ghi'), "
+                    + "exactMatch(" + SMR_CASE_EXACT_OID + ", value=='jkl'), "
+                    + "exactMatch(" + SMR_CASE_EXACT_OID + ", value=='abc')"
                     + "]");
     }
 
@@ -240,8 +245,8 @@
         assertEquals(
             assertion.createIndexQuery(new FakeIndexQueryFactory(newIndexingOptions())),
             "intersect["
-                    + "rangeMatch(equality, 'aa' <= value < 'ab'), "
-                    + "rangeMatch(substring, 'aa' <= value < 'ab')"
+                    + "rangeMatch(" + EMR_CASE_EXACT_OID + ", 'aa' <= value < 'ab'), "
+                    + "rangeMatch(" + SMR_CASE_EXACT_OID + ", 'aa' <= value < 'ab')"
                     + "]");
     }
 
@@ -257,19 +262,19 @@
             // 0x00 is the nul byte, a.k.a. string terminator
             // so everything after it is not part of the string
             "intersect["
-                    + "rangeMatch(equality, '" + lower + "' <= value < 'b\u0000'), "
-                    + "rangeMatch(substring, '" + lower + "' <= value < 'b\u0000')"
+                    + "rangeMatch(" + EMR_CASE_EXACT_OID + ", '" + lower + "' <= value < 'b\u0000'), "
+                    + "rangeMatch(" + SMR_CASE_EXACT_OID + ", '" + lower + "' <= value < 'b\u0000')"
                     + "]");
     }
 
     @Test
     public void testIndexer() throws Exception {
-        final Indexer indexer = getRule().getIndexers().iterator().next();
-        Assertions.assertThat(indexer.getIndexID()).isEqualTo("substring");
-
         final IndexingOptions options = newIndexingOptions();
+        final Indexer indexer = getRule().createIndexers(options).iterator().next();
+        Assertions.assertThat(indexer.getIndexID()).isEqualTo(SMR_CASE_EXACT_OID + ":" + options.substringKeySize());
+
         final TreeSet<ByteString> keys = new TreeSet<>();
-        indexer.createKeys(Schema.getCoreSchema(), valueOf("ABCDE"), options, keys);
+        indexer.createKeys(Schema.getCoreSchema(), valueOf("ABCDE"), keys);
         Assertions.assertThat(keys).containsOnly((Object[]) toByteStrings("ABC", "BCD", "CDE", "DE", "E"));
     }
 
diff --git a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/PartialDateAndTimeMatchingRuleTestCase.java b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/PartialDateAndTimeMatchingRuleTestCase.java
index f3545d7..27cef35 100644
--- a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/PartialDateAndTimeMatchingRuleTestCase.java
+++ b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/PartialDateAndTimeMatchingRuleTestCase.java
@@ -21,7 +21,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2014 ForgeRock AS.
+ *      Copyright 2014-2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -35,11 +35,11 @@
 import org.forgerock.opendj.ldap.schema.AbstractSubstringMatchingRuleImplTest.FakeIndexQueryFactory;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
-
 import org.forgerock.util.time.TimeService;
 
 import static org.fest.assertions.Assertions.*;
 import static org.forgerock.opendj.ldap.schema.AbstractSubstringMatchingRuleImplTest.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 @SuppressWarnings("javadoc")
 @Test
@@ -187,6 +187,7 @@
         Assertion assertion = getRule().getAssertion(ByteString.valueOf("2012Y"));
 
         String indexQuery = assertion.createIndexQuery(new FakeIndexQueryFactory(newIndexingOptions(), false));
-        assertThat(indexQuery).matches("intersect\\[exactMatch\\(pdt\\.ext, value=='[0-9A-Z ]*'\\)\\]");
+        assertThat(indexQuery).matches(
+                "intersect\\[exactMatch\\(" + MR_PARTIAL_DATE_AND_TIME_NAME + ", value=='[0-9A-Z ]*'\\)\\]");
     }
 }
diff --git a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeGreaterThanMatchingRuleTest.java b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeGreaterThanMatchingRuleTest.java
index ef7bda7..a8f2fdd 100644
--- a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeGreaterThanMatchingRuleTest.java
+++ b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeGreaterThanMatchingRuleTest.java
@@ -21,7 +21,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2014 ForgeRock AS.
+ *      Copyright 2014-2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -39,6 +39,7 @@
 
 import static org.fest.assertions.Assertions.*;
 import static org.forgerock.opendj.ldap.schema.AbstractSubstringMatchingRuleImplTest.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 @SuppressWarnings("javadoc")
 @Test
@@ -120,6 +121,7 @@
         Assertion assertion = getRule().getAssertion(ByteString.valueOf("+5m"));
 
         String indexQuery = assertion.createIndexQuery(new FakeIndexQueryFactory(newIndexingOptions(), false));
-        assertThat(indexQuery).startsWith("rangeMatch(rt.ext, '").endsWith("' < value < '')");
+        assertThat(indexQuery).startsWith("rangeMatch(" + EMR_GENERALIZED_TIME_NAME + ", '")
+                .endsWith("' < value < '')");
     }
 }
diff --git a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeLessThanMatchingRuleTest.java b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeLessThanMatchingRuleTest.java
index 4ef175e..664b1b6 100644
--- a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeLessThanMatchingRuleTest.java
+++ b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeLessThanMatchingRuleTest.java
@@ -21,7 +21,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2014 ForgeRock AS.
+ *      Copyright 2014-2015 ForgeRock AS.
  */
 package org.forgerock.opendj.ldap.schema;
 
@@ -39,6 +39,7 @@
 
 import static org.fest.assertions.Assertions.*;
 import static org.forgerock.opendj.ldap.schema.AbstractSubstringMatchingRuleImplTest.*;
+import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
 @SuppressWarnings("javadoc")
 @Test
@@ -121,6 +122,6 @@
         Assertion assertion = getRule().getAssertion(ByteString.valueOf("+5m"));
 
         String indexQuery = assertion.createIndexQuery(new FakeIndexQueryFactory(newIndexingOptions(), false));
-        assertThat(indexQuery).startsWith("rangeMatch(rt.ext, '' < value < '");
+        assertThat(indexQuery).startsWith("rangeMatch(" + EMR_GENERALIZED_TIME_NAME + ", '' < value < '");
     }
 }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndex.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndex.java
index 7396f2f..3a1dbb6 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndex.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndex.java
@@ -28,7 +28,6 @@
 package org.opends.server.backends.jeb;
 
 import static org.opends.messages.BackendMessages.*;
-import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
 
 import java.io.Closeable;
@@ -45,6 +44,7 @@
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
 import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
+import org.forgerock.opendj.ldap.spi.Indexer;
 import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.forgerock.util.Utils;
 import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -116,15 +116,11 @@
 
   /** The attribute index configuration. */
   private LocalDBIndexCfg indexConfig;
+  private IndexingOptions indexingOptions;
 
   /** The mapping from names to indexes. */
-  private final Map<String, Index> nameToIndexes = new HashMap<String, Index>();
-  private final IndexQueryFactory<IndexQuery> indexQueryFactory;
-
-  /**
-   * The mapping from extensible index types (e.g. "substring" or "shared") to list of indexes.
-   */
-  private Map<String, Collection<Index>> extensibleIndexesMapping;
+  private Map<String, Index> indexIdToIndexes;
+  private IndexQueryFactory<IndexQuery> indexQueryFactory;
 
   /**
    * Create a new attribute index object.
@@ -137,94 +133,119 @@
   {
     this.entryContainer = entryContainer;
     this.indexConfig = indexConfig;
-
-    buildPresenceIndex();
-    buildIndexes(IndexType.EQUALITY);
-    buildIndexes(IndexType.SUBSTRING);
-    buildIndexes(IndexType.ORDERING);
-    buildIndexes(IndexType.APPROXIMATE);
-    buildExtensibleIndexes();
-
-    final JEIndexConfig config = new JEIndexConfig(indexConfig.getSubstringLength());
-    indexQueryFactory = new IndexQueryFactoryImpl(nameToIndexes, config, indexConfig.getAttribute());
-    extensibleIndexesMapping = computeExtensibleIndexesMapping();
+    this.indexingOptions = new JEIndexingOptions(indexConfig.getSubstringLength());
+    this.indexIdToIndexes = Collections.unmodifiableMap(buildIndexes(entryContainer, indexConfig, indexingOptions));
+    this.indexQueryFactory = new IndexQueryFactoryImpl(indexIdToIndexes, indexingOptions, indexConfig.getAttribute());
   }
 
-  private void buildPresenceIndex()
+  private static Map<String, Index> buildIndexes(EntryContainer entryContainer,
+                                                 LocalDBIndexCfg config,
+                                                 IndexingOptions options) throws ConfigException
   {
-    final IndexType indexType = IndexType.PRESENCE;
-    if (indexConfig.getIndexType().contains(indexType))
-    {
-      String indexID = indexType.toString();
-      nameToIndexes.put(indexID, newPresenceIndex(indexConfig));
+    final Map<String, Index> indexes = new HashMap<>();
+    final AttributeType attributeType = config.getAttribute();
+    final int indexEntryLimit = config.getIndexEntryLimit();
+
+    for(IndexType indexType : config.getIndexType()) {
+      Collection<? extends Indexer> indexers;
+      switch (indexType)
+      {
+      case PRESENCE:
+        indexes.put(indexType.toString(), newPresenceIndex(entryContainer, config));
+        indexers = Collections.emptyList();
+        break;
+      case EXTENSIBLE:
+        indexers = getExtensibleIndexers(config.getAttribute(), config.getIndexExtensibleMatchingRule(), options);
+        break;
+      case APPROXIMATE:
+        indexers =
+            throwIfNoMatchingRule(attributeType, indexType, attributeType.getApproximateMatchingRule())
+              .createIndexers(options);
+        break;
+      case EQUALITY:
+        indexers =
+            throwIfNoMatchingRule(attributeType, indexType, attributeType.getEqualityMatchingRule())
+              .createIndexers(options);
+        break;
+      case ORDERING:
+        indexers =
+            throwIfNoMatchingRule(attributeType, indexType, attributeType.getOrderingMatchingRule())
+              .createIndexers(options);
+        break;
+      case SUBSTRING:
+        indexers =
+            throwIfNoMatchingRule(attributeType, indexType, attributeType.getSubstringMatchingRule())
+              .createIndexers(options);
+        break;
+      default:
+       throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, indexType.toString()));
+      }
+      buildAndRegisterIndexesWithIndexers(entryContainer, attributeType, indexEntryLimit, indexers, indexes);
     }
+
+    return indexes;
   }
 
-  private Index newPresenceIndex(LocalDBIndexCfg cfg)
+  private static Index newPresenceIndex(EntryContainer entryContainer, LocalDBIndexCfg cfg)
   {
     final AttributeType attrType = cfg.getAttribute();
-    final String indexName = getIndexName(attrType, IndexType.PRESENCE.toString());
+    final String indexName = getIndexName(entryContainer, attrType, IndexType.PRESENCE.toString());
     final PresenceIndexer indexer = new PresenceIndexer(attrType);
     return entryContainer.newIndexForAttribute(indexName, indexer, cfg.getIndexEntryLimit());
   }
 
-  private void buildExtensibleIndexes() throws ConfigException
+  private static MatchingRule throwIfNoMatchingRule(AttributeType attributeType, IndexType type, MatchingRule rule)
+      throws ConfigException
   {
-    final IndexType indexType = IndexType.EXTENSIBLE;
-    if (indexConfig.getIndexType().contains(indexType))
+    if (rule == null)
     {
-      final AttributeType attrType = indexConfig.getAttribute();
-      Set<String> extensibleRules = indexConfig.getIndexExtensibleMatchingRule();
-      if (extensibleRules == null || extensibleRules.isEmpty())
-      {
-        throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexType.toString()));
-      }
+      throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, type.toString()));
+    }
+    return rule;
+  }
 
-      // 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 (final String ruleName : extensibleRules)
+  private static void buildAndRegisterIndexesWithIndexers(EntryContainer entryContainer,
+                                                          AttributeType attributeType,
+                                                          int indexEntryLimit,
+                                                          Collection<? extends Indexer> indexers,
+                                                          Map<String, Index> indexes)
+  {
+    for (Indexer indexer : indexers)
+    {
+      final String indexID = indexer.getIndexID();
+      if (!indexes.containsKey(indexID))
       {
-        MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
-        if (rule == null)
-        {
-          logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
-          continue;
-        }
-        for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.getIndexers())
-        {
-          final String indexId = indexer.getIndexID();
-          if (!nameToIndexes.containsKey(indexId))
-          {
-            // There is no index available for this index id. Create a new index
-            nameToIndexes.put(indexId, newAttributeIndex(indexConfig, indexer));
-          }
-        }
+        final Index index = newAttributeIndex(entryContainer, attributeType, indexer, indexEntryLimit);
+        indexes.put(indexID, index);
       }
     }
   }
 
-  private void buildIndexes(IndexType indexType) throws ConfigException
+  private static Collection<Indexer> getExtensibleIndexers(AttributeType attributeType, Set<String> extensibleRules,
+      IndexingOptions options) throws ConfigException
   {
-    if (indexConfig.getIndexType().contains(indexType))
+    if (extensibleRules == null || extensibleRules.isEmpty())
     {
-      final AttributeType attrType = indexConfig.getAttribute();
-      final String indexID = indexType.toString();
-      final MatchingRule rule = getMatchingRule(indexType, attrType);
+      throw new ConfigException(
+          ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, IndexType.EXTENSIBLE.toString()));
+    }
+
+    final Collection<Indexer> indexers = new ArrayList<>();
+    for (final String ruleName : extensibleRules)
+    {
+      final MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
       if (rule == null)
       {
-        throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexID));
+        logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attributeType, ruleName);
+        continue;
       }
-
-      for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.getIndexers())
-      {
-        nameToIndexes.put(indexID, newAttributeIndex(indexConfig, indexer));
-      }
+      indexers.addAll(rule.createIndexers(options));
     }
+
+    return indexers;
   }
 
-  private MatchingRule getMatchingRule(IndexType indexType, AttributeType attrType)
+  private static MatchingRule getMatchingRule(IndexType indexType, AttributeType attrType)
   {
     switch (indexType)
     {
@@ -241,15 +262,15 @@
     }
   }
 
-  private Index newAttributeIndex(LocalDBIndexCfg indexConfig, org.forgerock.opendj.ldap.spi.Indexer indexer)
+  private static Index newAttributeIndex(EntryContainer entryContainer, AttributeType attributeType,
+      org.forgerock.opendj.ldap.spi.Indexer indexer, int indexEntryLimit)
   {
-    final AttributeType attrType = indexConfig.getAttribute();
-    final String indexName = getIndexName(attrType, indexer.getIndexID());
-    final AttributeIndexer attrIndexer = new AttributeIndexer(attrType, indexer);
-    return entryContainer.newIndexForAttribute(indexName, attrIndexer, indexConfig.getIndexEntryLimit());
+    final String indexName = getIndexName(entryContainer, attributeType, indexer.getIndexID());
+    final AttributeIndexer attrIndexer = new AttributeIndexer(attributeType, indexer);
+    return entryContainer.newIndexForAttribute(indexName, attrIndexer, indexEntryLimit);
   }
 
-  private String getIndexName(AttributeType attrType, String indexID)
+  private static String getIndexName(EntryContainer entryContainer, AttributeType attrType, String indexID)
   {
     return entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID() + "." + indexID;
   }
@@ -262,7 +283,7 @@
    */
   public void open() throws DatabaseException
   {
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
       index.open();
     }
@@ -273,7 +294,7 @@
   @Override
   public void close()
   {
-    Utils.closeSilently(nameToIndexes.values());
+    Utils.closeSilently(indexIdToIndexes.values());
     indexConfig.removeChangeListener(this);
     // The entryContainer is responsible for closing the JE databases.
   }
@@ -315,13 +336,11 @@
    * @throws DatabaseException If an error occurs in the JE database.
    * @throws DirectoryException If a Directory Server error occurs.
    */
-  public void addEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
-       throws DatabaseException, DirectoryException
+  public void addEntry(IndexBuffer buffer, EntryID entryID, Entry entry) throws DatabaseException, DirectoryException
   {
-    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
-      index.addEntry(buffer, entryID, entry, options);
+      index.addEntry(buffer, entryID, entry);
     }
   }
 
@@ -337,10 +356,9 @@
   public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
        throws DatabaseException, DirectoryException
   {
-    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
-      index.removeEntry(buffer, entryID, entry, options);
+      index.removeEntry(buffer, entryID, entry);
     }
   }
 
@@ -363,10 +381,9 @@
                           List<Modification> mods)
        throws DatabaseException
   {
-    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
-      index.modifyEntry(buffer, entryID, oldEntry, newEntry, mods, options);
+      index.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
     }
   }
 
@@ -379,7 +396,7 @@
    * @param len The length of the substring.
    * @return A byte string containing a substring key.
    */
-  private ByteString makeSubstringKey(byte[] bytes, int pos, int len)
+  private static ByteString makeSubstringKey(byte[] bytes, int pos, int len)
   {
     byte[] keyBytes = new byte[len];
     System.arraycopy(bytes, pos, keyBytes, 0, len);
@@ -602,7 +619,7 @@
   {
     long entryLimitExceededCount = 0;
 
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
       entryLimitExceededCount += index.getEntryLimitExceededCount();
     }
@@ -615,7 +632,7 @@
    */
   public void listDatabases(List<DatabaseContainer> dbList)
   {
-    dbList.addAll(nameToIndexes.values());
+    dbList.addAll(indexIdToIndexes.values());
   }
 
   /**
@@ -654,16 +671,14 @@
     return true;
   }
 
-  private boolean isIndexAcceptable(LocalDBIndexCfg cfg, IndexType indexType,
+  private static boolean isIndexAcceptable(LocalDBIndexCfg cfg, IndexType indexType,
       List<LocalizableMessage> unacceptableReasons)
   {
-    final String indexId = indexType.toString();
     final AttributeType attrType = cfg.getAttribute();
     if (cfg.getIndexType().contains(indexType)
-        && nameToIndexes.get(indexId) == null
         && getMatchingRule(indexType, attrType) == null)
     {
-      unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexId));
+      unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexType.toString()));
       return false;
     }
     return true;
@@ -671,218 +686,61 @@
 
   /** {@inheritDoc} */
   @Override
-  public synchronized ConfigChangeResult applyConfigurationChange(LocalDBIndexCfg cfg)
+  public synchronized ConfigChangeResult applyConfigurationChange(final LocalDBIndexCfg newConfiguration)
   {
     final ConfigChangeResult ccr = new ConfigChangeResult();
+    final IndexingOptions newIndexingOptions = new JEIndexingOptions(newConfiguration.getSubstringLength());
     try
     {
-      applyChangeToPresenceIndex(cfg, ccr);
-      applyChangeToIndex(IndexType.EQUALITY, cfg, ccr);
-      applyChangeToIndex(IndexType.SUBSTRING, cfg, ccr);
-      applyChangeToIndex(IndexType.ORDERING, cfg, ccr);
-      applyChangeToIndex(IndexType.APPROXIMATE, cfg, ccr);
-      applyChangeToExtensibleIndexes(cfg, ccr);
+      Map<String, Index> newIndexIdToIndexes = buildIndexes(entryContainer, newConfiguration, newIndexingOptions);
 
-      extensibleIndexesMapping = computeExtensibleIndexesMapping();
-      indexConfig = cfg;
+      final Map<String, Index> removedIndexes = new HashMap<>(indexIdToIndexes);
+      removedIndexes.keySet().removeAll(newIndexIdToIndexes.keySet());
 
-      return ccr;
+      final Map<String, Index> addedIndexes = new HashMap<>(newIndexIdToIndexes);
+      addedIndexes.keySet().removeAll(indexIdToIndexes.keySet());
+
+      final Map<String, Index> updatedIndexes = new HashMap<>(indexIdToIndexes);
+      updatedIndexes.keySet().retainAll(newIndexIdToIndexes.keySet());
+
+      // Replace instances of Index created by buildIndexes() with the one already opened and present in the actual
+      // indexIdToIndexes
+      newIndexIdToIndexes.putAll(updatedIndexes);
+
+      // Open added indexes *before* adding them to indexIdToIndexes
+      for (Index addedIndex : addedIndexes.values())
+      {
+        openIndex(addedIndex, ccr);
+      }
+
+      indexConfig = newConfiguration;
+      indexingOptions = newIndexingOptions;
+      indexIdToIndexes =  Collections.unmodifiableMap(newIndexIdToIndexes);
+      indexQueryFactory = new IndexQueryFactoryImpl(indexIdToIndexes, indexingOptions, indexConfig.getAttribute());
+
+      // FIXME: There is no guarantee here that deleted index are not currently involved in a query
+      for (Index removedIndex : removedIndexes.values())
+      {
+        deleteIndex(entryContainer, removedIndex);
+      }
+
+      for (Index updatedIndex : updatedIndexes.values())
+      {
+        updateIndex(updatedIndex, newConfiguration.getIndexEntryLimit(), ccr);
+      }
     }
-    catch(Exception e)
+    catch (Exception e)
     {
       ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
       ccr.addMessage(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e)));
-      return ccr;
     }
+
+    return ccr;
   }
 
-  private void applyChangeToExtensibleIndexes(LocalDBIndexCfg cfg, final ConfigChangeResult ccr)
-  {
-    final AttributeType attrType = cfg.getAttribute();
-    if (!cfg.getIndexType().contains(IndexType.EXTENSIBLE))
-    {
-      final Set<MatchingRule> validRules = Collections.emptySet();
-      final Set<String> validIndexIds = Collections.emptySet();
-      removeIndexesForExtensibleMatchingRules(validRules, validIndexIds);
-      return;
-    }
-
-    final Set<String> extensibleRules = cfg.getIndexExtensibleMatchingRule();
-    final Set<MatchingRule> validRules = new HashSet<MatchingRule>();
-    final Set<String> validIndexIds = new HashSet<String>();
-    final int indexEntryLimit = cfg.getIndexEntryLimit();
-
-    for (String ruleName : extensibleRules)
-    {
-      MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
-      if (rule == null)
-      {
-        logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
-        continue;
-      }
-      validRules.add(rule);
-      for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.getIndexers())
-      {
-        String indexId = indexer.getIndexID();
-        validIndexIds.add(indexId);
-        if (!nameToIndexes.containsKey(indexId))
-        {
-          Index index = newAttributeIndex(cfg, indexer);
-          openIndex(index, ccr);
-          nameToIndexes.put(indexId, index);
-        }
-        else
-        {
-          Index index = nameToIndexes.get(indexId);
-          if (index.setIndexEntryLimit(indexEntryLimit))
-          {
-            ccr.setAdminActionRequired(true);
-            ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(index.getName()));
-          }
-          if (indexConfig.getSubstringLength() != cfg.getSubstringLength())
-          {
-            index.setIndexer(new AttributeIndexer(attrType, indexer));
-          }
-        }
-      }
-    }
-    removeIndexesForExtensibleMatchingRules(validRules, validIndexIds);
-  }
-
-  /** Remove indexes which do not correspond to valid rules. */
-  private void removeIndexesForExtensibleMatchingRules(Set<MatchingRule> validRules, Set<String> validIndexIds)
-  {
-    final Set<MatchingRule> rulesToDelete = getCurrentExtensibleMatchingRules();
-    rulesToDelete.removeAll(validRules);
-    if (!rulesToDelete.isEmpty())
-    {
-      entryContainer.exclusiveLock.lock();
-      try
-      {
-        for (MatchingRule rule: rulesToDelete)
-        {
-          final List<String> indexIdsToRemove = new ArrayList<String>();
-          for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.getIndexers())
-          {
-            final String indexId = indexer.getIndexID();
-            if (!validIndexIds.contains(indexId))
-            {
-              indexIdsToRemove.add(indexId);
-            }
-          }
-          // Delete indexes which are not used
-          for (String indexId : indexIdsToRemove)
-          {
-            Index index = nameToIndexes.get(indexId);
-            if (index != null)
-            {
-              entryContainer.deleteDatabase(index);
-              nameToIndexes.remove(index);
-            }
-          }
-        }
-      }
-      finally
-      {
-        entryContainer.exclusiveLock.unlock();
-      }
-    }
-  }
-
-  private Set<MatchingRule> getCurrentExtensibleMatchingRules()
-  {
-    final Set<MatchingRule> rules = new HashSet<MatchingRule>();
-    for (String ruleName : indexConfig.getIndexExtensibleMatchingRule())
-    {
-        final MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
-        if (rule != null)
-        {
-          rules.add(rule);
-        }
-    }
-    return rules;
-  }
-
-  private void applyChangeToIndex(IndexType indexType, LocalDBIndexCfg cfg, final ConfigChangeResult ccr)
-  {
-    String indexId = indexType.toString();
-    Index index = nameToIndexes.get(indexId);
-    if (!cfg.getIndexType().contains(indexType))
-    {
-      removeIndex(index, indexType);
-      return;
-    }
-
-    if (index == null)
-    {
-      final MatchingRule matchingRule = getMatchingRule(indexType, cfg.getAttribute());
-      for (org.forgerock.opendj.ldap.spi.Indexer indexer : matchingRule.getIndexers())
-      {
-        index = newAttributeIndex(cfg, indexer);
-        openIndex(index, ccr);
-        nameToIndexes.put(indexId, index);
-      }
-    }
-    else
-    {
-      // already exists. Just update index entry limit.
-      if (index.setIndexEntryLimit(cfg.getIndexEntryLimit()))
-      {
-        ccr.setAdminActionRequired(true);
-        ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(index.getName()));
-      }
-    }
-  }
-
-  private void applyChangeToPresenceIndex(LocalDBIndexCfg cfg, final ConfigChangeResult ccr)
-  {
-    final IndexType indexType = IndexType.PRESENCE;
-    final String indexID = indexType.toString();
-    Index index = nameToIndexes.get(indexID);
-    if (!cfg.getIndexType().contains(indexType))
-    {
-      removeIndex(index, indexType);
-      return;
-    }
-
-    if (index == null)
-    {
-      index = newPresenceIndex(cfg);
-      openIndex(index, ccr);
-      nameToIndexes.put(indexID, index);
-    }
-    else
-    {
-      // already exists. Just update index entry limit.
-      if (index.setIndexEntryLimit(cfg.getIndexEntryLimit()))
-      {
-        ccr.setAdminActionRequired(true);
-        ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(index.getName()));
-      }
-    }
-  }
-
-  private void removeIndex(Index index, IndexType indexType)
-  {
-    if (index != null)
-    {
-      entryContainer.exclusiveLock.lock();
-      try
-      {
-        nameToIndexes.remove(indexType.toString());
-        entryContainer.deleteDatabase(index);
-      }
-      finally
-      {
-        entryContainer.exclusiveLock.unlock();
-      }
-    }
-  }
-
-  private void openIndex(Index index, final ConfigChangeResult ccr)
+  private static void openIndex(Index index, ConfigChangeResult ccr)
   {
     index.open();
-
     if (!index.isTrusted())
     {
       ccr.setAdminActionRequired(true);
@@ -890,13 +748,36 @@
     }
   }
 
+  private static void updateIndex(Index updatedIndex, int newIndexEntryLimit, ConfigChangeResult ccr)
+  {
+    if (updatedIndex.setIndexEntryLimit(newIndexEntryLimit))
+    {
+      // This index can still be used since index size limit doesn't impact validity of the results.
+      ccr.setAdminActionRequired(true);
+      ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(updatedIndex.getName()));
+    }
+  }
+
+  private static void deleteIndex(EntryContainer entryContainer, Index index)
+  {
+    entryContainer.exclusiveLock.lock();
+    try
+    {
+      entryContainer.deleteDatabase(index);
+    }
+    finally
+    {
+      entryContainer.exclusiveLock.unlock();
+    }
+  }
+
   /**
    * Return true iff this index is trusted.
    * @return the trusted state of this index
    */
   public boolean isTrusted()
   {
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
       if (!index.isTrusted())
       {
@@ -918,103 +799,18 @@
         + indexConfig.getAttribute().getNameOrOID();
   }
 
-  /**
-   * Return the equality index.
-   *
-   * @return The equality index.
-   */
-  public Index getEqualityIndex() {
-    return nameToIndexes.get(IndexType.EQUALITY.toString());
-  }
-
-  /**
-   * Return the approximate index.
-   *
-   * @return The approximate index.
-   */
-  public Index getApproximateIndex() {
-    return nameToIndexes.get(IndexType.APPROXIMATE.toString());
-  }
-
-  /**
-   * Return the ordering index.
-   *
-   * @return  The ordering index.
-   */
-  public Index getOrderingIndex() {
-    return nameToIndexes.get(IndexType.ORDERING.toString());
-  }
-
-  /**
-   * Return the substring index.
-   *
-   * @return The substring index.
-   */
-  public Index getSubstringIndex() {
-    return nameToIndexes.get(IndexType.SUBSTRING.toString());
-  }
-
-  /**
-   * Return the presence index.
-   *
-   * @return The presence index.
-   */
-  public Index getPresenceIndex() {
-    return nameToIndexes.get(IndexType.PRESENCE.toString());
-  }
-
-  /**
-   * Return the mapping of extensible index types and indexes.
-   *
-   * @return The map containing entries (extensible index type, list of indexes)
-   */
-  public Map<String, Collection<Index>> getExtensibleIndexes()
-  {
-    return extensibleIndexesMapping;
-  }
-
-  private Map<String, Collection<Index>> computeExtensibleIndexesMapping()
-  {
-    final Collection<Index> substring = new ArrayList<Index>();
-    final Collection<Index> shared = new ArrayList<Index>();
-    for (Map.Entry<String, Index> entry : nameToIndexes.entrySet())
-    {
-      final String indexId = entry.getKey();
-      if (isDefaultIndex(indexId)) {
-        continue;
-      }
-      if (indexId.endsWith(EXTENSIBLE_INDEXER_ID_SUBSTRING))
-      {
-        substring.add(entry.getValue());
-      }
-      else
-      {
-        shared.add(entry.getValue());
-      }
-    }
-    final Map<String, Collection<Index>> indexMap = new HashMap<String,Collection<Index>>();
-    indexMap.put(EXTENSIBLE_INDEXER_ID_SUBSTRING, substring);
-    indexMap.put(EXTENSIBLE_INDEXER_ID_SHARED, shared);
-    return Collections.unmodifiableMap(indexMap);
-  }
-
-  private boolean isDefaultIndex(String indexId)
-  {
-    return indexId.equals(IndexType.EQUALITY.toString())
-        || indexId.equals(IndexType.PRESENCE.toString())
-        || indexId.equals(IndexType.SUBSTRING.toString())
-        || indexId.equals(IndexType.ORDERING.toString())
-        || indexId.equals(IndexType.APPROXIMATE.toString());
+  Index getIndex(String indexID) {
+    return indexIdToIndexes.get(indexID);
   }
 
   /**
    * Retrieves all the indexes used by this attribute index.
    *
-   * @return A collection of all indexes in use by this attribute
+   * @return An immutable collection of all indexes in use by this attribute
    * index.
    */
   public Collection<Index> getAllIndexes() {
-    return new LinkedHashSet<Index>(nameToIndexes.values());
+    return indexIdToIndexes.values();
   }
 
   /**
@@ -1065,7 +861,7 @@
       if (debugBuffer != null)
       {
         debugBuffer.append("[INDEX:");
-        for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.getIndexers())
+        for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.createIndexers(indexingOptions))
         {
             debugBuffer.append(" ")
               .append(filter.getAttributeType().getNameOrOID())
@@ -1100,9 +896,9 @@
 
   private boolean ruleHasAtLeasOneIndex(MatchingRule rule)
   {
-    for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.getIndexers())
+    for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.createIndexers(indexingOptions))
     {
-      if (nameToIndexes.containsKey(indexer.getIndexID()))
+      if (indexIdToIndexes.containsKey(indexer.getIndexID()))
       {
         return true;
       }
@@ -1111,7 +907,7 @@
   }
 
   /** This class extends the IndexConfig for JE Backend. */
-  private final class JEIndexConfig implements IndexingOptions
+  private static final class JEIndexingOptions implements IndexingOptions
   {
     /** The length of the substring index. */
     private int substringLength;
@@ -1120,7 +916,7 @@
      * Creates a new JEIndexConfig instance.
      * @param substringLength The length of the substring.
      */
-    private JEIndexConfig(int substringLength)
+    private JEIndexingOptions(int substringLength)
     {
       this.substringLength = substringLength;
     }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndexer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndexer.java
index b64030a..c1a7ca7 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndexer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/AttributeIndexer.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2014 ForgeRock AS
+ *      Portions Copyright 2014-2015 ForgeRock AS
  */
 package org.opends.server.backends.jeb;
 
@@ -35,7 +35,6 @@
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.schema.Schema;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeType;
 import org.opends.server.types.Entry;
@@ -79,26 +78,25 @@
 
   /** {@inheritDoc} */
   @Override
-  public void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options)
+  public void indexEntry(Entry entry, Set<ByteString> keys)
   {
-    List<Attribute> attrList = entry.getAttribute(attributeType);
+    final List<Attribute> attrList = entry.getAttribute(attributeType);
     if (attrList != null)
     {
-      indexAttribute(attrList, keys, options);
+      indexAttribute(attrList, keys);
     }
   }
 
   /** {@inheritDoc} */
   @Override
   public void modifyEntry(Entry oldEntry, Entry newEntry,
-      List<Modification> mods, Map<ByteString, Boolean> modifiedKeys,
-      IndexingOptions options)
+      List<Modification> mods, Map<ByteString, Boolean> modifiedKeys)
   {
     List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
     List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
 
-    indexAttribute(oldAttributes, modifiedKeys, false, options);
-    indexAttribute(newAttributes, modifiedKeys, true, options);
+    indexAttribute(oldAttributes, modifiedKeys, false);
+    indexAttribute(newAttributes, modifiedKeys, true);
   }
 
 
@@ -108,8 +106,7 @@
    * @param attrList The attribute for which substring keys are required.
    * @param keys The set into which the generated keys will be inserted.
    */
-  private void indexAttribute(List<Attribute> attrList, Set<ByteString> keys,
-      IndexingOptions options)
+  private void indexAttribute(List<Attribute> attrList, Set<ByteString> keys)
   {
     if (attrList == null)
     {
@@ -124,7 +121,7 @@
         {
           try
           {
-            indexer.createKeys(Schema.getDefaultSchema(), value, options, keys);
+            indexer.createKeys(Schema.getDefaultSchema(), value, keys);
           }
           catch (DecodeException e)
           {
@@ -143,17 +140,15 @@
    * @param insert <code>true</code> if generated keys should
    * be inserted or <code>false</code> otherwise.
    */
-  private void indexAttribute(List<Attribute> attrList,
-      Map<ByteString, Boolean> modifiedKeys, Boolean insert,
-      IndexingOptions options)
+  private void indexAttribute(List<Attribute> attrList, Map<ByteString, Boolean> modifiedKeys, Boolean insert)
   {
     if (attrList == null)
     {
       return;
     }
 
-    final Set<ByteString> keys = new HashSet<ByteString>();
-    indexAttribute(attrList, keys, options);
+    final Set<ByteString> keys = new HashSet<>();
+    indexAttribute(attrList, keys);
     computeModifiedKeys(modifiedKeys, insert, keys);
   }
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/EqualityIndexer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/EqualityIndexer.java
index 42923aa..b3033c3 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/EqualityIndexer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/EqualityIndexer.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2014 ForgeRock AS
+ *      Portions Copyright 2014-2015 ForgeRock AS
  */
 package org.opends.server.backends.jeb;
 
@@ -34,7 +34,6 @@
 import org.forgerock.opendj.ldap.schema.MatchingRule;
 import org.forgerock.opendj.ldap.schema.Schema;
 import org.forgerock.opendj.ldap.spi.Indexer;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.types.AttributeType;
 
 /**
@@ -68,9 +67,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void createKeys(Schema schema, ByteSequence value,
-      IndexingOptions options, Collection<ByteString> keys)
-      throws DecodeException
+  public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) throws DecodeException
   {
     keys.add(equalityRule.normalizeAttributeValue(value));
   }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2CIndexer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2CIndexer.java
index dcdef39..54d3a52 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2CIndexer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2CIndexer.java
@@ -22,14 +22,13 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
- *      Portions Copyright 2014 ForgeRock AS
+ *      Portions Copyright 2014-2015 ForgeRock AS
  */
 package org.opends.server.backends.jeb;
 
 import java.util.*;
 
 import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.types.Entry;
 import org.opends.server.types.Modification;
 
@@ -57,7 +56,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void indexEntry(Entry entry, Set<ByteString> addKeys, IndexingOptions options)
+  public void indexEntry(Entry entry, Set<ByteString> addKeys)
   {
     // The superior entry IDs are in the entry attachment.
     ArrayList<EntryID> ids = (ArrayList<EntryID>) entry.getAttachment();
@@ -78,7 +77,7 @@
   @Override
   public void modifyEntry(Entry oldEntry, Entry newEntry,
                           List<Modification> mods,
-                          Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
+                          Map<ByteString, Boolean> modifiedKeys)
   {
     // Nothing to do.
   }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2SIndexer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2SIndexer.java
index 80cce87..c672282 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2SIndexer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ID2SIndexer.java
@@ -22,14 +22,13 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
- *      Portions Copyright 2014 ForgeRock AS
+ *      Portions Copyright 2014-2015 ForgeRock AS
  */
 package org.opends.server.backends.jeb;
 
 import java.util.*;
 
 import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.types.Entry;
 import org.opends.server.types.Modification;
 
@@ -56,7 +55,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void indexEntry(Entry entry, Set<ByteString> addKeys, IndexingOptions options)
+  public void indexEntry(Entry entry, Set<ByteString> addKeys)
   {
     // The superior entry IDs are in the entry attachment.
     ArrayList<EntryID> ids = (ArrayList<EntryID>) entry.getAttachment();
@@ -77,7 +76,7 @@
   @Override
   public void modifyEntry(Entry oldEntry, Entry newEntry,
                           List<Modification> mods,
-                          Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
+                          Map<ByteString, Boolean> modifiedKeys)
   {
     // Nothing to do.
   }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Importer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Importer.java
index cbe0733..ac49c00 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Importer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Importer.java
@@ -89,7 +89,6 @@
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.forgerock.util.Utils;
 import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType;
 import org.opends.server.admin.std.server.LocalDBBackendCfg;
@@ -689,26 +688,7 @@
   {
     for (AttributeIndex attributeIndex : suffix.getAttrIndexMap().values())
     {
-      putInIdContainerMap(attributeIndex.getEqualityIndex());
-      putInIdContainerMap(attributeIndex.getPresenceIndex());
-      putInIdContainerMap(attributeIndex.getSubstringIndex());
-      putInIdContainerMap(attributeIndex.getOrderingIndex());
-      putInIdContainerMap(attributeIndex.getApproximateIndex());
-      Map<String, Collection<Index>> extensibleMap = attributeIndex.getExtensibleIndexes();
-      if (!extensibleMap.isEmpty())
-      {
-        putInIdContainerMap(extensibleMap.get(EXTENSIBLE_INDEXER_ID_SUBSTRING));
-        putInIdContainerMap(extensibleMap.get(EXTENSIBLE_INDEXER_ID_SHARED));
-      }
-    }
-  }
-
-  private void putInIdContainerMap(Collection<Index> indexes)
-  {
-    if (indexes != null)
-    {
-      for (Index index : indexes)
-      {
+      for(Index index : attributeIndex.getAllIndexes()) {
         putInIdContainerMap(index);
       }
     }
@@ -1492,20 +1472,20 @@
     }
 
     @Override
-    void processAttribute(Index index, Entry entry, EntryID entryID, IndexingOptions options,
-        IndexKey indexKey) throws DatabaseException, InterruptedException
+    void processAttribute(Index index, Entry entry, EntryID entryID, IndexKey indexKey)
+        throws DatabaseException, InterruptedException
     {
       if (oldEntry != null)
       {
         deleteKeySet.clear();
-        index.indexEntry(oldEntry, deleteKeySet, options);
+        index.indexEntry(oldEntry, deleteKeySet);
         for (ByteString delKey : deleteKeySet)
         {
           processKey(index, delKey.toByteArray(), entryID, indexKey, false);
         }
       }
       insertKeySet.clear();
-      index.indexEntry(entry, insertKeySet, options);
+      index.indexEntry(entry, insertKeySet);
       for (ByteString key : insertKeySet)
       {
         processKey(index, key.toByteArray(), entryID, indexKey, true);
@@ -1522,7 +1502,7 @@
     private final Map<IndexKey, IndexOutputBuffer> indexBufferMap = new HashMap<IndexKey, IndexOutputBuffer>();
     private final Set<ByteString> insertKeySet = new HashSet<ByteString>();
     private final EntryInformation entryInfo = new EntryInformation();
-    private final IndexKey dnIndexKey = new IndexKey(dnType, ImportIndexType.DN, 1);
+    private final IndexKey dnIndexKey = new IndexKey(dnType, ImportIndexType.DN.toString(), 1);
     private DatabaseEntry keyEntry = new DatabaseEntry();
     private DatabaseEntry valEntry = new DatabaseEntry();
 
@@ -1623,57 +1603,45 @@
     void fillIndexKey(Suffix suffix, AttributeIndex attrIndex, Entry entry, AttributeType attrType, EntryID entryID)
         throws DatabaseException, InterruptedException, DirectoryException, JebException
     {
-      final IndexingOptions options = attrIndex.getIndexingOptions();
-
-      processAttribute(attrIndex.getEqualityIndex(), ImportIndexType.EQUALITY, entry, attrType, entryID, options);
-      processAttribute(attrIndex.getPresenceIndex(), ImportIndexType.PRESENCE, entry, attrType, entryID, options);
-      processAttribute(attrIndex.getSubstringIndex(), ImportIndexType.SUBSTRING, entry, attrType, entryID, options);
-      processAttribute(attrIndex.getOrderingIndex(), ImportIndexType.ORDERING, entry, attrType, entryID, options);
-      processAttribute(attrIndex.getApproximateIndex(), ImportIndexType.APPROXIMATE, entry, attrType, entryID, options);
+      for(Index index : attrIndex.getAllIndexes()) {
+        processAttribute(index,  entry, attrType, entryID);
+      }
 
       for (VLVIndex vlvIdx : suffix.getEntryContainer().getVLVIndexes())
       {
         Transaction transaction = null;
         vlvIdx.addEntry(transaction, entryID, entry);
       }
-      Map<String, Collection<Index>> extensibleMap = attrIndex.getExtensibleIndexes();
-      if (!extensibleMap.isEmpty())
-      {
-        Collection<Index> subIndexes = extensibleMap.get(EXTENSIBLE_INDEXER_ID_SUBSTRING);
-        processAttributes(subIndexes, ImportIndexType.EX_SUBSTRING, entry, attrType, entryID, options);
-        Collection<Index> sharedIndexes = extensibleMap.get(EXTENSIBLE_INDEXER_ID_SHARED);
-        processAttributes(sharedIndexes, ImportIndexType.EX_SHARED, entry, attrType, entryID, options);
-      }
     }
 
-    private void processAttribute(Index index, ImportIndexType presence, Entry entry,
-        AttributeType attributeType, EntryID entryID, IndexingOptions options) throws InterruptedException
+    private void processAttribute(Index index, Entry entry, AttributeType attributeType, EntryID entryID)
+        throws InterruptedException
     {
       if (index != null)
       {
-        IndexKey indexKey = new IndexKey(attributeType, presence, index.getIndexEntryLimit());
-        processAttribute(index, entry, entryID, options, indexKey);
+        processAttribute(index, entry, entryID,
+            new IndexKey(attributeType, index.getName(), index.getIndexEntryLimit()));
       }
     }
 
-    private void processAttributes(Collection<Index> indexes, ImportIndexType indexType, Entry entry,
-        AttributeType attributeType, EntryID entryID, IndexingOptions options) throws InterruptedException
+    private void processAttributes(Collection<Index> indexes, Entry entry, AttributeType attributeType, EntryID entryID)
+        throws InterruptedException
     {
       if (indexes != null)
       {
         for (Index index : indexes)
         {
-          IndexKey indexKey = new IndexKey(attributeType, indexType, index.getIndexEntryLimit());
-          processAttribute(index, entry, entryID, options, indexKey);
+          processAttribute(index, entry, entryID,
+              new IndexKey(attributeType, index.getName(), index.getIndexEntryLimit()));
         }
       }
     }
 
-    void processAttribute(Index index, Entry entry, EntryID entryID, IndexingOptions options,
-        IndexKey indexKey) throws DatabaseException, InterruptedException
+    void processAttribute(Index index, Entry entry, EntryID entryID, IndexKey indexKey)
+        throws DatabaseException, InterruptedException
     {
       insertKeySet.clear();
-      index.indexEntry(entry, insertKeySet, options);
+      index.indexEntry(entry, insertKeySet);
       for (ByteString key : insertKeySet)
       {
         processKey(index, key.toByteArray(), entryID, indexKey, true);
@@ -2754,7 +2722,7 @@
         {
           return;
         }
-        boolean isDN2ID = ImportIndexType.DN.equals(indexKey.getIndexType());
+        boolean isDN2ID = ImportIndexType.DN.toString().equals(indexKey.getIndexName());
         IndexManager indexMgr = new IndexManager(indexKey.getName(), isDN2ID, indexKey.getEntryLimit());
         if (isDN2ID)
         {
@@ -3178,60 +3146,19 @@
         final AttributeType attrType, final boolean onlyDegraded)
         throws DatabaseException
     {
-      fillIndexMap(attrType, attrIndex.getSubstringIndex(), ImportIndexType.SUBSTRING, onlyDegraded);
-      fillIndexMap(attrType, attrIndex.getOrderingIndex(), ImportIndexType.ORDERING, onlyDegraded);
-      fillIndexMap(attrType, attrIndex.getEqualityIndex(), ImportIndexType.EQUALITY, onlyDegraded);
-      fillIndexMap(attrType, attrIndex.getPresenceIndex(), ImportIndexType.PRESENCE, onlyDegraded);
-      fillIndexMap(attrType, attrIndex.getApproximateIndex(), ImportIndexType.APPROXIMATE, onlyDegraded);
-
-      final Map<String, Collection<Index>> extensibleMap = attrIndex.getExtensibleIndexes();
-      if (!extensibleMap.isEmpty())
-      {
-        final Collection<Index> subIndexes = extensibleMap.get(EXTENSIBLE_INDEXER_ID_SUBSTRING);
-        fillIndexMap(attrType, subIndexes, ImportIndexType.EX_SUBSTRING, onlyDegraded);
-        final Collection<Index> sharedIndexes = extensibleMap.get(EXTENSIBLE_INDEXER_ID_SHARED);
-        fillIndexMap(attrType, sharedIndexes, ImportIndexType.EX_SHARED, onlyDegraded);
+      for(Index index : attrIndex.getAllIndexes()) {
+        fillIndexMap(attrType, index, onlyDegraded);
       }
     }
 
-    private void fillIndexMap(final AttributeType attrType, final Collection<Index> indexes,
-        final ImportIndexType importIndexType, final boolean onlyDegraded)
-    {
-      if (indexes != null && !indexes.isEmpty())
-      {
-        final List<Index> mutableCopy = new LinkedList<Index>(indexes);
-        for (final Iterator<Index> it = mutableCopy.iterator(); it.hasNext();)
-        {
-          final Index sharedIndex = it.next();
-          if (!onlyDegraded || !sharedIndex.isTrusted())
-          {
-            if (!rebuildConfig.isClearDegradedState() || sharedIndex.getRecordCount() == 0)
-            {
-              putInIdContainerMap(sharedIndex);
-            }
-          }
-          else
-          {
-            // This index is not a candidate for rebuilding.
-            it.remove();
-          }
-        }
-        if (!mutableCopy.isEmpty())
-        {
-          extensibleIndexMap.put(new IndexKey(attrType, importIndexType, 0), mutableCopy);
-        }
-      }
-    }
-
-    private void fillIndexMap(final AttributeType attrType, final Index index,
-        final ImportIndexType importIndexType, final boolean onlyDegraded)
+    private void fillIndexMap(final AttributeType attrType, final Index index, final boolean onlyDegraded)
     {
       if (index != null
           && (!onlyDegraded || !index.isTrusted())
           && (!rebuildConfig.isClearDegradedState() || index.getRecordCount() == 0))
       {
         putInIdContainerMap(index);
-        final IndexKey key = new IndexKey(attrType, importIndexType, index.getIndexEntryLimit());
+        final IndexKey key = new IndexKey(attrType, index.getName(), index.getIndexEntryLimit());
         indexMap.put(key, index);
       }
     }
@@ -3588,11 +3515,9 @@
         AttributeType attrType = key.getAttributeType();
         if (entry.hasAttribute(attrType))
         {
-          AttributeIndex attributeIndex = entryContainer.getAttributeIndex(attrType);
-          IndexingOptions options = attributeIndex.getIndexingOptions();
           for (Index index : mapEntry.getValue())
           {
-            processAttribute(index, entry, entryID, options, key);
+            processAttribute(index, entry, entryID, key);
           }
         }
       }
@@ -3607,10 +3532,7 @@
         AttributeType attrType = key.getAttributeType();
         if (entry.hasAttribute(attrType))
         {
-          AttributeIndex attributeIndex = entryContainer.getAttributeIndex(attrType);
-          IndexingOptions options = attributeIndex.getIndexingOptions();
-          Index index = mapEntry.getValue();
-          processAttribute(index, entry, entryID, options, key);
+          processAttribute(mapEntry.getValue(), entry, entryID, key);
         }
       }
     }
@@ -4045,7 +3967,7 @@
   {
 
     private final AttributeType attributeType;
-    private final ImportIndexType indexType;
+    private final String indexName;
     private final int entryLimit;
 
     /**
@@ -4059,10 +3981,10 @@
      * @param entryLimit
      *          The entry limit for the index.
      */
-    private IndexKey(AttributeType attributeType, ImportIndexType indexType, int entryLimit)
+    private IndexKey(AttributeType attributeType, String indexName, int entryLimit)
     {
       this.attributeType = attributeType;
-      this.indexType = indexType;
+      this.indexName = indexName;
       this.entryLimit = entryLimit;
     }
 
@@ -4082,7 +4004,7 @@
       {
         IndexKey oKey = (IndexKey) obj;
         if (attributeType.equals(oKey.getAttributeType())
-            && indexType.equals(oKey.getIndexType()))
+            && indexName.equals(oKey.indexName))
         {
           return true;
         }
@@ -4100,7 +4022,7 @@
     @Override
     public int hashCode()
     {
-      return attributeType.hashCode() + indexType.hashCode();
+      return attributeType.hashCode() + indexName.hashCode();
     }
 
     /**
@@ -4118,9 +4040,9 @@
      *
      * @return The index type.
      */
-    public ImportIndexType getIndexType()
+    public String getIndexName()
     {
-      return indexType;
+      return indexName;
     }
 
     /**
@@ -4133,7 +4055,7 @@
     public String getName()
     {
       return attributeType.getPrimaryName() + "."
-          + StaticUtils.toLowerCase(indexType.name());
+          + StaticUtils.toLowerCase(indexName);
     }
 
     /**
@@ -4151,7 +4073,7 @@
     public String toString()
     {
       return getClass().getSimpleName()
-          + "(index=" + attributeType.getNameOrOID() + "." + indexType
+          + "(index=" + attributeType.getNameOrOID() + "." + indexName
           + ", entryLimit=" + entryLimit
           + ")";
     }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Index.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Index.java
index ef5afd2..e3fe279 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Index.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Index.java
@@ -35,7 +35,6 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.backends.jeb.IndexBuffer.BufferedIndexValues;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
@@ -140,9 +139,9 @@
     }
   }
 
-  void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options)
+  void indexEntry(Entry entry, Set<ByteString> keys)
   {
-    indexer.indexEntry(entry, keys, options);
+    indexer.indexEntry(entry, keys);
   }
 
   /**
@@ -684,15 +683,13 @@
    * @param buffer The index buffer to use to store the deleted keys
    * @param entryID     The entry ID.
    * @param entry       The entry to be indexed.
-   * @param options     The indexing options to use
    * @throws DatabaseException If an error occurs in the JE database.
    * @throws DirectoryException If a Directory Server error occurs.
    */
-  public void addEntry(IndexBuffer buffer, EntryID entryID, Entry entry,
-      IndexingOptions options) throws DatabaseException, DirectoryException
+  public void addEntry(IndexBuffer buffer, EntryID entryID, Entry entry) throws DatabaseException, DirectoryException
   {
-    HashSet<ByteString> addKeys = new HashSet<ByteString>();
-    indexer.indexEntry(entry, addKeys, options);
+    final Set<ByteString> addKeys = new HashSet<>();
+    indexer.indexEntry(entry, addKeys);
 
     for (ByteString keyBytes : addKeys)
     {
@@ -706,15 +703,14 @@
    * @param buffer The index buffer to use to store the deleted keys
    * @param entryID     The entry ID
    * @param entry       The contents of the deleted entry.
-   * @param options     The indexing options to use
    * @throws DatabaseException If an error occurs in the JE database.
    * @throws DirectoryException If a Directory Server error occurs.
    */
-  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry,
-      IndexingOptions options) throws DatabaseException, DirectoryException
+  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
+      throws DatabaseException, DirectoryException
   {
-    HashSet<ByteString> delKeys = new HashSet<ByteString>();
-    indexer.indexEntry(entry, delKeys, options);
+    final Set<ByteString> delKeys = new HashSet<>();
+    indexer.indexEntry(entry, delKeys);
 
     for (ByteString keyBytes : delKeys)
     {
@@ -731,19 +727,17 @@
    * @param oldEntry The entry before the modifications were applied.
    * @param newEntry The entry after the modifications were applied.
    * @param mods The sequence of modifications in the Modify operation.
-   * @param options The indexing options to use
    * @throws DatabaseException If an error occurs in the JE database.
    */
   public void modifyEntry(IndexBuffer buffer,
                           EntryID entryID,
                           Entry oldEntry,
                           Entry newEntry,
-                          List<Modification> mods, IndexingOptions options)
+                          List<Modification> mods)
       throws DatabaseException
   {
-    TreeMap<ByteString, Boolean> modifiedKeys =
-        new TreeMap<ByteString, Boolean>(indexer.getBSComparator());
-    indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys, options);
+    final Map<ByteString, Boolean> modifiedKeys = new TreeMap<ByteString, Boolean>(indexer.getBSComparator());
+    indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys);
 
     for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet())
     {
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Indexer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Indexer.java
index aff72aa..d2a39ed 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Indexer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Indexer.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
- *      Portions copyright 2012-2014 ForgeRock AS.
+ *      Portions copyright 2012-2015 ForgeRock AS.
  */
 package org.opends.server.backends.jeb;
 
@@ -33,7 +33,6 @@
 
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.backends.jeb.AttributeIndex.KeyComparator;
 import org.opends.server.types.Entry;
 import org.opends.server.types.Modification;
@@ -71,9 +70,8 @@
    *
    * @param entry The entry.
    * @param keys The set into which the generated keys will be inserted.
-   * @param options The indexing options to use
    */
-  public abstract void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options);
+  public abstract void indexEntry(Entry entry, Set<ByteString> keys);
 
   /**
    * Generate the set of index keys to be added and the set of index keys
@@ -83,11 +81,9 @@
    * @param newEntry The new entry contents.
    * @param mods The set of modifications that were applied to the entry.
    * @param modifiedKeys The map into which the modified keys will be inserted.
-   * @param options The indexing options to use
    */
   public abstract void modifyEntry(Entry oldEntry, Entry newEntry,
-      List<Modification> mods, Map<ByteString, Boolean> modifiedKeys,
-      IndexingOptions options);
+      List<Modification> mods, Map<ByteString, Boolean> modifiedKeys);
 
   /**
    * Get a string representation of this object.  The returned value is
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/NullIndex.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/NullIndex.java
index 4d57aac..c41a83b 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/NullIndex.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/NullIndex.java
@@ -28,7 +28,6 @@
 
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
 import org.opends.server.types.Modification;
@@ -131,7 +130,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void addEntry(IndexBuffer buffer, EntryID entryID, Entry entry, IndexingOptions options)
+  public void addEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
   {
     // Do nothing.
@@ -139,7 +138,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry, IndexingOptions options)
+  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
   {
     // Do nothing.
@@ -147,8 +146,8 @@
 
   /** {@inheritDoc} */
   @Override
-  public void modifyEntry(IndexBuffer buffer, EntryID entryID, Entry oldEntry, Entry newEntry, List<Modification> mods,
-      IndexingOptions options) throws DatabaseException
+  public void modifyEntry(IndexBuffer buffer, EntryID entryID, Entry oldEntry, Entry newEntry, List<Modification> mods)
+      throws DatabaseException
   {
     // Do nothing.
   }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/PresenceIndexer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/PresenceIndexer.java
index 6b3c117..d47f304 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/PresenceIndexer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/PresenceIndexer.java
@@ -31,7 +31,6 @@
 import java.util.Set;
 
 import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeType;
 import org.opends.server.types.Entry;
@@ -70,7 +69,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options)
+  public void indexEntry(Entry entry, Set<ByteString> keys)
   {
     List<Attribute> attrList = entry.getAttribute(attributeType);
     if (attrList != null && !attrList.isEmpty())
@@ -83,7 +82,7 @@
   @Override
   public void modifyEntry(Entry oldEntry, Entry newEntry,
                           List<Modification> mods,
-                          Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
+                          Map<ByteString, Boolean> modifiedKeys)
   {
     List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
     List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Suffix.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Suffix.java
index 06fed80..cff5632 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Suffix.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/Suffix.java
@@ -266,19 +266,13 @@
     entryContainer.getID2Subtree().setTrusted(null, trusted);
     for (AttributeIndex attributeIndex : entryContainer.getAttributeIndexes())
     {
-      setTrusted(attributeIndex.getEqualityIndex(), trusted);
-      setTrusted(attributeIndex.getPresenceIndex(), trusted);
-      setTrusted(attributeIndex.getSubstringIndex(), trusted);
-      setTrusted(attributeIndex.getOrderingIndex(), trusted);
-      setTrusted(attributeIndex.getApproximateIndex(), trusted);
-      Map<String, Collection<Index>> exIndexes = attributeIndex.getExtensibleIndexes();
-      if(!exIndexes.isEmpty())
+      for (Index index : attributeIndex.getAllIndexes())
       {
-        setTrusted(exIndexes.get(EXTENSIBLE_INDEXER_ID_SUBSTRING), trusted);
-        setTrusted(exIndexes.get(EXTENSIBLE_INDEXER_ID_SHARED), trusted);
+        setTrusted(index, trusted);
       }
     }
-    for(VLVIndex vlvIdx : entryContainer.getVLVIndexes()) {
+    for (VLVIndex vlvIdx : entryContainer.getVLVIndexes())
+    {
       vlvIdx.setTrusted(null, trusted);
     }
   }
@@ -291,17 +285,6 @@
     }
   }
 
-  private void setTrusted(Collection<Index> subIndexes, boolean trusted)
-  {
-    if (subIndexes != null)
-    {
-      for (Index subIndex : subIndexes)
-      {
-        subIndex.setTrusted(null, trusted);
-      }
-    }
-  }
-
   /**
    * Return a src entry container.
    *
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/VerifyJob.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/VerifyJob.java
index d758e20..2e6adc1 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/VerifyJob.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/VerifyJob.java
@@ -38,7 +38,6 @@
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.backends.VerifyConfig;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.*;
@@ -436,14 +435,10 @@
     }
     else if (attrIndexList.size() > 0)
     {
-      AttributeIndex attrIndex = attrIndexList.get(0);
-      final IndexingOptions options = attrIndex.getIndexingOptions();
-      iterateAttrIndex(attrIndex.getEqualityIndex(), options);
-      iterateAttrIndex(attrIndex.getPresenceIndex(), options);
-      iterateAttrIndex(attrIndex.getSubstringIndex(), options);
-      iterateAttrIndex(attrIndex.getOrderingIndex(), options);
-      iterateAttrIndex(attrIndex.getApproximateIndex(), options);
-     // TODO: Need to iterate through ExtendedMatchingRules indexes.
+      for (Index index : attrIndexList.get(0).getAllIndexes())
+      {
+        iterateAttrIndex(index);
+      }
     }
     else if (vlvIndexList.size() > 0)
     {
@@ -962,8 +957,7 @@
    * @throws JebException If an error occurs in the JE backend.
    * @throws DatabaseException If an error occurs in the JE database.
    */
-  private void iterateAttrIndex(Index index, IndexingOptions options)
-      throws JebException, DatabaseException
+  private void iterateAttrIndex(Index index) throws JebException, DatabaseException
   {
     if (index == null)
     {
@@ -1078,7 +1072,7 @@
 
             };
 
-            index.indexEntry(entry, dummySet, options);
+            index.indexEntry(entry, dummySet);
 
             if (!foundMatchingKey.get())
             {
@@ -1386,12 +1380,7 @@
     {
       try
       {
-        List<Attribute> attrList =
-             entry.getAttribute(attrIndex.getAttributeType());
-        if (attrList != null)
-        {
-          verifyAttribute(attrIndex, entryID, attrList);
-        }
+        verifyAttribute(attrIndex, entryID, entry);
       }
       catch (DirectoryException e)
       {
@@ -1462,86 +1451,37 @@
    * @param attrList The attribute to be checked.
    * @throws DirectoryException If a Directory Server error occurs.
    */
-  private void verifyAttribute(AttributeIndex attrIndex, EntryID entryID,
-                              List<Attribute> attrList)
-       throws DirectoryException
+  private void verifyAttribute(AttributeIndex attrIndex, EntryID entryID, Entry entry) throws DirectoryException
   {
-    if (attrList == null || attrList.isEmpty())
+    for (Index index : attrIndex.getAllIndexes())
     {
-      return;
-    }
-
-    Transaction txn = null;
-    Index equalityIndex = attrIndex.getEqualityIndex();
-    Index presenceIndex = attrIndex.getPresenceIndex();
-    Index substringIndex = attrIndex.getSubstringIndex();
-    Index orderingIndex = attrIndex.getOrderingIndex();
-    Index approximateIndex = attrIndex.getApproximateIndex();
-    // TODO: Add support for Extended Matching Rules indexes.
-
-    if (presenceIndex != null)
-    {
-      verifyAttributeInIndex(presenceIndex, txn, JEBUtils.presenceKey, entryID);
-    }
-
-    final DatabaseEntry key = new DatabaseEntry();
-    for (Attribute attr : attrList)
-    {
-      final AttributeType attrType = attr.getAttributeType();
-      MatchingRule equalityRule = attrType.getEqualityMatchingRule();
-      for (ByteString value : attr)
+      final Set<ByteString> keys = new HashSet<>();
+      index.indexEntry(entry, keys);
+      for (ByteString key : keys)
       {
-        byte[] normalizedBytes = normalize(equalityRule, value);
-
-        if (equalityIndex != null)
-        {
-          key.setData(normalizedBytes);
-          verifyAttributeInIndex(equalityIndex, txn, key, entryID);
-        }
-
-        if (substringIndex != null)
-        {
-          for (ByteString keyBytes : attrIndex.substringKeys(normalizedBytes))
-          {
-            key.setData(keyBytes.toByteArray());
-            verifyAttributeInIndex(substringIndex, txn, key, entryID);
-          }
-        }
-
-        if (orderingIndex != null)
-        {
-          key.setData(normalize(attrType.getOrderingMatchingRule(), value));
-          verifyAttributeInIndex(orderingIndex, txn, key, entryID);
-        }
-
-        if (approximateIndex != null)
-        {
-          key.setData(normalize(attrType.getApproximateMatchingRule(), value));
-          verifyAttributeInIndex(approximateIndex, txn, key, entryID);
-        }
+        verifyAttributeInIndex(index, null, key, entryID);
       }
     }
   }
 
-  private void verifyAttributeInIndex(Index index, Transaction txn,
-      DatabaseEntry key, EntryID entryID)
+  private void verifyAttributeInIndex(Index index, Transaction txn, ByteString key, EntryID entryID)
   {
     try
     {
-      ConditionResult cr = index.containsID(txn, key, entryID);
+      final ConditionResult cr = index.containsID(txn, new DatabaseEntry(key.toByteArray()), entryID);
       if (cr == ConditionResult.FALSE)
       {
         if (logger.isTraceEnabled())
         {
           logger.trace("Missing ID %d%n%s",
                      entryID.longValue(),
-                     keyDump(index, key.getData()));
+                     keyDump(index, key.toByteArray()));
         }
         errorCount++;
       }
       else if (cr == ConditionResult.UNDEFINED)
       {
-        incrEntryLimitStats(index, key.getData());
+        incrEntryLimitStats(index, key.toByteArray());
       }
     }
     catch (DatabaseException e)
@@ -1552,7 +1492,7 @@
 
         logger.trace("Error reading database: %s%n%s",
                    e.getMessage(),
-                   keyDump(index, key.getData()));
+                   keyDump(index, key.toByteArray()));
       }
       errorCount++;
     }
@@ -1640,12 +1580,10 @@
         {
           AttributeIndex attrIndex = attrIndexList.get(0);
           totalCount = 0;
-          totalCount += getRecordCount(attrIndex.getEqualityIndex());
-          totalCount += getRecordCount(attrIndex.getPresenceIndex());
-          totalCount += getRecordCount(attrIndex.getSubstringIndex());
-          totalCount += getRecordCount(attrIndex.getOrderingIndex());
-          totalCount += getRecordCount(attrIndex.getApproximateIndex());
-          // TODO: Add support for Extended Matching Rules indexes.
+          for (Index index : attrIndex.getAllIndexes())
+          {
+            totalCount += getRecordCount(index);
+          }
         }
         else if (vlvIndexList.size() > 0)
         {
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AbstractTree.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AbstractTree.java
index 735e99c..d246222 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AbstractTree.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AbstractTree.java
@@ -55,7 +55,7 @@
   /**
    * Override in order to perform any additional initialization after the index has opened.
    */
-  void open0(ReadableTransaction txn) throws StorageRuntimeException
+  void open0(WriteableTransaction txn) throws StorageRuntimeException
   {
     // Do nothing by default.
   }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java
index cd1d4b6..bb70938 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java
@@ -111,36 +111,35 @@
   /**
    * This class implements an attribute indexer for matching rules in a Backend.
    */
-  final class MatchingRuleIndex extends DefaultIndex
+  static final class MatchingRuleIndex extends DefaultIndex
   {
-    /**
-     * The matching rule's indexer.
-     */
+    private final AttributeType attributeType;
     private final Indexer indexer;
 
-    private MatchingRuleIndex(WriteableTransaction txn, BackendIndexCfg cfg, Indexer indexer)
+    private MatchingRuleIndex(EntryContainer entryContainer, AttributeType attributeType, State state, Indexer indexer,
+        int indexEntryLimit)
     {
-      super(getIndexName(attributeType, indexer.getIndexID()), state, cfg.getIndexEntryLimit(), txn, entryContainer);
+      super(getIndexName(entryContainer, attributeType, indexer.getIndexID()), state, indexEntryLimit, entryContainer);
+      this.attributeType = attributeType;
       this.indexer = indexer;
     }
 
-    void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options)
+    void indexEntry(Entry entry, Set<ByteString> keys)
     {
       List<Attribute> attributes = entry.getAttribute(attributeType, true);
       if (attributes != null)
       {
-        indexAttribute(attributes, keys, options);
+        indexAttribute(attributes, keys);
       }
     }
 
-    private void modifyEntry(Entry oldEntry, Entry newEntry, Map<ByteString, Boolean> modifiedKeys,
-        IndexingOptions options)
+    private void modifyEntry(Entry oldEntry, Entry newEntry, Map<ByteString, Boolean> modifiedKeys)
     {
       List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
       if (oldAttributes != null)
       {
         final Set<ByteString> keys = new HashSet<ByteString>();
-        indexAttribute(oldAttributes, keys, options);
+        indexAttribute(oldAttributes, keys);
         for (ByteString key : keys)
         {
           modifiedKeys.put(key, false);
@@ -151,7 +150,7 @@
       if (newAttributes != null)
       {
         final Set<ByteString> keys = new HashSet<ByteString>();
-        indexAttribute(newAttributes, keys, options);
+        indexAttribute(newAttributes, keys);
         for (ByteString key : keys)
         {
           final Boolean needsAdding = modifiedKeys.get(key);
@@ -169,7 +168,7 @@
       }
     }
 
-    private void indexAttribute(List<Attribute> attributes, Set<ByteString> keys, IndexingOptions options)
+    private void indexAttribute(List<Attribute> attributes, Set<ByteString> keys)
     {
       for (Attribute attr : attributes)
       {
@@ -179,7 +178,7 @@
           {
             try
             {
-              indexer.createKeys(Schema.getDefaultSchema(), value, options, keys);
+              indexer.createKeys(Schema.getDefaultSchema(), value, keys);
 
               /*
                * Optimization for presence: return immediately after first value since all values
@@ -209,8 +208,7 @@
   private static final Indexer PRESENCE_INDEXER = new Indexer()
   {
     @Override
-    public void createKeys(Schema schema, ByteSequence value, IndexingOptions options, Collection<ByteString> keys)
-        throws DecodeException
+    public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) throws DecodeException
     {
       keys.add(PRESENCE_KEY);
     }
@@ -235,118 +233,113 @@
   private BackendIndexCfg config;
 
   /** The mapping from names to indexes. */
-  private final Map<String, MatchingRuleIndex> nameToIndexes = new HashMap<String, MatchingRuleIndex>();
-  private final IndexingOptions indexingOptions;
+  private Map<String, MatchingRuleIndex> indexIdToIndexes;
+  private IndexingOptions indexingOptions;
   private final State state;
 
-  /** The attribute type for which this instance will generate index keys. */
-  private final AttributeType attributeType;
-
-  AttributeIndex(BackendIndexCfg config, State state, EntryContainer entryContainer, WriteableTransaction txn)
-      throws ConfigException
+  AttributeIndex(BackendIndexCfg config, State state, EntryContainer entryContainer) throws ConfigException
   {
     this.entryContainer = entryContainer;
     this.config = config;
     this.state = state;
-    this.attributeType = config.getAttribute();
-
-    buildPresenceIndex(txn);
-    buildIndexes(txn, IndexType.EQUALITY);
-    buildIndexes(txn, IndexType.SUBSTRING);
-    buildIndexes(txn, IndexType.ORDERING);
-    buildIndexes(txn, IndexType.APPROXIMATE);
-    buildExtensibleIndexes(txn);
-
-    indexingOptions = new IndexingOptionsImpl(config.getSubstringLength());
+    this.indexingOptions = new IndexingOptionsImpl(config.getSubstringLength());
+    this.indexIdToIndexes = Collections.unmodifiableMap(buildIndexes(entryContainer, state, config));
   }
 
-  private void buildPresenceIndex(WriteableTransaction txn)
+  private static Map<String, MatchingRuleIndex> buildIndexes(EntryContainer entryContainer, State state,
+      BackendIndexCfg config) throws ConfigException
   {
-    final IndexType indexType = IndexType.PRESENCE;
-    if (config.getIndexType().contains(indexType))
-    {
-      String indexID = indexType.toString();
-      nameToIndexes.put(indexID, new MatchingRuleIndex(txn, config, PRESENCE_INDEXER));
-    }
-  }
+    final AttributeType attributeType = config.getAttribute();
+    final int indexEntryLimit = config.getIndexEntryLimit();
+    final IndexingOptions indexingOptions = new IndexingOptionsImpl(config.getSubstringLength());
 
-  private void buildExtensibleIndexes(WriteableTransaction txn) throws ConfigException
-  {
-    final IndexType indexType = IndexType.EXTENSIBLE;
-    if (config.getIndexType().contains(indexType))
-    {
-      final AttributeType attrType = config.getAttribute();
-      Set<String> extensibleRules = config.getIndexExtensibleMatchingRule();
-      if (extensibleRules == null || extensibleRules.isEmpty())
+    final Map<String, MatchingRuleIndex> indexes = new HashMap<>();
+
+    for(IndexType indexType : config.getIndexType()) {
+      Collection<? extends Indexer> indexers;
+      switch (indexType)
       {
-        throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexType.toString()));
+      case PRESENCE:
+        indexers = Collections.singleton(PRESENCE_INDEXER);
+        break;
+      case EXTENSIBLE:
+        indexers =
+            getExtensibleIndexers(config.getAttribute(), config.getIndexExtensibleMatchingRule(), indexingOptions);
+        break;
+      case APPROXIMATE:
+        indexers =
+            throwIfNoMatchingRule(attributeType, indexType, attributeType.getApproximateMatchingRule()).createIndexers(
+                indexingOptions);
+        break;
+      case EQUALITY:
+        indexers =
+            throwIfNoMatchingRule(attributeType, indexType, attributeType.getEqualityMatchingRule()).createIndexers(
+                indexingOptions);
+        break;
+      case ORDERING:
+        indexers =
+            throwIfNoMatchingRule(attributeType, indexType, attributeType.getOrderingMatchingRule()).createIndexers(
+                indexingOptions);
+        break;
+      case SUBSTRING:
+        indexers =
+            throwIfNoMatchingRule(attributeType, indexType, attributeType.getSubstringMatchingRule()).createIndexers(
+                indexingOptions);
+        break;
+      default:
+       throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, indexType.toString()));
       }
+      buildIndexesForIndexers(entryContainer, attributeType, state, indexes, indexEntryLimit, indexers);
+    }
+    return indexes;
+  }
 
-      // 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 (final String ruleName : extensibleRules)
+  private static MatchingRule throwIfNoMatchingRule(AttributeType attributeType, IndexType type, MatchingRule rule)
+      throws ConfigException
+  {
+    if (rule == null)
+    {
+      throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, type.toString()));
+    }
+    return rule;
+  }
+
+  private static void buildIndexesForIndexers(EntryContainer entryContainer, AttributeType attributeType, State state,
+      Map<String, MatchingRuleIndex> indexes, int indexEntryLimit, Collection<? extends Indexer> indexers)
+  {
+    for (Indexer indexer : indexers)
+    {
+      final String indexID = indexer.getIndexID();
+      if (!indexes.containsKey(indexID))
       {
-        MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
-        if (rule == null)
-        {
-          logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
-          continue;
-        }
-        for (Indexer indexer : rule.getIndexers())
-        {
-          final String indexId = indexer.getIndexID();
-          if (!nameToIndexes.containsKey(indexId))
-          {
-            // There is no index available for this index id. Create a new index
-            nameToIndexes.put(indexId, new MatchingRuleIndex(txn, config, indexer));
-          }
-        }
+        indexes.put(indexID, new MatchingRuleIndex(entryContainer, attributeType, state, indexer, indexEntryLimit));
       }
     }
   }
 
-  private void buildIndexes(WriteableTransaction txn, IndexType indexType) throws ConfigException
+  private static Collection<Indexer> getExtensibleIndexers(AttributeType attributeType, Set<String> extensibleRules,
+      IndexingOptions options) throws ConfigException
   {
-    if (config.getIndexType().contains(indexType))
+    if (extensibleRules == null || extensibleRules.isEmpty())
     {
-      final AttributeType attrType = config.getAttribute();
-      final String indexID = indexType.toString();
-      final MatchingRule rule = getMatchingRule(indexType, attrType);
-      if (rule == null)
-      {
-        throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexID));
-      }
-
-      for (Indexer indexer : rule.getIndexers())
-      {
-        nameToIndexes.put(indexer.getIndexID(), new MatchingRuleIndex(txn, config, indexer));
-      }
+      throw new ConfigException(
+          ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, IndexType.EXTENSIBLE.toString()));
     }
+
+    final Collection<Indexer> indexers = new ArrayList<>();
+    for (final String ruleName : extensibleRules)
+    {
+      final MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
+      throwIfNoMatchingRule(attributeType, IndexType.EXTENSIBLE, rule);
+      indexers.addAll(rule.createIndexers(options));
+    }
+
+    return indexers;
   }
 
-  private MatchingRule getMatchingRule(IndexType indexType, AttributeType attrType)
+  private static TreeName getIndexName(EntryContainer entryContainer, AttributeType attrType, String indexID)
   {
-    switch (indexType)
-    {
-    case APPROXIMATE:
-      return attrType.getApproximateMatchingRule();
-    case EQUALITY:
-      return attrType.getEqualityMatchingRule();
-    case ORDERING:
-      return attrType.getOrderingMatchingRule();
-    case SUBSTRING:
-      return attrType.getSubstringMatchingRule();
-    default:
-      throw new IllegalArgumentException("Not implemented for index type " + indexType);
-    }
-  }
-
-  private TreeName getIndexName(AttributeType attrType, String indexID)
-  {
-    final String attrIndexId = attrType.getNameOrOID() + "." + indexID;
-    return new TreeName(entryContainer.getTreePrefix(), attrIndexId);
+    return new TreeName(entryContainer.getTreePrefix(), attrType.getNameOrOID() + "." + indexID);
   }
 
   /**
@@ -357,7 +350,7 @@
    */
   void open(WriteableTransaction txn) throws StorageRuntimeException
   {
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
       index.open(txn);
     }
@@ -436,10 +429,10 @@
    */
   void addEntry(IndexBuffer buffer, EntryID entryID, Entry entry) throws StorageRuntimeException, DirectoryException
   {
-    for (MatchingRuleIndex index : nameToIndexes.values())
+    for (MatchingRuleIndex index : indexIdToIndexes.values())
     {
-      HashSet<ByteString> keys = new HashSet<ByteString>();
-      index.indexEntry(entry, keys, indexingOptions);
+      final Set<ByteString> keys = new HashSet<>();
+      index.indexEntry(entry, keys);
       for (ByteString key : keys)
       {
         buffer.put(index, key, entryID);
@@ -458,10 +451,10 @@
    */
   void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry) throws StorageRuntimeException, DirectoryException
   {
-    for (MatchingRuleIndex index : nameToIndexes.values())
+    for (MatchingRuleIndex index : indexIdToIndexes.values())
     {
       HashSet<ByteString> keys = new HashSet<ByteString>();
-      index.indexEntry(entry, keys, indexingOptions);
+      index.indexEntry(entry, keys);
       for (ByteString key : keys)
       {
         buffer.remove(index, key, entryID);
@@ -482,10 +475,10 @@
    */
   void modifyEntry(IndexBuffer buffer, EntryID entryID, Entry oldEntry, Entry newEntry) throws StorageRuntimeException
   {
-    for (MatchingRuleIndex index : nameToIndexes.values())
+    for (MatchingRuleIndex index : indexIdToIndexes.values())
     {
       TreeMap<ByteString, Boolean> modifiedKeys = new TreeMap<ByteString, Boolean>();
-      index.modifyEntry(oldEntry, newEntry, modifiedKeys, indexingOptions);
+      index.modifyEntry(oldEntry, newEntry, modifiedKeys);
       for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet())
       {
         if (modifiedKey.getValue())
@@ -694,226 +687,143 @@
     return true;
   }
 
-  private boolean isIndexAcceptable(BackendIndexCfg cfg, IndexType indexType,
+  private static boolean isIndexAcceptable(BackendIndexCfg cfg, IndexType indexType,
       List<LocalizableMessage> unacceptableReasons)
   {
-    final String indexId = indexType.toString();
     final AttributeType attrType = cfg.getAttribute();
     if (cfg.getIndexType().contains(indexType)
-        && nameToIndexes.get(indexId) == null
         && getMatchingRule(indexType, attrType) == null)
     {
-      unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexId));
+      unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexType));
       return false;
     }
     return true;
   }
 
+  private static MatchingRule getMatchingRule(IndexType indexType, AttributeType attrType)
+  {
+    switch (indexType)
+    {
+    case APPROXIMATE:
+      return attrType.getApproximateMatchingRule();
+    case EQUALITY:
+      return attrType.getEqualityMatchingRule();
+    case ORDERING:
+      return attrType.getOrderingMatchingRule();
+    case SUBSTRING:
+      return attrType.getSubstringMatchingRule();
+    default:
+      throw new IllegalArgumentException("Not implemented for index type " + indexType);
+    }
+  }
+
   /** {@inheritDoc} */
   @Override
-  public synchronized ConfigChangeResult applyConfigurationChange(final BackendIndexCfg cfg)
+  public synchronized ConfigChangeResult applyConfigurationChange(final BackendIndexCfg newConfiguration)
   {
     final ConfigChangeResult ccr = new ConfigChangeResult();
+    final IndexingOptions newIndexingOptions = new IndexingOptionsImpl(newConfiguration.getSubstringLength());
     try
     {
+      final Map<String, MatchingRuleIndex> newIndexIdToIndexes = buildIndexes(entryContainer, state, newConfiguration);
+
+      final Map<String, MatchingRuleIndex> removedIndexes = new HashMap<>(indexIdToIndexes);
+      removedIndexes.keySet().removeAll(newIndexIdToIndexes.keySet());
+
+      final Map<String, MatchingRuleIndex> addedIndexes = new HashMap<>(newIndexIdToIndexes);
+      addedIndexes.keySet().removeAll(indexIdToIndexes.keySet());
+
+      final Map<String, MatchingRuleIndex> updatedIndexes = new HashMap<>(indexIdToIndexes);
+      updatedIndexes.keySet().retainAll(newIndexIdToIndexes.keySet());
+
+      // Replace instances of Index created by buildIndexes() with the one already opened and present in the actual
+      // indexIdToIndexes
+      newIndexIdToIndexes.putAll(updatedIndexes);
+
+      // Open added indexes *before* adding them to indexIdToIndexes
       entryContainer.getRootContainer().getStorage().write(new WriteOperation()
       {
         @Override
         public void run(WriteableTransaction txn) throws Exception
         {
-          applyChangeToIndex(txn, IndexType.PRESENCE, cfg, ccr);
-          applyChangeToIndex(txn, IndexType.EQUALITY, cfg, ccr);
-          applyChangeToIndex(txn, IndexType.SUBSTRING, cfg, ccr);
-          applyChangeToIndex(txn, IndexType.ORDERING, cfg, ccr);
-          applyChangeToIndex(txn, IndexType.APPROXIMATE, cfg, ccr);
-          applyChangeToExtensibleIndexes(txn, cfg, ccr);
+          for (MatchingRuleIndex addedIndex : addedIndexes.values())
+          {
+            openIndex(txn, addedIndex, ccr);
+          }
         }
       });
 
-      config = cfg;
+      config = newConfiguration;
+      indexingOptions = newIndexingOptions;
+      indexIdToIndexes = Collections.unmodifiableMap(newIndexIdToIndexes);
+
+      // We get exclusive lock to ensure that no query is actually using the indexes that will be deleted.
+      entryContainer.lock();
+      try
+      {
+        entryContainer.getRootContainer().getStorage().write(new WriteOperation()
+        {
+          @Override
+          public void run(WriteableTransaction txn) throws Exception
+          {
+            for (MatchingRuleIndex removedIndex : removedIndexes.values())
+            {
+              deleteIndex(txn, entryContainer, removedIndex);
+            }
+          }
+        });
+      }
+      finally
+      {
+        entryContainer.unlock();
+      }
+
+      for (Index updatedIndex : updatedIndexes.values())
+      {
+        updateIndex(updatedIndex, newConfiguration.getIndexEntryLimit(), ccr);
+      }
+
     }
-    catch(Exception e)
+    catch (Exception e)
     {
       ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
       ccr.addMessage(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e)));
     }
+
     return ccr;
   }
 
-  private void applyChangeToExtensibleIndexes(WriteableTransaction txn, BackendIndexCfg cfg, ConfigChangeResult ccr)
+  private static void openIndex(WriteableTransaction txn, MatchingRuleIndex index, ConfigChangeResult ccr)
   {
-    final AttributeType attrType = cfg.getAttribute();
-    if (!cfg.getIndexType().contains(IndexType.EXTENSIBLE))
-    {
-      final Set<MatchingRule> validRules = Collections.emptySet();
-      final Set<String> validIndexIds = Collections.emptySet();
-      removeIndexesForExtensibleMatchingRules(txn, validRules, validIndexIds);
-      return;
-    }
-
-    final Set<String> extensibleRules = cfg.getIndexExtensibleMatchingRule();
-    final Set<MatchingRule> validRules = new HashSet<MatchingRule>();
-    final Set<String> validIndexIds = new HashSet<String>();
-    final int indexEntryLimit = cfg.getIndexEntryLimit();
-
-    for (String ruleName : extensibleRules)
-    {
-      MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
-      if (rule == null)
-      {
-        logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
-        continue;
-      }
-      validRules.add(rule);
-      for (Indexer indexer : rule.getIndexers())
-      {
-        String indexId = indexer.getIndexID();
-        validIndexIds.add(indexId);
-        if (!nameToIndexes.containsKey(indexId))
-        {
-          nameToIndexes.put(indexId, openNewIndex(txn, cfg, indexer, ccr));
-        }
-        else
-        {
-          Index index = nameToIndexes.get(indexId);
-          if (index.setIndexEntryLimit(indexEntryLimit))
-          {
-            ccr.setAdminActionRequired(true);
-            ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(index.getName()));
-          }
-        }
-      }
-    }
-    removeIndexesForExtensibleMatchingRules(txn, validRules, validIndexIds);
-  }
-
-  /** Remove indexes which do not correspond to valid rules. */
-  private void removeIndexesForExtensibleMatchingRules(WriteableTransaction txn, Set<MatchingRule> validRules,
-      Set<String> validIndexIds)
-  {
-    final Set<MatchingRule> rulesToDelete = getCurrentExtensibleMatchingRules();
-    rulesToDelete.removeAll(validRules);
-    if (!rulesToDelete.isEmpty())
-    {
-      entryContainer.exclusiveLock.lock();
-      try
-      {
-        for (MatchingRule rule: rulesToDelete)
-        {
-          final List<String> indexIdsToRemove = new ArrayList<String>();
-          for (Indexer indexer : rule.getIndexers())
-          {
-            final String indexId = indexer.getIndexID();
-            if (!validIndexIds.contains(indexId))
-            {
-              indexIdsToRemove.add(indexId);
-            }
-          }
-          // Delete indexes which are not used
-          for (String indexId : indexIdsToRemove)
-          {
-            Index index = nameToIndexes.get(indexId);
-            if (index != null)
-            {
-              entryContainer.deleteTree(txn, index);
-              nameToIndexes.remove(index);
-            }
-          }
-        }
-      }
-      finally
-      {
-        entryContainer.exclusiveLock.unlock();
-      }
-    }
-  }
-
-  private Set<MatchingRule> getCurrentExtensibleMatchingRules()
-  {
-    final Set<MatchingRule> rules = new HashSet<MatchingRule>();
-    for (String ruleName : config.getIndexExtensibleMatchingRule())
-    {
-        final MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
-        if (rule != null)
-        {
-          rules.add(rule);
-        }
-    }
-    return rules;
-  }
-
-  private void applyChangeToIndex(final WriteableTransaction txn, final IndexType indexType, final BackendIndexCfg cfg,
-      final ConfigChangeResult ccr)
-  {
-    String indexId = indexType.toString();
-    MatchingRuleIndex index = nameToIndexes.get(indexId);
-    if (!cfg.getIndexType().contains(indexType))
-    {
-      removeIndex(txn, index, indexType);
-      return;
-    }
-
-    if (index == null)
-    {
-      if (indexType == IndexType.PRESENCE)
-      {
-        nameToIndexes.put(indexId, openNewIndex(txn, cfg, PRESENCE_INDEXER, ccr));
-      }
-      else
-      {
-        final MatchingRule matchingRule = getMatchingRule(indexType, cfg.getAttribute());
-        for (Indexer indexer : matchingRule.getIndexers())
-        {
-          nameToIndexes.put(indexId, openNewIndex(txn, cfg, indexer, ccr));
-        }
-      }
-    }
-    else
-    {
-      // already exists. Just update index entry limit.
-      if (index.setIndexEntryLimit(cfg.getIndexEntryLimit()))
-      {
-        ccr.setAdminActionRequired(true);
-        ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(index.getName()));
-      }
-
-      if (indexType == IndexType.SUBSTRING && config.getSubstringLength() != cfg.getSubstringLength())
-      {
-        ccr.setAdminActionRequired(true);
-        ccr.addMessage(NOTE_CONFIG_INDEX_SUBSTRING_LENGTH_REQUIRES_REBUILD.get(index.getName()));
-      }
-    }
-  }
-
-  private void removeIndex(WriteableTransaction txn, Index index, IndexType indexType)
-  {
-    if (index != null)
-    {
-      entryContainer.exclusiveLock.lock();
-      try
-      {
-        nameToIndexes.remove(indexType.toString());
-        entryContainer.deleteTree(txn, index);
-      }
-      finally
-      {
-        entryContainer.exclusiveLock.unlock();
-      }
-    }
-  }
-
-  private MatchingRuleIndex openNewIndex(WriteableTransaction txn, BackendIndexCfg cfg, Indexer indexer,
-      ConfigChangeResult ccr)
-  {
-    final MatchingRuleIndex index = new MatchingRuleIndex(txn, cfg, indexer);
     index.open(txn);
-
     if (!index.isTrusted())
     {
       ccr.setAdminActionRequired(true);
       ccr.addMessage(NOTE_INDEX_ADD_REQUIRES_REBUILD.get(index.getName()));
     }
-    return index;
+  }
+
+  private static void updateIndex(Index updatedIndex, int newIndexEntryLimit, ConfigChangeResult ccr)
+  {
+    if (updatedIndex.setIndexEntryLimit(newIndexEntryLimit))
+    {
+      // This index can still be used since index size limit doesn't impact validity of the results.
+      ccr.setAdminActionRequired(true);
+      ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(updatedIndex.getName()));
+    }
+  }
+
+  private static void deleteIndex(WriteableTransaction txn, EntryContainer entryContainer, Index index)
+  {
+    entryContainer.exclusiveLock.lock();
+    try
+    {
+      entryContainer.deleteTree(txn, index);
+    }
+    finally
+    {
+      entryContainer.exclusiveLock.unlock();
+    }
   }
 
   /**
@@ -922,7 +832,7 @@
    */
   boolean isTrusted()
   {
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
       if (!index.isTrusted())
       {
@@ -946,7 +856,7 @@
 
   Map<String, MatchingRuleIndex> getNameToIndexes()
   {
-    return Collections.unmodifiableMap(nameToIndexes);
+    return indexIdToIndexes;
   }
 
   /**
@@ -997,7 +907,7 @@
       if (debugBuffer != null)
       {
         debugBuffer.append("[INDEX:");
-        for (Indexer indexer : rule.getIndexers())
+        for (Indexer indexer : rule.createIndexers(indexingOptions))
         {
             debugBuffer.append(" ")
               .append(filter.getAttributeType().getNameOrOID())
@@ -1032,9 +942,9 @@
 
   private boolean ruleHasAtLeastOneIndex(MatchingRule rule)
   {
-    for (Indexer indexer : rule.getIndexers())
+    for (Indexer indexer : rule.createIndexers(indexingOptions))
     {
-      if (nameToIndexes.containsKey(indexer.getIndexID()))
+      if (indexIdToIndexes.containsKey(indexer.getIndexID()))
       {
         return true;
       }
@@ -1043,7 +953,7 @@
   }
 
   /** Indexing options implementation. */
-  private final class IndexingOptionsImpl implements IndexingOptions
+  private static final class IndexingOptionsImpl implements IndexingOptions
   {
     /** The length of substring keys used in substring indexes. */
     private int substringKeySize;
@@ -1063,7 +973,7 @@
   void closeAndDelete(WriteableTransaction txn)
   {
     close();
-    for (Index index : nameToIndexes.values())
+    for (Index index : indexIdToIndexes.values())
     {
       index.delete(txn);
       state.deleteRecord(txn, index.getName());
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DefaultIndex.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DefaultIndex.java
index c6b4272..a516ddf 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DefaultIndex.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DefaultIndex.java
@@ -64,7 +64,9 @@
 
   private final State state;
 
-  private final EntryIDSetCodec codec;
+  private final EntryContainer entryContainer;
+
+  private EntryIDSetCodec codec;
 
   /**
    * A flag to indicate if this index should be trusted to be consistent with the entries tree.
@@ -84,23 +86,26 @@
    *          The state tree to persist index state info.
    * @param indexEntryLimit
    *          The configured limit on the number of entry IDs that may be indexed by one key.
-   * @param txn
-   *          a non null transaction
    * @param entryContainer
    *          The entryContainer holding this index.
    * @throws StorageRuntimeException
    *           If an error occurs in the storage.
    */
-  DefaultIndex(TreeName name, State state, int indexEntryLimit, WriteableTransaction txn, EntryContainer entryContainer)
+  DefaultIndex(TreeName name, State state, int indexEntryLimit, EntryContainer entryContainer)
       throws StorageRuntimeException
   {
     super(name);
     this.indexEntryLimit = indexEntryLimit;
     this.state = state;
+    this.entryContainer = entryContainer;
+  }
 
+  @Override
+  final void open0(WriteableTransaction txn)
+  {
     final EnumSet<IndexFlag> flags = state.getIndexFlags(txn, getName());
-    this.codec = flags.contains(COMPACTED) ? CODEC_V2 : CODEC_V1;
-    this.trusted = flags.contains(TRUSTED);
+    codec = flags.contains(COMPACTED) ? CODEC_V2 : CODEC_V1;
+    trusted = flags.contains(TRUSTED);
     if (!trusted && entryContainer.getHighestEntryID(txn).longValue() == 0)
     {
       // If there are no entries in the entry container then there
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
index f9c80b7..54f6eff 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
@@ -195,17 +195,7 @@
     {
       try
       {
-        // FIXME this should be a read operation, but I cannot change it
-        // because of AttributeIndex ctor.
-        storage.write(new WriteOperation()
-        {
-          @Override
-          public void run(WriteableTransaction txn) throws Exception
-          {
-            //Try creating all the indexes before confirming they are valid ones.
-            new AttributeIndex(cfg, state, EntryContainer.this, txn);
-          }
-        });
+        new AttributeIndex(cfg, state, EntryContainer.this);
         return true;
       }
       catch(Exception e)
@@ -222,12 +212,12 @@
       final ConfigChangeResult ccr = new ConfigChangeResult();
       try
       {
+        final AttributeIndex index = new AttributeIndex(cfg, state, EntryContainer.this);
         storage.write(new WriteOperation()
         {
           @Override
           public void run(WriteableTransaction txn) throws Exception
           {
-            final AttributeIndex index = new AttributeIndex(cfg, state, EntryContainer.this, txn);
             index.open(txn);
             if (!index.isTrusted())
             {
@@ -496,7 +486,7 @@
       {
         BackendIndexCfg indexCfg = config.getBackendIndex(idx);
 
-        AttributeIndex index = new AttributeIndex(indexCfg, state, this, txn);
+        final AttributeIndex index = new AttributeIndex(indexCfg, state, this);
         index.open(txn);
         if(!index.isTrusted())
         {
@@ -2194,8 +2184,7 @@
                 }
 
                 // Move this entry.
-                removeSubordinateEntry(txn, buffer, oldSuperiorDN, oldID, newID, oldEntry, newDN, isApexEntryMoved,
-                    modifyDNOperation, current);
+                removeSubordinateEntry(txn, buffer, oldID, newID, oldEntry, newDN, modifyDNOperation, current);
                 current = current.next;
 
                 if (modifyDNOperation != null)
@@ -2364,10 +2353,8 @@
   }
 
   private void removeSubordinateEntry(WriteableTransaction txn, IndexBuffer buffer,
-      DN oldSuperiorDN,
       EntryID oldID, EntryID newID,
       Entry oldEntry, DN newDN,
-      boolean isApexEntryMoved,
       ModifyDNOperation modifyDNOperation,
       MovedEntry tail)
   throws DirectoryException, StorageRuntimeException
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java
index 0e4f9ef..92d24dd 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java
@@ -93,7 +93,6 @@
 import org.forgerock.opendj.ldap.ByteSequenceReader;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.forgerock.util.Utils;
 import org.opends.server.admin.std.meta.BackendIndexCfgDefn.IndexType;
 import org.opends.server.admin.std.server.BackendIndexCfg;
@@ -1436,20 +1435,20 @@
     }
 
     @Override
-    void processAttribute(MatchingRuleIndex index, Entry entry, EntryID entryID, IndexingOptions options,
-        IndexKey indexKey) throws StorageRuntimeException, InterruptedException
+    void processAttribute(MatchingRuleIndex index, Entry entry, EntryID entryID, IndexKey indexKey)
+        throws StorageRuntimeException, InterruptedException
     {
       if (oldEntry != null)
       {
         deleteKeySet.clear();
-        index.indexEntry(oldEntry, deleteKeySet, options);
+        index.indexEntry(oldEntry, deleteKeySet);
         for (ByteString delKey : deleteKeySet)
         {
           processKey(index, delKey, entryID, indexKey, false);
         }
       }
       insertKeySet.clear();
-      index.indexEntry(entry, insertKeySet, options);
+      index.indexEntry(entry, insertKeySet);
       for (ByteString key : insertKeySet)
       {
         processKey(index, key, entryID, indexKey, true);
@@ -1581,11 +1580,9 @@
     void fillIndexKey(AttributeIndex attrIndex, Entry entry, AttributeType attrType, EntryID entryID)
         throws InterruptedException, StorageRuntimeException
     {
-      final IndexingOptions options = attrIndex.getIndexingOptions();
-
       for (Map.Entry<String, MatchingRuleIndex> mapEntry : attrIndex.getNameToIndexes().entrySet())
       {
-        processAttribute(mapEntry.getValue(), mapEntry.getKey(), entry, attrType, entryID, options);
+        processAttribute(mapEntry.getValue(), mapEntry.getKey(), entry, attrType, entryID);
       }
     }
 
@@ -1602,20 +1599,20 @@
     }
 
     private void processAttribute(MatchingRuleIndex index, String indexID, Entry entry,
-        AttributeType attributeType, EntryID entryID, IndexingOptions options) throws InterruptedException
+        AttributeType attributeType, EntryID entryID) throws InterruptedException
     {
       if (index != null)
       {
         IndexKey indexKey = new IndexKey(attributeType, indexID, index.getIndexEntryLimit());
-        processAttribute(index, entry, entryID, options, indexKey);
+        processAttribute(index, entry, entryID, indexKey);
       }
     }
 
-    void processAttribute(MatchingRuleIndex index, Entry entry, EntryID entryID, IndexingOptions options,
-        IndexKey indexKey) throws StorageRuntimeException, InterruptedException
+    void processAttribute(MatchingRuleIndex index, Entry entry, EntryID entryID, IndexKey indexKey)
+        throws StorageRuntimeException, InterruptedException
     {
       insertKeySet.clear();
-      index.indexEntry(entry, insertKeySet, options);
+      index.indexEntry(entry, insertKeySet);
       for (ByteString key : insertKeySet)
       {
         processKey(index, key, entryID, indexKey, true);
@@ -3167,10 +3164,7 @@
         AttributeType attrType = indexKey.getAttributeType();
         if (entry.hasAttribute(attrType))
         {
-          AttributeIndex attributeIndex = entryContainer.getAttributeIndex(attrType);
-          IndexingOptions options = attributeIndex.getIndexingOptions();
-          MatchingRuleIndex index = mapEntry.getValue();
-          processAttribute(index, entry, entryID, options, indexKey);
+          processAttribute(mapEntry.getValue(), entry, entryID, indexKey);
         }
       }
     }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java
index bd96a84..b671e73 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java
@@ -164,7 +164,7 @@
   }
 
   @Override
-  void open0(final ReadableTransaction txn) throws StorageRuntimeException
+  void open0(final WriteableTransaction txn) throws StorageRuntimeException
   {
     count.set((int) txn.getRecordCount(getName()));
   }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VerifyJob.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VerifyJob.java
index 1fa084f..4d56ff0 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VerifyJob.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VerifyJob.java
@@ -51,7 +51,6 @@
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
-import org.forgerock.opendj.ldap.spi.IndexingOptions;
 import org.opends.server.backends.VerifyConfig;
 import org.opends.server.backends.pluggable.AttributeIndex.MatchingRuleIndex;
 import org.opends.server.backends.pluggable.spi.Cursor;
@@ -431,10 +430,9 @@
     else if (attrIndexList.size() > 0)
     {
       AttributeIndex attrIndex = attrIndexList.get(0);
-      final IndexingOptions options = attrIndex.getIndexingOptions();
       for (MatchingRuleIndex index : attrIndex.getNameToIndexes().values())
       {
-        iterateAttrIndex(txn, index, options);
+        iterateAttrIndex(txn, index);
       }
     }
     else if (vlvIndexList.size() > 0)
@@ -672,8 +670,7 @@
    * @param index The index tree to be checked.
    * @throws StorageRuntimeException If an error occurs in the storage.
    */
-  private void iterateAttrIndex(ReadableTransaction txn, MatchingRuleIndex index, IndexingOptions options)
-      throws StorageRuntimeException
+  private void iterateAttrIndex(ReadableTransaction txn, MatchingRuleIndex index) throws StorageRuntimeException
   {
     if (index == null)
     {
@@ -780,7 +777,7 @@
 
             };
 
-            index.indexEntry(entry, dummySet, options);
+            index.indexEntry(entry, dummySet);
 
             if (!foundMatchingKey.get())
             {
@@ -958,11 +955,10 @@
    */
   private void verifyAttribute(ReadableTransaction txn, EntryID entryID, Entry entry, AttributeIndex attrIndex)
   {
-    IndexingOptions options = attrIndex.getIndexingOptions();
     for (MatchingRuleIndex index : attrIndex.getNameToIndexes().values())
     {
       Set<ByteString> keys = new HashSet<ByteString>();
-      index.indexEntry(entry, keys, options);
+      index.indexEntry(entry, keys);
       for (ByteString key : keys)
       {
         verifyAttributeInIndex(index, txn, key, entryID);
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRuleImpl.java
index ae51b8d..296cc91 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/HistoricalCsnOrderingMatchingRuleImpl.java
@@ -51,7 +51,7 @@
  */
 public final class HistoricalCsnOrderingMatchingRuleImpl implements MatchingRuleImpl
 {
-  private static final String ORDERING_ID = "ordering";
+  private static final String ORDERING_ID = "changeSequenceNumberOrderingMatch";
 
   private final Collection<? extends Indexer> indexers = Collections.singleton(new HistoricalIndexer());
 
@@ -59,8 +59,7 @@
   private final class HistoricalIndexer implements Indexer
   {
     @Override
-    public void createKeys(Schema schema, ByteSequence value, IndexingOptions options, Collection<ByteString> keys)
-        throws DecodeException
+    public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) throws DecodeException
     {
       keys.add(normalizeAttributeValue(schema, value));
     }
@@ -172,16 +171,9 @@
 
   /** {@inheritDoc} */
   @Override
-  public Collection<? extends Indexer> getIndexers()
+  public Collection<? extends Indexer> createIndexers(IndexingOptions options)
   {
     return indexers;
   }
 
-  /** {@inheritDoc} */
-  @Override
-  public boolean isIndexingSupported()
-  {
-    return !indexers.isEmpty();
-  }
-
 }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/schema/AbstractPasswordEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/schema/AbstractPasswordEqualityMatchingRuleImpl.java
index 878025a..32e87ce 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/schema/AbstractPasswordEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/schema/AbstractPasswordEqualityMatchingRuleImpl.java
@@ -42,6 +42,7 @@
 import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 import static org.forgerock.opendj.ldap.Assertion.*;
+import static org.opends.server.schema.SchemaConstants.*;
 
 /**
  * Abstract implementation for password matching rules.
@@ -49,13 +50,12 @@
 abstract class AbstractPasswordEqualityMatchingRuleImpl implements MatchingRuleImpl
 {
 
-  private static final String EQUALITY_ID = "equality";
+  private static final String EQUALITY_ID =  EMR_AUTH_PASSWORD_NAME;
 
   private final Collection<? extends Indexer> indexers = Collections.singleton(new Indexer()
   {
     @Override
-    public void createKeys(Schema schema, ByteSequence value, IndexingOptions options, Collection<ByteString> keys)
-        throws DecodeException
+    public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) throws DecodeException
     {
       keys.add(normalizeAttributeValue(schema, value));
     }
@@ -131,18 +131,11 @@
 
   /** {@inheritDoc} */
   @Override
-  public Collection<? extends Indexer> getIndexers()
+  public Collection<? extends Indexer> createIndexers(IndexingOptions options)
   {
     return indexers;
   }
 
-  /** {@inheritDoc} */
-  @Override
-  public boolean isIndexingSupported()
-  {
-    return !indexers.isEmpty();
-  }
-
   /**
    * Indicates whether the provided attribute value should be considered a match
    * for the given assertion value.  This will only be used for the purpose of
diff --git a/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaTestMatchingRuleImpl.java b/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaTestMatchingRuleImpl.java
index 05bbeac..12cb327 100644
--- a/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaTestMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaTestMatchingRuleImpl.java
@@ -40,6 +40,7 @@
 import org.forgerock.opendj.ldap.schema.MatchingRuleImpl;
 import org.forgerock.opendj.ldap.schema.Schema;
 import org.forgerock.opendj.ldap.spi.Indexer;
+import org.forgerock.opendj.ldap.spi.IndexingOptions;
 
 
 /**
@@ -94,15 +95,10 @@
   }
 
   @Override
-  public Collection<? extends Indexer> getIndexers()
+  public Collection<? extends Indexer> createIndexers(IndexingOptions options)
   {
-    return caseIgnoreMatchingRule.getIndexers();
+    return caseIgnoreMatchingRule.createIndexers(options);
   }
 
-  @Override
-  public boolean isIndexingSupported()
-  {
-    return !getIndexers().isEmpty();
-  }
 }
 
diff --git a/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestBackendImpl.java b/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestBackendImpl.java
index c06cef4..bd9f098 100644
--- a/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestBackendImpl.java
+++ b/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestBackendImpl.java
@@ -26,11 +26,14 @@
  */
 package org.opends.server.backends.jeb;
 
+import static org.opends.server.schema.SchemaConstants.*;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.OutputStream;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -95,10 +98,15 @@
  */
 @SuppressWarnings("javadoc")
 public class TestBackendImpl extends JebTestCase {
+
   private String homeDirName;
 
   private BackendImpl backend;
 
+  private AttributeType givenName;
+  private AttributeType title;
+  private AttributeType name;
+
   private List<Entry> topEntries;
   private List<Entry> entries;
   private List<Entry> additionalEntries;
@@ -565,6 +573,9 @@
         "ou: People"
     );
 
+    givenName = DirectoryServer.getAttributeType("givenname");
+    title = DirectoryServer.getAttributeType("title");
+    name = DirectoryServer.getAttributeType("name");
   }
 
   @AfterClass
@@ -803,18 +814,17 @@
       AttributeIndex index = ec.getAttributeIndex(attribute);
       AttributeType attrType = index.getAttributeType();
 
-      List<? extends Indexer> indexers;
-      indexers = singletonList(new PresenceIndexer(index.getAttributeType()));
-      assertIndexContainsID(indexers, entry, index.getPresenceIndex(), entryID, FALSE);
+      List<? extends Indexer> indexers = singletonList(new PresenceIndexer(index.getAttributeType()));
+      assertIndexContainsID(indexers, entry, index.getIndex("presence"), entryID, FALSE);
 
       indexers = newAttributeIndexers(attrType, attrType.getEqualityMatchingRule());
-      assertIndexContainsID(indexers, entry, index.getEqualityIndex(), entryID, FALSE);
+      assertIndexContainsID(indexers, entry, index.getIndex(EMR_CASE_IGNORE_NAME), entryID, FALSE);
 
       indexers = newAttributeIndexers(attrType, attrType.getSubstringMatchingRule());
-      assertIndexContainsID(indexers, entry, index.getSubstringIndex(), entryID, FALSE);
+      assertIndexContainsID(indexers, entry, index.getIndex(substringIndexId()), entryID, FALSE);
 
-      indexers = newAttributeIndexers(attrType, attrType.getOrderingMatchingRule());
-      assertIndexContainsID(indexers, entry, index.getOrderingIndex(), entryID, FALSE);
+      // OrderingIndex is now handled by EqualityIndex (OPENDJ-1864)
+      assertThat(index.getIndex(OMR_CASE_IGNORE_NAME)).isNull();
     }
     finally
     {
@@ -825,7 +835,7 @@
   private static List<AttributeIndexer> newAttributeIndexers(AttributeType attrType, MatchingRule matchingRule)
   {
     List<AttributeIndexer> indexers = new ArrayList<AttributeIndexer>();
-    for (org.forgerock.opendj.ldap.spi.Indexer indexer : matchingRule.getIndexers())
+    for (org.forgerock.opendj.ldap.spi.Indexer indexer : matchingRule.createIndexers(getOptions()))
     {
       indexers.add(new AttributeIndexer(attrType, indexer));
     }
@@ -844,7 +854,7 @@
     for (Indexer indexer : indexers)
     {
       Set<ByteString> addKeys = new HashSet<ByteString>();
-      indexer.indexEntry(entry, addKeys, getOptions());
+      indexer.indexEntry(entry, addKeys);
 
       DatabaseEntry key = new DatabaseEntry();
       for (ByteString keyBytes : addKeys)
@@ -861,7 +871,7 @@
     for (Indexer indexer : indexers)
     {
       Set<ByteString> addKeys = new HashSet<ByteString>();
-      indexer.indexEntry(entry, addKeys, getOptions());
+      indexer.indexEntry(entry, addKeys);
 
       assertIndexContainsID(addKeys, index, entryID, expected);
     }
@@ -915,16 +925,16 @@
 
       List<? extends Indexer> indexers;
       indexers = newAttributeIndexers(attrType, attrType.getOrderingMatchingRule());
-      assertIndexContainsID(indexers, entry, index.getOrderingIndex(), entryID, TRUE);
-      assertIndexContainsID(indexers, oldEntry, index.getOrderingIndex(), entryID, FALSE);
+      // OrderingIndex is now handled by EqualityIndex (OPENDJ-1864)
+      assertThat(index.getIndex(OMR_CASE_IGNORE_NAME)).isNull();
 
       indexers = newAttributeIndexers(attrType, attrType.getSubstringMatchingRule());
-      assertIndexContainsID(indexers, entry, index.getSubstringIndex(), entryID, TRUE);
-      assertIndexContainsID(indexers, oldEntry, index.getSubstringIndex(), entryID, FALSE);
+      assertIndexContainsID(indexers, entry, index.getIndex(substringIndexId()), entryID, TRUE);
+      assertIndexContainsID(indexers, oldEntry, index.getIndex(substringIndexId()), entryID, FALSE);
 
       indexers = newAttributeIndexers(attrType, attrType.getEqualityMatchingRule());
-      assertIndexContainsID(indexers, entry, index.getEqualityIndex(), entryID, TRUE);
-      assertIndexContainsID(indexers, oldEntry, index.getEqualityIndex(), entryID, FALSE);
+      assertIndexContainsID(indexers, entry, index.getIndex(EMR_CASE_IGNORE_NAME), entryID, TRUE);
+      assertIndexContainsID(indexers, oldEntry, index.getIndex(EMR_CASE_IGNORE_NAME), entryID, FALSE);
     }
     finally
     {
@@ -987,20 +997,18 @@
 
       assertNotNull(entryID);
 
-      attribute = DirectoryServer.getAttributeType("title");
-      titleIndex = ec.getAttributeIndex(attribute);
-      attribute = DirectoryServer.getAttributeType("name");
-      nameIndex = ec.getAttributeIndex(attribute);
+      titleIndex = ec.getAttributeIndex(title);
+      nameIndex = ec.getAttributeIndex(name);
 
       // This current entry in the DB shouldn't be in the presence titleIndex.
       addKeys = new HashSet<ByteString>();
       addKeys.add(PresenceIndexer.presenceKey);
-      assertIndexContainsID(addKeys, titleIndex.getPresenceIndex(), entryID, FALSE);
+      assertIndexContainsID(addKeys, titleIndex.getIndex("presence"), entryID, FALSE);
 
       // This current entry should be in the presence nameIndex.
       addKeys = new HashSet<ByteString>();
       addKeys.add(PresenceIndexer.presenceKey);
-      assertIndexContainsID(addKeys, nameIndex.getPresenceIndex(), entryID, TRUE);
+      assertIndexContainsID(addKeys, nameIndex.getIndex("presence"), entryID, TRUE);
 
       List<Control> noControls = new ArrayList<Control>(0);
       ModifyOperationBasis modifyOp = new ModifyOperationBasis(getRootConnection(), nextOperationID(), nextMessageID(),
@@ -1039,24 +1047,30 @@
       AttributeType nameIndexAttrType = nameIndex.getAttributeType();
 
       indexers = singletonList(new PresenceIndexer(titleIndexAttrType));
-      assertIndexContainsID(indexers, entry, titleIndex.getPresenceIndex(), entryID);
+      assertIndexContainsID(indexers, entry, titleIndex.getIndex("presence"), entryID);
       indexers = singletonList(new PresenceIndexer(nameIndexAttrType));
-      assertIndexContainsID(indexers, entry, nameIndex.getPresenceIndex(), entryID);
+      assertIndexContainsID(indexers, entry, nameIndex.getIndex("presence"), entryID);
 
-      indexers = newAttributeIndexers(titleIndexAttrType, titleIndexAttrType.getOrderingMatchingRule());
-      assertIndexContainsID(indexers, entry, titleIndex.getOrderingIndex(), entryID);
-      indexers = newAttributeIndexers(nameIndexAttrType, nameIndexAttrType.getOrderingMatchingRule());
-      assertIndexContainsID(indexers, entry, nameIndex.getOrderingIndex(), entryID);
+      // OrderingIndex is now handled by EqualityIndex (OPENDJ-1864)
+      assertThat(getIndexNames(titleIndex)).containsOnly(
+          indexName(ec, titleIndexAttrType, "presence"),
+          indexName(ec, titleIndexAttrType, EMR_CASE_IGNORE_NAME),
+          indexName(ec, titleIndexAttrType, SMR_CASE_IGNORE_NAME + ":6"));
+      assertThat(getIndexNames(nameIndex)).containsOnly(
+          indexName(ec, nameIndexAttrType, "presence"),
+          indexName(ec, nameIndexAttrType, AMR_DOUBLE_METAPHONE_NAME),
+          indexName(ec, nameIndexAttrType, EMR_CASE_IGNORE_NAME),
+          indexName(ec, nameIndexAttrType, SMR_CASE_IGNORE_NAME + ":6"));
 
       indexers = newAttributeIndexers(titleIndexAttrType, titleIndexAttrType.getEqualityMatchingRule());
-      assertIndexContainsID(indexers, entry, titleIndex.getEqualityIndex(), entryID);
+      assertIndexContainsID(indexers, entry, titleIndex.getIndex(EMR_CASE_IGNORE_NAME), entryID);
       indexers = newAttributeIndexers(nameIndexAttrType, nameIndexAttrType.getEqualityMatchingRule());
-      assertIndexContainsID(indexers, entry, nameIndex.getEqualityIndex(), entryID);
+      assertIndexContainsID(indexers, entry, nameIndex.getIndex(EMR_CASE_IGNORE_NAME), entryID);
 
       indexers = newAttributeIndexers(titleIndexAttrType, titleIndexAttrType.getSubstringMatchingRule());
-      assertIndexContainsID(indexers, entry, titleIndex.getSubstringIndex(), entryID);
+      assertIndexContainsID(indexers, entry, titleIndex.getIndex(substringIndexId()), entryID);
       indexers = newAttributeIndexers(nameIndexAttrType, nameIndexAttrType.getSubstringMatchingRule());
-      assertIndexContainsID(indexers, entry, nameIndex.getSubstringIndex(), entryID);
+      assertIndexContainsID(indexers, entry, nameIndex.getIndex(substringIndexId()), entryID);
     }
     finally
     {
@@ -1176,6 +1190,39 @@
     assertNotNull(rootContainer.getEntryContainer(DN.valueOf("dc=newsuffix,dc=com")));
   }
 
+  /** @since OPENDJ-1864 Equality and Ordering indexes share the same database */
+  @Test
+  public void testRemovingOrderingIndexDoesNotRemoveEquality() throws Exception
+  {
+    int resultCode = TestCaseUtils.applyModifications(true,
+        "dn: ds-cfg-attribute=givenName,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config",
+        "changetype: modify",
+        "replace: ds-cfg-index-type",
+        "ds-cfg-index-type: equality",
+        "ds-cfg-index-type: ordering");
+    assertEquals(resultCode, 0);
+
+    RootContainer rootContainer = backend.getRootContainer();
+    EntryContainer ec = rootContainer.getEntryContainer(DN.valueOf("dc=test,dc=com"));
+
+    Collection<String> containerNames = getContainerNames(ec);
+    assertThat(containerNames).contains(indexName(ec, givenName, EMR_CASE_IGNORE_NAME));
+    assertThat(containerNames).doesNotContain(indexName(ec, givenName, OMR_CASE_IGNORE_NAME));
+
+    // Remove equality indexes
+    resultCode = TestCaseUtils.applyModifications(true,
+        "dn: ds-cfg-attribute=givenName,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config",
+        "changetype: modify",
+        "replace: ds-cfg-index-type",
+        "ds-cfg-index-type: ordering");
+    assertEquals(resultCode, 0);
+
+    // Since ordering is using the same equality db, it must remain
+    containerNames = getContainerNames(ec);
+    assertThat(containerNames).contains(indexName(ec, givenName, EMR_CASE_IGNORE_NAME));
+    assertThat(containerNames).doesNotContain(indexName(ec, givenName, OMR_CASE_IGNORE_NAME));
+  }
+
   @Test(dependsOnMethods = {"testModifyDN",
       "testSearchScope", "testSearchIndex", "testReplaceEntry",
       "testModifyEntry", "testModifyDN", "testDeleteSubtree",
@@ -1184,8 +1231,7 @@
       "testModifyDNNewSuperior", "testMatchedDN"})
   public void testApplyIndexConfig() throws Exception {
     int resultCode = TestCaseUtils.applyModifications(true,
-        "dn: ds-cfg-attribute=givenName,cn=Index," +
-            "ds-cfg-backend-id=indexRoot,cn=Backends,cn=config",
+        "dn: ds-cfg-attribute=givenName,cn=Index,ds-cfg-backend-id=indexRoot,cn=Backends,cn=config",
         "changetype: modify",
         "replace: ds-cfg-index-type",
         "ds-cfg-index-type: approximate");
@@ -1195,20 +1241,13 @@
     RootContainer rootContainer = backend.getRootContainer();
     EntryContainer ec = rootContainer.getEntryContainer(DN.valueOf("dc=test,dc=com"));
 
-    AttributeType givennameAttr = DirectoryServer.getAttributeType("givenname");
-    AttributeIndex attributeIndex = ec.getAttributeIndex(givennameAttr);
-    assertNull(attributeIndex.getEqualityIndex());
-    assertNull(attributeIndex.getPresenceIndex());
-    assertNull(attributeIndex.getSubstringIndex());
-    assertNull(attributeIndex.getOrderingIndex());
-    assertNotNull(attributeIndex.getApproximateIndex());
-    List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
-    ec.listDatabases(databases);
-    assertFalse(findContainer(databases, "givenname.equality"));
-    assertFalse(findContainer(databases, "givenname.presence"));
-    assertFalse(findContainer(databases, "givenname.substring"));
-    assertFalse(findContainer(databases, "givenname.ordering"));
-    assertTrue(findContainer(databases, "givenname.approximate"));
+    Collection<String> containerNames = getContainerNames(ec);
+    assertThat(containerNames).doesNotContain(
+        indexName(ec, givenName, EMR_CASE_IGNORE_NAME),
+        indexName(ec, givenName, "presence"),
+        indexName(ec, givenName, substringIndexId()),
+        indexName(ec, givenName, OMR_CASE_IGNORE_NAME));
+    assertThat(containerNames).contains(indexName(ec, givenName, AMR_DOUBLE_METAPHONE_NAME));
 
     final SearchRequest request = newSearchRequest("dc=test,dc=com", SearchScope.SUBORDINATES, "(givenName~=Aaccf)")
         .addAttribute(ATTR_DEBUG_SEARCH_INDEX);
@@ -1221,8 +1260,7 @@
     assertThat(debugString).contains("not-indexed");
 
     resultCode = TestCaseUtils.applyModifications(true,
-        "dn: ds-cfg-attribute=givenName,cn=Index," +
-            "ds-cfg-backend-id=indexRoot,cn=Backends,cn=config",
+        "dn: ds-cfg-attribute=givenName,cn=Index, ds-cfg-backend-id=indexRoot,cn=Backends,cn=config",
         "changetype: modify",
         "replace: ds-cfg-index-type",
         "ds-cfg-index-type: equality",
@@ -1232,18 +1270,15 @@
 
     assertEquals(resultCode, 0);
 
-    assertNotNull(attributeIndex.getEqualityIndex());
-    assertNotNull(attributeIndex.getPresenceIndex());
-    assertNotNull(attributeIndex.getSubstringIndex());
-    assertNotNull(attributeIndex.getOrderingIndex());
-    assertNull(attributeIndex.getApproximateIndex());
-    databases = new ArrayList<DatabaseContainer>();
-    ec.listDatabases(databases);
-    assertTrue(findContainer(databases, "givenname.equality"));
-    assertTrue(findContainer(databases, "givenname.presence"));
-    assertTrue(findContainer(databases, "givenname.substring"));
-    assertTrue(findContainer(databases, "givenname.ordering"));
-    assertFalse(findContainer(databases, "givenname.approximate"));
+    containerNames = getContainerNames(ec);
+    assertThat(containerNames).contains(
+        indexName(ec, givenName, EMR_CASE_IGNORE_NAME),
+        indexName(ec, givenName, "presence"),
+        indexName(ec, givenName, substringIndexId()));
+    // Ordering is also handled by equality since OPENDJ-1864
+    assertThat(containerNames).doesNotContain(
+        indexName(ec, givenName, OMR_CASE_IGNORE_NAME),
+        indexName(ec, givenName, AMR_DOUBLE_METAPHONE_NAME));
 
     // Delete the entries attribute index.
     resultCode = TestCaseUtils.applyModifications(true,
@@ -1253,8 +1288,10 @@
 
     assertEquals(resultCode, 0);
 
+    AttributeType givennameAttr = DirectoryServer.getAttributeType("givenname");
     assertNull(ec.getAttributeIndex(givennameAttr));
-    databases = new ArrayList<DatabaseContainer>();
+
+    List<DatabaseContainer> databases = new ArrayList<>();
     ec.listDatabases(databases);
     for(DatabaseContainer dc : databases)
     {
@@ -1277,13 +1314,16 @@
     assertEquals(resultCode, 0);
 
     assertNotNull(ec.getAttributeIndex(givennameAttr));
-    databases = new ArrayList<DatabaseContainer>();
-    ec.listDatabases(databases);
-    assertTrue(findContainer(databases, "givenname.equality"));
-    assertTrue(findContainer(databases, "givenname.presence"));
-    assertTrue(findContainer(databases, "givenname.substring"));
-    assertTrue(findContainer(databases, "givenname.ordering"));
-    assertFalse(findContainer(databases, "givenname.approximate"));
+
+    containerNames = getContainerNames(ec);
+    assertThat(containerNames).contains(
+        indexName(ec, givenName, EMR_CASE_IGNORE_NAME),
+        indexName(ec, givenName, "presence"),
+        indexName(ec, givenName, substringIndexId()));
+    // Equality and Ordering indexes share the same database since OPENDJ-1864
+    assertThat(containerNames).doesNotContain(
+        indexName(ec, givenName, OMR_CASE_IGNORE_NAME),
+        indexName(ec, givenName, AMR_DOUBLE_METAPHONE_NAME));
 
     // Make sure changing the index entry limit on an index where the limit
     // is already exceeded causes warnings.
@@ -1307,16 +1347,31 @@
     assertEquals(resultCode, 0);
   }
 
-  private static boolean findContainer(List<DatabaseContainer> databases, String lowercaseName)
+  private static Collection<String> getContainerNames(EntryContainer container)
   {
+    final List<DatabaseContainer> databases = new ArrayList<>();
+    container.listDatabases(databases);
+    final Collection<String> names = new ArrayList<>(databases.size());
     for (DatabaseContainer dc : databases)
     {
-      if (dc.getName().toLowerCase().contains(lowercaseName))
-      {
-        return true;
-      }
+      names.add(dc.getName().toLowerCase());
     }
-    return false;
+    return names;
+  }
+
+  private static Collection<String> getIndexNames(AttributeIndex index)
+  {
+    final Collection<String> names = new ArrayList<>();
+    for (Index idx : index.getAllIndexes())
+    {
+      names.add(idx.getName().toLowerCase());
+    }
+    return names;
+  }
+
+  private static String indexName(EntryContainer entryContainer, AttributeType attrType, String indexID)
+  {
+    return entryContainer.getDatabasePrefix() + "_" + attrType.getPrimaryName().toLowerCase() + "." + indexID.toLowerCase();
   }
 
   @Test(dependsOnMethods = {"testDeleteEntry", "testSearchScope",
@@ -1519,5 +1574,8 @@
     }
   }
 
+  private static String substringIndexId() {
+    return SMR_CASE_IGNORE_NAME + ":" + getOptions().substringKeySize();
+  }
 
 }
diff --git a/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestVerifyJob.java b/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestVerifyJob.java
index 606a5f7..d99525a 100644
--- a/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestVerifyJob.java
+++ b/opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/jeb/TestVerifyJob.java
@@ -26,6 +26,7 @@
  */
 package org.opends.server.backends.jeb;
 
+import static org.opends.server.schema.SchemaConstants.*;
 import static org.opends.server.util.ServerConstants.*;
 import static org.testng.Assert.*;
 
@@ -54,6 +55,12 @@
 @SuppressWarnings("javadoc")
 public class TestVerifyJob extends JebTestCase
 {
+
+  private static final String EQUALITY_CASE_IGNORE = EMR_CASE_IGNORE_NAME;
+  private static final String EQUALITY_TELEPHONE = EMR_TELEPHONE_NAME;
+  private static final String ORDERING_CASE_IGNORE = OMR_CASE_IGNORE_NAME;
+  private static final String SUBSTRING_CASE_IGNORE_IA5 = SMR_CASE_IGNORE_IA5_NAME;
+
   /** Root suffix for verify backend. */
   private static String suffix="dc=verify,dc=jeb";
   private static  String vBranch="ou=verify tests," + suffix;
@@ -344,7 +351,7 @@
     try
     {
       AttributeType attributeType = DirectoryServer.getAttributeType(phoneType);
-      Index index = eContainer.getAttributeIndex(attributeType).getEqualityIndex();
+      Index index = eContainer.getAttributeIndex(attributeType).getIndex(EQUALITY_TELEPHONE);
       //Add entry with bad JEB format Version
       addID2EntryReturnKey(junkDN, 4, true);
       //Add phone number with various bad id list entryIDs
@@ -636,10 +643,12 @@
           DirectoryServer.getAttributeType(mailType);
       //Get db handles to each index.
       AttributeIndex attributeIndex = eContainer.getAttributeIndex(attributeType);
-      Index eqIndex = attributeIndex.getEqualityIndex();
-      Index presIndex = attributeIndex.getPresenceIndex();
-      Index subIndex = attributeIndex.getSubstringIndex();
-      Index ordIndex = attributeIndex.getOrderingIndex();
+      Index eqIndex = attributeIndex.getIndex(EQUALITY_CASE_IGNORE);
+      Index presIndex = attributeIndex.getIndex("presence");
+      Index subIndex = attributeIndex.getIndex(SUBSTRING_CASE_IGNORE_IA5 + ":6");
+      // Ordering is processed by equality since OPENDJ-1864
+      assertNull(attributeIndex.getIndex(ORDERING_CASE_IGNORE));
+
       //Add invalid idlist ids to both equality and ordering indexes.
       DatabaseEntry key=
            new DatabaseEntry(StaticUtils.getBytes("user.0@example.com"));
@@ -650,15 +659,11 @@
       DatabaseEntry data= new DatabaseEntry(dataBytes);
       OperationStatus status = eqIndex.put(txn, key, data);
       assertEquals(status, OperationStatus.SUCCESS);
-      status = ordIndex.put(txn, key, data);
-      assertEquals(status, OperationStatus.SUCCESS);
-      //Add null idlist to both equality and ordering indexes.
+      //Add null idlist to equality index.
       key = new DatabaseEntry(StaticUtils.getBytes("user.1@example.com"));
       data= new DatabaseEntry(new EntryIDSet().toDatabase());
       status = eqIndex.put(txn, key, data);
       assertEquals(status, OperationStatus.SUCCESS);
-      status = ordIndex.put(txn, key, data);
-      assertEquals(status, OperationStatus.SUCCESS);
       //Add invalid idlist ids to presence index.
       key = new DatabaseEntry(StaticUtils.getBytes("+"));
       data = new DatabaseEntry(dataBytes);
@@ -669,7 +674,7 @@
       data = new DatabaseEntry(dataBytes);
       status = subIndex.put(txn, key, data);
       assertEquals(status, OperationStatus.SUCCESS);
-      performBECompleteVerify(mailType, 6);
+      performBECompleteVerify(mailType, 5);
     }
     finally
     {

--
Gitblit v1.10.0