001/*
002 * Copyright 2014-2017 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2017 Ping Identity Corporation
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 */
021package com.unboundid.ldap.sdk.unboundidds.extensions;
022
023
024
025import java.util.ArrayList;
026import java.util.Collection;
027import java.util.Collections;
028import java.util.Iterator;
029import java.util.LinkedHashSet;
030import java.util.Set;
031
032import com.unboundid.asn1.ASN1Element;
033import com.unboundid.asn1.ASN1OctetString;
034import com.unboundid.asn1.ASN1Sequence;
035import com.unboundid.asn1.ASN1Set;
036import com.unboundid.ldap.sdk.Control;
037import com.unboundid.ldap.sdk.ExtendedRequest;
038import com.unboundid.ldap.sdk.ExtendedResult;
039import com.unboundid.ldap.sdk.LDAPConnection;
040import com.unboundid.ldap.sdk.LDAPException;
041import com.unboundid.ldap.sdk.ResultCode;
042import com.unboundid.util.Debug;
043import com.unboundid.util.NotMutable;
044import com.unboundid.util.StaticUtils;
045import com.unboundid.util.ThreadSafety;
046import com.unboundid.util.ThreadSafetyLevel;
047import com.unboundid.util.Validator;
048
049import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
050
051
052
053/**
054 * This class provides an extended request that may be used to retrieve a list
055 * of the subscriptions associated with a specified notification manager,
056 * optionally restricted to a specified set of destinations.
057 * <BR>
058 * <BLOCKQUOTE>
059 *   <B>NOTE:</B>  This class, and other classes within the
060 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
061 *   supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661
062 *   server products.  These classes provide support for proprietary
063 *   functionality or for external specifications that are not considered stable
064 *   or mature enough to be guaranteed to work in an interoperable way with
065 *   other types of LDAP servers.
066 * </BLOCKQUOTE>
067 * <BR>
068 * The request has an OID of 1.3.6.1.4.1.30221.2.6.40 and a value with the
069 * following encoding: <BR><BR>
070 * <PRE>
071 *   ListNotificationSubscriptionsRequest ::= SEQUENCE {
072 *        notificationManagerID          OCTET STRING,
073 *        notificationDestinationIDs     SET OF OCTET STRING OPTIONAL }
074 * </PRE>
075 */
076@NotMutable()
077@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
078public final class ListNotificationSubscriptionsExtendedRequest
079       extends ExtendedRequest
080{
081  /**
082   * The OID (1.3.6.1.4.1.30221.2.6.40) for the list notification subscriptions
083   * extended request.
084   */
085  public static final String LIST_NOTIFICATION_SUBSCRIPTIONS_REQUEST_OID =
086       "1.3.6.1.4.1.30221.2.6.40";
087
088
089
090  /**
091   * The serial version UID for this serializable class.
092   */
093  private static final long serialVersionUID = -8124073083247944273L;
094
095
096
097  // The notification destination IDs.
098  private final Set<String> destinationIDs;
099
100  // The notification manager ID.
101  private final String managerID;
102
103
104
105  /**
106   * Creates a new list notification subscriptions extended request with the
107   * provided information.
108   *
109   * @param  managerID          The notification manager ID.  It must not be
110   *                            {@code null}.
111   * @param  destinationIDs     The set of notification destination IDs for
112   *                            which to retrieve the subscription information.
113   *                            It may be {@code null} or empty if subscription
114   *                            information for all destinations should be
115   *                            returned.
116   */
117  public ListNotificationSubscriptionsExtendedRequest(final String managerID,
118              final String... destinationIDs)
119  {
120    this(managerID, StaticUtils.toList(destinationIDs));
121  }
122
123
124
125  /**
126   * Creates a new list notification subscriptions extended request with the
127   * provided information.
128   *
129   * @param  managerID          The notification manager ID.  It must not be
130   *                            {@code null}.
131   * @param  destinationIDs     The set of notification destination IDs for
132   *                            which to retrieve the subscription information.
133   *                            It may be {@code null} or empty if subscription
134   *                            information for all destinations should be
135   *                            returned.
136   * @param  controls           The set of controls to include in the request.
137   *                            It may be {@code null} or empty if no controls
138   *                            are needed.
139   */
140  public ListNotificationSubscriptionsExtendedRequest(final String managerID,
141              final Collection<String> destinationIDs,
142              final Control... controls)
143  {
144    super(LIST_NOTIFICATION_SUBSCRIPTIONS_REQUEST_OID,
145         encodeValue(managerID, destinationIDs), controls);
146
147    this.managerID = managerID;
148
149    if (destinationIDs == null)
150    {
151      this.destinationIDs = Collections.emptySet();
152    }
153    else
154    {
155      this.destinationIDs = Collections.unmodifiableSet(
156           new LinkedHashSet<String>(destinationIDs));
157    }
158  }
159
160
161
162  /**
163   * Creates a new list notification subscriptions extended request from the
164   * provided generic extended request.
165   *
166   * @param  extendedRequest  The generic extended request to use to create this
167   *                          list notification subscriptions extended request.
168   *
169   * @throws  LDAPException  If a problem occurs while decoding the request.
170   */
171  public ListNotificationSubscriptionsExtendedRequest(
172              final ExtendedRequest extendedRequest)
173         throws LDAPException
174  {
175    super(extendedRequest);
176
177    final ASN1OctetString value = extendedRequest.getValue();
178    if (value == null)
179    {
180      throw new LDAPException(ResultCode.DECODING_ERROR,
181           ERR_LIST_NOTIFICATION_SUBS_REQ_DECODE_NO_VALUE.get());
182    }
183
184    try
185    {
186      final ASN1Element[] elements =
187           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
188      managerID =
189           ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
190
191      if (elements.length > 1)
192      {
193        final ASN1Element[] destIDElements =
194             ASN1Sequence.decodeAsSequence(elements[1]).elements();
195
196        final LinkedHashSet<String> destIDs =
197             new LinkedHashSet<String>(destIDElements.length);
198        for (final ASN1Element e : destIDElements)
199        {
200          destIDs.add(ASN1OctetString.decodeAsOctetString(e).stringValue());
201        }
202        destinationIDs = Collections.unmodifiableSet(destIDs);
203      }
204      else
205      {
206        destinationIDs = Collections.emptySet();
207      }
208    }
209    catch (final Exception e)
210    {
211      Debug.debugException(e);
212      throw new LDAPException(ResultCode.DECODING_ERROR,
213           ERR_LIST_NOTIFICATION_SUBS_REQ_ERROR_DECODING_VALUE.get(
214                StaticUtils.getExceptionMessage(e)),
215           e);
216    }
217  }
218
219
220
221  /**
222   * Encodes the provided information into an ASN.1 octet string suitable for
223   * use as the value of this extended request.
224   *
225   * @param  managerID          The notification manager ID.  It must not be
226   *                            {@code null}.
227   * @param  destinationIDs     The set of notification destination IDs for
228   *                            which to retrieve the subscription information.
229   *                            It may be {@code null} or empty if subscription
230   *                            information for all destinations should be
231   *                            returned.
232   *
233   * @return  The ASN.1 octet string containing the encoded value.
234   */
235  private static ASN1OctetString encodeValue(final String managerID,
236                      final Collection<String> destinationIDs)
237  {
238    Validator.ensureNotNull(managerID);
239
240    final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
241    elements.add(new ASN1OctetString(managerID));
242
243    if ((destinationIDs != null) && (! destinationIDs.isEmpty()))
244    {
245      final LinkedHashSet<ASN1Element> destIDElements =
246           new LinkedHashSet<ASN1Element>(destinationIDs.size());
247      for (final String destinationID : destinationIDs)
248      {
249        destIDElements.add(new ASN1OctetString(destinationID));
250      }
251      elements.add(new ASN1Set(destIDElements));
252    }
253
254    return new ASN1OctetString(new ASN1Sequence(elements).encode());
255  }
256
257
258
259  /**
260   * {@inheritDoc}
261   */
262  @Override()
263  public ListNotificationSubscriptionsExtendedResult
264              process(final LDAPConnection connection, final int depth)
265         throws LDAPException
266  {
267    final ExtendedResult extendedResponse = super.process(connection, depth);
268    return new ListNotificationSubscriptionsExtendedResult(extendedResponse);
269  }
270
271
272
273  /**
274   * Retrieves the notification manager ID.
275   *
276   * @return  The notification manager ID.
277   */
278  public String getManagerID()
279  {
280    return managerID;
281  }
282
283
284
285  /**
286   * Retrieves the notification destination IDs, if any were provided.
287   *
288   * @return  The notification destination IDs, or an empty set if none were
289   *          provided.
290   */
291  public Set<String> getDestinationIDs()
292  {
293    return destinationIDs;
294  }
295
296
297
298  /**
299   * {@inheritDoc}
300   */
301  @Override()
302  public ListNotificationSubscriptionsExtendedRequest duplicate()
303  {
304    return duplicate(getControls());
305  }
306
307
308
309  /**
310   * {@inheritDoc}
311   */
312  @Override()
313  public ListNotificationSubscriptionsExtendedRequest
314              duplicate(final Control[] controls)
315  {
316    final ListNotificationSubscriptionsExtendedRequest r =
317         new ListNotificationSubscriptionsExtendedRequest(managerID,
318              destinationIDs, controls);
319    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
320    return r;
321  }
322
323
324
325  /**
326   * {@inheritDoc}
327   */
328  @Override()
329  public String getExtendedRequestName()
330  {
331    return INFO_EXTENDED_REQUEST_NAME_LIST_NOTIFICATION_SUBS.get();
332  }
333
334
335
336  /**
337   * {@inheritDoc}
338   */
339  @Override()
340  public void toString(final StringBuilder buffer)
341  {
342    buffer.append("ListNotificationSubscriptionsExtendedRequest(managerID='");
343    buffer.append(managerID);
344    buffer.append('\'');
345
346    if (! destinationIDs.isEmpty())
347    {
348      buffer.append(", destinationIDs={");
349
350      final Iterator<String> iterator = destinationIDs.iterator();
351      while (iterator.hasNext())
352      {
353        buffer.append('\'');
354        buffer.append(iterator.next());
355        buffer.append('\'');
356
357        if (iterator.hasNext())
358        {
359          buffer.append(", ");
360        }
361      }
362
363      buffer.append('}');
364    }
365
366    final Control[] controls = getControls();
367    if (controls.length > 0)
368    {
369      buffer.append(", controls={");
370      for (int i=0; i < controls.length; i++)
371      {
372        if (i > 0)
373        {
374          buffer.append(", ");
375        }
376
377        buffer.append(controls[i]);
378      }
379      buffer.append('}');
380    }
381
382    buffer.append(')');
383  }
384}