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