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
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.backends.jeb;
028    
029    import static org.opends.server.loggers.debug.DebugLogger.*;
030    import org.opends.server.loggers.debug.DebugTracer;
031    import org.opends.server.types.DebugLogLevel;
032    
033    import org.opends.server.types.Attribute;
034    import org.opends.server.types.AttributeType;
035    import org.opends.server.types.AttributeValue;
036    import org.opends.server.types.DirectoryException;
037    import org.opends.server.types.Entry;
038    import org.opends.server.types.Modification;
039    
040    import java.util.*;
041    
042    /**
043     * An implementation of an Indexer for attribute equality.
044     */
045    public class EqualityIndexer extends Indexer
046    {
047      /**
048       * The tracer object for the debug logger.
049       */
050      private static final DebugTracer TRACER = getTracer();
051    
052    
053    
054      /**
055       * The comparator for index keys generated by this class.
056       */
057      private static final Comparator<byte[]> comparator =
058           new AttributeIndex.KeyComparator();
059    
060      /**
061       * The attribute type for which this instance will
062       * generate index keys.
063       */
064      private AttributeType attributeType;
065    
066    
067      /**
068       * Create a new attribute equality indexer for the given attribute type.
069       * @param attributeType The attribute type for which an indexer is
070       * required.
071       */
072      public EqualityIndexer(AttributeType attributeType)
073      {
074        this.attributeType = attributeType;
075      }
076    
077      /**
078       * Get a string representation of this object.  The returned value is
079       * used to name an index created using this object.
080       * @return A string representation of this object.
081       */
082      public String toString()
083      {
084        return attributeType.getNameOrOID() + ".equality";
085      }
086    
087      /**
088       * Get the comparator that must be used to compare index keys
089       * generated by this class.
090       *
091       * @return A byte array comparator.
092       */
093      public Comparator<byte[]> getComparator()
094      {
095        return comparator;
096      }
097    
098    
099    
100      /**
101       * Generate the set of index keys for an entry.
102       *
103       * @param entry The entry.
104       * @param keys The set into which the generated keys will be inserted.
105       */
106      public void indexEntry(Entry entry, Set<byte[]> keys)
107      {
108        List<Attribute> attrList =
109             entry.getAttribute(attributeType);
110        if (attrList != null)
111        {
112          indexAttribute(attrList, keys);
113        }
114      }
115    
116    
117    
118      /**
119       * Generate the set of index keys to be added and the set of index keys
120       * to be deleted for an entry that has been replaced.
121       *
122       * @param oldEntry The original entry contents.
123       * @param newEntry The new entry contents.
124       * @param modifiedKeys The map into which the modified keys will be inserted.
125       */
126      public void replaceEntry(Entry oldEntry, Entry newEntry,
127                               Map<byte[], Boolean> modifiedKeys)
128      {
129        List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
130        List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
131    
132        indexAttribute(oldAttributes, modifiedKeys, false);
133        indexAttribute(newAttributes, modifiedKeys, true);
134      }
135    
136    
137    
138    
139      /**
140       * Generate the set of index keys to be added and the set of index keys
141       * to be deleted for an entry that was modified.
142       *
143       * @param oldEntry The original entry contents.
144       * @param newEntry The new entry contents.
145       * @param mods The set of modifications that were applied to the entry.
146       * @param modifiedKeys The map into which the modified keys will be inserted.
147       */
148      public void modifyEntry(Entry oldEntry, Entry newEntry,
149                              List<Modification> mods,
150                              Map<byte[], Boolean> modifiedKeys)
151      {
152        List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
153        List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
154    
155        indexAttribute(oldAttributes, modifiedKeys, false);
156        indexAttribute(newAttributes, modifiedKeys, true);
157      }
158    
159      /**
160       * Generate the set of index keys for a set of attribute values.
161       * @param values The set of attribute values to be indexed.
162       * @param keys The set into which the keys will be inserted.
163       */
164      private void indexValues(Set<AttributeValue> values,
165                               Set<byte[]> keys)
166      {
167        if (values == null) return;
168    
169        for (AttributeValue value : values)
170        {
171          try
172          {
173            byte[] keyBytes = value.getNormalizedValue().value();
174    
175            keys.add(keyBytes);
176          }
177          catch (DirectoryException e)
178          {
179            if (debugEnabled())
180            {
181              TRACER.debugCaught(DebugLogLevel.ERROR, e);
182            }
183          }
184        }
185      }
186    
187      /**
188       * Generate the set of index keys for an attribute.
189       * @param attrList The attribute to be indexed.
190       * @param keys The set into which the keys will be inserted.
191       */
192      private void indexAttribute(List<Attribute> attrList,
193                                  Set<byte[]> keys)
194      {
195        if (attrList == null) return;
196    
197        for (Attribute attr : attrList)
198        {
199          indexValues(attr.getValues(), keys);
200        }
201      }
202    
203      /**
204       * Generate the set of index keys for an attribute.
205       * @param attrList The attribute to be indexed.
206       * @param modifiedKeys The map into which the modified
207       * keys will be inserted.
208       * @param insert <code>true</code> if generated keys should
209       * be inserted or <code>false</code> otherwise.
210       */
211      private void indexAttribute(List<Attribute> attrList,
212                                  Map<byte[], Boolean> modifiedKeys,
213                                  Boolean insert)
214      {
215        if (attrList == null) return;
216    
217        for (Attribute attr : attrList)
218        {
219          indexValues(attr.getValues(), modifiedKeys, insert);
220        }
221      }
222    
223      /**
224       * Generate the set of index keys for a set of attribute values.
225       * @param values The set of attribute values to be indexed.
226       * @param modifiedKeys The map into which the modified
227       *  keys will be inserted.
228       * @param insert <code>true</code> if generated keys should
229       * be inserted or <code>false</code> otherwise.
230       */
231      private void indexValues(Set<AttributeValue> values,
232                               Map<byte[], Boolean> modifiedKeys,
233                               Boolean insert)
234      {
235        if (values == null) return;
236    
237        for (AttributeValue value : values)
238        {
239          try
240          {
241            byte[] keyBytes = value.getNormalizedValue().value();
242    
243            Boolean cInsert = modifiedKeys.get(keyBytes);
244            if(cInsert == null)
245            {
246              modifiedKeys.put(keyBytes, insert);
247            }
248            else if(!cInsert.equals(insert))
249            {
250              modifiedKeys.remove(keyBytes);
251            }
252          }
253          catch (DirectoryException e)
254          {
255            if (debugEnabled())
256            {
257              TRACER.debugCaught(DebugLogLevel.ERROR, e);
258            }
259          }
260        }
261      }
262    }