001/*
002 * Copyright 2013-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 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 Alcatel-Lucent 8661
061 *   server products.  These classes provide support for proprietary
062 *   functionality or for external specifications that are not considered stable
063 *   or mature enough to be guaranteed to work in an interoperable way with
064 *   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<AssuredReplicationServerResult>(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<AssuredReplicationServerResult>(
374                      srElements.length);
375            for (final ASN1Element srElement : srElements)
376            {
377              try
378              {
379                srList.add(AssuredReplicationServerResult.decode(srElement));
380              }
381              catch (final Exception ex)
382              {
383                Debug.debugException(ex);
384                throw new LDAPException(ResultCode.DECODING_ERROR,
385                     ERR_ASSURED_REPLICATION_RESPONSE_ERROR_DECODING_SR.get(
386                          StaticUtils.getExceptionMessage(ex)),
387                     ex);
388              }
389            }
390            sResults = Collections.unmodifiableList(srList);
391            break;
392
393          default:
394            throw new LDAPException(ResultCode.DECODING_ERROR,
395                 ERR_ASSURED_REPLICATION_RESPONSE_UNEXPECTED_ELEMENT_TYPE.get(
396                      StaticUtils.toHex(e.getType())));
397        }
398      }
399    }
400    catch (final LDAPException le)
401    {
402      Debug.debugException(le);
403      throw le;
404    }
405    catch (final Exception e)
406    {
407      Debug.debugException(e);
408      throw new LDAPException(ResultCode.DECODING_ERROR,
409           ERR_ASSURED_REPLICATION_RESPONSE_ERROR_DECODING_VALUE.get(
410                StaticUtils.getExceptionMessage(e)),
411           e);
412    }
413
414    if (lSatisfied == null)
415    {
416      throw new LDAPException(ResultCode.DECODING_ERROR,
417           ERR_ASSURED_REPLICATION_RESPONSE_NO_LOCAL_SATISFIED.get());
418    }
419
420    if (rSatisfied == null)
421    {
422      throw new LDAPException(ResultCode.DECODING_ERROR,
423           ERR_ASSURED_REPLICATION_RESPONSE_NO_REMOTE_SATISFIED.get());
424    }
425
426    localLevel               = lLevel;
427    localAssuranceSatisfied  = lSatisfied;
428    localAssuranceMessage    = lMessage;
429    remoteLevel              = rLevel;
430    remoteAssuranceSatisfied = rSatisfied;
431    remoteAssuranceMessage   = rMessage;
432    csn                      = seqNum;
433    serverResults            = sResults;
434  }
435
436
437
438  /**
439   * Encodes the provided information to an ASN.1 octet string suitable for
440   * use as an assured replication response control value.
441   *
442   * @param  localLevel                The local assurance level selected by the
443   *                                   server for the associated operation.  It
444   *                                   may be {@code null} if this is not
445   *                                   available.
446   * @param  localAssuranceSatisfied   Indicates whether the desired local level
447   *                                   of assurance is known to have been
448   *                                   satisfied.
449   * @param  localAssuranceMessage     An optional message providing additional
450   *                                   information about local assurance
451   *                                   processing.  This may be {@code null} if
452   *                                   no additional message is needed.
453   * @param  remoteLevel               The remote assurance level selected by
454   *                                   the server for the associated operation.
455   *                                   It may be {@code null} if this is not
456   *                                   available.
457   * @param  remoteAssuranceSatisfied  Indicates whether the desired remote
458   *                                   level of assurance is known to have been
459   *                                   satisfied.
460   * @param  remoteAssuranceMessage    An optional message providing additional
461   *                                   information about remote assurance
462   *                                   processing.  This may be {@code null} if
463   *                                   no additional message is needed.
464   * @param  csn                       The change sequence number (CSN) that has
465   *                                   been assigned to the associated
466   *                                   operation.  It may be {@code null} if no
467   *                                   CSN is available.
468   * @param  serverResults             The set of individual results from the
469   *                                   local and/or remote replication servers
470   *                                   and/or directory servers used in
471   *                                   assurance processing.  This may be
472   *                                   {@code null} or empty if no server
473   *                                   results are available.
474   *
475   * @return  The ASN.1 octet string containing the encoded value.
476   */
477  private static ASN1OctetString encodeValue(
478               final AssuredReplicationLocalLevel localLevel,
479               final boolean localAssuranceSatisfied,
480               final String localAssuranceMessage,
481               final AssuredReplicationRemoteLevel remoteLevel,
482               final boolean remoteAssuranceSatisfied,
483               final String remoteAssuranceMessage, final String csn,
484               final Collection<AssuredReplicationServerResult> serverResults)
485  {
486    final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(8);
487
488    if (localLevel != null)
489    {
490      elements.add(new ASN1Enumerated(TYPE_LOCAL_LEVEL, localLevel.intValue()));
491    }
492
493    elements.add(new ASN1Boolean(TYPE_LOCAL_SATISFIED,
494         localAssuranceSatisfied));
495
496    if (localAssuranceMessage != null)
497    {
498      elements.add(new ASN1OctetString(TYPE_LOCAL_MESSAGE,
499           localAssuranceMessage));
500    }
501
502    if (remoteLevel != null)
503    {
504      elements.add(new ASN1Enumerated(TYPE_REMOTE_LEVEL,
505           remoteLevel.intValue()));
506    }
507
508    elements.add(new ASN1Boolean(TYPE_REMOTE_SATISFIED,
509         remoteAssuranceSatisfied));
510
511    if (remoteAssuranceMessage != null)
512    {
513      elements.add(new ASN1OctetString(TYPE_REMOTE_MESSAGE,
514           remoteAssuranceMessage));
515    }
516
517    if (csn != null)
518    {
519      elements.add(new ASN1OctetString(TYPE_CSN, csn));
520    }
521
522    if ((serverResults !=  null) && (! serverResults.isEmpty()))
523    {
524      final ArrayList<ASN1Element> srElements =
525           new ArrayList<ASN1Element>(serverResults.size());
526      for (final AssuredReplicationServerResult r : serverResults)
527      {
528        srElements.add(r.encode());
529      }
530      elements.add(new ASN1Sequence(TYPE_SERVER_RESULTS, srElements));
531    }
532
533    return new ASN1OctetString(new ASN1Sequence(elements).encode());
534  }
535
536
537
538  /**
539   * {@inheritDoc}
540   */
541  @Override()
542  public AssuredReplicationResponseControl decodeControl(final String oid,
543                                                final boolean isCritical,
544                                                final ASN1OctetString value)
545         throws LDAPException
546  {
547    return new AssuredReplicationResponseControl(oid, isCritical, value);
548  }
549
550
551
552  /**
553   * Extracts an assured replication response control from the provided LDAP
554   * result.  If there are multiple assured replication response controls
555   * included in the result, then only the first will be returned.
556   *
557   * @param  result  The LDAP result from which to retrieve the assured
558   *                 replication response control.
559   *
560   * @return  The assured replication response control contained in the provided
561   *          LDAP result, or {@code null} if the result did not contain an
562   *          assured replication response control.
563   *
564   * @throws  LDAPException  If a problem is encountered while attempting to
565   *                         decode the assured replication response control
566   *                         contained in the provided result.
567   */
568  public static AssuredReplicationResponseControl get(final LDAPResult result)
569         throws LDAPException
570  {
571    final Control c =
572         result.getResponseControl(ASSURED_REPLICATION_RESPONSE_OID);
573    if (c == null)
574    {
575      return null;
576    }
577
578    if (c instanceof AssuredReplicationResponseControl)
579    {
580      return (AssuredReplicationResponseControl) c;
581    }
582    else
583    {
584      return new AssuredReplicationResponseControl(c.getOID(), c.isCritical(),
585           c.getValue());
586    }
587  }
588
589
590
591  /**
592   * Extracts all assured replication response controls from the provided LDAP
593   * result.
594   *
595   * @param  result  The LDAP result from which to retrieve the assured
596   *                 replication response controls.
597   *
598   * @return  A list containing the assured replication response controls
599   *          contained in the provided LDAP result, or an empty list if the
600   *          result did not contain any assured replication response control.
601   *
602   * @throws  LDAPException  If a problem is encountered while attempting to
603   *                         decode any assured replication response control
604   *                         contained in the provided result.
605   */
606  public static List<AssuredReplicationResponseControl> getAll(
607                     final LDAPResult result)
608         throws LDAPException
609  {
610    final Control[] controls = result.getResponseControls();
611    final ArrayList<AssuredReplicationResponseControl> decodedControls =
612         new ArrayList<AssuredReplicationResponseControl>(controls.length);
613    for (final Control c : controls)
614    {
615      if (c.getOID().equals(ASSURED_REPLICATION_RESPONSE_OID))
616      {
617        if (c instanceof AssuredReplicationResponseControl)
618        {
619          decodedControls.add((AssuredReplicationResponseControl) c);
620        }
621        else
622        {
623          decodedControls.add(new AssuredReplicationResponseControl(c.getOID(),
624               c.isCritical(), c.getValue()));
625        }
626      }
627    }
628
629    return Collections.unmodifiableList(decodedControls);
630  }
631
632
633
634  /**
635   * Retrieves the local assurance level selected by the server for the
636   * associated operation, if available.
637   *
638   * @return  The local assurance level selected by the server for the
639   *          associated operation, or {@code null} if this is not available.
640   */
641  public AssuredReplicationLocalLevel getLocalLevel()
642  {
643    return localLevel;
644  }
645
646
647
648  /**
649   * Indicates whether the desired local level of assurance is known to have
650   * been satisfied.
651   *
652   * @return  {@code true} if the desired local level of assurance is known to
653   *          have been satisfied, or {@code false} if not.
654   */
655  public boolean localAssuranceSatisfied()
656  {
657    return localAssuranceSatisfied;
658  }
659
660
661
662  /**
663   * Retrieves a message with additional information about local assurance
664   * processing, if available.
665   *
666   * @return  A message with additional information about local assurance
667   *          processing, or {@code null} if none is available.
668   */
669  public String getLocalAssuranceMessage()
670  {
671    return localAssuranceMessage;
672  }
673
674
675
676  /**
677   * Retrieves the remote assurance level selected by the server for the
678   * associated operation, if available.
679   *
680   * @return  The remote assurance level selected by the server for the
681   *          associated operation, or {@code null} if the remote assurance
682   *          level is not available.
683   */
684  public AssuredReplicationRemoteLevel getRemoteLevel()
685  {
686    return remoteLevel;
687  }
688
689
690
691  /**
692   * Indicates whether the desired remote level of assurance is known to have
693   * been satisfied.
694   *
695   * @return  {@code true} if the desired remote level of assurance is known to
696   *          have been satisfied, or {@code false} if not.
697   */
698  public boolean remoteAssuranceSatisfied()
699  {
700    return remoteAssuranceSatisfied;
701  }
702
703
704
705  /**
706   * Retrieves a message with additional information about remote assurance
707   * processing, if available.
708   *
709   * @return  A message with additional information about remote assurance
710   *          processing, or {@code null} if none is available.
711   */
712  public String getRemoteAssuranceMessage()
713  {
714    return remoteAssuranceMessage;
715  }
716
717
718
719  /**
720   * Retrieves the replication change sequence number (CSN) assigned to the
721   * associated operation, if available.
722   *
723   * @return  The replication CSN assigned to the associated operation, or
724   *          {@code null} if the CSN is not available.
725   */
726  public String getCSN()
727  {
728    return csn;
729  }
730
731
732
733  /**
734   * Retrieves a list of the results from individual replication servers and/or
735   * directory servers used in assurance processing.  It may be empty if no
736   * server results are available.
737   *
738   * @return  A list of the results from individual replication servers and/or
739   *          directory servers used in assurance processing.
740   */
741  public List<AssuredReplicationServerResult> getServerResults()
742  {
743    return serverResults;
744  }
745
746
747
748  /**
749   * {@inheritDoc}
750   */
751  @Override()
752  public String getControlName()
753  {
754    return INFO_CONTROL_NAME_ASSURED_REPLICATION_RESPONSE.get();
755  }
756
757
758
759  /**
760   * {@inheritDoc}
761   */
762  @Override()
763  public void toString(final StringBuilder buffer)
764  {
765    buffer.append("AssuredReplicationResponseControl(isCritical=");
766    buffer.append(isCritical());
767
768    if (localLevel != null)
769    {
770      buffer.append(", localLevel=");
771      buffer.append(localLevel.name());
772    }
773
774    buffer.append(", localAssuranceSatisfied=");
775    buffer.append(localAssuranceSatisfied);
776
777    if (localAssuranceMessage != null)
778    {
779      buffer.append(", localMessage='");
780      buffer.append(localAssuranceMessage);
781      buffer.append('\'');
782    }
783
784    if (remoteLevel != null)
785    {
786      buffer.append(", remoteLevel=");
787      buffer.append(remoteLevel.name());
788    }
789
790    buffer.append(", remoteAssuranceSatisfied=");
791    buffer.append(remoteAssuranceSatisfied);
792
793    if (remoteAssuranceMessage != null)
794    {
795      buffer.append(", remoteMessage='");
796      buffer.append(remoteAssuranceMessage);
797      buffer.append('\'');
798    }
799
800    if (csn != null)
801    {
802      buffer.append(", csn='");
803      buffer.append(csn);
804      buffer.append('\'');
805    }
806
807    if ((serverResults != null) && (! serverResults.isEmpty()))
808    {
809      buffer.append(", serverResults={");
810
811      final Iterator<AssuredReplicationServerResult> iterator =
812           serverResults.iterator();
813      while (iterator.hasNext())
814      {
815        if (iterator.hasNext())
816        {
817          iterator.next().toString(buffer);
818          buffer.append(", ");
819        }
820      }
821
822      buffer.append('}');
823    }
824
825    buffer.append(')');
826  }
827}