001    /*
002     * Copyright 2014-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.sdk.unboundidds.extensions;
022    
023    
024    
025    import java.util.ArrayList;
026    import java.util.Collection;
027    import java.util.Collections;
028    import java.util.List;
029    
030    import com.unboundid.asn1.ASN1Element;
031    import com.unboundid.asn1.ASN1Enumerated;
032    import com.unboundid.asn1.ASN1OctetString;
033    import com.unboundid.asn1.ASN1Sequence;
034    import com.unboundid.ldap.sdk.Control;
035    import com.unboundid.ldap.sdk.ExtendedRequest;
036    import com.unboundid.ldap.sdk.LDAPException;
037    import com.unboundid.ldap.sdk.ResultCode;
038    import com.unboundid.util.Debug;
039    import com.unboundid.util.NotMutable;
040    import com.unboundid.util.StaticUtils;
041    import com.unboundid.util.ThreadSafety;
042    import com.unboundid.util.ThreadSafetyLevel;
043    import com.unboundid.util.Validator;
044    
045    import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
046    
047    
048    
049    /**
050     * <BLOCKQUOTE>
051     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
052     *   LDAP SDK for Java.  It is not available for use in applications that
053     *   include only the Standard Edition of the LDAP SDK, and is not supported for
054     *   use in conjunction with non-UnboundID products.
055     * </BLOCKQUOTE>
056     * This class provides an extended request that may be used to create or update
057     * a notification destination.  The request has an OID of
058     * 1.3.6.1.4.1.30221.2.6.36 and a value with the following encoding:
059     * <BR><BR>
060     * <PRE>
061     *   SetNotificationDestinationRequest ::= SEQUENCE {
062     *        notificationManagerID         OCTET STRING,
063     *        notificationDestinationID     OCTET STRING,
064     *        destinationDetails            SEQUENCE OF OCTET STRING,
065     *        changeType                    [0] ENUMERATED {
066     *             replace (0),
067     *             add (1),
068     *             delete (2) } DEFAULT replace }
069     * </PRE>
070     */
071    @NotMutable()
072    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
073    public final class SetNotificationDestinationExtendedRequest
074           extends ExtendedRequest
075    {
076      /**
077       * The OID (1.3.6.1.4.1.30221.2.6.36) for the set notification destination
078       * extended request.
079       */
080      public static final String SET_NOTIFICATION_DESTINATION_REQUEST_OID =
081           "1.3.6.1.4.1.30221.2.6.36";
082    
083    
084    
085      /**
086       * The BER type for the value sequence element that specifies the destination
087       * details change type.
088       */
089      private static final byte BER_TYPE_CHANGE_TYPE = (byte) 0x80;
090    
091    
092    
093      /**
094       * The serial version UID for this serializable class.
095       */
096      private static final long serialVersionUID = 8651862605802389433L;
097    
098    
099    
100      // The implementation-specific details for the notification destination.
101      private final List<ASN1OctetString> destinationDetails;
102    
103      // The change type for the destination details.
104      private final SetNotificationDestinationChangeType changeType;
105    
106      // The notification destination ID.
107      private final String destinationID;
108    
109      // The notification manager ID.
110      private final String managerID;
111    
112    
113    
114      /**
115       * Creates a new set notification destination extended request with the
116       * provided information.
117       *
118       * @param  managerID           The notification manager ID.  It must not be
119       *                             {@code null}.
120       * @param  destinationID       The notification destination ID.  It must not
121       *                             be {@code null}.
122       * @param  destinationDetails  The implementation-specific details for the
123       *                             notification destination.  At least one detail
124       *                             value must be provided.
125       */
126      public SetNotificationDestinationExtendedRequest(final String managerID,
127                  final String destinationID,
128                  final ASN1OctetString... destinationDetails)
129      {
130        this(managerID, destinationID, StaticUtils.toList(destinationDetails),
131             SetNotificationDestinationChangeType.REPLACE);
132      }
133    
134    
135    
136      /**
137       * Creates a new set notification destination extended request with the
138       * provided information.
139       *
140       * @param  managerID           The notification manager ID.  It must not be
141       *                             {@code null}.
142       * @param  destinationID       The notification destination ID.  It must not
143       *                             be {@code null}.
144       * @param  destinationDetails  The implementation-specific details for the
145       *                             notification destination.  At least one detail
146       *                             value must be provided.
147       * @param  controls            The set of controls to include in the request.
148       *                             It may be {@code null} or empty if no controls
149       *                             are needed.
150       */
151      public SetNotificationDestinationExtendedRequest(final String managerID,
152                  final String destinationID,
153                  final Collection<ASN1OctetString> destinationDetails,
154                  final Control... controls)
155      {
156        this(managerID, destinationID, destinationDetails,
157             SetNotificationDestinationChangeType.REPLACE, controls);
158      }
159    
160    
161    
162      /**
163       * Creates a new set notification destination extended request with the
164       * provided information.
165       *
166       * @param  managerID           The notification manager ID.  It must not be
167       *                             {@code null}.
168       * @param  destinationID       The notification destination ID.  It must not
169       *                             be {@code null}.
170       * @param  destinationDetails  The implementation-specific details for the
171       *                             notification destination.  At least one detail
172       *                             value must be provided.
173       * @param  changeType          The change type for the destination details.
174       * @param  controls            The set of controls to include in the request.
175       *                             It may be {@code null} or empty if no controls
176       *                             are needed.
177       */
178      public SetNotificationDestinationExtendedRequest(final String managerID,
179                  final String destinationID,
180                  final Collection<ASN1OctetString> destinationDetails,
181                  final SetNotificationDestinationChangeType changeType,
182                  final Control... controls)
183      {
184        super(SET_NOTIFICATION_DESTINATION_REQUEST_OID,
185             encodeValue(managerID, destinationID, destinationDetails, changeType),
186             controls);
187    
188        this.managerID = managerID;
189        this.destinationID = destinationID;
190        this.destinationDetails = Collections.unmodifiableList(
191             new ArrayList<ASN1OctetString>(destinationDetails));
192    
193        if (changeType == null)
194        {
195          this.changeType = SetNotificationDestinationChangeType.REPLACE;
196        }
197        else
198        {
199          this.changeType = changeType;
200        }
201      }
202    
203    
204    
205      /**
206       * Creates a new set notification destination extended request from the
207       * provided generic extended request.
208       *
209       * @param  extendedRequest  The generic extended request to use to create this
210       *                          set notification destination extended request.
211       *
212       * @throws  LDAPException  If a problem occurs while decoding the request.
213       */
214      public SetNotificationDestinationExtendedRequest(
215                  final ExtendedRequest extendedRequest)
216             throws LDAPException
217      {
218        super(extendedRequest);
219    
220        final ASN1OctetString value = extendedRequest.getValue();
221        if (value == null)
222        {
223          throw new LDAPException(ResultCode.DECODING_ERROR,
224               ERR_SET_NOTIFICATION_DEST_REQ_DECODE_NO_VALUE.get());
225        }
226    
227        try
228        {
229          final ASN1Element[] elements =
230               ASN1Sequence.decodeAsSequence(value.getValue()).elements();
231          managerID =
232               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
233          destinationID =
234               ASN1OctetString.decodeAsOctetString(elements[1]).stringValue();
235    
236          final ASN1Element[] detailElements =
237               ASN1Sequence.decodeAsSequence(elements[2]).elements();
238          final ArrayList<ASN1OctetString> detailList =
239               new ArrayList<ASN1OctetString>(detailElements.length);
240          for (final ASN1Element e : detailElements)
241          {
242            detailList.add(ASN1OctetString.decodeAsOctetString(e));
243          }
244          destinationDetails = Collections.unmodifiableList(detailList);
245    
246          SetNotificationDestinationChangeType ct =
247               SetNotificationDestinationChangeType.REPLACE;
248          for (int i=3; i < elements.length; i++)
249          {
250            final ASN1Element e = elements[i];
251            switch (e.getType())
252            {
253              case BER_TYPE_CHANGE_TYPE:
254                final int ctIntValue =
255                     ASN1Enumerated.decodeAsEnumerated(e).intValue();
256                ct = SetNotificationDestinationChangeType.valueOf(ctIntValue);
257                if (ct == null)
258                {
259                  throw new LDAPException(ResultCode.DECODING_ERROR,
260                       ERR_SET_NOTIFICATION_DEST_REQ_INVALID_CT.get(ctIntValue));
261                }
262                break;
263    
264              default:
265                throw new LDAPException(ResultCode.DECODING_ERROR,
266                     ERR_SET_NOTIFICATION_DEST_REQ_INVALID_ELEMENT_TYPE.get(
267                          StaticUtils.toHex(e.getType())));
268            }
269          }
270    
271          changeType = ct;
272        }
273        catch (final LDAPException le)
274        {
275          Debug.debugException(le);
276          throw le;
277        }
278        catch (final Exception e)
279        {
280          Debug.debugException(e);
281          throw new LDAPException(ResultCode.DECODING_ERROR,
282               ERR_SET_NOTIFICATION_DEST_REQ_ERROR_DECODING_VALUE.get(
283                    StaticUtils.getExceptionMessage(e)),
284               e);
285        }
286      }
287    
288    
289    
290      /**
291       * Encodes the provided information into an ASN.1 octet string suitable for
292       * use as the value of this extended request.
293       *
294       * @param  managerID           The notification manager ID.  It must not be
295       *                             {@code null}.
296       * @param  destinationID       The notification destination ID.  It must not
297       *                             be {@code null}.
298       * @param  destinationDetails  The implementation-specific details for the
299       *                             notification destination.  At least one detail
300       *                             value must be provided.
301       * @param  changeType          The change type for the destination details.
302       *
303       * @return  The ASN.1 octet string containing the encoded value.
304       */
305      private static ASN1OctetString encodeValue(final String managerID,
306                          final String destinationID,
307                          final Collection<ASN1OctetString> destinationDetails,
308                          final SetNotificationDestinationChangeType changeType)
309      {
310        Validator.ensureNotNull(managerID);
311        Validator.ensureNotNull(destinationID);
312        Validator.ensureNotNull(destinationDetails);
313        Validator.ensureFalse(destinationDetails.isEmpty());
314    
315        final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(4);
316        elements.add(new ASN1OctetString(managerID));
317        elements.add(new ASN1OctetString(destinationID));
318        elements.add(new ASN1Sequence(
319             new ArrayList<ASN1Element>(destinationDetails)));
320    
321        if ((changeType != null) &&
322            (changeType != SetNotificationDestinationChangeType.REPLACE))
323        {
324          elements.add(new ASN1Enumerated(BER_TYPE_CHANGE_TYPE,
325               changeType.intValue()));
326        }
327    
328        return new ASN1OctetString(new ASN1Sequence(elements).encode());
329      }
330    
331    
332    
333      /**
334       * Retrieves the notification manager ID.
335       *
336       * @return  The notification manager ID.
337       */
338      public String getManagerID()
339      {
340        return managerID;
341      }
342    
343    
344    
345      /**
346       * Retrieves the notification destination ID.
347       *
348       * @return  The notification destination ID.
349       */
350      public String getDestinationID()
351      {
352        return destinationID;
353      }
354    
355    
356    
357      /**
358       * Retrieves the implementation-specific details for the notification
359       * destination.
360       *
361       * @return  The implementation-specific details for the notification
362       *          destination.
363       */
364      public List<ASN1OctetString> getDestinationDetails()
365      {
366        return destinationDetails;
367      }
368    
369    
370    
371      /**
372       * Retrieves the change type for the destination details.
373       *
374       * @return  The change type for the destination details.
375       */
376      public SetNotificationDestinationChangeType getChangeType()
377      {
378        return changeType;
379      }
380    
381    
382    
383      /**
384       * {@inheritDoc}
385       */
386      @Override()
387      public SetNotificationDestinationExtendedRequest duplicate()
388      {
389        return duplicate(getControls());
390      }
391    
392    
393    
394      /**
395       * {@inheritDoc}
396       */
397      @Override()
398      public SetNotificationDestinationExtendedRequest
399                  duplicate(final Control[] controls)
400      {
401        final SetNotificationDestinationExtendedRequest r =
402             new SetNotificationDestinationExtendedRequest(managerID,
403                  destinationID, destinationDetails, changeType, controls);
404        r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
405        return r;
406      }
407    
408    
409    
410      /**
411       * {@inheritDoc}
412       */
413      @Override()
414      public String getExtendedRequestName()
415      {
416        return INFO_EXTENDED_REQUEST_NAME_SET_NOTIFICATION_DEST.get();
417      }
418    
419    
420    
421      /**
422       * {@inheritDoc}
423       */
424      @Override()
425      public void toString(final StringBuilder buffer)
426      {
427        buffer.append("SetNotificationDestinationExtendedRequest(managerID='");
428        buffer.append(managerID);
429        buffer.append("', destinationID='");
430        buffer.append(destinationID);
431        buffer.append("', destinationDetails=ASN1OctetString[");
432        buffer.append(destinationDetails.size());
433        buffer.append("], changeType=");
434        buffer.append(changeType.name());
435    
436        final Control[] controls = getControls();
437        if (controls.length > 0)
438        {
439          buffer.append(", controls={");
440          for (int i=0; i < controls.length; i++)
441          {
442            if (i > 0)
443            {
444              buffer.append(", ");
445            }
446    
447            buffer.append(controls[i]);
448          }
449          buffer.append('}');
450        }
451    
452        buffer.append(')');
453      }
454    }