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

Jean-Noel Rouvignac
24.22.2014 a290c34a5ac2f5654f6f26f398459bf2d904bfb4
opendj3-server-dev/src/server/org/opends/server/api/ExtensibleMatchingRule.java
@@ -31,7 +31,6 @@
import org.forgerock.opendj.ldap.ByteSequence;
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
/**
 * This interface defines the set of methods that must be
@@ -49,12 +48,10 @@
   * Returns a collection of extensible indexers associated with this matching
   * rule.
   *
   * @param indexingOptions
   *          The indexing options to be used by this matching rule.
   * @return The collection of extensible indexers associated with this matching
   *         rule.
   */
  Collection<ExtensibleIndexer> getIndexers(IndexingOptions indexingOptions);
  Collection<ExtensibleIndexer> getIndexers();
opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
@@ -42,7 +42,10 @@
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn;
import org.opends.server.admin.std.server.LocalDBIndexCfg;
import org.opends.server.api.*;
import org.opends.server.api.ExtensibleIndexer;
import org.opends.server.api.ExtensibleMatchingRule;
import org.opends.server.api.MatchingRule;
import org.opends.server.api.SubstringMatchingRule;
import org.opends.server.core.DirectoryServer;
import org.opends.server.monitors.DatabaseEnvironmentMonitor;
import org.opends.server.types.*;
@@ -148,8 +151,7 @@
    AttributeType attrType = indexConfig.getAttribute();
    String name =
        entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID();
    int indexEntryLimit = indexConfig.getIndexEntryLimit();
    JEIndexConfig config = new JEIndexConfig(indexConfig.getSubstringLength());
    final JEIndexConfig config = new JEIndexConfig(indexConfig.getSubstringLength());
    if (indexConfig.getIndexType().contains(
            LocalDBIndexCfgDefn.IndexType.EQUALITY))
@@ -161,15 +163,8 @@
    if (indexConfig.getIndexType().contains(
            LocalDBIndexCfgDefn.IndexType.PRESENCE))
    {
      Indexer presenceIndexer = new PresenceIndexer(attrType);
      this.presenceIndex = new Index(name + ".presence",
                                     presenceIndexer,
                                     state,
                                     indexEntryLimit,
                                     cursorEntryLimit,
                                     false,
                                     env,
                                     entryContainer);
      this.presenceIndex = newIndex(name + ".presence",
          new PresenceIndexer(attrType), indexConfig.getIndexEntryLimit());
    }
    if (indexConfig.getIndexType().contains(
@@ -208,40 +203,27 @@
      for(String ruleName:extensibleRules)
      {
        ExtensibleMatchingRule rule =
                DirectoryServer.getExtensibleMatchingRule(
                                                    toLowerCase(ruleName));
            DirectoryServer.getExtensibleMatchingRule(toLowerCase(ruleName));
        if(rule == null)
        {
          logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
          continue;
        }
        Map<String,Index> indexMap = new HashMap<String,Index>();
        for(ExtensibleIndexer indexer : rule.getIndexers(config))
        for (ExtensibleIndexer indexer : rule.getIndexers())
        {
          String indexID = attrType.getNameOrOID() + "." + indexer.getIndexID();
          if(!extensibleIndexes.isIndexPresent(indexID))
          {
            //There is no index available for this index id. Create a new index.
            Indexer extensibleIndexer =
                    new JEExtensibleIndexer(attrType,
                                               rule,
                                               indexer);
            String indexName = entryContainer.getDatabasePrefix() + "_"
                                                  + indexID;
            Index extensibleIndex = new Index(indexName,
                                      extensibleIndexer,
                                      state,
                                      indexEntryLimit,
                                      cursorEntryLimit,
                                      false,
                                      env,
                                      entryContainer);
              extensibleIndexes.addIndex(extensibleIndex,indexID);
            String indexName = entryContainer.getDatabasePrefix() + "_" + indexID;
            Index extIndex = newExtensibleIndex(indexName, attrType, indexer);
            extensibleIndexes.addIndex(extIndex, indexID);
          }
        extensibleIndexes.addRule(indexID, rule);
        indexMap.put(indexer.getExtensibleIndexID(),
                extensibleIndexes.getIndex(indexID));
      }
          extensibleIndexes.addRule(indexID, rule);
          indexMap.put(indexer.getExtensibleIndexID(),
              extensibleIndexes.getIndex(indexID));
        }
        IndexQueryFactory<IndexQuery> factory =
            new IndexQueryFactoryImpl(indexMap, config);
        extensibleIndexes.addQueryFactory(rule, factory);
@@ -249,6 +231,13 @@
    }
  }
  private Index newIndex(String indexName, Indexer indexer,
      int indexEntryLimit)
  {
    return new Index(indexName, indexer, state, indexEntryLimit,
        cursorEntryLimit, false, env, entryContainer);
  }
  private Index buildExtIndex(String name, AttributeType attrType,
      MatchingRule rule, ExtensibleIndexer extIndexer) throws ConfigException
  {
@@ -258,15 +247,15 @@
          attrType, extIndexer.getExtensibleIndexID()));
    }
    Indexer indexer = new JEExtensibleIndexer(attrType, rule, extIndexer);
    return new Index(name + "." + extIndexer.getExtensibleIndexID(),
                                   indexer,
                                   state,
                                   indexConfig.getIndexEntryLimit(),
                                   cursorEntryLimit,
                                   false,
                                   env,
                                   entryContainer);
    final String indexName = name + "." + extIndexer.getExtensibleIndexID();
    return newExtensibleIndex(indexName, attrType, extIndexer);
  }
  private Index newExtensibleIndex(String indexName, AttributeType attrType,
      ExtensibleIndexer extIndexer)
  {
    return newIndex(indexName, new JEExtensibleIndexer(attrType, extIndexer),
        indexConfig.getIndexEntryLimit());
  }
  /**
@@ -1536,10 +1525,7 @@
    if(extensibleIndexes!=null)
    {
      for(Index extensibleIndex:extensibleIndexes.getIndexes())
      {
        dbList.add(extensibleIndex);
      }
      dbList.addAll(extensibleIndexes.getIndexes());
    }
  }
@@ -1625,16 +1611,15 @@
      AttributeType attrType = cfg.getAttribute();
      String name =
        entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID();
      int indexEntryLimit = cfg.getIndexEntryLimit();
      JEIndexConfig config = new JEIndexConfig(cfg.getSubstringLength());
      final int indexEntryLimit = cfg.getIndexEntryLimit();
      final JEIndexConfig config = new JEIndexConfig(cfg.getSubstringLength());
      if (cfg.getIndexType().contains(LocalDBIndexCfgDefn.IndexType.EQUALITY))
      {
        if (equalityIndex == null)
        {
          EqualityIndexer indexer = new EqualityIndexer(attrType);
          Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getEqualityMatchingRule(), indexer);
          equalityIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages);
          equalityIndex = openNewIndex(name, attrType,
              new EqualityIndexer(attrType), adminActionRequired, messages);
        }
        else
        {
@@ -1642,10 +1627,8 @@
          if(this.equalityIndex.setIndexEntryLimit(indexEntryLimit))
          {
            adminActionRequired.set(true);
            LocalizableMessage message =
                    NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                            equalityIndex.getName());
            messages.add(message);
            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
                .get(equalityIndex.getName()));
            this.equalityIndex.setIndexEntryLimit(indexEntryLimit);
          }
        }
@@ -1672,22 +1655,8 @@
        if(presenceIndex == null)
        {
          Indexer presenceIndexer = new PresenceIndexer(attrType);
          presenceIndex = new Index(name + ".presence",
                                    presenceIndexer,
                                    state,
                                    indexEntryLimit,
                                    cursorEntryLimit,
                                    false,
                                    env,
                                    entryContainer);
          presenceIndex.open();
          if(!presenceIndex.isTrusted())
          {
            adminActionRequired.set(true);
            messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(
                presenceIndex.getName()));
          }
          presenceIndex = newIndex(name + ".presence", presenceIndexer, indexEntryLimit);
          openIndex(presenceIndex, adminActionRequired, messages);
        }
        else
        {
@@ -1695,10 +1664,8 @@
          if(this.presenceIndex.setIndexEntryLimit(indexEntryLimit))
          {
            adminActionRequired.set(true);
            LocalizableMessage message =
                    NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                            presenceIndex.getName());
            messages.add(message);
            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
                .get(presenceIndex.getName()));
          }
        }
      }
@@ -1722,10 +1689,12 @@
      if (cfg.getIndexType().contains(LocalDBIndexCfgDefn.IndexType.SUBSTRING))
      {
        SubstringIndexer indexer = new SubstringIndexer(attrType, config);
        Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), indexer);
        Indexer extIndexer = new JEExtensibleIndexer(attrType, indexer);
        if(substringIndex == null)
        {
          substringIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages);
          Index index = newIndex(name + "." + indexer.getExtensibleIndexID(),
              extIndexer, indexEntryLimit);
          substringIndex = openIndex(index, adminActionRequired, messages);
        }
        else
        {
@@ -1733,10 +1702,8 @@
          if(this.substringIndex.setIndexEntryLimit(indexEntryLimit))
          {
            adminActionRequired.set(true);
            LocalizableMessage message =
                    NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                            substringIndex.getName());
            messages.add(message);
            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
                .get(substringIndex.getName()));
          }
          if (indexConfig.getSubstringLength() != cfg.getSubstringLength())
@@ -1766,9 +1733,8 @@
      {
        if(orderingIndex == null)
        {
          OrderingIndexer indexer = new OrderingIndexer(attrType);
          Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getOrderingMatchingRule(), indexer);
          orderingIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages);
          orderingIndex = openNewIndex(name, attrType,
              new OrderingIndexer(attrType), adminActionRequired, messages);
        }
        else
        {
@@ -1776,10 +1742,8 @@
          if(this.orderingIndex.setIndexEntryLimit(indexEntryLimit))
          {
            adminActionRequired.set(true);
            LocalizableMessage message =
                    NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                            orderingIndex.getName());
            messages.add(message);
            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
                .get(orderingIndex.getName()));
          }
        }
      }
@@ -1805,9 +1769,8 @@
      {
        if(approximateIndex == null)
        {
          ApproximateIndexer indexer = new ApproximateIndexer(attrType);
          Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getApproximateMatchingRule(), indexer);
          approximateIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages);
          approximateIndex = openNewIndex(name, attrType,
              new ApproximateIndexer(attrType), adminActionRequired, messages);
        }
        else
        {
@@ -1815,10 +1778,8 @@
          if(this.approximateIndex.setIndexEntryLimit(indexEntryLimit))
          {
            adminActionRequired.set(true);
            LocalizableMessage message =
                    NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                            approximateIndex.getName());
            messages.add(message);
            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
                .get(approximateIndex.getName()));
          }
        }
      }
@@ -1853,8 +1814,7 @@
        for(String ruleName:extensibleRules)
        {
          ExtensibleMatchingRule rule =
                  DirectoryServer.getExtensibleMatchingRule(
                                            toLowerCase(ruleName));
              DirectoryServer.getExtensibleMatchingRule(toLowerCase(ruleName));
           if(rule == null)
          {
            logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
@@ -1862,34 +1822,15 @@
          }
          validRules.add(rule);
          Map<String,Index> indexMap = new HashMap<String,Index>();
          for(ExtensibleIndexer indexer: rule.getIndexers(config))
          for (ExtensibleIndexer indexer : rule.getIndexers())
          {
            String indexID = attrType.getNameOrOID() + "." + indexer.getIndexID();
            if(!extensibleIndexes.isIndexPresent(indexID))
            {
              Indexer extensibleIndexer =
                      new JEExtensibleIndexer(attrType,
                                                 rule,
                                                 indexer);
              String indexName =  entryContainer.getDatabasePrefix() + "_"
                      + indexID;
              Index extensibleIndex = new Index(indexName,
                                        extensibleIndexer,
                                        state,
                                        indexEntryLimit,
                                        cursorEntryLimit,
                                        false,
                                        env,
                                        entryContainer);
              extensibleIndexes.addIndex(extensibleIndex,indexID);
              extensibleIndex.open();
              if(!extensibleIndex.isTrusted())
              {
                adminActionRequired.set(true);
                messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(
                    extensibleIndex.getName()));
              }
              String indexName =  entryContainer.getDatabasePrefix() + "_" + indexID;
              Index extIndex = newExtensibleIndex(indexName, attrType, indexer);
              extensibleIndexes.addIndex(extIndex,indexID);
              openIndex(extIndex, adminActionRequired, messages);
            }
            else
            {
@@ -1897,38 +1838,26 @@
              if(extensibleIndex.setIndexEntryLimit(indexEntryLimit))
              {
                adminActionRequired.set(true);
                LocalizableMessage message =
                      NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                              extensibleIndex.getName());
                messages.add(message);
                messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD
                    .get(extensibleIndex.getName()));
              }
              if(indexConfig.getSubstringLength() !=
              cfg.getSubstringLength())
              if (indexConfig.getSubstringLength() != cfg.getSubstringLength())
              {
                Indexer extensibleIndexer =
                      new JEExtensibleIndexer(attrType,
                                                  rule,
                                                 indexer);
                extensibleIndex.setIndexer(extensibleIndexer);
                extensibleIndex.setIndexer(
                    new JEExtensibleIndexer(attrType, indexer));
              }
            }
            extensibleIndexes.addRule(indexID, rule);
            indexMap.put(indexer.getExtensibleIndexID(), extensibleIndexes.getIndex(indexID));
          }
          IndexQueryFactory<IndexQuery> factory =
          final IndexQueryFactory<IndexQuery> factory =
              new IndexQueryFactoryImpl(indexMap, config);
          extensibleIndexes.addQueryFactory(rule, factory);
        }
        //Some rules might have been removed from the configuration.
        Set<ExtensibleMatchingRule> deletedRules =
                new HashSet<ExtensibleMatchingRule>();
        for(ExtensibleMatchingRule r:extensibleIndexes.getRules())
        {
          if(!validRules.contains(r))
          {
            deletedRules.add(r);
          }
        }
            new HashSet<ExtensibleMatchingRule>(extensibleIndexes.getRules());
        deletedRules.removeAll(validRules);
        if(deletedRules.size() > 0)
        {
          entryContainer.exclusiveLock.lock();
@@ -1939,7 +1868,7 @@
              Set<ExtensibleMatchingRule> rules =
                      new HashSet<ExtensibleMatchingRule>();
              List<String> ids = new ArrayList<String>();
              for(ExtensibleIndexer indexer: rule.getIndexers(config))
              for (ExtensibleIndexer indexer : rule.getIndexers())
              {
                String id = attrType.getNameOrOID()  + "." + indexer.getIndexID();
                rules.addAll(extensibleIndexes.getRules(id));
@@ -1950,8 +1879,7 @@
                //Rule has been already deleted.
                continue;
              }
              //If all the rules are part of the deletedRules, delete
              //this index.
              //If all the rules are part of the deletedRules, delete this index
              if(deletedRules.containsAll(rules))
              {
                //it is safe to delete this index as it is not shared.
@@ -1959,7 +1887,6 @@
                {
                  Index extensibleIndex = extensibleIndexes.getIndex(indexID);
                  entryContainer.deleteDatabase(extensibleIndex);
                  extensibleIndex = null;
                  extensibleIndexes.deleteIndex(indexID);
                  extensibleIndexes.deleteRule(indexID);
                }
@@ -1989,7 +1916,6 @@
            for(Index extensibleIndex:extensibleIndexes.getIndexes())
            {
              entryContainer.deleteDatabase(extensibleIndex);
              extensibleIndex =  null;
            }
            extensibleIndexes.deleteAll();
          }
@@ -2013,19 +1939,24 @@
    }
  }
  private Index openNewIndex(String name, Indexer indexer, ExtensibleIndexer extIndexer,
      AtomicBoolean adminActionRequired, ArrayList<LocalizableMessage> messages)
  private Index openNewIndex(String name, AttributeType attrType,
      ExtensibleIndexer indexer, AtomicBoolean adminActionRequired,
      ArrayList<LocalizableMessage> messages)
  {
    Index index = new Index(name + "." + extIndexer.getExtensibleIndexID(), indexer,
        state, indexConfig.getIndexEntryLimit(), cursorEntryLimit, false, env,
        entryContainer);
    String indexName = name + "." + indexer.getExtensibleIndexID();
    Index index = newExtensibleIndex(indexName, attrType, indexer);
    return openIndex(index, adminActionRequired, messages);
  }
  private Index openIndex(Index index, AtomicBoolean adminActionRequired,
      ArrayList<LocalizableMessage> messages)
  {
    index.open();
    if (!index.isTrusted())
    {
      adminActionRequired.set(true);
      messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(index
          .getName()));
      messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(index.getName()));
    }
    return index;
  }
@@ -2334,9 +2265,7 @@
      if(debugBuffer != null)
      {
        debugBuffer.append("[INDEX:");
        JEIndexConfig config =
                new JEIndexConfig(indexConfig.getSubstringLength());
        for(ExtensibleIndexer indexer :  rule.getIndexers(config))
        for (ExtensibleIndexer indexer : rule.getIndexers())
        {
          debugBuffer.append(" ")
                     .append(extensibleFilter.getAttributeType().getNameOrOID())
@@ -2426,18 +2355,14 @@
     * @return A Set of extensible matching rules corresponding to
     *                 an index ID.
     */
    private Set<ExtensibleMatchingRule>
            getRules(String indexID)
    private Set<ExtensibleMatchingRule> getRules(String indexID)
    {
      Set<ExtensibleMatchingRule> rules = id2RulesMap.get(indexID);
      if(rules == null)
      if (rules != null)
      {
        return Collections.emptySet();
        return Collections.unmodifiableSet(rules);
      }
      else
      {
        return Collections.unmodifiableSet(id2RulesMap.get(indexID));
      }
      return Collections.emptySet();
    }
    /**
opendj3-server-dev/src/server/org/opends/server/backends/jeb/JEExtensibleIndexer.java
@@ -35,7 +35,6 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DecodeException;
import org.opends.server.api.ExtensibleIndexer;
import org.opends.server.api.MatchingRule;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.Entry;
@@ -69,11 +68,9 @@
   *
   * @param attributeType The attribute type for which an indexer is
   *                                            required.
   * @param matchingRule  The extensible matching rule to be indexed.
   * @param extensibleIndexer The extensible indexer to be used.
   */
  public JEExtensibleIndexer(AttributeType attributeType,
          MatchingRule matchingRule,
          ExtensibleIndexer extensibleIndexer)
  {
    this.attributeType = attributeType;
opendj3-server-dev/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java
@@ -85,19 +85,15 @@
  private boolean substringMatchingRuleType;
  // Stores the list of available locales on this JVM.
  private static final Set<Locale> supportedLocales;
  private static final Set<Locale> supportedLocales = new HashSet<Locale>(
      Arrays.asList(Locale.getAvailableLocales()));
  // Current Configuration.
  private CollationMatchingRuleCfg currentConfig;
  // Map of OID and the Matching Rule.
  private final Map<String, MatchingRule> matchingRules;
  static
  {
    supportedLocales = new HashSet<Locale>();
    supportedLocales.addAll(Arrays.asList(Locale.getAvailableLocales()));
  }
  private final Map<String, MatchingRule> matchingRules =
      new HashMap<String, MatchingRule>();
@@ -106,8 +102,7 @@
   */
  public CollationMatchingRuleFactory()
  {
    // Initialize the matchingRules.
    matchingRules = new HashMap<String, MatchingRule>();
    super();
  }
@@ -131,8 +126,7 @@
   * @param matchingRule
   *          instance of a MatchingRule.
   */
  private void addMatchingRule(String oid,
      MatchingRule matchingRule)
  private void addMatchingRule(String oid, MatchingRule matchingRule)
  {
    matchingRules.put(oid, matchingRule);
  }
@@ -169,8 +163,7 @@
   * @param ruleTypes
   *          The Set containing allowed matching rule types.
   */
  private void initializeMatchingRuleTypes(
      SortedSet<MatchingRuleType> ruleTypes)
  private void initializeMatchingRuleTypes(SortedSet<MatchingRuleType> ruleTypes)
  {
    for (MatchingRuleType type : ruleTypes)
    {
@@ -223,9 +216,8 @@
   * {@inheritDoc}
   */
  @Override
  public void initializeMatchingRule(
      CollationMatchingRuleCfg configuration) throws ConfigException,
      InitializationException
  public void initializeMatchingRule(CollationMatchingRuleCfg configuration)
      throws ConfigException, InitializationException
  {
    initializeMatchingRuleTypes(configuration.getMatchingRuleType());
    for (String collation : configuration.getCollation())
@@ -298,8 +290,7 @@
      // 2. There is a change in the enable status
      // i.e. (disable->enable or enable->disable). In this case, the
      // ConfigManager will have already created the new Factory object.
      return new ConfigChangeResult(resultCode, adminActionRequired,
          messages);
      return new ConfigChangeResult(resultCode, adminActionRequired, messages);
    }
    // Since we have come here it means that this Factory is enabled and
@@ -317,6 +308,7 @@
    initializeMatchingRuleTypes(configuration.getMatchingRuleType());
    for (String collation : configuration.getCollation())
    {
      // validation has already been performed in isConfigurationChangeAcceptable()
      CollationMapper mapper = new CollationMapper(collation);
      String languageTag = mapper.getLanguageTag();
      Locale locale = getLocale(languageTag);
@@ -343,8 +335,7 @@
      messages.add(message);
    }
    currentConfig = configuration;
    return new ConfigChangeResult(resultCode, adminActionRequired,
        messages);
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
@@ -423,8 +414,7 @@
   * @param locale
   *          Locale value
   */
  private void createLessThanMatchingRule(CollationMapper mapper,
      Locale locale)
  private void createLessThanMatchingRule(CollationMapper mapper, Locale locale)
  {
    if (!lessThanMatchingRuleType) return;
@@ -477,8 +467,7 @@
   * @param locale
   *          Locale value
   */
  private void createEqualityMatchingRule(CollationMapper mapper,
      Locale locale)
  private void createEqualityMatchingRule(CollationMapper mapper, Locale locale)
  {
    if (!equalityMatchingRuleType)
    {
@@ -907,8 +896,7 @@
     * {@inheritDoc}
     */
    @Override
    public Collection<ExtensibleIndexer> getIndexers(
        IndexingOptions indexingOptions)
    public Collection<ExtensibleIndexer> getIndexers()
    {
      if (indexer == null)
      {
@@ -1293,8 +1281,7 @@
      // Normalize the Values in the following format:
      // initialLength, initial, numberofany, anyLength1, any1,
      // anyLength2, any2, ..., anyLengthn, anyn, finalLength,
      // final
      // anyLength2, any2, ..., anyLengthn, anyn, finalLength, final
      List<Integer> normalizedList = new ArrayList<Integer>();
      if (subInitial == null)
@@ -1335,7 +1322,6 @@
      {
        normalizedBytes[i] = normalizedList.get(i).byteValue();
      }
      return ByteString.wrap(normalizedBytes);
    }
@@ -1470,28 +1456,13 @@
     * {@inheritDoc}
     */
    @Override
    public final Collection<ExtensibleIndexer> getIndexers(
        IndexingOptions indexingOptions)
    public final Collection<ExtensibleIndexer> getIndexers()
    {
      Collection<ExtensibleIndexer> indexers =
          new ArrayList<ExtensibleIndexer>();
      int substrLength = 6; // Default substring length;
      List<ExtensibleIndexer> indexers = new ArrayList<ExtensibleIndexer>();
      if (subIndexer == null)
      {
        if (indexingOptions != null)
        {
          substrLength = indexingOptions.substringKeySize();
        }
        subIndexer =
            new CollationSubstringExtensibleIndexer(this, substrLength);
        subIndexer = new CollationSubstringExtensibleIndexer(this);
      }
      else if (indexingOptions != null
          && indexingOptions.substringKeySize() != subIndexer
              .getSubstringLength())
      {
        subIndexer.setSubstringLength(substrLength);
      }
      if (indexer == null)
      {
        indexer = new CollationSharedExtensibleIndexer(this);
@@ -1578,11 +1549,10 @@
     *          The length of the substring.
     * @return The candidate entry IDs.
     */
    private <T> T matchSubstring(String value,
        IndexQueryFactory<T> factory)
    private <T> T matchSubstring(String value, IndexQueryFactory<T> factory)
    { // FIXME Code similar to
      // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.substringMatch()
      int substrLength = subIndexer.getSubstringLength();
      int substrLength = factory.getIndexingOptions().substringKeySize();
      if (value.length() < substrLength)
      {
        return createRangeMatchQuery(value, factory, subIndexer);
@@ -1629,8 +1599,7 @@
      if (subInitial != null)
      {
        // Always use the shared indexer for initial match.
        T query = matchInitialSubstring(subInitial, factory);
        queries.add(query);
        queries.add(matchInitialSubstring(subInitial, factory));
      }
      if (subAny != null && subAny.size() > 0)
@@ -2030,40 +1999,27 @@
  private final class CollationSubstringExtensibleIndexer extends
      ExtensibleIndexer
  {
    // The CollationSubstringMatching Rule.
    private final CollationSubstringMatchingRule matchingRule;
    // The substring length.
    private int substringLen;
    /**
     * Creates a new instance of CollationSubstringExtensibleIndexer.
     *
     * @param matchingRule
     *          The CollationSubstringMatching Rule.
     * @param substringLen
     *          The substring length.
     */
    private CollationSubstringExtensibleIndexer(
        CollationSubstringMatchingRule matchingRule, int substringLen)
        CollationSubstringMatchingRule matchingRule)
    {
      this.matchingRule = matchingRule;
      this.substringLen = substringLen;
    }
    /**
     * {@inheritDoc}
     */
    /** {@inheritDoc} */
    @Override
    public void createKeys(Schema schema, ByteSequence value,
        IndexingOptions options, Collection<ByteString> keys)
    { // TODO merge with AbstractSubstringMatchingRuleImpl.SubstringIndexer.createKeys();
      String normValue = value.toString();
      int keyLength = substringLen;
      int keyLength = options.substringKeySize();
      for (int i = 0, remain = normValue.length(); remain > 0; i++, remain--)
      {
        int len = Math.min(keyLength, remain);
@@ -2078,42 +2034,13 @@
      return matchingRule.getIndexName() + "." + getExtensibleIndexID();
    }
    /**
     * {@inheritDoc}
     */
    /** {@inheritDoc} */
    @Override
    public String getExtensibleIndexID()
    {
      return EXTENSIBLE_INDEXER_ID_SUBSTRING;
    }
    /**
     * Returns the substring length.
     *
     * @return The length of the substring.
     */
    private int getSubstringLength()
    {// TODO JNR remove
      return substringLen;
    }
    /**
     * Sets the substring length.
     *
     * @param substringLen
     *          The substring length.
     */
    private void setSubstringLength(int substringLen)
    {// TODO JNR remove
      this.substringLen = substringLen;
    }
  }
  /**
opendj3-server-dev/src/server/org/opends/server/schema/TimeBasedMatchingRuleFactory.java
@@ -323,8 +323,7 @@
    /** {@inheritDoc} */
    @Override
    public Collection<ExtensibleIndexer> getIndexers(
        IndexingOptions indexingOptions)
    public Collection<ExtensibleIndexer> getIndexers()
    {
      if(indexer == null)
      {
@@ -891,8 +890,7 @@
    /** {@inheritDoc} */
    @Override
    public Collection<ExtensibleIndexer> getIndexers(
        IndexingOptions indexingOptions)
    public Collection<ExtensibleIndexer> getIndexers()
    {
      if(indexer == null)
      {
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
@@ -38,7 +38,6 @@
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.opends.server.admin.std.meta.LocalDBBackendCfgDefn;
import org.opends.server.admin.std.server.LocalDBBackendCfg;
import org.opends.server.api.ExtensibleIndexer;
import org.opends.server.controls.SubtreeDeleteControl;
import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
@@ -870,15 +869,13 @@
  private Indexer newOrderingIndexer(AttributeIndex index)
  {
    AttributeType attrType = index.getAttributeType();
    ExtensibleIndexer extIndexer = new OrderingIndexer(index.getAttributeType());
    return new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), extIndexer);
    return new JEExtensibleIndexer(attrType, new OrderingIndexer(attrType));
  }
  private Indexer newEqualityIndexer(AttributeIndex index)
  {
    AttributeType attrType = index.getAttributeType();
    ExtensibleIndexer extIndexer = new EqualityIndexer(index.getAttributeType());
    return new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), extIndexer);
    return new JEExtensibleIndexer(attrType, new EqualityIndexer(attrType));
  }
  private Indexer newSubstringIndexer(AttributeIndex index)
@@ -887,8 +884,7 @@
    when(options.substringKeySize()).thenReturn(
        index.getConfiguration().getSubstringLength());
    AttributeType attrType = index.getAttributeType();
    ExtensibleIndexer extIndexer = new SubstringIndexer(attrType, options);
    return new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), extIndexer);
    return new JEExtensibleIndexer(attrType, new SubstringIndexer(attrType, options));
  }
  private void assertIndexContainsID(Indexer indexer, Entry entry, Index index,
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CollationMatchingRuleFactoryTest.java
New file
@@ -0,0 +1,95 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
 * or http://forgerock.org/license/CDDLv1.0.html.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at legal-notices/CDDLv1_0.txt.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *      Copyright 2014 ForgeRock AS
 */
package org.opends.server.schema;
import java.util.*;
import org.forgerock.opendj.config.server.ConfigException;
import org.opends.server.admin.std.meta.CollationMatchingRuleCfgDefn.MatchingRuleType;
import org.opends.server.admin.std.server.CollationMatchingRuleCfg;
import org.opends.server.api.MatchingRule;
import org.opends.server.types.InitializationException;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
@SuppressWarnings("javadoc")
public class CollationMatchingRuleFactoryTest extends SchemaTestCase
{
  @Test
  public void testMatchingRulesBuilding() throws Exception
  {
    final List<String> allRuleNames = new ArrayList<String>();
    final Collection<MatchingRule> mRules =
        getMatchingRules("fr:1.3.6.1.4.1.42.2.27.9.4.76.1");
    for (MatchingRule rule : mRules)
    {
      allRuleNames.addAll(rule.getNames());
    }
    assertThat(allRuleNames).containsOnly("fr",
        "fr.1", "fr.lt", "fr.2", "fr.lte",
        "fr.3", "fr.eq",
        "fr.4", "fr.gte", "fr.5", "fr.gt",
        "fr.6", "fr.sub");
  }
  @Test
  public void testRecursiveMatchingRulesBuilding() throws Exception
  {
    final List<String> allRuleNames = new ArrayList<String>();
    final Collection<MatchingRule> mRules =
        getMatchingRules("fr-FR:1.3.6.1.4.1.42.2.27.9.4.76.1");
    for (MatchingRule rule : mRules)
    {
      allRuleNames.addAll(rule.getNames());
    }
    assertThat(allRuleNames).containsOnly("fr-FR",
        "fr-FR.1", "fr-FR.lt", "fr-FR.2", "fr-FR.lte",
        "fr-FR.3", "fr-FR.eq",
        "fr-FR.4", "fr-FR.gte", "fr-FR.5", "fr-FR.gt",
        "fr-FR.6", "fr-FR.sub");
  }
  private Collection<MatchingRule> getMatchingRules(String collationOID)
      throws ConfigException, InitializationException
  {
    final CollationMatchingRuleFactory factory =
        new CollationMatchingRuleFactory();
    final CollationMatchingRuleCfg cfg = mock(CollationMatchingRuleCfg.class);
    when(cfg.getMatchingRuleType()).thenReturn(
        toSortedSet(EnumSet.allOf(MatchingRuleType.class)));
    when(cfg.getCollation()).thenReturn(
        toSortedSet(Collections.singleton(collationOID)));
    factory.initializeMatchingRule(cfg);
    return factory.getMatchingRules();
  }
  private <T> SortedSet<T> toSortedSet(Set<T> set)
  {
    return new TreeSet<T>(set);
  }
}
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/TimeBasedMatchingRuleFactoryTest.java
@@ -31,7 +31,6 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.DecodeException;
import org.opends.server.admin.std.server.CollationMatchingRuleCfg;
import org.opends.server.admin.std.server.MatchingRuleCfg;
import org.opends.server.api.MatchingRule;
import org.opends.server.util.TimeThread;
@@ -225,7 +224,7 @@
  {
    final TimeBasedMatchingRuleFactory factory =
        new TimeBasedMatchingRuleFactory();
    final MatchingRuleCfg cfg = mock(CollationMatchingRuleCfg.class);
    final MatchingRuleCfg cfg = mock(MatchingRuleCfg.class);
    factory.initializeMatchingRule(cfg);
    final Collection<MatchingRule> mRules = factory.getMatchingRules();
    verifyNoMoreInteractions(cfg);