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 }