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