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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2008 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2015 ForgeRock AS 026 */ 027package org.opends.server.controls; 028 029import static org.opends.messages.ProtocolMessages.*; 030 031import java.util.HashSet; 032import java.util.Iterator; 033import java.util.Set; 034 035import org.forgerock.i18n.LocalizableMessage; 036import org.opends.server.protocols.ldap.LDAPResultCode; 037import org.opends.server.types.LDAPException; 038 039/** 040 * This enumeration defines the set of possible change types that may be used in 041 * conjunction with the persistent search control, as defined in 042 * draft-ietf-ldapext-psearch. 043 * <p> 044 * It is a different type from {@link ChangeOperationType} to enforce type 045 * safety, despite mirroring it completely. 046 */ 047public enum PersistentSearchChangeType 048{ 049 /** The change type that will be used for add operations. */ 050 ADD(1), 051 052 /** The change type that will be used for delete operations. */ 053 DELETE(2), 054 055 /** The change type that will be used for modify operations. */ 056 MODIFY(4), 057 058 /** The change type that will be used for modify DN operations. */ 059 MODIFY_DN(8); 060 061 062 063 /** The integer value associated with this change type. */ 064 private int intValue; 065 066 /** 067 * Creates a new instance of a persistent search change type with the provided 068 * integer value. 069 * 070 * @param intValue The integer value associated with this change type. 071 */ 072 private PersistentSearchChangeType(int intValue) 073 { 074 this.intValue = intValue; 075 } 076 077 078 079 /** 080 * Retrieves the integer value associated with this change type. 081 * 082 * @return The integer value associated with this change type. 083 */ 084 public int intValue() 085 { 086 return intValue; 087 } 088 089 090 091 /** 092 * Retrieves a string representation of this persistent search change type. 093 * 094 * @return A string representation of this persistent search change type, or 095 * "unknown" if it has an unknown type. 096 */ 097 @Override 098 public String toString() 099 { 100 switch (intValue) 101 { 102 case 1: 103 return "add"; 104 case 2: 105 return "delete"; 106 case 4: 107 return "modify"; 108 case 8: 109 return "modDN"; 110 default: 111 return "unknown"; 112 } 113 } 114 115 116 117 /** 118 * Retrieves the change type associated with the provided integer value. 119 * 120 * @param intValue The integer value to decode as a change type. 121 * 122 * @return The change type corresponding to the provided integer value. 123 * 124 * @throws LDAPException If the provided integer value is not associated 125 * with a valid change type. 126 */ 127 public static PersistentSearchChangeType valueOf(int intValue) 128 throws LDAPException 129 { 130 switch (intValue) 131 { 132 case 1: 133 return ADD; 134 case 2: 135 return DELETE; 136 case 4: 137 return MODIFY; 138 case 8: 139 return MODIFY_DN; 140 default: 141 LocalizableMessage message = ERR_PSEARCH_CHANGETYPES_INVALID_TYPE.get(intValue); 142 throw new LDAPException(LDAPResultCode.CONSTRAINT_VIOLATION, message); 143 } 144 } 145 146 147 148 /** 149 * Decodes the provided int value into a set of change types as per the 150 * specification in draft-ietf-ldapext-psearch. 151 * 152 * @param intValue The integer value representing the encoded change types. 153 * 154 * @return The set of change types decoded from the provided integer value. 155 * 156 * @throws LDAPException If the provided integer value does not represent a 157 * valid encoded set of change types. 158 */ 159 public static Set<PersistentSearchChangeType> intToTypes(int intValue) 160 throws LDAPException 161 { 162 Set<PersistentSearchChangeType> changeTypes = new HashSet<>(4); 163 164 switch (intValue) 165 { 166 case 0: 167 // No change types are included. This won't be allowed because it 168 // doesn't make any sense. 169 LocalizableMessage message = ERR_PSEARCH_CHANGETYPES_NO_TYPES.get(); 170 throw new LDAPException(LDAPResultCode.CONSTRAINT_VIOLATION, message); 171 case 1: 172 changeTypes.add(ADD); 173 break; 174 case 2: 175 changeTypes.add(DELETE); 176 break; 177 case 3: 178 changeTypes.add(ADD); 179 changeTypes.add(DELETE); 180 break; 181 case 4: 182 changeTypes.add(MODIFY); 183 break; 184 case 5: 185 changeTypes.add(ADD); 186 changeTypes.add(MODIFY); 187 break; 188 case 6: 189 changeTypes.add(DELETE); 190 changeTypes.add(MODIFY); 191 break; 192 case 7: 193 changeTypes.add(ADD); 194 changeTypes.add(DELETE); 195 changeTypes.add(MODIFY); 196 break; 197 case 8: 198 changeTypes.add(MODIFY_DN); 199 break; 200 case 9: 201 changeTypes.add(ADD); 202 changeTypes.add(MODIFY_DN); 203 break; 204 case 10: 205 changeTypes.add(DELETE); 206 changeTypes.add(MODIFY_DN); 207 break; 208 case 11: 209 changeTypes.add(ADD); 210 changeTypes.add(DELETE); 211 changeTypes.add(MODIFY_DN); 212 break; 213 case 12: 214 changeTypes.add(MODIFY); 215 changeTypes.add(MODIFY_DN); 216 break; 217 case 13: 218 changeTypes.add(ADD); 219 changeTypes.add(MODIFY); 220 changeTypes.add(MODIFY_DN); 221 break; 222 case 14: 223 changeTypes.add(DELETE); 224 changeTypes.add(MODIFY); 225 changeTypes.add(MODIFY_DN); 226 break; 227 case 15: 228 changeTypes.add(ADD); 229 changeTypes.add(DELETE); 230 changeTypes.add(MODIFY); 231 changeTypes.add(MODIFY_DN); 232 break; 233 default: 234 message = ERR_PSEARCH_CHANGETYPES_INVALID_TYPES.get(intValue); 235 throw new LDAPException(LDAPResultCode.CONSTRAINT_VIOLATION, message); 236 } 237 238 return changeTypes; 239 } 240 241 242 243 /** 244 * Retrieves the integer representation of the provided set of change types. 245 * 246 * @param changeTypes The set of change types to be encoded. 247 * 248 * @return The integer representation of the provided set of change types. 249 */ 250 public static int changeTypesToInt(Set<PersistentSearchChangeType> 251 changeTypes) 252 { 253 int intValue = 0; 254 255 if (changeTypes.contains(ADD)) 256 { 257 intValue |= 1; 258 } 259 260 if (changeTypes.contains(DELETE)) 261 { 262 intValue |= 2; 263 } 264 265 if (changeTypes.contains(MODIFY)) 266 { 267 intValue |= 4; 268 } 269 270 if (changeTypes.contains(MODIFY_DN)) 271 { 272 intValue |= 8; 273 } 274 275 return intValue; 276 } 277 278 279 280 /** 281 * Retrieves a string representation of the provided set of change types. 282 * 283 * @param changeTypes The set of change types to encode. 284 * 285 * @return A string representation of the provided set of change types. 286 */ 287 public static String changeTypesToString(Set<PersistentSearchChangeType> 288 changeTypes) 289 { 290 StringBuilder buffer = new StringBuilder(); 291 changeTypesToString(changeTypes, buffer); 292 return buffer.toString(); 293 } 294 295 296 297 /** 298 * Appends a string representation of the specified set of change types to the 299 * provided buffer. 300 * 301 * @param changeTypes The set of change types to encode. 302 * @param buffer The buffer to which the information should be written. 303 */ 304 public static void changeTypesToString(Set<PersistentSearchChangeType> 305 changeTypes, 306 StringBuilder buffer) 307 { 308 Iterator<PersistentSearchChangeType> iterator = changeTypes.iterator(); 309 if (iterator.hasNext()) 310 { 311 buffer.append(iterator.next()); 312 313 while (iterator.hasNext()) 314 { 315 buffer.append("|"); 316 buffer.append(iterator.next()); 317 } 318 } 319 } 320} 321