001/*
002 * Copyright 2014-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2014-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2014-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk.unboundidds.extensions;
037
038
039
040import java.util.ArrayList;
041import java.util.Collection;
042import java.util.Collections;
043import java.util.List;
044
045import com.unboundid.asn1.ASN1Element;
046import com.unboundid.asn1.ASN1OctetString;
047import com.unboundid.asn1.ASN1Sequence;
048import com.unboundid.ldap.sdk.Control;
049import com.unboundid.ldap.sdk.ExtendedRequest;
050import com.unboundid.ldap.sdk.LDAPException;
051import com.unboundid.ldap.sdk.ResultCode;
052import com.unboundid.util.Debug;
053import com.unboundid.util.NotMutable;
054import com.unboundid.util.NotNull;
055import com.unboundid.util.Nullable;
056import com.unboundid.util.StaticUtils;
057import com.unboundid.util.ThreadSafety;
058import com.unboundid.util.ThreadSafetyLevel;
059import com.unboundid.util.Validator;
060
061import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
062
063
064
065/**
066 * This class provides an extended request that may be used to create or update
067 * a notification subscription.
068 * <BR>
069 * <BLOCKQUOTE>
070 *   <B>NOTE:</B>  This class, and other classes within the
071 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
072 *   supported for use against Ping Identity, UnboundID, and
073 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
074 *   for proprietary functionality or for external specifications that are not
075 *   considered stable or mature enough to be guaranteed to work in an
076 *   interoperable way with other types of LDAP servers.
077 * </BLOCKQUOTE>
078 * <BR>
079 * The request has an OID of 1.3.6.1.4.1.30221.2.6.38 and a value with the
080 * following encoding:
081 * <BR><BR>
082 * <PRE>
083 *   SetNotificationSubscriptionRequest ::= SEQUENCE {
084 *        notificationManagerID          OCTET STRING,
085 *        notificationDestinationID      OCTET STRING,
086 *        notificationSubscriptionID     OCTET STRING,
087 *        subscriptionDetails            SEQUENCE OF OCTET STRING }
088 * </PRE>
089 */
090@NotMutable()
091@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
092public final class SetNotificationSubscriptionExtendedRequest
093       extends ExtendedRequest
094{
095  /**
096   * The OID (1.3.6.1.4.1.30221.2.6.38) for the set notification subscription
097   * extended request.
098   */
099  @NotNull public static final String
100       SET_NOTIFICATION_SUBSCRIPTION_REQUEST_OID =
101            "1.3.6.1.4.1.30221.2.6.38";
102
103
104
105  /**
106   * The serial version UID for this serializable class.
107   */
108  private static final long serialVersionUID = -5822283773149091097L;
109
110
111
112  // The implementation-specific details for the notification subscription.
113  @NotNull private final List<ASN1OctetString> subscriptionDetails;
114
115  // The notification destination ID.
116  @NotNull private final String destinationID;
117
118  // The notification manager ID.
119  @NotNull private final String managerID;
120
121  // The notification subscription ID.
122  @NotNull private final String subscriptionID;
123
124
125
126  /**
127   * Creates a new set notification subscription extended request with the
128   * provided information.
129   *
130   * @param  managerID            The notification manager ID.  It must not be
131   *                              {@code null}.
132   * @param  destinationID        The notification destination ID.  It must not
133   *                              be {@code null}.
134   * @param  subscriptionID       The notification subscription ID.  It must not
135   *                              be {@code null}.
136   * @param  subscriptionDetails  The implementation-specific details for the
137   *                              notification subscription.  At least one
138   *                              detail value must be provided.
139   */
140  public SetNotificationSubscriptionExtendedRequest(
141              @NotNull final String managerID,
142              @NotNull final String destinationID,
143              @NotNull final String subscriptionID,
144              @Nullable final ASN1OctetString... subscriptionDetails)
145  {
146    this(managerID, destinationID, subscriptionID,
147         StaticUtils.toList(subscriptionDetails));
148  }
149
150
151
152  /**
153   * Creates a new set notification subscription extended request with the
154   * provided information.
155   *
156   * Creates a new set notification subscription extended request with the
157   * provided information.
158   *
159   * @param  managerID            The notification manager ID.  It must not be
160   *                              {@code null}.
161   * @param  destinationID        The notification destination ID.  It must not
162   *                              be {@code null}.
163   * @param  subscriptionID       The notification subscription ID.  It must not
164   *                              be {@code null}.
165   * @param  subscriptionDetails  The implementation-specific details for the
166   *                              notification subscription.  At least one
167   *                              detail value must be provided.
168   * @param  controls             The set of controls to include in the request.
169   *                              It may be {@code null} or empty if no controls
170   *                              are needed.
171   */
172  public SetNotificationSubscriptionExtendedRequest(
173              @NotNull final String managerID,
174              @NotNull final String destinationID,
175              @NotNull final String subscriptionID,
176              @NotNull final Collection<ASN1OctetString> subscriptionDetails,
177              @Nullable final Control... controls)
178  {
179    super(SET_NOTIFICATION_SUBSCRIPTION_REQUEST_OID,
180         encodeValue(managerID, destinationID, subscriptionID,
181              subscriptionDetails),
182         controls);
183
184    this.managerID = managerID;
185    this.destinationID = destinationID;
186    this.subscriptionID = subscriptionID;
187    this.subscriptionDetails =
188         Collections.unmodifiableList(new ArrayList<>(subscriptionDetails));
189  }
190
191
192
193  /**
194   * Creates a new set notification subscription extended request from the
195   * provided generic extended request.
196   *
197   * @param  extendedRequest  The generic extended request to use to create this
198   *                          set notification subscription extended request.
199   *
200   * @throws  LDAPException  If a problem occurs while decoding the request.
201   */
202  public SetNotificationSubscriptionExtendedRequest(
203              @NotNull final ExtendedRequest extendedRequest)
204         throws LDAPException
205  {
206    super(extendedRequest);
207
208    final ASN1OctetString value = extendedRequest.getValue();
209    if (value == null)
210    {
211      throw new LDAPException(ResultCode.DECODING_ERROR,
212           ERR_SET_NOTIFICATION_SUB_REQ_DECODE_NO_VALUE.get());
213    }
214
215    try
216    {
217      final ASN1Element[] elements =
218           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
219      managerID =
220           ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
221      destinationID =
222           ASN1OctetString.decodeAsOctetString(elements[1]).stringValue();
223      subscriptionID =
224           ASN1OctetString.decodeAsOctetString(elements[2]).stringValue();
225
226      final ASN1Element[] detailElements =
227           ASN1Sequence.decodeAsSequence(elements[3]).elements();
228      final ArrayList<ASN1OctetString> detailList =
229           new ArrayList<>(detailElements.length);
230      for (final ASN1Element e : detailElements)
231      {
232        detailList.add(ASN1OctetString.decodeAsOctetString(e));
233      }
234      subscriptionDetails = Collections.unmodifiableList(detailList);
235    }
236    catch (final Exception e)
237    {
238      Debug.debugException(e);
239      throw new LDAPException(ResultCode.DECODING_ERROR,
240           ERR_SET_NOTIFICATION_SUB_REQ_ERROR_DECODING_VALUE.get(
241                StaticUtils.getExceptionMessage(e)),
242           e);
243    }
244  }
245
246
247
248  /**
249   * Encodes the provided information into an ASN.1 octet string suitable for
250   * use as the value of this extended request.
251   *
252   * @param  managerID            The notification manager ID.  It must not be
253   *                              {@code null}.
254   * @param  destinationID        The notification destination ID.  It must not
255   *                              be {@code null}.
256   * @param  subscriptionID       The notification subscription ID.  It must not
257   *                              be {@code null}.
258   * @param  subscriptionDetails  The implementation-specific details for the
259   *                              notification subscription.  At least one
260   *                              detail value must be provided.
261   *
262   * @return  The ASN.1 octet string containing the encoded value.
263   */
264  @NotNull()
265  private static ASN1OctetString encodeValue(@NotNull final String managerID,
266               @NotNull final String destinationID,
267               @NotNull final String subscriptionID,
268               @NotNull final Collection<ASN1OctetString> subscriptionDetails)
269  {
270    Validator.ensureNotNull(managerID);
271    Validator.ensureNotNull(destinationID);
272    Validator.ensureNotNull(subscriptionID);
273    Validator.ensureNotNull(subscriptionDetails);
274    Validator.ensureFalse(subscriptionDetails.isEmpty());
275
276    final ASN1Sequence valueSequence = new ASN1Sequence(
277         new ASN1OctetString(managerID),
278         new ASN1OctetString(destinationID),
279         new ASN1OctetString(subscriptionID),
280         new ASN1Sequence(new ArrayList<ASN1Element>(subscriptionDetails)));
281    return new ASN1OctetString(valueSequence.encode());
282  }
283
284
285
286  /**
287   * Retrieves the notification manager ID.
288   *
289   * @return  The notification manager ID.
290   */
291  @NotNull()
292  public String getManagerID()
293  {
294    return managerID;
295  }
296
297
298
299  /**
300   * Retrieves the notification destination ID.
301   *
302   * @return  The notification destination ID.
303   */
304  @NotNull()
305  public String getDestinationID()
306  {
307    return destinationID;
308  }
309
310
311
312  /**
313   * Retrieves the notification subscription ID.
314   *
315   * @return  The notification subscription ID.
316   */
317  @NotNull()
318  public String getSubscriptionID()
319  {
320    return subscriptionID;
321  }
322
323
324
325  /**
326   * Retrieves the implementation-specific details for the notification
327   * subscription.
328   *
329   * @return  The implementation-specific details for the notification
330   *          subscription.
331   */
332  @NotNull()
333  public List<ASN1OctetString> getSubscriptionDetails()
334  {
335    return subscriptionDetails;
336  }
337
338
339
340  /**
341   * {@inheritDoc}
342   */
343  @Override()
344  @NotNull()
345  public SetNotificationSubscriptionExtendedRequest duplicate()
346  {
347    return duplicate(getControls());
348  }
349
350
351
352  /**
353   * {@inheritDoc}
354   */
355  @Override()
356  @NotNull()
357  public SetNotificationSubscriptionExtendedRequest duplicate(
358              @Nullable final Control[] controls)
359  {
360    final SetNotificationSubscriptionExtendedRequest r =
361         new SetNotificationSubscriptionExtendedRequest(managerID,
362              destinationID, subscriptionID, subscriptionDetails, controls);
363    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
364    r.setIntermediateResponseListener(getIntermediateResponseListener());
365    r.setReferralDepth(getReferralDepth());
366    r.setReferralConnector(getReferralConnectorInternal());
367    return r;
368  }
369
370
371
372  /**
373   * {@inheritDoc}
374   */
375  @Override()
376  @NotNull()
377  public String getExtendedRequestName()
378  {
379    return INFO_EXTENDED_REQUEST_NAME_SET_NOTIFICATION_SUB.get();
380  }
381
382
383
384  /**
385   * {@inheritDoc}
386   */
387  @Override()
388  public void toString(@NotNull final StringBuilder buffer)
389  {
390    buffer.append("SetNotificationSubscriptionExtendedRequest(managerID='");
391    buffer.append(managerID);
392    buffer.append("', destinationID='");
393    buffer.append(destinationID);
394    buffer.append("', subscriptionID='");
395    buffer.append(subscriptionID);
396    buffer.append("', subscriptionDetails=ASN1OctetString[");
397    buffer.append(subscriptionDetails.size());
398    buffer.append(']');
399
400    final Control[] controls = getControls();
401    if (controls.length > 0)
402    {
403      buffer.append(", controls={");
404      for (int i=0; i < controls.length; i++)
405      {
406        if (i > 0)
407        {
408          buffer.append(", ");
409        }
410
411        buffer.append(controls[i]);
412      }
413      buffer.append('}');
414    }
415
416    buffer.append(')');
417  }
418}