001/*
002 * Copyright 2025 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2025 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) 2025 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.controls;
037
038
039
040import java.io.Serializable;
041import java.util.ArrayList;
042import java.util.List;
043
044import com.unboundid.asn1.ASN1Element;
045import com.unboundid.asn1.ASN1Enumerated;
046import com.unboundid.asn1.ASN1OctetString;
047import com.unboundid.asn1.ASN1Sequence;
048import com.unboundid.ldap.sdk.LDAPException;
049import com.unboundid.ldap.sdk.ResultCode;
050import com.unboundid.util.Debug;
051import com.unboundid.util.Mutable;
052import com.unboundid.util.NotNull;
053import com.unboundid.util.Nullable;
054import com.unboundid.util.StaticUtils;
055import com.unboundid.util.ThreadSafety;
056import com.unboundid.util.ThreadSafetyLevel;
057
058import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
059
060
061
062/**
063 * This class provides a data structure that holds information that may be used
064 * if the server needs to acquire a scoped lock that may apply to a subset of
065 * related requests within a backend, without affecting other unrelated
066 * operations being processed in that backend.
067 * <BR>
068 * <BLOCKQUOTE>
069 *   <B>NOTE:</B>  This class, and other classes within the
070 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
071 *   supported for use against Ping Identity, UnboundID, and
072 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
073 *   for proprietary functionality or for external specifications that are not
074 *   considered stable or mature enough to be guaranteed to work in an
075 *   interoperable way with other types of LDAP servers.
076 * </BLOCKQUOTE>
077 */
078@Mutable()
079@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
080public final class TransactionSettingsScopedLockDetails
081       implements Serializable
082{
083  /**
084   * The BER type for the element used to contain the scope identifier.
085   */
086  private static final byte TYPE_SCOPE_IDENTIFIER = (byte) 0x89;
087
088
089
090  /**
091   * The BER type for the element used to contain the scoped lock behavior.
092   */
093  private static final byte TYPE_LOCK_BEHAVIOR = (byte) 0x8A;
094
095
096
097  /**
098   * The serial version UID for this serializable class.
099   */
100  private static final long serialVersionUID = -1374000956873071172L;
101
102
103
104  // A string that identifies which scoped lock to acquire.
105  @NotNull private final String scopeIdentifier;
106
107  // The behavior that should be used when acquiring the lock.
108  @NotNull private final TransactionSettingsBackendLockBehavior lockBehavior;
109
110
111
112  /**
113   * Creates a new scoped lock details object with the provided information.
114   *
115   * @param  scopeIdentifier  A string that identifies which scoped lock to
116   *                          acquire.  It must not be {@code null}.
117   * @param  lockBehavior     The behavior that indicates when the server
118   *                          should attempt to acquire the scoped lock.  It
119   *                          must not be {@code null}, and should not be
120   *                          {@code DO_NOT_ACQUIRE}.
121   */
122  public TransactionSettingsScopedLockDetails(
123       @NotNull final String scopeIdentifier,
124       @NotNull final TransactionSettingsBackendLockBehavior lockBehavior)
125  {
126    this.scopeIdentifier = scopeIdentifier;
127    this.lockBehavior = lockBehavior;
128  }
129
130
131
132  /**
133   * Retrieves s string that identifies which scoped lock to acquire.
134   *
135   * @return  A string that identifies which scoped lock to acquire.
136   */
137  @NotNull()
138  public String getScopeIdentifier()
139  {
140    return scopeIdentifier;
141  }
142
143
144
145  /**
146   * Retrieves the behavior that indicates when the lock should be acquired.
147   *
148   * @return  The behavior that indicates when the lock should be acquired.
149   */
150  @NotNull()
151  public TransactionSettingsBackendLockBehavior getLockBehavior()
152  {
153    return lockBehavior;
154  }
155
156
157
158  /**
159   * Encodes the scoped lock details into an ASN.1 element for inclusion in a
160   * transaction settings request control.
161   *
162   * @return  The ASN.1 element containing the encoded scoped lock details, or
163   *          {@code null} if no scoped lock is needed (as indicated by a
164   *          lock behavior of {@code DO_NOT_ACQUIRE}).
165   */
166  @Nullable()
167  public ASN1Element encode()
168  {
169    if (lockBehavior == TransactionSettingsBackendLockBehavior.DO_NOT_ACQUIRE)
170    {
171      return null;
172    }
173
174    final List<ASN1Element> elements = new ArrayList<>(2);
175    elements.add(new ASN1OctetString(TYPE_SCOPE_IDENTIFIER, scopeIdentifier));
176    elements.add(new ASN1Enumerated(TYPE_LOCK_BEHAVIOR,
177         lockBehavior.intValue()));
178
179    return new ASN1Sequence(
180         TransactionSettingsRequestControl.TYPE_SCOPED_LOCK_DETAILS, elements);
181  }
182
183
184
185  /**
186   * Decodes the provided ASN.1 element as a set of scoped lock settings.
187   *
188   * @param  element  The ASN.1 element to decode as a set of scoped lock
189   *                  settings.  It may be {@code null} if the associated
190   *                  transaction settings request control did not include any
191   *                  scoped lock settings.
192   *
193   * @return  The decoded scoped lock settings.
194   *
195   * @throws  LDAPException  If a problem occurs while attempting to decode the
196   *                         provided ASN.1 element as a set of scoped lock
197   *                         settings.
198   */
199  @Nullable()
200  public static TransactionSettingsScopedLockDetails decode(
201              @Nullable final ASN1Element element)
202         throws LDAPException
203  {
204    if (element == null)
205    {
206      return null;
207    }
208
209    try
210    {
211      final ASN1Element[] elements = element.decodeAsSequence().elements();
212      final String scopeIdentifier =
213           elements[0].decodeAsOctetString().stringValue();
214
215      final int lockBehaviorIntValue =
216           elements[1].decodeAsEnumerated().intValue();
217      final TransactionSettingsBackendLockBehavior lockBehavior =
218           TransactionSettingsBackendLockBehavior.valueOf(lockBehaviorIntValue);
219
220      return new TransactionSettingsScopedLockDetails(scopeIdentifier,
221           lockBehavior);
222    }
223    catch (final Exception e)
224    {
225      Debug.debugException(e);
226      throw new LDAPException(ResultCode.PROTOCOL_ERROR,
227           ERR_TXN_SETTINGS_SCOPED_LOCK_DETAILS_CANNOT_DECODE.get(
228                StaticUtils.getExceptionMessage(e)),
229           e);
230    }
231  }
232
233
234
235  /**
236   * Retrieves a string representation of the scoped lock details.
237   *
238   * @return  A string representation of the scoped lock details.
239   */
240  @Override()
241  @NotNull()
242  public String toString()
243  {
244    final StringBuilder buffer = new StringBuilder();
245    toString(buffer);
246    return buffer.toString();
247  }
248
249
250
251  /**
252   * Appends a string representation of the scoped lock details to the provided
253   * buffer.
254   *
255   * @param  buffer  The buffer to which the string representation should be
256   *                 appended.
257   */
258  public void toString(@NotNull final StringBuilder buffer)
259  {
260    buffer.append("TransactionSettingsScopedLockDetails(scopeIdentifier='");
261    buffer.append(scopeIdentifier);
262    buffer.append("', lockBehavior='");
263    buffer.append(lockBehavior.name());
264    buffer.append("')");
265  }
266}