1 21 package oracle.toplink.essentials.internal.sessions; 23 24 import java.io.*; 25 import java.util.HashSet ; 26 import java.util.Vector ; 27 import java.util.Hashtable ; 28 import java.util.Enumeration ; 29 import oracle.toplink.essentials.queryframework.*; 30 import oracle.toplink.essentials.internal.helper.ConversionManager; 31 import oracle.toplink.essentials.internal.helper.ClassConstants; 32 import oracle.toplink.essentials.mappings.*; 33 import oracle.toplink.essentials.internal.identitymaps.CacheKey; 34 import oracle.toplink.essentials.descriptors.ClassDescriptor; 35 import oracle.toplink.essentials.internal.descriptors.OptimisticLockingPolicy; 36 37 45 public class ObjectChangeSet implements Serializable, oracle.toplink.essentials.changesets.ObjectChangeSet { 46 47 48 protected java.util.Vector changes; 49 protected java.util.Hashtable attributesToChanges; 50 protected boolean shouldBeDeleted; 51 protected CacheKey cacheKey; 52 protected transient Class classType; 53 protected String className; 54 protected boolean isNew; 55 protected boolean isAggregate; 56 protected Object oldKey; 57 protected Object newKey; 58 59 60 protected UnitOfWorkChangeSet unitOfWorkChangeSet; 61 62 protected transient OptimisticLockingPolicy optimisticLockingPolicy; 63 protected Object initialWriteLockValue; 64 protected Object writeLockValue; 65 66 protected boolean isInvalid; 67 protected transient Object cloneObject; 68 protected boolean hasVersionChange; 69 protected Boolean shouldModifyVersionField; 71 protected boolean hasCmpPolicyForcedUpdate; 73 protected boolean hasChangesFromCascadeLocking; 74 75 79 protected transient HashSet deferredSet; 80 81 84 public ObjectChangeSet() { 85 super(); 86 } 87 88 91 public ObjectChangeSet(Object cloneObject, UnitOfWorkChangeSet parent, boolean isNew) { 92 this.cloneObject = cloneObject; 93 this.shouldBeDeleted = false; 94 this.classType = cloneObject.getClass(); 95 this.className = this.classType.getName(); 96 this.unitOfWorkChangeSet = parent; 97 this.isNew = isNew; 98 } 99 100 103 public ObjectChangeSet(Vector primaryKey, Object cloneObject, UnitOfWorkChangeSet parent, boolean isNew) { 104 super(); 105 this.cloneObject = cloneObject; 106 this.isNew = isNew; 107 this.shouldBeDeleted = false; 108 if ((primaryKey != null) && !oracle.toplink.essentials.internal.helper.Helper.containsNull(primaryKey, 0)) { 109 this.cacheKey = new CacheKey(primaryKey); 110 } 111 this.classType = cloneObject.getClass(); 112 this.className = this.classType.getName(); 113 this.unitOfWorkChangeSet = parent; 114 this.isAggregate = false; 115 } 116 117 121 public void clear() { 122 this.shouldBeDeleted = false; 123 this.setOldKey(null); 124 this.setNewKey(null); 125 this.changes = null; 126 this.attributesToChanges = null; 127 } 128 129 132 public void addChange(ChangeRecord changeRecord) { 133 if (changeRecord == null) { 134 return; 135 } 136 ChangeRecord existingChangeRecord = (ChangeRecord)getAttributesToChanges().get(changeRecord.getAttribute()); 137 if ( existingChangeRecord != null){ 139 getChanges().remove(existingChangeRecord); 140 } 141 getChanges().addElement(changeRecord); 142 getAttributesToChanges().put(changeRecord.getAttribute(), changeRecord); 143 updateUOWChangeSet(); 144 } 145 146 153 public void deferredDetectionRequiredOn(String attributeName){ 154 getDeferredSet().add(attributeName); 155 } 156 157 164 public boolean containsChangesFromSynchronization() { 165 return false; 166 } 167 168 172 public boolean equals(Object object) { 173 if (object instanceof ObjectChangeSet) { 174 return equals((ObjectChangeSet)object); 175 } 176 return false; 177 } 178 179 183 public boolean equals(oracle.toplink.essentials.changesets.ObjectChangeSet objectChange) { 184 if (this == objectChange) { 185 return true; 186 } else if (getCacheKey() == null) { 187 return false; 189 } 190 191 return (getCacheKey().equals(((ObjectChangeSet)objectChange).getCacheKey())); 192 } 193 194 198 public Hashtable getAttributesToChanges() { 199 if (this.attributesToChanges == null) { 200 this.attributesToChanges = new Hashtable (2); 201 } 202 return this.attributesToChanges; 203 } 204 205 209 public oracle.toplink.essentials.changesets.ChangeRecord getChangesForAttributeNamed(String attributeName) { 210 return (ChangeRecord)this.getAttributesToChanges().get(attributeName); 211 } 212 213 216 public CacheKey getCacheKey() { 217 return cacheKey; 220 } 221 222 227 public Vector getChangedAttributeNames() { 228 Vector names = new Vector (); 229 Enumeration attributes = getChanges().elements(); 230 while (attributes.hasMoreElements()) { 231 names.addElement(((ChangeRecord)attributes.nextElement()).getAttribute()); 232 } 233 return names; 234 } 235 236 241 public java.util.Vector getChanges() { 242 if (this.changes == null) { 243 this.changes = new Vector (1); 244 } 245 return changes; 246 } 247 248 254 public Class getClassType(oracle.toplink.essentials.sessions.Session session) { 255 if (classType == null) { 256 classType = (Class )((AbstractSession)session).getDatasourcePlatform().getConversionManager().convertObject(getClassName(), ClassConstants.CLASS); 257 } 258 return classType; 259 } 260 261 267 public String getClassName() { 268 return className; 269 } 270 271 276 public java.lang.Object getInitialWriteLockValue() { 277 return initialWriteLockValue; 278 } 279 280 284 public Object getOldKey() { 285 return this.oldKey; 286 } 287 288 292 public Object getNewKey() { 293 return this.newKey; 294 } 295 296 301 public java.util.Vector getPrimaryKeys() { 302 if (getCacheKey() == null) { 303 return null; 304 } 305 return getCacheKey().getKey(); 306 } 307 308 315 public Object getTargetVersionOfSourceObject(AbstractSession session) { 316 return getTargetVersionOfSourceObject(session, false); 317 } 318 319 327 public Object getTargetVersionOfSourceObject(AbstractSession session, boolean shouldRead) { 328 Object attributeValue = null; 329 ClassDescriptor descriptor = session.getDescriptor(getClassType(session)); 330 331 if (session.isUnitOfWork()) { if (((UnitOfWorkImpl)session).getLifecycle() == UnitOfWorkImpl.MergePending) { attributeValue = ((UnitOfWorkImpl)session).getOriginalVersionOfObjectOrNull(((UnitOfWorkChangeSet)getUOWChangeSet()).getObjectChangeSetToUOWClone().get(this)); 334 } else { 335 attributeValue = ((UnitOfWorkChangeSet)getUOWChangeSet()).getObjectChangeSetToUOWClone().get(this); 339 } 340 } else { attributeValue = session.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(getPrimaryKeys(), getClassType(session), descriptor); 342 343 } 344 if ((attributeValue == null) && (shouldRead)) { 345 ReadObjectQuery query = new ReadObjectQuery(); 348 query.setShouldUseWrapperPolicy(false); 349 query.setReferenceClass(getClassType(session)); 350 query.setSelectionKey(getPrimaryKeys()); 351 attributeValue = session.executeQuery(query); 352 } 353 return attributeValue; 354 } 355 356 360 public Object getUnitOfWorkClone() { 361 return this.cloneObject; 362 } 363 364 369 public oracle.toplink.essentials.changesets.UnitOfWorkChangeSet getUOWChangeSet() { 370 return unitOfWorkChangeSet; 371 } 372 373 378 public java.lang.Object getWriteLockValue() { 379 return writeLockValue; 380 } 381 382 388 public boolean hasChangeFor(String attributeName) { 389 Enumeration attributes = getChanges().elements(); 390 while (attributes.hasMoreElements()) { 391 if (((ChangeRecord)attributes.nextElement()).getAttribute().equals(attributeName)) { 392 return true; 393 } 394 } 395 return false; 396 } 397 398 403 public boolean hasChanges() { 404 return this.hasVersionChange || !this.getChanges().isEmpty(); 408 } 409 410 418 public boolean hasForcedChanges() { 419 return this.shouldModifyVersionField != null || this.hasCmpPolicyForcedUpdate; 420 } 421 422 429 public void setShouldModifyVersionField(Boolean shouldModifyVersionField) { 430 this.shouldModifyVersionField = shouldModifyVersionField; 431 if(shouldModifyVersionField != null && shouldModifyVersionField.booleanValue()) { 432 this.hasVersionChange = true; 436 } 437 } 438 439 443 public Boolean shouldModifyVersionField() { 444 return this.shouldModifyVersionField; 445 } 446 447 450 public void setHasCmpPolicyForcedUpdate(boolean hasCmpPolicyForcedUpdate) { 451 this.hasCmpPolicyForcedUpdate = hasCmpPolicyForcedUpdate; 452 } 453 454 457 public boolean hasCmpPolicyForcedUpdate() { 458 return this.hasCmpPolicyForcedUpdate; 459 } 460 461 467 public boolean hasForcedChangesFromCascadeLocking() { 468 return this.hasChangesFromCascadeLocking; 469 } 470 471 476 public void setHasForcedChangesFromCascadeLocking(boolean newValue) { 477 this.setShouldModifyVersionField(Boolean.TRUE); 478 this.hasChangesFromCascadeLocking = newValue; 479 } 480 481 486 public int hashCode() { 487 if (getCacheKey() == null) { 488 return System.identityHashCode(this); 490 } 491 return getCacheKey().hashCode(); 492 } 493 494 499 public boolean hasKeys() { 500 return (this.newKey != null) || (this.oldKey != null); 501 } 502 503 508 public boolean isAggregate() { 509 return isAggregate; 510 } 511 512 517 public boolean isNew() { 518 return isNew; 519 } 520 521 526 public boolean isInvalid() { 527 return isInvalid; 528 } 529 530 535 public void mergeObjectChanges(ObjectChangeSet changeSetToMergeFrom, UnitOfWorkChangeSet mergeToChangeSet, UnitOfWorkChangeSet mergeFromChangeSet) { 536 if (this == changeSetToMergeFrom || this.isInvalid()) { 537 return; 538 } 539 if(changeSetToMergeFrom.optimisticLockingPolicy != null) { 540 if(this.optimisticLockingPolicy == null) { 542 this.optimisticLockingPolicy = changeSetToMergeFrom.optimisticLockingPolicy; 543 this.initialWriteLockValue = changeSetToMergeFrom.initialWriteLockValue; 544 this.writeLockValue = changeSetToMergeFrom.writeLockValue; 545 } else { 546 Object writeLockValueToCompare = this.writeLockValue; 548 if(writeLockValueToCompare == null) { 549 writeLockValueToCompare = this.initialWriteLockValue; 550 } 551 if(this.optimisticLockingPolicy.compareWriteLockValues(writeLockValueToCompare, changeSetToMergeFrom.initialWriteLockValue) != 0) { 563 this.isInvalid = true; 564 return; 565 } 566 this.writeLockValue = changeSetToMergeFrom.writeLockValue; 567 } 568 } 569 for (int index = 0; index < changeSetToMergeFrom.getChanges().size(); ++index) { 570 ChangeRecord record = (ChangeRecord)changeSetToMergeFrom.getChanges().get(index); 571 ChangeRecord thisRecord = (ChangeRecord) this.getChangesForAttributeNamed(record.getAttribute()); 572 if (thisRecord == null) { 573 record.updateReferences(mergeToChangeSet, mergeFromChangeSet); 574 this.addChange(record); 575 } else { 576 thisRecord.mergeRecord(record, mergeToChangeSet, mergeFromChangeSet); 577 } 578 } 579 this.shouldBeDeleted = changeSetToMergeFrom.shouldBeDeleted; 580 this.setOldKey(changeSetToMergeFrom.oldKey); 581 this.setNewKey(changeSetToMergeFrom.newKey); 582 this.hasVersionChange = changeSetToMergeFrom.hasVersionChange; 583 this.shouldModifyVersionField = changeSetToMergeFrom.shouldModifyVersionField; 584 this.hasCmpPolicyForcedUpdate = changeSetToMergeFrom.hasCmpPolicyForcedUpdate; 585 this.hasChangesFromCascadeLocking = changeSetToMergeFrom.hasChangesFromCascadeLocking; 586 } 587 588 593 public void prepareChangeRecordsForSynchronization(AbstractSession session) { 594 Enumeration records = getChanges().elements(); 595 while (records.hasMoreElements()) { 596 ((ChangeRecord)records.nextElement()).prepareForSynchronization(session); 597 } 598 } 599 600 605 public void readCompleteChangeSet(java.io.ObjectInputStream stream) throws java.io.IOException , ClassNotFoundException { 606 readIdentityInformation(stream); 607 changes = (Vector )stream.readObject(); 610 setOldKey(stream.readObject()); 611 newKey = stream.readObject(); 612 } 613 614 619 public void readIdentityInformation(java.io.ObjectInputStream stream) throws java.io.IOException , ClassNotFoundException { 620 cacheKey = (CacheKey)stream.readObject(); 622 className = (String )stream.readObject(); 623 writeLockValue = stream.readObject(); 624 } 625 626 629 public void setCacheKey(CacheKey cacheKey) { 630 this.cacheKey = cacheKey; 631 } 632 633 636 public void setChanges(java.util.Vector changesList) { 637 this.changes = changesList; 638 updateUOWChangeSet(); 639 } 640 641 644 public void setClassType(Class newValue) { 645 this.classType = newValue; 646 } 647 648 652 public void setClassName(String newValue) { 653 this.className = newValue; 654 } 655 656 661 public void setIsAggregate(boolean isAggregate) { 662 this.isAggregate = isAggregate; 663 } 664 665 670 protected void setIsNew(boolean newIsNew) { 671 isNew = newIsNew; 672 } 673 674 678 public void setOldKey(Object key) { 679 if ((key == null) || (this.oldKey == null)) { 682 this.oldKey = key; 683 } 684 } 685 686 690 public void setNewKey(Object key) { 691 this.newKey = key; 692 } 693 694 698 public void setShouldBeDeleted(boolean newValue) { 699 this.shouldBeDeleted = newValue; 700 } 701 702 707 public void setUOWChangeSet(UnitOfWorkChangeSet newUnitOfWorkChangeSet) { 708 unitOfWorkChangeSet = newUnitOfWorkChangeSet; 709 } 710 711 717 public void setOptimisticLockingPolicyAndInitialWriteLockValue(OptimisticLockingPolicy optimisticLockingPolicy, AbstractSession session) { 718 this.optimisticLockingPolicy = optimisticLockingPolicy; 719 this.initialWriteLockValue = optimisticLockingPolicy.getWriteLockValue(cloneObject, getPrimaryKeys(), session); 720 } 721 722 730 public void setWriteLockValue(java.lang.Object newWriteLockValue) { 731 this.writeLockValue = newWriteLockValue; 732 733 this.hasVersionChange = true; 735 updateUOWChangeSet(); 736 } 737 738 744 public void setInitialWriteLockValue(java.lang.Object initialWriteLockValue) { 745 if (this.initialWriteLockValue == null) { 746 this.initialWriteLockValue = initialWriteLockValue; 747 } 748 } 749 750 754 public boolean shouldBeDeleted() { 755 return shouldBeDeleted; 756 } 757 758 public String toString() { 759 return this.getClass().getName() + "(" + this.getClassName() + ")" + getChanges().toString(); 760 } 761 762 766 public void updateChangeRecordForAttribute(String attributeName, Object value) { 767 ChangeRecord changeRecord = (ChangeRecord)getChangesForAttributeNamed(attributeName); 768 if (changeRecord != null) { 769 changeRecord.updateChangeRecordWithNewValue(value); 770 } 771 } 772 773 778 public void updateChangeRecordForAttributeWithMappedObject(String attributeName, Object value, AbstractSession session) { 779 ObjectChangeSet referenceChangeSet = (ObjectChangeSet)this.getUOWChangeSet().getObjectChangeSetForClone(value); 780 if (referenceChangeSet == null) { 781 ClassDescriptor descriptor = session.getDescriptor(value.getClass()); 782 if (descriptor != null) { 783 referenceChangeSet = descriptor.getObjectBuilder().createObjectChangeSet(value, (UnitOfWorkChangeSet)this.getUOWChangeSet(), false, session); 784 } 785 } 786 updateChangeRecordForAttribute(attributeName, referenceChangeSet); 787 } 788 789 793 public void updateChangeRecordForAttribute(DatabaseMapping mapping, Object value) { 794 String attributeName = mapping.getAttributeName(); 795 ChangeRecord changeRecord = (ChangeRecord)getChangesForAttributeNamed(attributeName); 796 797 value = ConversionManager.getDefaultManager().convertObject(value, mapping.getAttributeClassification()); 799 if (changeRecord != null) { 800 changeRecord.updateChangeRecordWithNewValue(value); 801 } else if (mapping.isDirectToFieldMapping()) { 802 changeRecord = new DirectToFieldChangeRecord(this); 805 changeRecord.setAttribute(attributeName); 806 changeRecord.setMapping(mapping); 807 ((DirectToFieldChangeRecord)changeRecord).setNewValue(value); 808 this.addChange(changeRecord); 809 } 810 } 811 812 818 public void updateReferences(UnitOfWorkChangeSet localChangeSet, UnitOfWorkChangeSet mergingChangeSet) { 819 for (int index = 0; index < this.getChanges().size(); ++index) { 820 ((ChangeRecord)this.getChanges().get(index)).updateReferences(localChangeSet, mergingChangeSet); 821 } 822 } 823 824 829 public void writeIdentityInformation(java.io.ObjectOutputStream stream) throws java.io.IOException { 830 stream.writeObject(cacheKey); 831 stream.writeObject(className); 832 stream.writeObject(writeLockValue); 833 } 834 835 839 public void writeCompleteChangeSet(java.io.ObjectOutputStream stream) throws java.io.IOException { 840 writeIdentityInformation(stream); 841 stream.writeObject(changes); 842 stream.writeObject(oldKey); 843 stream.writeObject(newKey); 844 } 845 846 849 public void setPrimaryKeys(Vector key) { 850 if (key == null) { 851 return; 852 } 853 if (getCacheKey() == null) { 854 setCacheKey(new CacheKey(key)); 855 } else { 856 getCacheKey().setKey(key); 857 } 858 } 859 860 863 public HashSet getDeferredSet() { 864 if (deferredSet == null){ 865 this.deferredSet = new HashSet (); 866 } 867 return deferredSet; 868 } 869 870 873 public boolean hasDeferredAttributes() { 874 return ! (deferredSet == null || this.deferredSet.isEmpty()); 875 } 876 877 protected void updateUOWChangeSet() { 878 if (this.getUOWChangeSet() != null) { 883 ((oracle.toplink.essentials.internal.sessions.UnitOfWorkChangeSet)this.getUOWChangeSet()).setHasChanges(this.hasChanges()); 884 } 885 } 886 887 892 public void removeChange(String attributeName){ 893 Object record = getChangesForAttributeNamed(attributeName); 894 if (record != null){ 895 getChanges().removeElement(record); 896 } 897 } 898 899 902 protected void removeFromIdentityMap(AbstractSession session) { 903 session.getIdentityMapAccessor().removeFromIdentityMap(getPrimaryKeys(), getClassType(session)); 904 } 905 906 912 public boolean shouldInvalidateObject(Object original, AbstractSession session) { 913 if (optimisticLockingPolicy == null) { 915 return false; 916 } 917 918 if(isInvalid()) { 919 return true; 920 } 921 922 Object originalWriteLockValue = optimisticLockingPolicy.getWriteLockValue(original, getPrimaryKeys(), session); 923 if (optimisticLockingPolicy.compareWriteLockValues(initialWriteLockValue, originalWriteLockValue) != 0) { 932 return true; 933 } else { 934 return false; 935 } 936 } 937 } 938 | Popular Tags |