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