001/*
002 * Copyright 2013-2023 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2013-2023 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) 2013-2023 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;
042
043import com.unboundid.asn1.ASN1Element;
044import com.unboundid.asn1.ASN1Enumerated;
045import com.unboundid.asn1.ASN1Integer;
046import com.unboundid.asn1.ASN1Sequence;
047import com.unboundid.ldap.sdk.LDAPException;
048import com.unboundid.ldap.sdk.ResultCode;
049import com.unboundid.util.Debug;
050import com.unboundid.util.NotMutable;
051import com.unboundid.util.NotNull;
052import com.unboundid.util.Nullable;
053import com.unboundid.util.StaticUtils;
054import com.unboundid.util.ThreadSafety;
055import com.unboundid.util.ThreadSafetyLevel;
056
057import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
058
059
060
061/**
062 * This class defines a data structure that provides information about the
063 * result of assured replication processing, either on a replication server (if
064 * that is all that is needed to satisfy the desired level of assurance) or
065 * on a directory server (if required by the desired level of assurance).
066 * <BR>
067 * <BLOCKQUOTE>
068 *   <B>NOTE:</B>  This class, and other classes within the
069 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
070 *   supported for use against Ping Identity, UnboundID, and
071 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
072 *   for proprietary functionality or for external specifications that are not
073 *   considered stable or mature enough to be guaranteed to work in an
074 *   interoperable way with other types of LDAP servers.
075 * </BLOCKQUOTE>
076 */
077@NotMutable()
078@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
079public final class AssuredReplicationServerResult
080       implements Serializable
081{
082  /**
083   * The BER type for the result code element.
084   */
085  private static final byte TYPE_RESULT_CODE = (byte) 0x80;
086
087
088  /**
089   * The BER type for the server ID element.
090   */
091  private static final byte TYPE_SERVER_ID = (byte) 0x81;
092
093
094  /**
095   * The BER type for the replica ID element.
096   */
097  private static final byte TYPE_REPLICA_ID = (byte) 0x82;
098
099
100
101  /**
102   * The serial version UID for this serializable class.
103   */
104  private static final long serialVersionUID = 3015162215769386343L;
105
106
107
108  // The result code for this server result.
109  @NotNull private final AssuredReplicationServerResultCode resultCode;
110
111  // The replica ID of the associated directory server.
112  @Nullable private final Short replicaID;
113
114  // The server ID of the associated replication server.
115  @Nullable private final Short replicationServerID;
116
117
118
119  /**
120   * Creates a new assured replication server result with the provided
121   * information.
122   *
123   * @param  resultCode           The result code that indicates the state of
124   *                              assurance processing for the associated
125   *                              replication server and/or directory server.
126   *                              It must not be {@code null}.
127   * @param  replicationServerID  The server ID of the replication server from
128   *                              which this server result was obtained.  It may
129   *                              be {@code null} if no replication server ID is
130   *                              available for this result.
131   * @param  replicaID            The replica ID of the directory server with
132   *                              which this result is associated.  It may be
133   *                              {@code null} if no replica ID is available
134   *                              for this result.
135   */
136  public AssuredReplicationServerResult(
137       @NotNull final AssuredReplicationServerResultCode resultCode,
138       @Nullable final Short replicationServerID,
139       @Nullable final Short replicaID)
140  {
141    this.resultCode = resultCode;
142    this.replicationServerID = replicationServerID;
143    this.replicaID = replicaID;
144  }
145
146
147
148  /**
149   * Retrieves the result code that indicates the state of assurance processing
150   * for this server result.
151   *
152   * @return  The result code for this server result.
153   */
154  @NotNull()
155  public AssuredReplicationServerResultCode getResultCode()
156  {
157    return resultCode;
158  }
159
160
161
162  /**
163   * Retrieves the server ID for the replication server from which this server
164   * result was obtained, if available.
165   *
166   * @return  The server ID for the replication server from which this server
167   *          result was obtained, or {@code null} if no replication server ID
168   *          is available.
169   */
170  @Nullable()
171  public Short getReplicationServerID()
172  {
173    return replicationServerID;
174  }
175
176
177
178  /**
179   * Retrieves the replica ID for the directory server with which this server
180   * result is associated, if applicable.
181   *
182   * @return  The replica ID for the directory server with which this server
183   *          result is associated, or {@code null} if there is no associated
184   *          directory server.
185   */
186  @Nullable()
187  public Short getReplicaID()
188  {
189    return replicaID;
190  }
191
192
193
194  /**
195   * Encodes this assured replication server result to an ASN.1 element suitable
196   * for use in a {@link AssuredReplicationResponseControl}.
197   *
198   * @return  The encoded representation of this assured replication server
199   *          result.
200   */
201  @NotNull()
202  ASN1Element encode()
203  {
204    final ArrayList<ASN1Element> elements = new ArrayList<>(3);
205
206    elements.add(new ASN1Enumerated(TYPE_RESULT_CODE, resultCode.intValue()));
207
208    if (replicationServerID != null)
209    {
210      elements.add(new ASN1Integer(TYPE_SERVER_ID, replicationServerID));
211    }
212
213    if (replicaID != null)
214    {
215      elements.add(new ASN1Integer(TYPE_REPLICA_ID, replicaID));
216    }
217
218    return new ASN1Sequence(elements);
219  }
220
221
222
223  /**
224   * Decodes the provided ASN.1 element as an assured replication server
225   * result.
226   *
227   * @param  element  The ASN.1 element to be decoded.  It must not be
228   *                  {@code null}.
229   *
230   * @return  The decoded assured replication server result.
231   *
232   * @throws  LDAPException  If a problem is encountered while attempting to
233   *                         decode the provided ASN.1 element as an assured
234   *                         replication server result.
235   */
236  @NotNull()
237  static AssuredReplicationServerResult decode(
238              @NotNull final ASN1Element element)
239         throws LDAPException
240  {
241    AssuredReplicationServerResultCode resultCode = null;
242    Short serverID  = null;
243    Short replicaID = null;
244
245    try
246    {
247      for (final ASN1Element e :
248           ASN1Sequence.decodeAsSequence(element).elements())
249      {
250        switch (e.getType())
251        {
252          case TYPE_RESULT_CODE:
253            final int rcValue = ASN1Enumerated.decodeAsEnumerated(e).intValue();
254            resultCode = AssuredReplicationServerResultCode.valueOf(rcValue);
255            if (resultCode == null)
256            {
257              throw new LDAPException(ResultCode.DECODING_ERROR,
258                   ERR_ASSURED_REPLICATION_SERVER_RESULT_INVALID_RESULT_CODE.
259                        get(rcValue));
260            }
261            break;
262
263          case TYPE_SERVER_ID:
264            serverID = (short) ASN1Integer.decodeAsInteger(e).intValue();
265            break;
266
267          case TYPE_REPLICA_ID:
268            replicaID = (short) ASN1Integer.decodeAsInteger(e).intValue();
269            break;
270
271          default:
272            throw new LDAPException(ResultCode.DECODING_ERROR,
273                 ERR_ASSURED_REPLICATION_SERVER_RESULT_UNEXPECTED_ELEMENT_TYPE.
274                      get(StaticUtils.toHex(e.getType())));
275        }
276      }
277    }
278    catch (final LDAPException le)
279    {
280      Debug.debugException(le);
281      throw le;
282    }
283    catch (final Exception e)
284    {
285      Debug.debugException(e);
286      throw new LDAPException(ResultCode.DECODING_ERROR,
287           ERR_ASSURED_REPLICATION_SERVER_RESULT_CANNOT_DECODE.get(
288                StaticUtils.getExceptionMessage(e)),
289           e);
290    }
291
292    if (resultCode == null)
293    {
294      throw new LDAPException(ResultCode.DECODING_ERROR,
295           ERR_ASSURED_REPLICATION_SERVER_RESULT_NO_RESULT_CODE.get());
296    }
297
298    return new AssuredReplicationServerResult(resultCode, serverID, replicaID);
299  }
300
301
302
303  /**
304   * Retrieves a string representation of this assured replication server
305   * result.
306   *
307   * @return  A string representation of this assured replication server
308   *          result.
309   */
310  @Override()
311  @NotNull()
312  public String toString()
313  {
314    final StringBuilder buffer = new StringBuilder();
315    toString(buffer);
316    return buffer.toString();
317  }
318
319
320
321  /**
322   * Appends a string representation of this assured replication server result
323   * to the provided buffer.
324   *
325   * @param  buffer  The buffer to which the information should be appended.
326   */
327  public void toString(@NotNull final StringBuilder buffer)
328  {
329    buffer.append("AssuredReplicationServerResult(resultCode=");
330    buffer.append(resultCode.name());
331
332    if (replicationServerID != null)
333    {
334      buffer.append(", replicationServerID=");
335      buffer.append(replicationServerID);
336    }
337
338    if (replicaID != null)
339    {
340      buffer.append(", replicaID=");
341      buffer.append(replicaID);
342    }
343
344    buffer.append(')');
345  }
346}