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