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