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 }