001    /*
002     * Copyright 2012-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.Iterator;
029    import java.util.List;
030    
031    import com.unboundid.asn1.ASN1Element;
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.ExtendedResult;
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    
044    import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
045    
046    
047    
048    /**
049     * <BLOCKQUOTE>
050     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
051     *   LDAP SDK for Java.  It is not available for use in applications that
052     *   include only the Standard Edition of the LDAP SDK, and is not supported for
053     *   use in conjunction with non-UnboundID products.
054     * </BLOCKQUOTE>
055     * This class provides an implementation of an extended result that can be used
056     * to provide information about the notification subscriptions defined in the
057     * target server.  The OID for this result is 1.3.6.1.4.1.30221.2.6.41, and the
058     * value (if present) should have the following encoding:
059     * <BR><BR>
060     * <PRE>
061     *   ListNotificationSubscriptionsResponse ::= SEQUENCE OF SEQUENCE {
062     *        notificationDestinationID     OCTET STRING,
063     *        destinationDetails            SEQUENCE OF OCTET STRING,
064     *        subscriptions                 SEQUENCE OF SEQUENCE {
065     *             subscriptionID          OCTET STRING,
066     *             subscriptionDetails     SEQUENCE OF OCTET STRING } }
067     * </PRE>
068     */
069    @NotMutable()
070    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
071    public final class ListNotificationSubscriptionsExtendedResult
072           extends ExtendedResult
073    {
074      /**
075       * The OID (1.3.6.1.4.1.30221.2.6.41) for the list notification subscriptions
076       * extended result.
077       */
078      public static final String LIST_NOTIFICATION_SUBSCRIPTIONS_RESULT_OID =
079           "1.3.6.1.4.1.30221.2.6.41";
080    
081    
082    
083      /**
084       * The serial version UID for this serializable class.
085       */
086      private static final long serialVersionUID = 8876370324325619149L;
087    
088    
089    
090      // The notification destination details for this result.
091      private final List<NotificationDestinationDetails> destinations;
092    
093    
094    
095      /**
096       * Creates a new list notification subscriptions extended result from the
097       * provided extended result.
098       *
099       * @param  extendedResult  The extended result to be decoded as a list
100       *                         notification subscriptions extended result.
101       *
102       * @throws LDAPException  If a problem is encountered while attempting to
103       *                         decode the provided extended result as a
104       *                         multi-update result.
105       */
106      public ListNotificationSubscriptionsExtendedResult(
107                  final ExtendedResult extendedResult)
108             throws LDAPException
109      {
110        super(extendedResult);
111    
112        final ASN1OctetString value = extendedResult.getValue();
113        if (value == null)
114        {
115          destinations = Collections.emptyList();
116          return;
117        }
118    
119        try
120        {
121          final ASN1Element[] destsElements =
122               ASN1Sequence.decodeAsSequence(value.getValue()).elements();
123          final ArrayList<NotificationDestinationDetails> destList =
124               new ArrayList<NotificationDestinationDetails>(destsElements.length);
125          for (final ASN1Element destElement : destsElements)
126          {
127            final ASN1Element[] destElements =
128                 ASN1Sequence.decodeAsSequence(destElement).elements();
129            final String destID =
130                 ASN1OctetString.decodeAsOctetString(destElements[0]).stringValue();
131    
132            final ASN1Element[] destDetailsElements =
133                 ASN1Sequence.decodeAsSequence(destElements[1]).elements();
134            final ArrayList<ASN1OctetString> destDetailsList =
135                 new ArrayList<ASN1OctetString>(destDetailsElements.length);
136            for (final ASN1Element e : destDetailsElements)
137            {
138              destDetailsList.add(ASN1OctetString.decodeAsOctetString(e));
139            }
140    
141            final ASN1Element[] subElements =
142                 ASN1Sequence.decodeAsSequence(destElements[2]).elements();
143            final ArrayList<NotificationSubscriptionDetails> subscriptions =
144                 new ArrayList<NotificationSubscriptionDetails>(subElements.length);
145            for (final ASN1Element e : subElements)
146            {
147              final ASN1Element[] sElements =
148                   ASN1Sequence.decodeAsSequence(e).elements();
149              final String subID =
150                   ASN1OctetString.decodeAsOctetString(sElements[0]).stringValue();
151    
152              final ASN1Element[] subDetailsElements =
153                   ASN1Sequence.decodeAsSequence(sElements[1]).elements();
154              final ArrayList<ASN1OctetString> subDetails =
155                   new ArrayList<ASN1OctetString>(subDetailsElements.length);
156              for (final ASN1Element sde : subDetailsElements)
157              {
158                subDetails.add(ASN1OctetString.decodeAsOctetString(sde));
159              }
160              subscriptions.add(
161                   new NotificationSubscriptionDetails(subID, subDetails));
162            }
163    
164            destList.add(new NotificationDestinationDetails(destID, destDetailsList,
165                 subscriptions));
166          }
167    
168          destinations = Collections.unmodifiableList(destList);
169        }
170        catch (final Exception e)
171        {
172          Debug.debugException(e);
173          throw new LDAPException(ResultCode.DECODING_ERROR,
174               ERR_LIST_NOTIFICATION_SUBS_RESULT_CANNOT_DECODE_VALUE.get(
175                    StaticUtils.getExceptionMessage(e)),
176               e);
177        }
178      }
179    
180    
181    
182      /**
183       * Creates a new list notification subscriptions extended request with the
184       * provided information.
185       *
186       * @param  messageID          The message ID for this extended result.
187       * @param  resultCode         The result code for this result.  It must not be
188       *                            {@code null}.
189       * @param  diagnosticMessage  The diagnostic message to include in the result.
190       *                            It may be {@code null} if no diagnostic message
191       *                            should be included.
192       * @param  matchedDN          The matched DN to include in the result.  It may
193       *                            be {@code null} if no matched DN should be
194       *                            included.
195       * @param  referralURLs       The set of referral URLs to include in the
196       *                            result.  It may be {@code null} or empty if no
197       *                            referral URLs should be included.
198       * @param  destinations       The notification destination details for this
199       *                            result.  It may be {@code null} or empty for a
200       *                            non-success result.
201       * @param  controls           The set of controls to include in the
202       *                            multi-update result.  It may be {@code null} or
203       *                            empty if no controls should be included.
204       *
205       * @throws  LDAPException  If any of the results are for an inappropriate
206       *                         operation type.
207       */
208      public ListNotificationSubscriptionsExtendedResult(final int messageID,
209                  final ResultCode resultCode, final String diagnosticMessage,
210                  final String matchedDN, final String[] referralURLs,
211                  final Collection<NotificationDestinationDetails> destinations,
212                  final Control... controls)
213             throws LDAPException
214      {
215        super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
216             LIST_NOTIFICATION_SUBSCRIPTIONS_RESULT_OID, encodeValue(destinations),
217             controls);
218    
219        if (destinations == null)
220        {
221          this.destinations = Collections.emptyList();
222        }
223        else
224        {
225          this.destinations = Collections.unmodifiableList(
226               new ArrayList<NotificationDestinationDetails>(destinations));
227        }
228      }
229    
230    
231    
232      /**
233       * Encodes the information from the provided set of results into a form
234       * suitable for use as the value of the extended result.
235       *
236       * @param  destinations  The notification destination details for the result.
237       *                       It may be {@code null} or empty for a non-success
238       *                       result.
239       *
240       * @return  An ASN.1 element suitable for use as the value of the extended
241       *          result.
242       */
243      private static ASN1OctetString encodeValue(
244                   final Collection<NotificationDestinationDetails> destinations)
245      {
246        if ((destinations == null) || destinations.isEmpty())
247        {
248          return null;
249        }
250    
251        final ArrayList<ASN1Element> elements =
252             new ArrayList<ASN1Element>(destinations.size());
253        for (final NotificationDestinationDetails destDetails : destinations)
254        {
255          final ArrayList<ASN1Element> destElements = new ArrayList<ASN1Element>(3);
256          destElements.add(new ASN1OctetString(destDetails.getID()));
257          destElements.add(new ASN1Sequence(destDetails.getDetails()));
258    
259          final ArrayList<ASN1Element> subElements =
260               new ArrayList<ASN1Element>(destDetails.getSubscriptions().size());
261          for (final NotificationSubscriptionDetails subDetails :
262               destDetails.getSubscriptions())
263          {
264            subElements.add(new ASN1Sequence(
265                 new ASN1OctetString(subDetails.getID()),
266                 new ASN1Sequence(subDetails.getDetails())));
267          }
268          destElements.add(new ASN1Sequence(subElements));
269          elements.add(new ASN1Sequence(destElements));
270        }
271    
272        return new ASN1OctetString(new ASN1Sequence(elements).encode());
273      }
274    
275    
276    
277      /**
278       * Retrieves a list of the defined notification destinations and their
279       * associated subscriptions.
280       *
281       * @return  A list of the defined notification destinations and their
282       *          associated subscriptions.
283       */
284      public List<NotificationDestinationDetails> getDestinations()
285      {
286        return destinations;
287      }
288    
289    
290    
291      /**
292       * {@inheritDoc}
293       */
294      @Override()
295      public String getExtendedResultName()
296      {
297        return INFO_EXTENDED_RESULT_NAME_LIST_NOTIFICATION_SUBS.get();
298      }
299    
300    
301    
302      /**
303       * Appends a string representation of this extended result to the provided
304       * buffer.
305       *
306       * @param  buffer  The buffer to which a string representation of this
307       *                 extended result will be appended.
308       */
309      @Override()
310      public void toString(final StringBuilder buffer)
311      {
312        buffer.append("ListNotificationSubscriptionsExtendedResult(resultCode=");
313        buffer.append(getResultCode());
314    
315        final int messageID = getMessageID();
316        if (messageID >= 0)
317        {
318          buffer.append(", messageID=");
319          buffer.append(messageID);
320        }
321    
322        buffer.append(", notificationDestinations={");
323        final Iterator<NotificationDestinationDetails> destIterator =
324             destinations.iterator();
325        while (destIterator.hasNext())
326        {
327          destIterator.next().toString(buffer);
328          if (destIterator.hasNext())
329          {
330            buffer.append(", ");
331          }
332        }
333        buffer.append('}');
334    
335        final String diagnosticMessage = getDiagnosticMessage();
336        if (diagnosticMessage != null)
337        {
338          buffer.append(", diagnosticMessage='");
339          buffer.append(diagnosticMessage);
340          buffer.append('\'');
341        }
342    
343        final String matchedDN = getMatchedDN();
344        if (matchedDN != null)
345        {
346          buffer.append(", matchedDN='");
347          buffer.append(matchedDN);
348          buffer.append('\'');
349        }
350    
351        final String[] referralURLs = getReferralURLs();
352        if (referralURLs.length > 0)
353        {
354          buffer.append(", referralURLs={");
355          for (int i=0; i < referralURLs.length; i++)
356          {
357            if (i > 0)
358            {
359              buffer.append(", ");
360            }
361    
362            buffer.append('\'');
363            buffer.append(referralURLs[i]);
364            buffer.append('\'');
365          }
366          buffer.append('}');
367        }
368    
369        final Control[] responseControls = getResponseControls();
370        if (responseControls.length > 0)
371        {
372          buffer.append(", responseControls={");
373          for (int i=0; i < responseControls.length; i++)
374          {
375            if (i > 0)
376            {
377              buffer.append(", ");
378            }
379    
380            buffer.append(responseControls[i]);
381          }
382          buffer.append('}');
383        }
384    
385        buffer.append(')');
386      }
387    }