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.api.OrderingMatchingRule;
034 import org.opends.server.types.Attribute;
035 import org.opends.server.types.AttributeType;
036 import org.opends.server.types.AttributeValue;
037 import org.opends.server.types.DirectoryException;
038 import org.opends.server.types.Entry;
039 import org.opends.server.types.Modification;
040
041 import java.util.*;
042
043 /**
044 * An implementation of an Indexer for attribute ordering.
045 */
046 public class OrderingIndexer extends Indexer
047 {
048 /**
049 * The tracer object for the debug logger.
050 */
051 private static final DebugTracer TRACER = getTracer();
052
053
054
055 /**
056 * The attribute type for which this instance will
057 * generate index keys.
058 */
059 private AttributeType attributeType;
060
061 /**
062 * The attribute type ordering matching rule which is also the
063 * comparator for the index keys generated by this class.
064 */
065 private OrderingMatchingRule orderingRule;
066
067
068 /**
069 * Create a new attribute ordering indexer for the given index configuration.
070 * @param attributeType The attribute type for which an indexer is
071 * required.
072 */
073 public OrderingIndexer(AttributeType attributeType)
074 {
075 this.attributeType = attributeType;
076 this.orderingRule = attributeType.getOrderingMatchingRule();
077 }
078
079 /**
080 * Get a string representation of this object. The returned value is
081 * used to name an index created using this object.
082 * @return A string representation of this object.
083 */
084 public String toString()
085 {
086 return attributeType.getNameOrOID() + ".ordering";
087 }
088
089 /**
090 * Get the comparator that must be used to compare index keys
091 * generated by this class.
092 *
093 * @return A byte array comparator.
094 */
095 public Comparator<byte[]> getComparator()
096 {
097 return orderingRule;
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 * Generate the set of index keys to be added and the set of index keys
118 * to be deleted for an entry that has been replaced.
119 *
120 * @param oldEntry The original entry contents.
121 * @param newEntry The new entry contents.
122 * @param modifiedKeys The map into which the modified keys will be inserted.
123 */
124 public void replaceEntry(Entry oldEntry, Entry newEntry,
125 Map<byte[], Boolean> modifiedKeys)
126 {
127 List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
128 List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
129
130 indexAttribute(oldAttributes, modifiedKeys, false);
131 indexAttribute(newAttributes, modifiedKeys, true);
132 }
133
134 /**
135 * Generate the set of index keys to be added and the set of index keys
136 * to be deleted for an entry that was modified.
137 *
138 * @param oldEntry The original entry contents.
139 * @param newEntry The new entry contents.
140 * @param mods The set of modifications that were applied to the entry.
141 * @param modifiedKeys The map into which the modified keys will be inserted.
142 */
143 public void modifyEntry(Entry oldEntry, Entry newEntry,
144 List<Modification> mods,
145 Map<byte[], Boolean> modifiedKeys)
146 {
147 List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
148 List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
149
150 indexAttribute(oldAttributes, modifiedKeys, false);
151 indexAttribute(newAttributes, modifiedKeys, true);
152 }
153
154
155 /**
156 * Generate the set of index keys for a set of attribute values.
157 * @param values The set of attribute values to be indexed.
158 * @param keys The set into which the keys will be inserted.
159 */
160 private void indexValues(Set<AttributeValue> values,
161 Set<byte[]> keys)
162 {
163 if (values == null) return;
164
165 for (AttributeValue value : values)
166 {
167 try
168 {
169 byte[] keyBytes =
170 orderingRule.normalizeValue(value.getValue()).value();
171
172 keys.add(keyBytes);
173 }
174 catch (DirectoryException e)
175 {
176 if (debugEnabled())
177 {
178 TRACER.debugCaught(DebugLogLevel.ERROR, e);
179 }
180 }
181 }
182 }
183
184 /**
185 * Generate the set of index keys for an attribute.
186 * @param attrList The attribute to be indexed.
187 * @param keys The set into which the keys will be inserted.
188 */
189 private void indexAttribute(List<Attribute> attrList,
190 Set<byte[]> keys)
191 {
192 if (attrList == null) return;
193
194 for (Attribute attr : attrList)
195 {
196 indexValues(attr.getValues(), keys);
197 }
198 }
199
200
201 /**
202 * Generate the set of index keys for an attribute.
203 * @param attrList The attribute to be indexed.
204 * @param modifiedKeys The map into which the modified
205 * keys will be inserted.
206 * @param insert <code>true</code> if generated keys should
207 * be inserted or <code>false</code> otherwise.
208 */
209 private void indexAttribute(List<Attribute> attrList,
210 Map<byte[], Boolean> modifiedKeys,
211 Boolean insert)
212 {
213 if (attrList == null) return;
214
215 for (Attribute attr : attrList)
216 {
217 indexValues(attr.getValues(), modifiedKeys, insert);
218 }
219 }
220
221 /**
222 * Generate the set of index keys for a set of attribute values.
223 * @param values The set of attribute values to be indexed.
224 * @param modifiedKeys The map into which the modified
225 * keys will be inserted.
226 * @param insert <code>true</code> if generated keys should
227 * be inserted or <code>false</code> otherwise.
228 */
229 private void indexValues(Set<AttributeValue> values,
230 Map<byte[], Boolean> modifiedKeys,
231 Boolean insert)
232 {
233 if (values == null) return;
234
235 for (AttributeValue value : values)
236 {
237 try
238 {
239 byte[] keyBytes =
240 orderingRule.normalizeValue(value.getValue()).value();
241
242 Boolean cInsert = modifiedKeys.get(keyBytes);
243 if(cInsert == null)
244 {
245 modifiedKeys.put(keyBytes, insert);
246 }
247 else if(!cInsert.equals(insert))
248 {
249 modifiedKeys.remove(keyBytes);
250 }
251 }
252 catch (DirectoryException e)
253 {
254 if (debugEnabled())
255 {
256 TRACER.debugCaught(DebugLogLevel.ERROR, e);
257 }
258 }
259 }
260 }
261 }