001/*
002 * Copyright 2013-2022 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2013-2022 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-2022 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.util.ArrayList;
041import java.util.Collection;
042import java.util.Collections;
043import java.util.Iterator;
044import java.util.List;
045
046import com.unboundid.asn1.ASN1Boolean;
047import com.unboundid.asn1.ASN1Element;
048import com.unboundid.asn1.ASN1Enumerated;
049import com.unboundid.asn1.ASN1OctetString;
050import com.unboundid.asn1.ASN1Sequence;
051import com.unboundid.ldap.sdk.Control;
052import com.unboundid.ldap.sdk.DecodeableControl;
053import com.unboundid.ldap.sdk.LDAPException;
054import com.unboundid.ldap.sdk.LDAPResult;
055import com.unboundid.ldap.sdk.ResultCode;
056import com.unboundid.util.Debug;
057import com.unboundid.util.NotMutable;
058import com.unboundid.util.NotNull;
059import com.unboundid.util.Nullable;
060import com.unboundid.util.StaticUtils;
061import com.unboundid.util.ThreadSafety;
062import com.unboundid.util.ThreadSafetyLevel;
063
064import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
065
066
067
068/**
069 * This class provides an implementation of an LDAP control that can be included
070 * in add, bind, modify, modify DN, and certain extended responses to provide
071 * information about the result of replication assurance processing for that
072 * operation.
073 * <BR>
074 * <BLOCKQUOTE>
075 *   <B>NOTE:</B>  This class, and other classes within the
076 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
077 *   supported for use against Ping Identity, UnboundID, and
078 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
079 *   for proprietary functionality or for external specifications that are not
080 *   considered stable or mature enough to be guaranteed to work in an
081 *   interoperable way with other types of LDAP servers.
082 * </BLOCKQUOTE>
083 * <BR>
084 * The OID for this control is 1.3.6.1.4.1.30221.2.5.29.  It will have a
085 * criticality of FALSE, and will have a value with the following encoding:
086 * <PRE>
087 *   AssuredReplicationResponse ::= SEQUENCE {
088 *        localLevel                   [0] LocalLevel OPTIONAL,
089 *        localAssuranceSatisfied      [1] BOOLEAN,
090 *        localAssuranceMessage        [2] OCTET STRING OPTIONAL,
091 *        remoteLevel                  [3] RemoteLevel OPTIONAL,
092 *        remoteAssuranceSatisfied     [4] BOOLEAN,
093 *        remoteAssuranceMessage       [5] OCTET STRING OPTIONAL,
094 *        csn                          [6] OCTET STRING OPTIONAL,
095 *        serverResults                [7] SEQUENCE OF ServerResult OPTIONAL,
096 *        ... }
097 *
098 *   ServerResult ::= SEQUENCE {
099 *        resultCode              [0] ENUMERATED {
100 *             complete           (0),
101 *             timeout            (1),
102 *             conflict           (2),
103 *             serverShutdown     (3),
104 *             unavailable        (4),
105 *             duplicate          (5),
106 *             ... },
107 *        replicationServerID     [1] INTEGER OPTIONAL,
108 *        replicaID               [2] INTEGER OPTIONAL,
109 *        ... }
110 * </PRE>
111 *
112 * @see  AssuredReplicationRequestControl
113 */
114@NotMutable()
115@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
116public final class AssuredReplicationResponseControl
117       extends Control
118       implements DecodeableControl
119{
120  /**
121   * The OID (1.3.6.1.4.1.30221.2.5.29) for the assured replication response
122   * control.
123   */
124  @NotNull public static final String ASSURED_REPLICATION_RESPONSE_OID =
125       "1.3.6.1.4.1.30221.2.5.29";
126
127
128  /**
129   * The BER type for the local level element.
130   */
131  private static final byte TYPE_LOCAL_LEVEL = (byte) 0x80;
132
133
134  /**
135   * The BER type for the local assurance satisfied element.
136   */
137  private static final byte TYPE_LOCAL_SATISFIED = (byte) 0x81;
138
139
140  /**
141   * The BER type for the local message element.
142   */
143  private static final byte TYPE_LOCAL_MESSAGE = (byte) 0x82;
144
145
146  /**
147   * The BER type for the remote level element.
148   */
149  private static final byte TYPE_REMOTE_LEVEL = (byte) 0x83;
150
151
152  /**
153   * The BER type for the remote assurance satisfied element.
154   */
155  private static final byte TYPE_REMOTE_SATISFIED = (byte) 0x84;
156
157
158  /**
159   * The BER type for the remote message element.
160   */
161  private static final byte TYPE_REMOTE_MESSAGE = (byte) 0x85;
162
163
164  /**
165   * The BER type for the CSN element.
166   */
167  private static final byte TYPE_CSN = (byte) 0x86;
168
169
170  /**
171   * The BER type for the server results element.
172   */
173  private static final byte TYPE_SERVER_RESULTS = (byte) 0xA7;
174
175
176
177  /**
178   * The serial version UID for this serializable class.
179   */
180  private static final long serialVersionUID = -4521456074629871607L;
181
182
183
184  // The assurance level for local processing.
185  @Nullable private final AssuredReplicationLocalLevel localLevel;
186
187  // The assurance level for remote processing.
188  @Nullable private final AssuredReplicationRemoteLevel remoteLevel;
189
190  // Indicates whether the desired local assurance has been satisfied.
191  private final boolean localAssuranceSatisfied;
192
193  // Indicates whether the desired remote assurance has been satisfied.
194  private final boolean remoteAssuranceSatisfied;
195
196  // The results from individual replication and/or directory servers.
197  @NotNull private final List<AssuredReplicationServerResult> serverResults;
198
199  // The replication change sequence number for the associated operation.
200  @Nullable private final String csn;
201
202  // An optional message with additional information about local assurance
203  // processing.
204  @Nullable private final String localAssuranceMessage;
205
206  // An optional message with additional information about local assurance
207  // processing.
208  @Nullable private final String remoteAssuranceMessage;
209
210
211
212  /**
213   * Creates a new empty control instance that is intended to be used only for
214   * decoding controls via the {@code DecodeableControl} interface.
215   */
216  AssuredReplicationResponseControl()
217  {
218    localLevel = null;
219    localAssuranceSatisfied = false;
220    localAssuranceMessage = null;
221    remoteLevel = null;
222    remoteAssuranceSatisfied = false;
223    remoteAssuranceMessage = null;
224    csn = null;
225    serverResults = null;
226  }
227
228
229
230  /**
231   * Creates a new assured replication response control with the provided
232   * information.
233   *
234   * @param  localLevel                The local assurance level selected by the
235   *                                   server for the associated operation.  It
236   *                                   may be {@code null} if this is not
237   *                                   available.
238   * @param  localAssuranceSatisfied   Indicates whether the desired local level
239   *                                   of assurance is known to have been
240   *                                   satisfied.
241   * @param  localAssuranceMessage     An optional message providing additional
242   *                                   information about local assurance
243   *                                   processing.  This may be {@code null} if
244   *                                   no additional message is needed.
245   * @param  remoteLevel               The remote assurance level selected by
246   *                                   the server for the associated operation.
247   *                                   It may be {@code null} if this is not
248   *                                   available.
249   * @param  remoteAssuranceSatisfied  Indicates whether the desired remote
250   *                                   level of assurance is known to have been
251   *                                   satisfied.
252   * @param  remoteAssuranceMessage    An optional message providing additional
253   *                                   information about remote assurance
254   *                                   processing.  This may be {@code null} if
255   *                                   no additional message is needed.
256   * @param  csn                       The change sequence number (CSN) that has
257   *                                   been assigned to the associated
258   *                                   operation.  It may be {@code null} if no
259   *                                   CSN is available.
260   * @param  serverResults             The set of individual results from the
261   *                                   local and/or remote replication servers
262   *                                   and/or directory servers used in
263   *                                   assurance processing.  This may be
264   *                                   {@code null} or empty if no server
265   *                                   results are available.
266   */
267  public AssuredReplicationResponseControl(
268       @Nullable final AssuredReplicationLocalLevel localLevel,
269       final boolean localAssuranceSatisfied,
270       @Nullable final String localAssuranceMessage,
271       @Nullable final AssuredReplicationRemoteLevel remoteLevel,
272       final boolean remoteAssuranceSatisfied,
273       @Nullable final String remoteAssuranceMessage,
274       @Nullable final String csn,
275       @Nullable final Collection<AssuredReplicationServerResult> serverResults)
276  {
277    super(ASSURED_REPLICATION_RESPONSE_OID, false,
278         encodeValue(localLevel, localAssuranceSatisfied,
279              localAssuranceMessage, remoteLevel, remoteAssuranceSatisfied,
280              remoteAssuranceMessage, csn, serverResults));
281
282    this.localLevel               = localLevel;
283    this.localAssuranceSatisfied  = localAssuranceSatisfied;
284    this.localAssuranceMessage    = localAssuranceMessage;
285    this.remoteLevel              = remoteLevel;
286    this.remoteAssuranceSatisfied = remoteAssuranceSatisfied;
287    this.remoteAssuranceMessage   = remoteAssuranceMessage;
288    this.csn                      = csn;
289
290    if (serverResults == null)
291    {
292      this.serverResults = Collections.emptyList();
293    }
294    else
295    {
296      this.serverResults = Collections.unmodifiableList(
297           new ArrayList<>(serverResults));
298    }
299  }
300
301
302
303  /**
304   * Creates a new assured replication response control with the provided
305   * information.
306   *
307   * @param  oid         The OID for the control.
308   * @param  isCritical  Indicates whether the control should be marked
309   *                     critical.
310   * @param  value       The encoded value for the control.  This may be
311   *                     {@code null} if no value was provided.
312   *
313   * @throws  LDAPException  If the provided control cannot be decoded as an
314   *                         assured replication response control.
315   */
316  public AssuredReplicationResponseControl(@NotNull final String oid,
317              final boolean isCritical,
318              @Nullable final ASN1OctetString value)
319         throws LDAPException
320  {
321    super(oid, isCritical, value);
322
323    if (value == null)
324    {
325      throw new LDAPException(ResultCode.DECODING_ERROR,
326           ERR_ASSURED_REPLICATION_RESPONSE_NO_VALUE.get());
327    }
328
329    AssuredReplicationLocalLevel         lLevel     = null;
330    Boolean                              lSatisfied = null;
331    String                               lMessage   = null;
332    AssuredReplicationRemoteLevel        rLevel     = null;
333    Boolean                              rSatisfied = null;
334    String                               rMessage   = null;
335    String                               seqNum     = null;
336    List<AssuredReplicationServerResult> sResults   = Collections.emptyList();
337
338    try
339    {
340      for (final ASN1Element e :
341           ASN1Sequence.decodeAsSequence(value.getValue()).elements())
342      {
343        switch (e.getType())
344        {
345          case TYPE_LOCAL_LEVEL:
346            int intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue();
347            lLevel = AssuredReplicationLocalLevel.valueOf(intValue);
348            if (lLevel == null)
349            {
350              throw new LDAPException(ResultCode.DECODING_ERROR,
351                   ERR_ASSURED_REPLICATION_RESPONSE_INVALID_LOCAL_LEVEL.get(
352                        intValue));
353            }
354            break;
355
356          case TYPE_LOCAL_SATISFIED:
357            lSatisfied = ASN1Boolean.decodeAsBoolean(e).booleanValue();
358            break;
359
360          case TYPE_LOCAL_MESSAGE:
361            lMessage = ASN1OctetString.decodeAsOctetString(e).stringValue();
362            break;
363
364          case TYPE_REMOTE_LEVEL:
365            intValue = ASN1Enumerated.decodeAsEnumerated(e).intValue();
366            rLevel = AssuredReplicationRemoteLevel.valueOf(intValue);
367            if (lLevel == null)
368            {
369              throw new LDAPException(ResultCode.DECODING_ERROR,
370                   ERR_ASSURED_REPLICATION_RESPONSE_INVALID_REMOTE_LEVEL.get(
371                        intValue));
372            }
373            break;
374
375          case TYPE_REMOTE_SATISFIED:
376            rSatisfied = ASN1Boolean.decodeAsBoolean(e).booleanValue();
377            break;
378
379          case TYPE_REMOTE_MESSAGE:
380            rMessage = ASN1OctetString.decodeAsOctetString(e).stringValue();
381            break;
382
383          case TYPE_CSN:
384            seqNum = ASN1OctetString.decodeAsOctetString(e).stringValue();
385            break;
386
387          case TYPE_SERVER_RESULTS:
388            final ASN1Element[] srElements =
389                 ASN1Sequence.decodeAsSequence(e).elements();
390            final ArrayList<AssuredReplicationServerResult> srList =
391                 new ArrayList<>(srElements.length);
392            for (final ASN1Element srElement : srElements)
393            {
394              try
395              {
396                srList.add(AssuredReplicationServerResult.decode(srElement));
397              }
398              catch (final Exception ex)
399              {
400                Debug.debugException(ex);
401                throw new LDAPException(ResultCode.DECODING_ERROR,
402                     ERR_ASSURED_REPLICATION_RESPONSE_ERROR_DECODING_SR.get(
403                          StaticUtils.getExceptionMessage(ex)),
404                     ex);
405              }
406            }
407            sResults = Collections.unmodifiableList(srList);
408            break;
409
410          default:
411            throw new LDAPException(ResultCode.DECODING_ERROR,
412                 ERR_ASSURED_REPLICATION_RESPONSE_UNEXPECTED_ELEMENT_TYPE.get(
413                      StaticUtils.toHex(e.getType())));
414        }
415      }
416    }
417    catch (final LDAPException le)
418    {
419      Debug.debugException(le);
420      throw le;
421    }
422    catch (final Exception e)
423    {
424      Debug.debugException(e);
425      throw new LDAPException(ResultCode.DECODING_ERROR,
426           ERR_ASSURED_REPLICATION_RESPONSE_ERROR_DECODING_VALUE.get(
427                StaticUtils.getExceptionMessage(e)),
428           e);
429    }
430
431    if (lSatisfied == null)
432    {
433      throw new LDAPException(ResultCode.DECODING_ERROR,
434           ERR_ASSURED_REPLICATION_RESPONSE_NO_LOCAL_SATISFIED.get());
435    }
436
437    if (rSatisfied == null)
438    {
439      throw new LDAPException(ResultCode.DECODING_ERROR,
440           ERR_ASSURED_REPLICATION_RESPONSE_NO_REMOTE_SATISFIED.get());
441    }
442
443    localLevel               = lLevel;
444    localAssuranceSatisfied  = lSatisfied;
445    localAssuranceMessage    = lMessage;
446    remoteLevel              = rLevel;
447    remoteAssuranceSatisfied = rSatisfied;
448    remoteAssuranceMessage   = rMessage;
449    csn                      = seqNum;
450    serverResults            = sResults;
451  }
452
453
454
455  /**
456   * Encodes the provided information to an ASN.1 octet string suitable for
457   * use as an assured replication response control value.
458   *
459   * @param  localLevel                The local assurance level selected by the
460   *                                   server for the associated operation.  It
461   *                                   may be {@code null} if this is not
462   *                                   available.
463   * @param  localAssuranceSatisfied   Indicates whether the desired local level
464   *                                   of assurance is known to have been
465   *                                   satisfied.
466   * @param  localAssuranceMessage     An optional message providing additional
467   *                                   information about local assurance
468   *                                   processing.  This may be {@code null} if
469   *                                   no additional message is needed.
470   * @param  remoteLevel               The remote assurance level selected by
471   *                                   the server for the associated operation.
472   *                                   It may be {@code null} if this is not
473   *                                   available.
474   * @param  remoteAssuranceSatisfied  Indicates whether the desired remote
475   *                                   level of assurance is known to have been
476   *                                   satisfied.
477   * @param  remoteAssuranceMessage    An optional message providing additional
478   *                                   information about remote assurance
479   *                                   processing.  This may be {@code null} if
480   *                                   no additional message is needed.
481   * @param  csn                       The change sequence number (CSN) that has
482   *                                   been assigned to the associated
483   *                                   operation.  It may be {@code null} if no
484   *                                   CSN is available.
485   * @param  serverResults             The set of individual results from the
486   *                                   local and/or remote replication servers
487   *                                   and/or directory servers used in
488   *                                   assurance processing.  This may be
489   *                                   {@code null} or empty if no server
490   *                                   results are available.
491   *
492   * @return  The ASN.1 octet string containing the encoded value.
493   */
494  @NotNull()
495  private static ASN1OctetString encodeValue(
496       @Nullable final AssuredReplicationLocalLevel localLevel,
497       final boolean localAssuranceSatisfied,
498       @Nullable final String localAssuranceMessage,
499       @Nullable final AssuredReplicationRemoteLevel remoteLevel,
500       final boolean remoteAssuranceSatisfied,
501       @Nullable final String remoteAssuranceMessage,
502       @Nullable final String csn,
503       @Nullable final Collection<AssuredReplicationServerResult> serverResults)
504  {
505    final ArrayList<ASN1Element> elements = new ArrayList<>(8);
506
507    if (localLevel != null)
508    {
509      elements.add(new ASN1Enumerated(TYPE_LOCAL_LEVEL, localLevel.intValue()));
510    }
511
512    elements.add(new ASN1Boolean(TYPE_LOCAL_SATISFIED,
513         localAssuranceSatisfied));
514
515    if (localAssuranceMessage != null)
516    {
517      elements.add(new ASN1OctetString(TYPE_LOCAL_MESSAGE,
518           localAssuranceMessage));
519    }
520
521    if (remoteLevel != null)
522    {
523      elements.add(new ASN1Enumerated(TYPE_REMOTE_LEVEL,
524           remoteLevel.intValue()));
525    }
526
527    elements.add(new ASN1Boolean(TYPE_REMOTE_SATISFIED,
528         remoteAssuranceSatisfied));
529
530    if (remoteAssuranceMessage != null)
531    {
532      elements.add(new ASN1OctetString(TYPE_REMOTE_MESSAGE,
533           remoteAssuranceMessage));
534    }
535
536    if (csn != null)
537    {
538      elements.add(new ASN1OctetString(TYPE_CSN, csn));
539    }
540
541    if ((serverResults !=  null) && (! serverResults.isEmpty()))
542    {
543      final ArrayList<ASN1Element> srElements =
544           new ArrayList<>(serverResults.size());
545      for (final AssuredReplicationServerResult r : serverResults)
546      {
547        srElements.add(r.encode());
548      }
549      elements.add(new ASN1Sequence(TYPE_SERVER_RESULTS, srElements));
550    }
551
552    return new ASN1OctetString(new ASN1Sequence(elements).encode());
553  }
554
555
556
557  /**
558   * {@inheritDoc}
559   */
560  @Override()
561  @NotNull()
562  public AssuredReplicationResponseControl decodeControl(
563              @NotNull final String oid, final boolean isCritical,
564              @Nullable final ASN1OctetString value)
565         throws LDAPException
566  {
567    return new AssuredReplicationResponseControl(oid, isCritical, value);
568  }
569
570
571
572  /**
573   * Extracts an assured replication response control from the provided LDAP
574   * result.  If there are multiple assured replication response controls
575   * included in the result, then only the first will be returned.
576   *
577   * @param  result  The LDAP result from which to retrieve the assured
578   *                 replication response control.
579   *
580   * @return  The assured replication response control contained in the provided
581   *          LDAP result, or {@code null} if the result did not contain an
582   *          assured replication response control.
583   *
584   * @throws  LDAPException  If a problem is encountered while attempting to
585   *                         decode the assured replication response control
586   *                         contained in the provided result.
587   */
588  @Nullable()
589  public static AssuredReplicationResponseControl get(
590                     @NotNull final LDAPResult result)
591         throws LDAPException
592  {
593    final Control c =
594         result.getResponseControl(ASSURED_REPLICATION_RESPONSE_OID);
595    if (c == null)
596    {
597      return null;
598    }
599
600    if (c instanceof AssuredReplicationResponseControl)
601    {
602      return (AssuredReplicationResponseControl) c;
603    }
604    else
605    {
606      return new AssuredReplicationResponseControl(c.getOID(), c.isCritical(),
607           c.getValue());
608    }
609  }
610
611
612
613  /**
614   * Extracts all assured replication response controls from the provided LDAP
615   * result.
616   *
617   * @param  result  The LDAP result from which to retrieve the assured
618   *                 replication response controls.
619   *
620   * @return  A list containing the assured replication response controls
621   *          contained in the provided LDAP result, or an empty list if the
622   *          result did not contain any assured replication response control.
623   *
624   * @throws  LDAPException  If a problem is encountered while attempting to
625   *                         decode any assured replication response control
626   *                         contained in the provided result.
627   */
628  @NotNull()
629  public static List<AssuredReplicationResponseControl> getAll(
630                     @NotNull final LDAPResult result)
631         throws LDAPException
632  {
633    final Control[] controls = result.getResponseControls();
634    final ArrayList<AssuredReplicationResponseControl> decodedControls =
635         new ArrayList<>(controls.length);
636    for (final Control c : controls)
637    {
638      if (c.getOID().equals(ASSURED_REPLICATION_RESPONSE_OID))
639      {
640        if (c instanceof AssuredReplicationResponseControl)
641        {
642          decodedControls.add((AssuredReplicationResponseControl) c);
643        }
644        else
645        {
646          decodedControls.add(new AssuredReplicationResponseControl(c.getOID(),
647               c.isCritical(), c.getValue()));
648        }
649      }
650    }
651
652    return Collections.unmodifiableList(decodedControls);
653  }
654
655
656
657  /**
658   * Retrieves the local assurance level selected by the server for the
659   * associated operation, if available.
660   *
661   * @return  The local assurance level selected by the server for the
662   *          associated operation, or {@code null} if this is not available.
663   */
664  @Nullable()
665  public AssuredReplicationLocalLevel getLocalLevel()
666  {
667    return localLevel;
668  }
669
670
671
672  /**
673   * Indicates whether the desired local level of assurance is known to have
674   * been satisfied.
675   *
676   * @return  {@code true} if the desired local level of assurance is known to
677   *          have been satisfied, or {@code false} if not.
678   */
679  public boolean localAssuranceSatisfied()
680  {
681    return localAssuranceSatisfied;
682  }
683
684
685
686  /**
687   * Retrieves a message with additional information about local assurance
688   * processing, if available.
689   *
690   * @return  A message with additional information about local assurance
691   *          processing, or {@code null} if none is available.
692   */
693  @Nullable()
694  public String getLocalAssuranceMessage()
695  {
696    return localAssuranceMessage;
697  }
698
699
700
701  /**
702   * Retrieves the remote assurance level selected by the server for the
703   * associated operation, if available.
704   *
705   * @return  The remote assurance level selected by the server for the
706   *          associated operation, or {@code null} if the remote assurance
707   *          level is not available.
708   */
709  @Nullable()
710  public AssuredReplicationRemoteLevel getRemoteLevel()
711  {
712    return remoteLevel;
713  }
714
715
716
717  /**
718   * Indicates whether the desired remote level of assurance is known to have
719   * been satisfied.
720   *
721   * @return  {@code true} if the desired remote level of assurance is known to
722   *          have been satisfied, or {@code false} if not.
723   */
724  public boolean remoteAssuranceSatisfied()
725  {
726    return remoteAssuranceSatisfied;
727  }
728
729
730
731  /**
732   * Retrieves a message with additional information about remote assurance
733   * processing, if available.
734   *
735   * @return  A message with additional information about remote assurance
736   *          processing, or {@code null} if none is available.
737   */
738  @Nullable()
739  public String getRemoteAssuranceMessage()
740  {
741    return remoteAssuranceMessage;
742  }
743
744
745
746  /**
747   * Retrieves the replication change sequence number (CSN) assigned to the
748   * associated operation, if available.
749   *
750   * @return  The replication CSN assigned to the associated operation, or
751   *          {@code null} if the CSN is not available.
752   */
753  @Nullable()
754  public String getCSN()
755  {
756    return csn;
757  }
758
759
760
761  /**
762   * Retrieves a list of the results from individual replication servers and/or
763   * directory servers used in assurance processing.  It may be empty if no
764   * server results are available.
765   *
766   * @return  A list of the results from individual replication servers and/or
767   *          directory servers used in assurance processing.
768   */
769  @NotNull()
770  public List<AssuredReplicationServerResult> getServerResults()
771  {
772    return serverResults;
773  }
774
775
776
777  /**
778   * {@inheritDoc}
779   */
780  @Override()
781  @NotNull()
782  public String getControlName()
783  {
784    return INFO_CONTROL_NAME_ASSURED_REPLICATION_RESPONSE.get();
785  }
786
787
788
789  /**
790   * {@inheritDoc}
791   */
792  @Override()
793  public void toString(@NotNull final StringBuilder buffer)
794  {
795    buffer.append("AssuredReplicationResponseControl(isCritical=");
796    buffer.append(isCritical());
797
798    if (localLevel != null)
799    {
800      buffer.append(", localLevel=");
801      buffer.append(localLevel.name());
802    }
803
804    buffer.append(", localAssuranceSatisfied=");
805    buffer.append(localAssuranceSatisfied);
806
807    if (localAssuranceMessage != null)
808    {
809      buffer.append(", localMessage='");
810      buffer.append(localAssuranceMessage);
811      buffer.append('\'');
812    }
813
814    if (remoteLevel != null)
815    {
816      buffer.append(", remoteLevel=");
817      buffer.append(remoteLevel.name());
818    }
819
820    buffer.append(", remoteAssuranceSatisfied=");
821    buffer.append(remoteAssuranceSatisfied);
822
823    if (remoteAssuranceMessage != null)
824    {
825      buffer.append(", remoteMessage='");
826      buffer.append(remoteAssuranceMessage);
827      buffer.append('\'');
828    }
829
830    if (csn != null)
831    {
832      buffer.append(", csn='");
833      buffer.append(csn);
834      buffer.append('\'');
835    }
836
837    if ((serverResults != null) && (! serverResults.isEmpty()))
838    {
839      buffer.append(", serverResults={");
840
841      final Iterator<AssuredReplicationServerResult> iterator =
842           serverResults.iterator();
843      while (iterator.hasNext())
844      {
845        if (iterator.hasNext())
846        {
847          iterator.next().toString(buffer);
848          buffer.append(", ");
849        }
850      }
851
852      buffer.append('}');
853    }
854
855    buffer.append(')');
856  }
857}