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}