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}