001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2009-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027package org.opends.server.backends.jeb;
028
029import java.util.HashSet;
030import java.util.List;
031import java.util.Map;
032import java.util.Set;
033
034import org.forgerock.i18n.slf4j.LocalizedLogger;
035import org.forgerock.opendj.ldap.ByteString;
036import org.forgerock.opendj.ldap.DecodeException;
037import org.forgerock.opendj.ldap.schema.Schema;
038import org.opends.server.types.Attribute;
039import org.opends.server.types.AttributeType;
040import org.opends.server.types.Entry;
041import org.opends.server.types.Modification;
042
043/**
044 * This class implements an attribute indexer for matching rules in JE Backend.
045 */
046public final class AttributeIndexer extends Indexer
047{
048  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
049
050  /** The attribute type for which this instance will generate index keys. */
051  private final AttributeType attributeType;
052
053  /**
054   * The indexer which will generate the keys
055   * for the associated extensible matching rule.
056   */
057  private final org.forgerock.opendj.ldap.spi.Indexer indexer;
058
059  /**
060   * Creates a new extensible indexer for JE backend.
061   *
062   * @param attributeType The attribute type for which an indexer is
063   *                                            required.
064   * @param extensibleIndexer The extensible indexer to be used.
065   */
066  public AttributeIndexer(AttributeType attributeType, org.forgerock.opendj.ldap.spi.Indexer extensibleIndexer)
067  {
068    this.attributeType = attributeType;
069    this.indexer = extensibleIndexer;
070  }
071
072  /** {@inheritDoc} */
073  @Override
074  public String toString()
075  {
076    return attributeType.getNameOrOID() + "." + indexer.getIndexID();
077  }
078
079  /** {@inheritDoc} */
080  @Override
081  public void indexEntry(Entry entry, Set<ByteString> keys)
082  {
083    final List<Attribute> attrList = entry.getAttribute(attributeType);
084    if (attrList != null)
085    {
086      indexAttribute(attrList, keys);
087    }
088  }
089
090  /** {@inheritDoc} */
091  @Override
092  public void modifyEntry(Entry oldEntry, Entry newEntry,
093      List<Modification> mods, Map<ByteString, Boolean> modifiedKeys)
094  {
095    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
096    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
097
098    indexAttribute(oldAttributes, modifiedKeys, false);
099    indexAttribute(newAttributes, modifiedKeys, true);
100  }
101
102
103
104  /**
105   * Generates the set of extensible  index keys for an attribute.
106   * @param attrList The attribute for which substring keys are required.
107   * @param keys The set into which the generated keys will be inserted.
108   */
109  private void indexAttribute(List<Attribute> attrList, Set<ByteString> keys)
110  {
111    if (attrList == null)
112    {
113      return;
114    }
115
116    for (Attribute attr : attrList)
117    {
118      if (!attr.isVirtual())
119      {
120        for (ByteString value : attr)
121        {
122          try
123          {
124            indexer.createKeys(Schema.getDefaultSchema(), value, keys);
125          }
126          catch (DecodeException e)
127          {
128            logger.traceException(e);
129          }
130        }
131      }
132    }
133  }
134
135  /**
136   * Generates the set of index keys for an attribute.
137   * @param attrList The attribute to be indexed.
138   * @param modifiedKeys The map into which the modified
139   * keys will be inserted.
140   * @param insert <code>true</code> if generated keys should
141   * be inserted or <code>false</code> otherwise.
142   */
143  private void indexAttribute(List<Attribute> attrList, Map<ByteString, Boolean> modifiedKeys, Boolean insert)
144  {
145    if (attrList == null)
146    {
147      return;
148    }
149
150    final Set<ByteString> keys = new HashSet<>();
151    indexAttribute(attrList, keys);
152    computeModifiedKeys(modifiedKeys, insert, keys);
153  }
154
155  /**
156   * Computes a map of index keys and a boolean flag indicating whether the
157   * corresponding key will be inserted or deleted.
158   *
159   * @param modifiedKeys
160   *          A map containing the keys and a boolean. Keys corresponding to the
161   *          boolean value <code>true</code> should be inserted and
162   *          <code>false</code> should be deleted.
163   * @param insert
164   *          <code>true</code> if generated keys should be inserted or
165   *          <code>false</code> otherwise.
166   * @param keys
167   *          The index keys to map.
168   */
169  private static void computeModifiedKeys(Map<ByteString, Boolean> modifiedKeys,
170      Boolean insert, Set<ByteString> keys)
171  {
172    for (ByteString key : keys)
173    {
174      Boolean cInsert = modifiedKeys.get(key);
175      if (cInsert == null)
176      {
177        modifiedKeys.put(key, insert);
178      }
179      else if (!cInsert.equals(insert))
180      {
181        modifiedKeys.remove(key);
182      }
183    }
184  }
185}