001/* 002 * Copyright 2011-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; 022 023 024 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collections; 028import java.util.Date; 029import java.util.List; 030 031import com.unboundid.ldap.sdk.Attribute; 032import com.unboundid.ldap.sdk.ChangeLogEntry; 033import com.unboundid.ldap.sdk.ChangeType; 034import com.unboundid.ldap.sdk.Entry; 035import com.unboundid.ldap.sdk.LDAPException; 036import com.unboundid.ldap.sdk.Modification; 037import com.unboundid.ldap.sdk.ModificationType; 038import com.unboundid.ldap.sdk.ReadOnlyEntry; 039import com.unboundid.util.NotMutable; 040import com.unboundid.util.ThreadSafety; 041import com.unboundid.util.ThreadSafetyLevel; 042 043import static com.unboundid.ldap.sdk.unboundidds.UnboundIDDSMessages.*; 044 045 046 047/** 048 * This class provides an implementation of a changelog entry which provides 049 * support for all standard changelog entry attributes as well as those unique 050 * to the Ping Identity, UnboundID, and Nokia/Alcatel-Lucent 8661 Directory 051 * Server. 052 * <BR> 053 * <BLOCKQUOTE> 054 * <B>NOTE:</B> This class, and other classes within the 055 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 056 * supported for use against Ping Identity, UnboundID, and 057 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 058 * for proprietary functionality or for external specifications that are not 059 * considered stable or mature enough to be guaranteed to work in an 060 * interoperable way with other types of LDAP servers. 061 * </BLOCKQUOTE> 062 */ 063@NotMutable() 064@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 065public final class UnboundIDChangeLogEntry 066 extends ChangeLogEntry 067{ 068 /** 069 * The name of the attribute used to hold the previous values for all 070 * attributes affected by the change. 071 */ 072 public static final String ATTR_BEFORE_VALUES = "ds-changelog-before-values"; 073 074 075 076 /** 077 * The name of the attribute used to hold the resulting values for all 078 * attributes affected by the change. 079 */ 080 public static final String ATTR_AFTER_VALUES = "ds-changelog-after-values"; 081 082 083 084 /** 085 * The name of the attribute used to indicate whether the operation represents 086 * a change to a soft-deleted entry. 087 */ 088 public static final String ATTR_CHANGE_TO_SOFT_DELETED_ENTRY = 089 "ds-change-to-soft-deleted-entry"; 090 091 092 093 /** 094 * The name of the attribute used to hold the values of key attributes from 095 * the entry after the change was applied. 096 */ 097 public static final String ATTR_KEY_VALUES = 098 "ds-changelog-entry-key-attr-values"; 099 100 101 102 /** 103 * The name of the attribute used to hold information about updated attributes 104 * which had more values (whether before the change, after the change, or 105 * both) than allowed to be shown in the before/after values attributes. 106 */ 107 public static final String ATTR_EXCEEDED_MAX_VALUES = 108 "ds-changelog-attr-exceeded-max-values-count"; 109 110 111 112 /** 113 * The name of the attribute used to hold information about the number of 114 * user attributes that may have been excluded by access control and/or 115 * sensitive attribute processing. 116 */ 117 public static final String ATTR_EXCLUDED_USER_ATTR_COUNT = 118 "ds-changelog-num-excluded-user-attributes"; 119 120 121 122 /** 123 * The name of the attribute used to hold information about the number of 124 * operational attributes that may have been excluded by access control and/or 125 * sensitive attribute processing. 126 */ 127 public static final String ATTR_EXCLUDED_OPERATIONAL_ATTR_COUNT = 128 "ds-changelog-num-excluded-operational-attributes"; 129 130 131 132 /** 133 * The name of the attribute used to hold information about the names of the 134 * user attributes that may have been excluded by access control and/or 135 * sensitive attribute processing. 136 */ 137 public static final String ATTR_EXCLUDED_USER_ATTR_NAME = 138 "ds-changelog-excluded-user-attribute"; 139 140 141 142 /** 143 * The name of the attribute used to hold information about the names of the 144 * operational attributes that may have been excluded by access control and/or 145 * sensitive attribute processing. 146 */ 147 public static final String ATTR_EXCLUDED_OPERATIONAL_ATTR_NAME = 148 "ds-changelog-excluded-operational-attribute"; 149 150 151 152 /** 153 * The name of the attribute used to hold the entryUUID value for the entry 154 * that was targeted by the change. 155 */ 156 public static final String ATTR_TARGET_UNIQUE_ID = "targetUniqueID"; 157 158 159 160 /** 161 * The name of the attribute used to hold a timestamp of the time the change 162 * was processed. 163 */ 164 public static final String ATTR_CHANGE_TIME = "changeTime"; 165 166 167 168 /** 169 * The name of the attribute used to hold the local change sequence number 170 * assigned to the change. 171 */ 172 public static final String ATTR_LOCAL_CSN = "localCSN"; 173 174 175 176 /** 177 * The name of the attribute used to hold the DN of the soft-deleted entry 178 * resulting from a soft delete operation. 179 */ 180 public static final String ATTR_SOFT_DELETE_TO_DN = "ds-soft-delete-entry-dn"; 181 182 183 184 /** 185 * The name of the attribute used to hold the names of the attributes targeted 186 * by the change. 187 */ 188 public static final String ATTR_TARGET_ATTRIBUTE = 189 "ds-changelog-target-attribute"; 190 191 192 193 /** 194 * The name of the attribute used to hold the DN of the soft-deleted entry 195 * from which the content of an undelete was obtained. 196 */ 197 public static final String ATTR_UNDELETE_FROM_DN = "ds-undelete-from-dn"; 198 199 200 201 /** 202 * The name of the attribute used to hold information about virtual values 203 * for an add or delete operation. 204 */ 205 public static final String ATTR_VIRTUAL_ATTRS = 206 "ds-changelog-virtual-attributes"; 207 208 209 210 /** 211 * The name of the attribute used to hold information about virtual values 212 * for modified attributes before the change. 213 */ 214 public static final String ATTR_BEFORE_VIRTUAL_VALUES = 215 "ds-changelog-before-virtual-values"; 216 217 218 219 /** 220 * The name of the attribute used to hold information about virtual values 221 * for modified attributes after the change. 222 */ 223 public static final String ATTR_AFTER_VIRTUAL_VALUES = 224 "ds-changelog-after-virtual-values"; 225 226 227 228 /** 229 * The name of the attribute used to hold information about virtual values 230 * for key attributes after the change. 231 */ 232 public static final String ATTR_KEY_VIRTUAL_VALUES = 233 "ds-changelog-entry-key-virtual-values"; 234 235 236 237 /** 238 * The name of the attribute used to hold information about updated attributes 239 * which had more virtual values (whether before the change, after the change, 240 * or both) than allowed to be shown in the before/after values attributes. 241 */ 242 public static final String ATTR_VIRTUAL_EXCEEDED_MAX_VALUES = 243 "ds-changelog-virtual-attr-exceeded-max-values-count"; 244 245 246 247 /** 248 * The name of the attribute used to hold the entryUUID values for the 249 * notification destinations matched by the change. 250 */ 251 public static final String ATTR_NOTIFICATION_DESTINATION_ENTRY_UUID = 252 "ds-notification-destination-entry-uuid"; 253 254 255 256 /** 257 * The name of the attribute used to hold a number of properties related to 258 * the notification matched by the change. 259 */ 260 public static final String ATTR_NOTIFICATION_PROPERTIES = 261 "ds-changelog-notification-properties"; 262 263 264 265 /** 266 * The serial version UID for this serializable class. 267 */ 268 private static final long serialVersionUID = -6127912254495185946L; 269 270 271 272 // Indicates whether the changelog record represents a change to a 273 // soft-deleted entry. 274 private final Boolean changeToSoftDeletedEntry; 275 276 // The time that the change was processed. 277 private final Date changeTime; 278 279 // The number of user attributes excluded by access control and/or sensitive 280 // attribute processing. 281 private final Integer numExcludedUserAttributes; 282 283 // The number of operational attributes excluded by access control and/or 284 // sensitive attribute processing. 285 private final Integer numExcludedOperationalAttributes; 286 287 // The names of virtual attributes as they appeared in the entry after an add 288 // or before a delete operation. 289 private final List<Attribute> entryVirtualAttributes; 290 291 // The values of key attributes as they appeared in the entry after the change 292 // was applied (or before the delete if the entry was removed). 293 private final List<Attribute> keyEntryAttributes; 294 295 // The virtual values of key attributes as they appeared in the entry after 296 // the change was applied (or before the delete if the entry was removed). 297 private final List<Attribute> keyEntryVirtualAttributes; 298 299 // The updated attributes as they appeared in the entry after the change was 300 // applied. 301 private final List<Attribute> updatedAttributesAfterChange; 302 303 // The updated attributes as they appeared in the entry before the change was 304 // applied. 305 private final List<Attribute> updatedAttributesBeforeChange; 306 307 // The virtual values of updated attributes as they appeared in the entry 308 // after the change was applied. 309 private final List<Attribute> updatedVirtualAttributesAfterChange; 310 311 // The virtual values of updated attributes as they appeared in the entry 312 // before the change was applied. 313 private final List<Attribute> updatedVirtualAttributesBeforeChange; 314 315 // Information about updated attributes that had more values than are allowed 316 // to be included in the ds-changelog-before-values or 317 // ds-changelog-after-values attributes. 318 private final List<ChangeLogEntryAttributeExceededMaxValuesCount> 319 attributesThatExceededMaxValuesCount; 320 321 // Information about updated attributes that had more virtual values than are 322 // allowed to be included in the ds-changelog-before-virtual-values or 323 // ds-changelog-after-virtual-values attributes. 324 private final List<ChangeLogEntryAttributeExceededMaxValuesCount> 325 virtualAttributesThatExceededMaxValuesCount; 326 327 // The names of user attributes excluded by access control and/or sensitive 328 // attribute processing. 329 private final List<String> excludedUserAttributeNames; 330 331 // The names of operational attributes excluded by access control and/or 332 // sensitive attribute processing. 333 private final List<String> excludedOperationalAttributeNames; 334 335 // The entryUUID values for the notification destinations matched by the 336 // change. 337 private final List<String> notificationDestinationEntryUUIDs; 338 339 // The values of any notification properties for the change. 340 private final List<String> notificationProperties; 341 342 // The names of the attributes targeted by the change. 343 private final List<String> targetAttributeNames; 344 345 // The local change sequence number for the change. 346 private final String localCSN; 347 348 // The DN of the soft-deleted entry resulting from a soft delete operation. 349 private final String softDeleteToDN; 350 351 // The entryUUID value for the target entry. 352 private final String targetUniqueID; 353 354 // The DN of the soft-deleted entry from which the content of an undelete 355 // operation was created. 356 private final String undeleteFromDN; 357 358 359 360 /** 361 * Creates a new UnboundID changelog entry object from the provided entry. 362 * 363 * @param entry The entry from which to create this changelog entry. 364 * 365 * @throws LDAPException If the provided entry cannot be parsed as a 366 * changelog entry. 367 */ 368 public UnboundIDChangeLogEntry(final Entry entry) 369 throws LDAPException 370 { 371 super(entry); 372 373 final String targetDN = entry.getAttributeValue(ATTR_TARGET_DN); 374 375 targetUniqueID = entry.getAttributeValue(ATTR_TARGET_UNIQUE_ID); 376 localCSN = entry.getAttributeValue(ATTR_LOCAL_CSN); 377 changeTime = entry.getAttributeValueAsDate(ATTR_CHANGE_TIME); 378 softDeleteToDN = entry.getAttributeValue(ATTR_SOFT_DELETE_TO_DN); 379 undeleteFromDN = entry.getAttributeValue(ATTR_UNDELETE_FROM_DN); 380 381 changeToSoftDeletedEntry = 382 entry.getAttributeValueAsBoolean(ATTR_CHANGE_TO_SOFT_DELETED_ENTRY); 383 384 if (entry.hasAttribute(ATTR_VIRTUAL_ATTRS)) 385 { 386 entryVirtualAttributes = parseAddAttributeList(entry, ATTR_VIRTUAL_ATTRS, 387 targetDN); 388 } 389 else 390 { 391 entryVirtualAttributes = Collections.emptyList(); 392 } 393 394 if (entry.hasAttribute(ATTR_BEFORE_VALUES)) 395 { 396 updatedAttributesBeforeChange = parseAddAttributeList(entry, 397 ATTR_BEFORE_VALUES, targetDN); 398 } 399 else 400 { 401 updatedAttributesBeforeChange = Collections.emptyList(); 402 } 403 404 if (entry.hasAttribute(ATTR_BEFORE_VIRTUAL_VALUES)) 405 { 406 updatedVirtualAttributesBeforeChange = parseAddAttributeList(entry, 407 ATTR_BEFORE_VIRTUAL_VALUES, targetDN); 408 } 409 else 410 { 411 updatedVirtualAttributesBeforeChange = Collections.emptyList(); 412 } 413 414 if (entry.hasAttribute(ATTR_AFTER_VALUES)) 415 { 416 updatedAttributesAfterChange = parseAddAttributeList(entry, 417 ATTR_AFTER_VALUES, targetDN); 418 } 419 else 420 { 421 updatedAttributesAfterChange = Collections.emptyList(); 422 } 423 424 if (entry.hasAttribute(ATTR_AFTER_VIRTUAL_VALUES)) 425 { 426 updatedVirtualAttributesAfterChange = parseAddAttributeList(entry, 427 ATTR_AFTER_VIRTUAL_VALUES, targetDN); 428 } 429 else 430 { 431 updatedVirtualAttributesAfterChange = Collections.emptyList(); 432 } 433 434 if (entry.hasAttribute(ATTR_KEY_VALUES)) 435 { 436 keyEntryAttributes = 437 parseAddAttributeList(entry, ATTR_KEY_VALUES, targetDN); 438 } 439 else 440 { 441 keyEntryAttributes = Collections.emptyList(); 442 } 443 444 if (entry.hasAttribute(ATTR_KEY_VIRTUAL_VALUES)) 445 { 446 keyEntryVirtualAttributes = 447 parseAddAttributeList(entry, ATTR_KEY_VIRTUAL_VALUES, targetDN); 448 } 449 else 450 { 451 keyEntryVirtualAttributes = Collections.emptyList(); 452 } 453 454 final Attribute exceededMaxValues = 455 entry.getAttribute(ATTR_EXCEEDED_MAX_VALUES); 456 if (exceededMaxValues == null) 457 { 458 attributesThatExceededMaxValuesCount = Collections.emptyList(); 459 } 460 else 461 { 462 final String[] values = exceededMaxValues.getValues(); 463 final ArrayList<ChangeLogEntryAttributeExceededMaxValuesCount> l = 464 new ArrayList<>(values.length); 465 for (final String value : values) 466 { 467 l.add(new ChangeLogEntryAttributeExceededMaxValuesCount(value)); 468 } 469 attributesThatExceededMaxValuesCount = Collections.unmodifiableList(l); 470 } 471 472 final Attribute virtualExceededMaxValues = 473 entry.getAttribute(ATTR_VIRTUAL_EXCEEDED_MAX_VALUES); 474 if (virtualExceededMaxValues == null) 475 { 476 virtualAttributesThatExceededMaxValuesCount = Collections.emptyList(); 477 } 478 else 479 { 480 final String[] values = virtualExceededMaxValues.getValues(); 481 final ArrayList<ChangeLogEntryAttributeExceededMaxValuesCount> l = 482 new ArrayList<>(values.length); 483 for (final String value : values) 484 { 485 l.add(new ChangeLogEntryAttributeExceededMaxValuesCount(value)); 486 } 487 virtualAttributesThatExceededMaxValuesCount = 488 Collections.unmodifiableList(l); 489 } 490 491 numExcludedUserAttributes = 492 entry.getAttributeValueAsInteger(ATTR_EXCLUDED_USER_ATTR_COUNT); 493 numExcludedOperationalAttributes = 494 entry.getAttributeValueAsInteger(ATTR_EXCLUDED_OPERATIONAL_ATTR_COUNT); 495 496 final String[] excludedUserAttrNames = 497 entry.getAttributeValues(ATTR_EXCLUDED_USER_ATTR_NAME); 498 if (excludedUserAttrNames == null) 499 { 500 excludedUserAttributeNames = Collections.emptyList(); 501 } 502 else 503 { 504 excludedUserAttributeNames = Collections.unmodifiableList( 505 new ArrayList<>(Arrays.asList(excludedUserAttrNames))); 506 } 507 508 final String[] excludedOpAttrNames = 509 entry.getAttributeValues(ATTR_EXCLUDED_OPERATIONAL_ATTR_NAME); 510 if (excludedOpAttrNames == null) 511 { 512 excludedOperationalAttributeNames = Collections.emptyList(); 513 } 514 else 515 { 516 excludedOperationalAttributeNames = Collections.unmodifiableList( 517 new ArrayList<>(Arrays.asList(excludedOpAttrNames))); 518 } 519 520 final String[] targetAttrNames = 521 entry.getAttributeValues(ATTR_TARGET_ATTRIBUTE); 522 if (targetAttrNames == null) 523 { 524 targetAttributeNames = Collections.emptyList(); 525 } 526 else 527 { 528 targetAttributeNames = Collections.unmodifiableList( 529 new ArrayList<>(Arrays.asList(targetAttrNames))); 530 } 531 532 final String[] notificationUUIDValues = 533 entry.getAttributeValues(ATTR_NOTIFICATION_DESTINATION_ENTRY_UUID); 534 if (notificationUUIDValues == null) 535 { 536 notificationDestinationEntryUUIDs = Collections.emptyList(); 537 } 538 else 539 { 540 notificationDestinationEntryUUIDs = Collections.unmodifiableList( 541 new ArrayList<>(Arrays.asList(notificationUUIDValues))); 542 } 543 544 final String[] notificationPropertyValues = 545 entry.getAttributeValues(ATTR_NOTIFICATION_PROPERTIES); 546 if (notificationPropertyValues == null) 547 { 548 notificationProperties = Collections.emptyList(); 549 } 550 else 551 { 552 notificationProperties = Collections.unmodifiableList( 553 new ArrayList<>(Arrays.asList(notificationPropertyValues))); 554 } 555 } 556 557 558 559 /** 560 * Retrieves the entryUUID value of the entry targeted by the change, if 561 * available. 562 * 563 * @return The entryUUID value of the entry targeted by the change, or 564 * {@code null} if it was not included in the changelog entry. 565 */ 566 public String getTargetUniqueID() 567 { 568 return targetUniqueID; 569 } 570 571 572 573 /** 574 * Retrieves the local change sequence number (CSN) for the change, if 575 * available. 576 * 577 * @return The local CSN for the change, or {@code null} if it was not 578 * included in the changelog entry. 579 */ 580 public String getLocalCSN() 581 { 582 return localCSN; 583 } 584 585 586 587 /** 588 * Retrieves the time that the change was processed, if available. 589 * 590 * @return The time that the change was processed, or {@code null} if it was 591 * not included in the changelog entry. 592 */ 593 public Date getChangeTime() 594 { 595 return changeTime; 596 } 597 598 599 600 /** 601 * Retrieves the attribute list for an add changelog entry, optionally 602 * including information about virtual attributes. 603 * 604 * @param includeVirtual Indicates whether to include both real and virtual 605 * values (if {@code true}, or only real values (if 606 * {@code false}), for the attributes to be returned. 607 * 608 * @return The attribute list for an add changelog entry, optionally 609 * including virtual attributes, or {@code null} if this changelog 610 * entry does not represent an add operation. 611 */ 612 public List<Attribute> getAddAttributes(final boolean includeVirtual) 613 { 614 if (includeVirtual && (getChangeType() == ChangeType.ADD) && 615 (! entryVirtualAttributes.isEmpty())) 616 { 617 final Entry e = new Entry(getTargetDN(), getAddAttributes()); 618 for (final Attribute a : entryVirtualAttributes) 619 { 620 e.addAttribute(a); 621 } 622 623 return Collections.unmodifiableList(new ArrayList<>(e.getAttributes())); 624 } 625 else 626 { 627 return getAddAttributes(); 628 } 629 } 630 631 632 633 /** 634 * Retrieves the virtual attribute list for an add changelog entry, if 635 * available. 636 * 637 * @return The virtual attribute list for an add changelog entry, or 638 * {@code null} if the changelog entry does not represent an add 639 * operation, or an empty list if it does represent an add operation 640 * but no virtual attribute information is available in the 641 * changelog entry. 642 */ 643 public List<Attribute> getAddVirtualAttributes() 644 { 645 if (getChangeType() == ChangeType.ADD) 646 { 647 return entryVirtualAttributes; 648 } 649 else 650 { 651 return null; 652 } 653 } 654 655 656 657 /** 658 * Retrieves the list of attributes contained in the target entry at the time 659 * that it was deleted, optionally including information about virtual 660 * attributes. 661 * 662 * @param includeVirtual Indicates whether to include both real and virtual 663 * values (if {@code true}, or only real values (if 664 * {@code false}), for the attributes to be returned. 665 * 666 * @return The list of attributes contained in the target entry at the time 667 * that it was deleted, optionally including virtual attributes, or 668 * {@code null} if this changelog entry does not represent a delete 669 * operation or no deleted attribute information is available. 670 */ 671 public List<Attribute> getDeletedEntryAttributes( 672 final boolean includeVirtual) 673 { 674 if (includeVirtual && (getChangeType() == ChangeType.DELETE) && 675 (! entryVirtualAttributes.isEmpty())) 676 { 677 final Entry e; 678 final List<Attribute> realAttrs = getDeletedEntryAttributes(); 679 if (realAttrs != null) 680 { 681 e = new Entry(getTargetDN(), realAttrs); 682 for (final Attribute a : entryVirtualAttributes) 683 { 684 e.addAttribute(a); 685 } 686 } 687 else 688 { 689 e = new Entry(getTargetDN(), entryVirtualAttributes); 690 } 691 692 return Collections.unmodifiableList(new ArrayList<>(e.getAttributes())); 693 } 694 else 695 { 696 return getDeletedEntryAttributes(); 697 } 698 } 699 700 701 702 /** 703 * Retrieves the virtual attribute list for a delete changelog entry, if 704 * available. 705 * 706 * @return The virtual attribute list for a delete changelog entry, or 707 * {@code null} if the changelog entry does not represent a delete 708 * operation, or an empty list if it does represent a delete 709 * operation but no virtual attribute information is available in the 710 * changelog entry. 711 */ 712 public List<Attribute> getDeletedEntryVirtualAttributes() 713 { 714 if (getChangeType() == ChangeType.DELETE) 715 { 716 return entryVirtualAttributes; 717 } 718 else 719 { 720 return null; 721 } 722 } 723 724 725 726 /** 727 * Retrieves a list containing the set of attributes that were updated in the 728 * associated modify or modify DN operation as they appeared before the change 729 * was processed. Virtual attribute information will not be included. 730 * 731 * @return A list containing the set of updated attributes as they appeared 732 * in the entry before the associated modify or modify DN was 733 * processed, or an empty list if the change was not a modify or 734 * modify DN operation, none of the updated attributes previously 735 * existed in the target entry, the previous versions of the updated 736 * attributes had too many values to include, or the server is not 737 * configured to provide (or does not support providing) previous 738 * versions of updated attributes. 739 */ 740 public List<Attribute> getUpdatedAttributesBeforeChange() 741 { 742 return updatedAttributesBeforeChange; 743 } 744 745 746 747 /** 748 * Retrieves a list containing the set of attributes (optionally including 749 * both real and virtual values) that were updated in the associated modify or 750 * modify DN operation as they appeared before the change was processed. 751 * 752 * @param includeVirtual Indicates whether to include both real and virtual 753 * values (if {@code true}, or only real values (if 754 * {@code false}), for the attributes to be returned. 755 * 756 * @return A list containing the set of updated attributes as they appeared 757 * in the entry before the associated modify or modify DN was 758 * processed, or an empty list if the change was not a modify or 759 * modify DN operation, none of the updated attributes previously 760 * existed in the target entry, the previous versions of the updated 761 * attributes had too many values to include, or the server is not 762 * configured to provide (or does not support providing) previous 763 * versions of updated attributes. 764 */ 765 public List<Attribute> getUpdatedAttributesBeforeChange( 766 final boolean includeVirtual) 767 { 768 if (includeVirtual && (! updatedVirtualAttributesBeforeChange.isEmpty())) 769 { 770 final Entry e = new Entry(getTargetDN(), updatedAttributesBeforeChange); 771 for (final Attribute a : updatedVirtualAttributesBeforeChange) 772 { 773 e.addAttribute(a); 774 } 775 776 return Collections.unmodifiableList(new ArrayList<>(e.getAttributes())); 777 } 778 else 779 { 780 return updatedAttributesBeforeChange; 781 } 782 } 783 784 785 786 /** 787 * Retrieves a list containing information about virtual values for attributes 788 * that were updated in the associated modify or modify DN operation, as they 789 * appeared in the entry before the change was processed. 790 * 791 * @return A list containing information about virtual values for attributes 792 * that were updated in the associated modify or modify DN operation, 793 * as they appeared in the entry before the change was processed. It 794 * may be empty if the change was not a modify or modify DN 795 * operation, or if the changelog entry did not include any 796 * information about virtual attributes as they appeared before the 797 * change. 798 */ 799 public List<Attribute> getUpdatedVirtualAttributesBeforeChange() 800 { 801 return updatedVirtualAttributesBeforeChange; 802 } 803 804 805 806 /** 807 * Retrieves a list containing the set of attributes that were updated in the 808 * associated modify or modify DN operation as they appeared after the change 809 * was processed. Virtual attribute information will not be included. 810 * 811 * @return A list containing the set of updated attributes as they appeared 812 * in the entry after the associated modify or modify DN was 813 * processed, or an empty list if the change was not a modify or 814 * modify DN operation, none of the updated attributes existed in the 815 * entry after the change was processed, the resulting versions of 816 * the updated attributes had too many values to include, or the 817 * server is not configured to provide (or does not support 818 * providing) resulting versions of updated attributes. 819 */ 820 public List<Attribute> getUpdatedAttributesAfterChange() 821 { 822 return updatedAttributesAfterChange; 823 } 824 825 826 827 /** 828 * Retrieves a list containing the set of attributes (optionally including 829 * both real and virtual values) that were updated in the associated modify or 830 * modify DN operation as they appeared after the change was processed. 831 * 832 * @param includeVirtual Indicates whether to include both real and virtual 833 * values (if {@code true}, or only real values (if 834 * {@code false}), for the attributes to be returned. 835 * 836 * @return A list containing the set of updated attributes as they appeared 837 * in the entry after the associated modify or modify DN was 838 * processed, or an empty list if the change was not a modify or 839 * modify DN operation, none of the updated attributes previously 840 * existed in the target entry, the previous versions of the updated 841 * attributes had too many values to include, or the server is not 842 * configured to provide (or does not support providing) previous 843 * versions of updated attributes. 844 */ 845 public List<Attribute> getUpdatedAttributesAfterChange( 846 final boolean includeVirtual) 847 { 848 if (includeVirtual && (! updatedVirtualAttributesAfterChange.isEmpty())) 849 { 850 final Entry e = new Entry(getTargetDN(), updatedAttributesAfterChange); 851 for (final Attribute a : updatedVirtualAttributesAfterChange) 852 { 853 e.addAttribute(a); 854 } 855 856 return Collections.unmodifiableList(new ArrayList<>(e.getAttributes())); 857 } 858 else 859 { 860 return updatedAttributesAfterChange; 861 } 862 } 863 864 865 866 /** 867 * Retrieves a list containing information about virtual values for attributes 868 * that were updated in the associated modify or modify DN operation, as they 869 * appeared in the entry after the change was processed. 870 * 871 * @return A list containing information about virtual values for attributes 872 * that were updated in the associated modify or modify DN operation, 873 * as they appeared in the entry after the change was processed. It 874 * may be empty if the change was not a modify or modify DN 875 * operation, or if the changelog entry did not include any 876 * information about virtual attributes as they appeared after the 877 * change. 878 */ 879 public List<Attribute> getUpdatedVirtualAttributesAfterChange() 880 { 881 return updatedVirtualAttributesAfterChange; 882 } 883 884 885 886 /** 887 * Retrieves information about any attributes updated in the associated modify 888 * or modify DN operation that had too many values to include in the changelog 889 * entry's set of before and/or after values. 890 * 891 * @return Information about attributes updated in the associated modify or 892 * modify DN operation that had too many values to include in the 893 * changelog entry's set of before and/or after values, or an empty 894 * list if none of the updated attributes had too many values, the 895 * server is not configured to provide (or does not support 896 * providing) previous and resulting versions of updated attributes, 897 * or the change was not the result of a modify or modify DN 898 * operation. 899 */ 900 public List<ChangeLogEntryAttributeExceededMaxValuesCount> 901 getAttributesThatExceededMaxValuesCount() 902 { 903 return attributesThatExceededMaxValuesCount; 904 } 905 906 907 908 /** 909 * Retrieves information about any attributes updated in the associated modify 910 * or modify DN operation that had too many virtual values to include in the 911 * changelog entry's set of before and/or after virtual values. 912 * 913 * @return Information about attributes updated in the associated modify or 914 * modify DN operation that had too many virtual values to include in 915 * the changelog entry's set of before and/or after virtual values, 916 * or an empty list if none of the updated attributes had too many 917 * virtual values, the server is not configured to provide (or does 918 * not support providing) previous and resulting versions of updated 919 * attributes, or the change was not the result of a modify or modify 920 * DN operation. 921 */ 922 public List<ChangeLogEntryAttributeExceededMaxValuesCount> 923 getVirtualAttributesThatExceededMaxValuesCount() 924 { 925 return virtualAttributesThatExceededMaxValuesCount; 926 } 927 928 929 930 /** 931 * Retrieves a list containing key attributes from the target entry, as 932 * defined in the server configuration. For add, modify, and modify DN 933 * operations, this will include the key attributes as they appeared in the 934 * entry after the change had been processed. For delete operations, this 935 * will include the key attributes as they appeared in the entry just before 936 * it was removed. 937 * 938 * @return A list containing key attributes from the target entry, or an 939 * empty list if the associated entry did not have any key attributes 940 * or there are no key attribute types defined in the server 941 * configuration. 942 */ 943 public List<Attribute> getKeyEntryAttributes() 944 { 945 return keyEntryAttributes; 946 } 947 948 949 950 /** 951 * Retrieves a list containing key attributes from the target entry, as 952 * defined in the server configuration. For add, modify, and modify DN 953 * operations, this will include the key attributes as they appeared in the 954 * entry after the change had been processed. For delete operations, this 955 * will include the key attributes as they appeared in the entry just before 956 * it was removed. 957 * 958 * @param includeVirtual Indicates whether to include both real and virtual 959 * values (if {@code true}, or only real values (if 960 * {@code false}), for the attributes to be returned. 961 * 962 * @return A list containing key attributes from the target entry, or an 963 * empty list if the associated entry did not have any key attributes 964 * or there are no key attribute types defined in the server 965 * configuration. 966 */ 967 public List<Attribute> getKeyEntryAttributes(final boolean includeVirtual) 968 { 969 if (includeVirtual && (! keyEntryVirtualAttributes.isEmpty())) 970 { 971 final Entry e = new Entry(getTargetDN(), keyEntryAttributes); 972 for (final Attribute a : keyEntryVirtualAttributes) 973 { 974 e.addAttribute(a); 975 } 976 977 return Collections.unmodifiableList(new ArrayList<>(e.getAttributes())); 978 } 979 else 980 { 981 return keyEntryAttributes; 982 } 983 } 984 985 986 987 /** 988 * Retrieves a list containing virtual values for key attributes from the 989 * target entry, as defined in the server configuration. For add, modify, and 990 * modify DN operations, this will include the virtual values for key 991 * attributes as they appeared in the entry after the change had been 992 * processed. For delete operations, this will include the virtual values for 993 * key attributes as they appeared in the entry just before it was removed. 994 * 995 * @return A list containing virtual values for key attributes from the 996 * target entry, or an empty list if the associated entry did not 997 * have any virtual values for key attributes or there are no key 998 * attribute types defined in the server configuration. 999 */ 1000 public List<Attribute> getKeyEntryVirtualAttributes() 1001 { 1002 return keyEntryVirtualAttributes; 1003 } 1004 1005 1006 1007 /** 1008 * Retrieves the number of user attributes for which information was excluded 1009 * from the changelog entry by access control and/or sensitive attribute 1010 * processing, if available. 1011 * 1012 * @return The number of user attributes for which information was excluded 1013 * from the changelog entry by access control and/or sensitive 1014 * attribute processing, or -1 if that information was not included 1015 * in the changelog entry. 1016 */ 1017 public int getNumExcludedUserAttributes() 1018 { 1019 if (numExcludedUserAttributes == null) 1020 { 1021 return -1; 1022 } 1023 else 1024 { 1025 return numExcludedUserAttributes; 1026 } 1027 } 1028 1029 1030 1031 /** 1032 * Retrieves the number of operational attributes for which information was 1033 * excluded from the changelog entry by access control and/or sensitive 1034 * attribute processing, if available. 1035 * 1036 * @return The number of operational attributes for which information was 1037 * excluded from the changelog entry by access control and/or 1038 * sensitive attribute processing, or -1 if that information was not 1039 * included in the changelog entry. 1040 */ 1041 public int getNumExcludedOperationalAttributes() 1042 { 1043 if (numExcludedOperationalAttributes == null) 1044 { 1045 return -1; 1046 } 1047 else 1048 { 1049 return numExcludedOperationalAttributes; 1050 } 1051 } 1052 1053 1054 1055 /** 1056 * Retrieves the names of any user attributes for which information was 1057 * excluded from the changelog entry by access control and/or sensitive 1058 * attribute processing, if available. 1059 * 1060 * @return The names of any user attributes for which information was 1061 * excluded from the changelog entry by access control and/or 1062 * sensitive attribute processing, or an empty list if that 1063 * information was not included in the changelog entry. 1064 */ 1065 public List<String> getExcludedUserAttributeNames() 1066 { 1067 return excludedUserAttributeNames; 1068 } 1069 1070 1071 1072 /** 1073 * Retrieves the names of any operational attributes for which information was 1074 * excluded from the changelog entry by access control and/or sensitive 1075 * attribute processing, if available. 1076 * 1077 * @return The names of any operational attributes for which information was 1078 * excluded from the changelog entry by access control and/or 1079 * sensitive processing, or an empty list if that information was not 1080 * included in the changelog entry. 1081 */ 1082 public List<String> getExcludedOperationalAttributeNames() 1083 { 1084 return excludedOperationalAttributeNames; 1085 } 1086 1087 1088 1089 /** 1090 * Indicates whether the associated modify or delete operation targeted a 1091 * soft-deleted entry. 1092 * 1093 * @return {@code true} if the modify or delete operation targeted a 1094 * soft-deleted entry, {@code false} if not, or {@code null} if that 1095 * information was not included in the changelog entry (which likely 1096 * indicates that the operation did not target a soft-deleted 1097 * entry). 1098 */ 1099 public Boolean getChangeToSoftDeletedEntry() 1100 { 1101 return changeToSoftDeletedEntry; 1102 } 1103 1104 1105 1106 /** 1107 * Retrieves the DN of the soft-deleted entry that resulted from the 1108 * associated soft delete operation. 1109 * 1110 * @return The DN of the soft-deleted entry that resulted from the associated 1111 * soft delete operation, or {@code null} if that information was not 1112 * included in the changelog entry (e.g., because it does not 1113 * represent a soft delete operation). 1114 */ 1115 public String getSoftDeleteToDN() 1116 { 1117 return softDeleteToDN; 1118 } 1119 1120 1121 1122 /** 1123 * Retrieves the DN of the soft-deleted entry from which the content of an add 1124 * operation was obtained, if that operation represents an undelete rather 1125 * than a normal add. 1126 * 1127 * @return The DN of the soft-deleted entry from which the content of an add 1128 * operation was obtained, or {@code null} if that information was 1129 * not included in the changelog entry (e.g., because it does not 1130 * represent an undelete operation). 1131 */ 1132 public String getUndeleteFromDN() 1133 { 1134 return undeleteFromDN; 1135 } 1136 1137 1138 1139 /** 1140 * Retrieves the names of any attributes targeted by the change, if available. 1141 * For an add operation, this may include the attributes in the entry that 1142 * was added. For a delete operation, this may include the attributes in the 1143 * entry that was deleted. For a modify operation, this may include the 1144 * attributes targeted by modifications. For a modify DN operation, this may 1145 * include attributes used in the new RDN and potentially any other attributes 1146 * altered during the change. 1147 * <BR><BR> 1148 * Note that this information may not be available in all changelog entries or 1149 * Directory Server versions, and complete information about some changes may 1150 * only be available in some changelog configurations (e.g., information about 1151 * attributes included in delete operations may only be available if 1152 * changelog-deleted-entry-include-attribute is configured, and information 1153 * about changes to non-RDN attributes for modify DN operations may only be 1154 * available if changelog-max-before-after-values is configured). 1155 * 1156 * @return The names of any attributes targeted by the change, or an empty 1157 * list if that information was not included in the changelog entry. 1158 */ 1159 public List<String> getTargetAttributeNames() 1160 { 1161 return targetAttributeNames; 1162 } 1163 1164 1165 1166 /** 1167 * Retrieves a list of the entryUUID values for any notification destinations 1168 * for which the change matches one or more subscriptions. 1169 * 1170 * @return A list of the entryUUID values for any notification destinations 1171 * for which the change matches one or more subscriptions, or an 1172 * empty list if that information was not included in the changelog 1173 * entry. 1174 */ 1175 public List<String> getNotificationDestinationEntryUUIDs() 1176 { 1177 return notificationDestinationEntryUUIDs; 1178 } 1179 1180 1181 1182 /** 1183 * Retrieves a list of any notification properties included in the changelog 1184 * entry. 1185 * 1186 * @return A list of any notification properties included in the changelog 1187 * entry, or an empty list if that information was not included in 1188 * the changelog entry. 1189 */ 1190 public List<String> getNotificationProperties() 1191 { 1192 return notificationProperties; 1193 } 1194 1195 1196 1197 /** 1198 * Retrieves the specified attribute as it appeared in the target entry before 1199 * the change was processed, if available. It will not include any virtual 1200 * values. 1201 * 1202 * @param name The name of the attribute to retrieve as it appeared before 1203 * the change. 1204 * 1205 * @return The requested attribute as it appeared in the target entry before 1206 * the change was processed, or {@code null} if it was not available 1207 * in the changelog entry. 1208 * 1209 * @throws ChangeLogEntryAttributeExceededMaxValuesException If the 1210 * specified attribute had more values before the change than 1211 * may be included in a changelog entry. 1212 */ 1213 public Attribute getAttributeBeforeChange(final String name) 1214 throws ChangeLogEntryAttributeExceededMaxValuesException 1215 { 1216 return getAttributeBeforeChange(name, false); 1217 } 1218 1219 1220 1221 /** 1222 * Retrieves the specified attribute as it appeared in the target entry before 1223 * the change was processed, if available. It may optionally include virtual 1224 * values. 1225 * 1226 * @param name The name of the attribute to retrieve as it 1227 * appeared before the change. 1228 * @param includeVirtual Indicates whether to include both real and virtual 1229 * values (if {@code true}, or only real values (if 1230 * {@code false}), for the attribute to be returned. 1231 * 1232 * @return The requested attribute as it appeared in the target entry before 1233 * the change was processed, or {@code null} if it was not available 1234 * in the changelog entry. 1235 * 1236 * @throws ChangeLogEntryAttributeExceededMaxValuesException If the 1237 * specified attribute had more values before the change than 1238 * may be included in a changelog entry. 1239 */ 1240 public Attribute getAttributeBeforeChange(final String name, 1241 final boolean includeVirtual) 1242 throws ChangeLogEntryAttributeExceededMaxValuesException 1243 { 1244 if (getChangeType() == ChangeType.ADD) 1245 { 1246 return null; 1247 } 1248 1249 for (final Attribute a : getUpdatedAttributesBeforeChange(includeVirtual)) 1250 { 1251 if (a.getName().equalsIgnoreCase(name)) 1252 { 1253 return a; 1254 } 1255 } 1256 1257 for (final ChangeLogEntryAttributeExceededMaxValuesCount a : 1258 attributesThatExceededMaxValuesCount) 1259 { 1260 if (a.getAttributeName().equalsIgnoreCase(name)) 1261 { 1262 // TODO: In the event that the before count was exceeded but the after 1263 // count was not, then we may be able to reconstruct the before values 1264 // if the changes included deleting specific values for the attribute. 1265 throw new ChangeLogEntryAttributeExceededMaxValuesException( 1266 ERR_CHANGELOG_EXCEEDED_BEFORE_VALUE_COUNT.get(name, getTargetDN(), 1267 a.getBeforeCount()), 1268 a); 1269 } 1270 } 1271 1272 if (includeVirtual) 1273 { 1274 for (final ChangeLogEntryAttributeExceededMaxValuesCount a : 1275 virtualAttributesThatExceededMaxValuesCount) 1276 { 1277 if (a.getAttributeName().equalsIgnoreCase(name)) 1278 { 1279 // TODO: In the event that the before count was exceeded but the 1280 // after count was not, then we may be able to reconstruct the before 1281 // values if the changes included deleting specific values for the 1282 // attribute. 1283 throw new ChangeLogEntryAttributeExceededMaxValuesException( 1284 ERR_CHANGELOG_EXCEEDED_VIRTUAL_BEFORE_VALUE_COUNT.get(name, 1285 getTargetDN(), a.getBeforeCount()), 1286 a); 1287 } 1288 } 1289 } 1290 1291 for (final Attribute a : getKeyEntryAttributes(includeVirtual)) 1292 { 1293 if (a.getName().equalsIgnoreCase(name)) 1294 { 1295 return a; 1296 } 1297 } 1298 1299 final List<Attribute> deletedAttrs = 1300 getDeletedEntryAttributes(includeVirtual); 1301 if (deletedAttrs != null) 1302 { 1303 for (final Attribute a : deletedAttrs) 1304 { 1305 if (a.getName().equalsIgnoreCase(name)) 1306 { 1307 return a; 1308 } 1309 } 1310 } 1311 1312 return null; 1313 } 1314 1315 1316 1317 /** 1318 * Retrieves the specified attribute as it appeared in the target entry after 1319 * the change was processed, if available. It will not include any virtual 1320 * values. 1321 * 1322 * @param name The name of the attribute to retrieve as it appeared after 1323 * the change. 1324 * 1325 * @return The requested attribute as it appeared in the target entry after 1326 * the change was processed, or {@code null} if it was not available 1327 * in the changelog entry. 1328 * 1329 * @throws ChangeLogEntryAttributeExceededMaxValuesException If the 1330 * specified attribute had more values before the change than 1331 * may be included in a changelog entry. 1332 */ 1333 public Attribute getAttributeAfterChange(final String name) 1334 throws ChangeLogEntryAttributeExceededMaxValuesException 1335 { 1336 return getAttributeAfterChange(name, false); 1337 } 1338 1339 1340 1341 /** 1342 * Retrieves the specified attribute as it appeared in the target entry after 1343 * the change was processed, if available. It may optionally include virtual 1344 * values. 1345 * 1346 * @param name The name of the attribute to retrieve as it 1347 * appeared after the change. 1348 * @param includeVirtual Indicates whether to include both real and virtual 1349 * values (if {@code true}, or only real values (if 1350 * {@code false}), for the attributes to be returned. 1351 * 1352 * @return The requested attribute as it appeared in the target entry after 1353 * the change was processed, or {@code null} if it was not available 1354 * in the changelog entry. 1355 * 1356 * @throws ChangeLogEntryAttributeExceededMaxValuesException If the 1357 * specified attribute had more values before the change than 1358 * may be included in a changelog entry. 1359 */ 1360 public Attribute getAttributeAfterChange(final String name, 1361 final boolean includeVirtual) 1362 throws ChangeLogEntryAttributeExceededMaxValuesException 1363 { 1364 if (getChangeType() == ChangeType.DELETE) 1365 { 1366 return null; 1367 } 1368 1369 for (final Attribute a : getUpdatedAttributesAfterChange(includeVirtual)) 1370 { 1371 if (a.getName().equalsIgnoreCase(name)) 1372 { 1373 return a; 1374 } 1375 } 1376 1377 for (final Attribute a : getKeyEntryAttributes(includeVirtual)) 1378 { 1379 if (a.getName().equalsIgnoreCase(name)) 1380 { 1381 return a; 1382 } 1383 } 1384 1385 for (final ChangeLogEntryAttributeExceededMaxValuesCount a : 1386 attributesThatExceededMaxValuesCount) 1387 { 1388 if (a.getAttributeName().equalsIgnoreCase(name)) 1389 { 1390 // TODO: In the event that the after count was exceeded but the before 1391 // count was not, then we may be able to reconstruct the after values 1392 // if the changes included adding specific values for the attribute. 1393 throw new ChangeLogEntryAttributeExceededMaxValuesException( 1394 ERR_CHANGELOG_EXCEEDED_AFTER_VALUE_COUNT.get(name, getTargetDN(), 1395 a.getAfterCount()), 1396 a); 1397 } 1398 } 1399 1400 if (includeVirtual) 1401 { 1402 for (final ChangeLogEntryAttributeExceededMaxValuesCount a : 1403 virtualAttributesThatExceededMaxValuesCount) 1404 { 1405 if (a.getAttributeName().equalsIgnoreCase(name)) 1406 { 1407 // TODO: In the event that the after count was exceeded but the 1408 // before count was not, then we may be able to reconstruct the after 1409 // values if the changes included adding specific values for the 1410 // attribute. 1411 throw new ChangeLogEntryAttributeExceededMaxValuesException( 1412 ERR_CHANGELOG_EXCEEDED_VIRTUAL_AFTER_VALUE_COUNT.get(name, 1413 getTargetDN(), a.getAfterCount()), 1414 a); 1415 } 1416 } 1417 } 1418 1419 final List<Attribute> addAttrs = getAddAttributes(includeVirtual); 1420 if (addAttrs != null) 1421 { 1422 for (final Attribute a : addAttrs) 1423 { 1424 if (a.getName().equalsIgnoreCase(name)) 1425 { 1426 return a; 1427 } 1428 } 1429 } 1430 1431 final List<Modification> mods = getModifications(); 1432 if (mods != null) 1433 { 1434 for (final Modification m : mods) 1435 { 1436 if (m.getAttributeName().equalsIgnoreCase(name)) 1437 { 1438 final byte[][] values = m.getValueByteArrays(); 1439 if ((m.getModificationType() == ModificationType.REPLACE) && 1440 (values.length > 0)) 1441 { 1442 return new Attribute(name, values); 1443 } 1444 } 1445 } 1446 } 1447 1448 return null; 1449 } 1450 1451 1452 1453 /** 1454 * Attempts to construct a partial representation of the target entry as it 1455 * appeared before the change was processed. The information contained in the 1456 * constructed entry will be based solely on information contained in the 1457 * changelog entry, including information provided in the deletedEntryAttrs, 1458 * ds-changelog-before-values, ds-changelog-after-values, 1459 * ds-changelog-entry-key-attr-values, and 1460 * ds-changelog-attr-exceeded-max-values-count attributes. It will not 1461 * include any virtual attribute information. 1462 * 1463 * @return A partial representation of the target entry as it appeared before 1464 * the change was processed, or {@code null} if the change was an 1465 * add operation and therefore the entry did not exist before the 1466 * change. 1467 */ 1468 public ReadOnlyEntry constructPartialEntryBeforeChange() 1469 { 1470 return constructPartialEntryBeforeChange(false); 1471 } 1472 1473 1474 1475 /** 1476 * Attempts to construct a partial representation of the target entry as it 1477 * appeared before the change was processed. The information contained in the 1478 * constructed entry will be based solely on information contained in the 1479 * changelog entry, including information provided in the deletedEntryAttrs, 1480 * ds-changelog-before-values, ds-changelog-after-values, 1481 * ds-changelog-entry-key-attr-values, and 1482 * ds-changelog-attr-exceeded-max-values-count attributes, and optionally 1483 * virtual versions of all of those elements. 1484 * 1485 * @param includeVirtual Indicates whether to include both real and virtual 1486 * values (if {@code true}, or only real values (if 1487 * {@code false}), for the attributes to be returned. 1488 * 1489 * @return A partial representation of the target entry as it appeared before 1490 * the change was processed, or {@code null} if the change was an 1491 * add operation and therefore the entry did not exist before the 1492 * change. 1493 */ 1494 public ReadOnlyEntry constructPartialEntryBeforeChange( 1495 final boolean includeVirtual) 1496 { 1497 if (getChangeType() == ChangeType.ADD) 1498 { 1499 return null; 1500 } 1501 1502 final Entry e = new Entry(getTargetDN()); 1503 1504 // If there is a set of deleted entry attributes available, then use them. 1505 final List<Attribute> deletedEntryAttrs = 1506 getDeletedEntryAttributes(includeVirtual); 1507 if (deletedEntryAttrs != null) 1508 { 1509 for (final Attribute a : deletedEntryAttrs) 1510 { 1511 e.addAttribute(a); 1512 } 1513 } 1514 1515 // If there is a set of before attributes, then use them. 1516 for (final Attribute a : getUpdatedAttributesBeforeChange(includeVirtual)) 1517 { 1518 e.addAttribute(a); 1519 } 1520 1521 // If there is a set of key attributes, then only use them if the 1522 // associated attributes aren't already in the entry and aren't in either 1523 // the after values and exceeded max values count. 1524 for (final Attribute a : getKeyEntryAttributes(includeVirtual)) 1525 { 1526 boolean shouldExclude = e.hasAttribute(a.getName()); 1527 1528 for (final Attribute ba : getUpdatedAttributesAfterChange(includeVirtual)) 1529 { 1530 if (ba.getName().equalsIgnoreCase(a.getName())) 1531 { 1532 shouldExclude = true; 1533 } 1534 } 1535 1536 for (final ChangeLogEntryAttributeExceededMaxValuesCount ea : 1537 attributesThatExceededMaxValuesCount) 1538 { 1539 if (ea.getAttributeName().equalsIgnoreCase(a.getName())) 1540 { 1541 // TODO: In the event that the before count was exceeded but the 1542 // after count was not, then we may be able to reconstruct the before 1543 // values if the changes included deleting specific values for the 1544 // attribute. 1545 shouldExclude = true; 1546 } 1547 } 1548 1549 if (includeVirtual) 1550 { 1551 for (final ChangeLogEntryAttributeExceededMaxValuesCount ea : 1552 virtualAttributesThatExceededMaxValuesCount) 1553 { 1554 if (ea.getAttributeName().equalsIgnoreCase(a.getName())) 1555 { 1556 // TODO: In the event that the before count was exceeded but the 1557 // after count was not, then we may be able to reconstruct the 1558 // before values if the changes included deleting specific values 1559 // for the attribute. 1560 shouldExclude = true; 1561 } 1562 } 1563 } 1564 1565 if (! shouldExclude) 1566 { 1567 e.addAttribute(a); 1568 } 1569 } 1570 1571 // NOTE: Although we could possibly get additional attribute values from 1572 // the entry's RDN, that can't be considered authoritative because those 1573 // same attributes may have additional values that aren't in the RDN, and we 1574 // don't want to include an attribute without the entire set of values. 1575 1576 return new ReadOnlyEntry(e); 1577 } 1578 1579 1580 1581 /** 1582 * Attempts to construct a partial representation of the target entry as it 1583 * appeared after the change was processed. The information contained in the 1584 * constructed entry will be based solely on information contained in the 1585 * changelog entry, including information provided in the changes, 1586 * ds-changelog-after-values, and ds-changelog-entry-key-attr-values 1587 * attributes. It will not include any virtual attribute information. 1588 * 1589 * @return A partial representation of the target entry as it appeared after 1590 * the change was processed, or {@code null} if the change was a 1591 * delete operation and therefore did not exist after the change. 1592 */ 1593 public ReadOnlyEntry constructPartialEntryAfterChange() 1594 { 1595 return constructPartialEntryAfterChange(false); 1596 } 1597 1598 1599 1600 /** 1601 * Attempts to construct a partial representation of the target entry as it 1602 * appeared after the change was processed. The information contained in the 1603 * constructed entry will be based solely on information contained in the 1604 * changelog entry, including information provided in the changes, 1605 * ds-changelog-after-values, and ds-changelog-entry-key-attr-values 1606 * attributes, and optionally virtual versions of all of those elements. 1607 * 1608 * @param includeVirtual Indicates whether to include both real and virtual 1609 * values (if {@code true}, or only real values (if 1610 * {@code false}), for the attributes to be returned. 1611 * 1612 * @return A partial representation of the target entry as it appeared after 1613 * the change was processed, or {@code null} if the change was a 1614 * delete operation and therefore did not exist after the change. 1615 */ 1616 public ReadOnlyEntry constructPartialEntryAfterChange( 1617 final boolean includeVirtual) 1618 { 1619 final Entry e; 1620 switch (getChangeType()) 1621 { 1622 case ADD: 1623 case MODIFY: 1624 e = new Entry(getTargetDN()); 1625 break; 1626 1627 case MODIFY_DN: 1628 e = new Entry(getNewDN()); 1629 break; 1630 1631 case DELETE: 1632 default: 1633 return null; 1634 } 1635 1636 1637 // If there is a set of add attributes, then use them. 1638 final List<Attribute> addAttrs = getAddAttributes(includeVirtual); 1639 if (addAttrs != null) 1640 { 1641 for (final Attribute a : addAttrs) 1642 { 1643 e.addAttribute(a); 1644 } 1645 } 1646 1647 // If there is a set of modifications and any of them are replace 1648 // modifications with a set of values, then we can use them to determine 1649 // the new values of those attributes. 1650 final List<Modification> mods = getModifications(); 1651 if (mods != null) 1652 { 1653 for (final Modification m : mods) 1654 { 1655 final byte[][] values = m.getValueByteArrays(); 1656 if ((m.getModificationType() == ModificationType.REPLACE) && 1657 (values.length > 0)) 1658 { 1659 e.addAttribute(m.getAttributeName(), values); 1660 } 1661 } 1662 } 1663 1664 // If there is a set of after attributes, then use them. 1665 for (final Attribute a : getUpdatedAttributesAfterChange(includeVirtual)) 1666 { 1667 e.addAttribute(a); 1668 } 1669 1670 // If there is a set of key attributes, then use them. 1671 for (final Attribute a : getKeyEntryAttributes(includeVirtual)) 1672 { 1673 e.addAttribute(a); 1674 } 1675 1676 // TODO: In the event that the after count was exceeded but the before 1677 // count was not, then we may be able to reconstruct the after values if the 1678 // changes included adding specific values for the attribute. 1679 1680 // NOTE: Although we could possibly get additional attribute values from 1681 // the entry's RDN, that can't be considered authoritative because those 1682 // same attributes may have additional values that aren't in the RDN, and we 1683 // don't want to include an attribute without the entire set of values. 1684 1685 return new ReadOnlyEntry(e); 1686 } 1687}