1 21 package oracle.toplink.essentials.mappings; 23 24 import java.util.*; 25 import oracle.toplink.essentials.exceptions.*; 26 import oracle.toplink.essentials.indirection.*; 27 import oracle.toplink.essentials.internal.descriptors.*; 28 import oracle.toplink.essentials.internal.helper.*; 29 import oracle.toplink.essentials.internal.identitymaps.*; 30 import oracle.toplink.essentials.internal.indirection.*; 31 import oracle.toplink.essentials.internal.queryframework.*; 32 import oracle.toplink.essentials.internal.sessions.*; 33 import oracle.toplink.essentials.queryframework.*; 34 import oracle.toplink.essentials.sessions.ObjectCopyingPolicy; 35 import oracle.toplink.essentials.expressions.Expression; 36 import oracle.toplink.essentials.expressions.ExpressionBuilder; 37 import oracle.toplink.essentials.internal.sessions.AbstractRecord; 38 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl; 39 import oracle.toplink.essentials.internal.sessions.AbstractSession; 40 import oracle.toplink.essentials.descriptors.ClassDescriptor; 41 42 48 public abstract class CollectionMapping extends ForeignReferenceMapping implements ContainerMapping { 49 50 protected transient ModifyQuery deleteAllQuery; 51 protected transient boolean hasCustomDeleteAllQuery; 52 protected ContainerPolicy containerPolicy; 53 protected transient boolean hasOrderBy; 54 55 59 public CollectionMapping() { 60 this.selectionQuery = new ReadAllQuery(); 61 this.hasCustomDeleteAllQuery = false; 62 this.containerPolicy = ContainerPolicy.buildPolicyFor(ClassConstants.Vector_class); 63 this.hasOrderBy = false; 64 } 65 66 70 public void addAscendingOrdering(String queryKeyName) { 71 if (queryKeyName == null) { 72 return; 73 } 74 75 ((ReadAllQuery)getSelectionQuery()).addAscendingOrdering(queryKeyName); 76 } 77 78 82 public void addDescendingOrdering(String queryKeyName) { 83 if (queryKeyName == null) { 84 return; 85 } 86 87 ((ReadAllQuery)getSelectionQuery()).addDescendingOrdering(queryKeyName); 88 } 89 90 95 public void addOrderBy(String queryKeyName, boolean isDescending) { 96 this.hasOrderBy = true; 97 98 if (isDescending) { 99 addDescendingOrdering(queryKeyName); 100 } else { 101 addAscendingOrdering(queryKeyName); 102 } 103 } 104 105 111 public void addAggregateOrderBy(String aggregateName, String queryKeyName, boolean isDescending) { 112 this.hasOrderBy = true; 113 114 ReadAllQuery readAllQuery = (ReadAllQuery) getSelectionQuery(); 115 ExpressionBuilder builder = readAllQuery.getExpressionBuilder(); 116 Expression expression = builder.get(aggregateName).get(queryKeyName).toUpperCase(); 117 118 if (isDescending) { 119 readAllQuery.addOrdering(expression.descending()); 120 } else { 121 readAllQuery.addOrdering(expression.ascending()); 122 } 123 } 124 125 130 public Object buildBackupCloneForPartObject(Object attributeValue, Object clone, Object backup, UnitOfWorkImpl unitOfWork) { 131 if (attributeValue == null) { 133 return getContainerPolicy().containerInstance(1); 134 } else { 135 return getContainerPolicy().cloneFor(attributeValue); 136 } 137 } 138 139 144 public Object buildCloneForPartObject(Object attributeValue, Object original, Object clone, UnitOfWorkImpl unitOfWork, boolean isExisting) { 145 ContainerPolicy containerPolicy = getContainerPolicy(); 146 if (attributeValue == null) { 147 Object container = containerPolicy.containerInstance(1); 148 return container; 149 } 150 Object clonedAttributeValue = containerPolicy.containerInstance(containerPolicy.sizeFor(attributeValue)); 151 152 Object temporaryCollection = null; 157 synchronized (attributeValue) { 158 temporaryCollection = containerPolicy.cloneFor(attributeValue); 159 } 160 for (Object valuesIterator = containerPolicy.iteratorFor(temporaryCollection); 161 containerPolicy.hasNext(valuesIterator);) { 162 Object cloneValue = buildElementClone(containerPolicy.next(valuesIterator, unitOfWork), unitOfWork, isExisting); 163 containerPolicy.addInto(cloneValue, clonedAttributeValue, unitOfWork); 164 } 165 return clonedAttributeValue; 166 } 167 168 173 public void buildCopy(Object copy, Object original, ObjectCopyingPolicy policy) { 174 Object attributeValue = getRealCollectionAttributeValueFromObject(original, policy.getSession()); 175 Object valuesIterator = getContainerPolicy().iteratorFor(attributeValue); 176 attributeValue = getContainerPolicy().containerInstance(getContainerPolicy().sizeFor(attributeValue)); 177 while (getContainerPolicy().hasNext(valuesIterator)) { 178 Object originalValue = getContainerPolicy().next(valuesIterator, policy.getSession()); 179 Object copyValue = originalValue; 180 if (policy.shouldCascadeAllParts() || (policy.shouldCascadePrivateParts() && isPrivateOwned())) { 181 copyValue = policy.getSession().copyObject(originalValue, policy); 182 } else { 183 copyValue = policy.getCopies().get(originalValue); 185 if (copyValue == null) { 186 copyValue = originalValue; 187 } 188 } 189 getContainerPolicy().addInto(copyValue, attributeValue, policy.getSession()); 190 } 191 setRealAttributeValueInObject(copy, attributeValue); 192 } 193 194 198 protected Object buildElementClone(Object element, UnitOfWorkImpl unitOfWork, boolean isExisting) { 199 if (isExisting) { 201 return unitOfWork.registerExistingObject(element); 202 } else { return unitOfWork.registerObject(element); 204 } 205 } 206 207 211 public void cascadePerformRemoveIfRequired(Object object, UnitOfWorkImpl uow, IdentityHashtable visitedObjects){ 212 Object cloneAttribute = null; 213 cloneAttribute = getAttributeValueFromObject(object); 214 if ((cloneAttribute == null) || (!this.isCascadeRemove())) { 215 return; 216 } 217 218 ContainerPolicy cp = getContainerPolicy(); 219 Object cloneObjectCollection = null; 220 cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow); 221 Object cloneIter = cp.iteratorFor(cloneObjectCollection); 222 while (cp.hasNext(cloneIter)) { 223 Object nextObject = cp.next(cloneIter, uow); 224 if (nextObject != null && (! visitedObjects.contains(nextObject)) ){ 225 visitedObjects.put(nextObject, nextObject); 226 uow.performRemove(nextObject, visitedObjects); 227 } 228 } 229 } 230 231 235 public void cascadeRegisterNewIfRequired(Object object, UnitOfWorkImpl uow, IdentityHashtable visitedObjects){ 236 Object cloneAttribute = null; 237 cloneAttribute = getAttributeValueFromObject(object); 238 if ((cloneAttribute == null) || (!this.isCascadePersist()) || (!getIndirectionPolicy().objectIsInstantiated(cloneAttribute))) { 239 return; 240 } 241 242 ContainerPolicy cp = getContainerPolicy(); 243 Object cloneObjectCollection = null; 244 cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow); 245 Object cloneIter = cp.iteratorFor(cloneObjectCollection); 246 while (cp.hasNext(cloneIter)) { 247 Object nextObject = cp.next(cloneIter, uow); 248 if (nextObject != null && (! visitedObjects.contains(nextObject)) ){ 249 visitedObjects.put(nextObject, nextObject); 250 uow.registerNewObjectForPersist(nextObject, visitedObjects); 251 } 252 } 253 } 254 255 259 private void checkMapClass(Class concreteClass) { 260 if (getReferenceClass() == null) { 262 throw DescriptorException.referenceClassNotSpecified(this); 263 } 264 265 if (! Helper.classImplementsInterface(concreteClass, ClassConstants.Map_Class)) { 266 throw ValidationException.illegalContainerClass(concreteClass); 267 } 268 } 269 270 276 public void calculateDeferredChanges(ChangeRecord changeRecord, AbstractSession session){ 277 CollectionChangeRecord collectionRecord = (CollectionChangeRecord) changeRecord; 278 compareCollectionsForChange(collectionRecord.getOriginalCollection(), collectionRecord.getLatestCollection(), collectionRecord, session); 282 } 283 284 288 public void cascadeMerge(Object sourceElement, MergeManager mergeManager) { 289 if (shouldMergeCascadeParts(mergeManager)) { 290 mergeManager.mergeChanges(mergeManager.getObjectToMerge(sourceElement), null); 291 } 292 } 293 294 299 public void compareCollectionsForChange(Object oldCollection, Object newCollection, ChangeRecord changeRecord, AbstractSession session) { 300 getContainerPolicy().compareCollectionsForChange(oldCollection, newCollection, (CollectionChangeRecord) changeRecord, session, getReferenceDescriptor()); 301 } 302 303 308 public ChangeRecord compareForChange(Object clone, Object backUp, ObjectChangeSet owner, AbstractSession session) { 309 Object cloneAttribute = null; 310 Object backUpAttribute = null; 311 312 Object backUpObjectCollection = null; 313 314 cloneAttribute = getAttributeValueFromObject(clone); 315 316 if ((cloneAttribute != null) && (!getIndirectionPolicy().objectIsInstantiated(cloneAttribute))) { 317 return null; 318 } 319 320 321 if (!owner.isNew()) { backUpAttribute = getAttributeValueFromObject(backUp); 323 324 if ((cloneAttribute == null) && (backUpAttribute == null)) { 325 return null; 326 } 327 328 backUpObjectCollection = getRealCollectionAttributeValueFromObject(backUp, session); 329 } 330 331 Object cloneObjectCollection = null; 332 if (cloneAttribute != null) { 333 cloneObjectCollection = getRealCollectionAttributeValueFromObject(clone, session); 334 } else { 335 cloneObjectCollection = getContainerPolicy().containerInstance(1); 336 } 337 338 CollectionChangeRecord changeRecord = new CollectionChangeRecord(owner); 339 changeRecord.setAttribute(getAttributeName()); 340 changeRecord.setMapping(this); 341 compareCollectionsForChange(backUpObjectCollection, cloneObjectCollection, changeRecord, session); 342 if (changeRecord.hasChanges()) { 343 return changeRecord; 344 } 345 return null; 346 } 347 348 352 public boolean compareObjects(Object firstObject, Object secondObject, AbstractSession session) { 353 Object firstObjectCollection = getRealCollectionAttributeValueFromObject(firstObject, session); 354 Object secondObjectCollection = getRealCollectionAttributeValueFromObject(secondObject, session); 355 356 return super.compareObjects(firstObjectCollection, secondObjectCollection, session); 357 } 358 359 363 protected void compareObjectsAndWrite(Object previousObjects, Object currentObjects, WriteObjectQuery query) throws DatabaseException, OptimisticLockException { 364 ContainerPolicy cp = getContainerPolicy(); 365 366 if ((query.getObjectChangeSet() != null) && !this.isAggregateCollectionMapping()) { 370 ObjectChangeSet changeSet = query.getObjectChangeSet(); 371 CollectionChangeRecord record = (CollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName()); 372 373 if (record != null) { 374 ObjectChangeSet removedChangeSet = null; 375 ObjectChangeSet addedChangeSet = null; 376 UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)changeSet.getUOWChangeSet(); 377 Enumeration removedObjects = record.getRemoveObjectList().elements(); 378 379 while (removedObjects.hasMoreElements()) { 380 removedChangeSet = (ObjectChangeSet)removedObjects.nextElement(); 381 objectRemovedDuringUpdate(query, removedChangeSet.getUnitOfWorkClone()); 382 } 383 384 Enumeration addedObjects = record.getAddObjectList().elements(); 385 386 while (addedObjects.hasMoreElements()) { 387 addedChangeSet = (ObjectChangeSet)addedObjects.nextElement(); 388 objectAddedDuringUpdate(query, addedChangeSet.getUnitOfWorkClone(), addedChangeSet); 389 } 390 } 391 392 return; 393 } 394 395 Hashtable previousObjectsByKey = new Hashtable(cp.sizeFor(previousObjects) + 2); Hashtable currentObjectsByKey = new Hashtable(cp.sizeFor(currentObjects) + 2); 398 IdentityHashtable cacheKeysOfCurrentObjects = new IdentityHashtable(cp.sizeFor(currentObjects) + 1); 399 400 for (Object currentObjectsIter = cp.iteratorFor(currentObjects); 402 cp.hasNext(currentObjectsIter);) { 403 Object currentObject = cp.next(currentObjectsIter, query.getSession()); 404 try { 405 Vector primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession()); 406 CacheKey key = new CacheKey(primaryKey); 407 currentObjectsByKey.put(key, currentObject); 408 cacheKeysOfCurrentObjects.put(currentObject, key); 409 } catch (NullPointerException e) { 410 if (currentObject != null) { 414 throw e; 415 } 416 } 417 } 418 419 for (Object previousObjectsIter = cp.iteratorFor(previousObjects); 422 cp.hasNext(previousObjectsIter);) { 423 Object previousObject = cp.next(previousObjectsIter, query.getSession()); 424 Vector primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession()); 425 CacheKey key = new CacheKey(primaryKey); 426 previousObjectsByKey.put(key, previousObject); 427 428 if (!currentObjectsByKey.containsKey(key)) { 431 objectRemovedDuringUpdate(query, previousObject); 432 } 433 } 434 435 for (Object currentObjectsIter = cp.iteratorFor(currentObjects); 436 cp.hasNext(currentObjectsIter);) { 437 Object currentObject = cp.next(currentObjectsIter, query.getSession()); 438 try { 439 CacheKey cacheKey = (CacheKey)cacheKeysOfCurrentObjects.get(currentObject); 440 441 if (!(previousObjectsByKey.containsKey(cacheKey))) { 442 objectAddedDuringUpdate(query, currentObject, null); 443 } else { 444 objectUnchangedDuringUpdate(query, currentObject, previousObjectsByKey, cacheKey); 445 } 446 } catch (NullPointerException e) { 447 if (currentObject != null) { 449 throw e; 450 } 451 } 452 } 453 } 454 455 458 protected boolean compareObjectsWithoutPrivateOwned(Object firstCollection, Object secondCollection, AbstractSession session) { 459 ContainerPolicy cp = getContainerPolicy(); 460 if (cp.sizeFor(firstCollection) != cp.sizeFor(secondCollection)) { 461 return false; 462 } 463 464 Object firstIter = cp.iteratorFor(firstCollection); 465 Object secondIter = cp.iteratorFor(secondCollection); 466 467 Vector keyValue = new Vector(); 468 469 while (cp.hasNext(secondIter)) { 470 Object secondObject = cp.next(secondIter, session); 471 Vector primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session); 472 keyValue.addElement(new CacheKey(primaryKey)); 473 } 474 475 while (cp.hasNext(firstIter)) { 476 Object firstObject = cp.next(firstIter, session); 477 Vector primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session); 478 479 if (!keyValue.contains(new CacheKey(primaryKey))) { 480 return false; 481 } 482 } 483 return true; 484 } 485 486 489 protected boolean compareObjectsWithPrivateOwned(Object firstCollection, Object secondCollection, AbstractSession session) { 490 ContainerPolicy cp = getContainerPolicy(); 491 if (cp.sizeFor(firstCollection) != cp.sizeFor(secondCollection)) { 492 return false; 493 } 494 495 Object firstIter = cp.iteratorFor(firstCollection); 496 Object secondIter = cp.iteratorFor(secondCollection); 497 498 Hashtable keyValueToObject = new Hashtable(cp.sizeFor(firstCollection) + 2); 499 CacheKey cacheKey; 500 501 while (cp.hasNext(secondIter)) { 502 Object secondObject = cp.next(secondIter, session); 503 Vector primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session); 504 keyValueToObject.put(new CacheKey(primaryKey), secondObject); 505 } 506 507 while (cp.hasNext(firstIter)) { 508 Object firstObject = cp.next(firstIter, session); 509 Vector primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session); 510 cacheKey = new CacheKey(primaryKey); 511 512 if (keyValueToObject.containsKey(cacheKey)) { 513 Object object = keyValueToObject.get(cacheKey); 514 515 if (!session.compareObjects(firstObject, object)) { 516 return false; 517 } 518 } else { 519 return false; 520 } 521 } 522 523 return true; 524 } 525 526 533 public void convertClassNamesToClasses(ClassLoader classLoader){ 534 super.convertClassNamesToClasses(classLoader); 535 containerPolicy.convertClassNamesToClasses(classLoader); 536 }; 537 538 542 public ContainerPolicy getContainerPolicy() { 543 return containerPolicy; 544 } 545 546 protected ModifyQuery getDeleteAllQuery() { 547 if (deleteAllQuery == null) { 548 deleteAllQuery = new DataModifyQuery(); 549 } 550 return deleteAllQuery; 551 } 552 553 558 public Object getRealAttributeValueFromObject(Object object, AbstractSession session) throws DescriptorException { 559 Object value = super.getRealAttributeValueFromObject(object, session); 560 if (value != null) { 561 if (!getContainerPolicy().isValidContainer(value)) { 562 throw DescriptorException.attributeTypeNotValid(this); 563 } 564 } 565 return value; 566 } 567 568 573 public Object getRealCollectionAttributeValueFromObject(Object object, AbstractSession session) throws DescriptorException { 574 Object value = this.getRealAttributeValueFromObject(object, session); 575 if (value == null) { 576 value = this.getContainerPolicy().containerInstance(1); 577 } 578 return value; 579 } 580 581 protected boolean hasCustomDeleteAllQuery() { 582 return hasCustomDeleteAllQuery; 583 } 584 585 590 public boolean hasOrderBy() { 591 return hasOrderBy; 592 } 593 594 598 public void initialize(AbstractSession session) throws DescriptorException { 599 super.initialize(session); 600 setFields(collectFields()); 601 getContainerPolicy().prepare(getSelectionQuery(), session); 602 603 if ((!usesIndirection()) && (!getAttributeAccessor().getAttributeClass().isAssignableFrom(getContainerPolicy().getContainerClass()))) { 605 throw DescriptorException.incorrectCollectionPolicy(this, getAttributeAccessor().getAttributeClass(), getContainerPolicy().getContainerClass()); 606 } 607 } 608 609 612 public boolean isCollectionMapping() { 613 return true; 614 } 615 616 620 public void iterateOnElement(DescriptorIterator iterator, Object element) { 621 iterator.iterateReferenceObjectForMapping(element, this); 622 } 623 624 629 public void iterateOnRealAttributeValue(DescriptorIterator iterator, Object realAttributeValue) { 630 if (realAttributeValue == null) { 631 return; 632 } 633 ContainerPolicy cp = getContainerPolicy(); 634 for (Object iter = cp.iteratorFor(realAttributeValue); cp.hasNext(iter);) { 635 iterateOnElement(iterator, cp.next(iter, iterator.getSession())); 636 } 637 } 638 639 645 public void mergeChangesIntoObject(Object target, ChangeRecord chgRecord, Object source, MergeManager mergeManager) { 646 Object valueOfTarget = null; 647 Object valueOfSource = null; 648 AbstractSession parentSession = null; 649 ContainerPolicy containerPolicy = getContainerPolicy(); 650 CollectionChangeRecord changeRecord = (CollectionChangeRecord) chgRecord; 651 UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)changeRecord.getOwner().getUOWChangeSet(); 652 653 if (isAttributeValueInstantiated(target)) { 656 if (changeRecord.getOwner().isNew()) { 658 valueOfTarget = containerPolicy.containerInstance(changeRecord.getAddObjectList().size()); 659 } else { 660 valueOfTarget = getRealCollectionAttributeValueFromObject(target, mergeManager.getSession()); 661 } 662 663 if (mergeManager.getSession().isUnitOfWork() && !mergeManager.shouldMergeWorkingCopyIntoBackup()) { 666 parentSession = ((UnitOfWorkImpl)mergeManager.getSession()).getParent(); 667 } else { 668 parentSession = mergeManager.getSession(); 669 } 670 671 containerPolicy.mergeChanges(changeRecord, valueOfTarget, shouldMergeCascadeParts(mergeManager), mergeManager, parentSession); 672 } else { 673 if (mergeManager.shouldMergeChangesIntoDistributedCache()) { 675 return; } 677 678 valueOfSource = getRealCollectionAttributeValueFromObject(source, mergeManager.getSession()); 680 Object iterator = containerPolicy.iteratorFor(valueOfSource); 681 valueOfTarget = containerPolicy.containerInstance(containerPolicy.sizeFor(valueOfSource)); 682 683 while (containerPolicy.hasNext(iterator)) { 684 Object objectToMerge = containerPolicy.next(iterator, mergeManager.getSession()); 686 687 ObjectChangeSet changeSet = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(objectToMerge); 688 if (shouldMergeCascadeParts(mergeManager) && (valueOfSource != null)) { 689 mergeManager.mergeChanges(objectToMerge, changeSet); 690 } 691 692 containerPolicy.addInto(mergeManager.getTargetVersionOfSourceObject(objectToMerge), valueOfTarget, mergeManager.getSession()); 695 } 696 } 697 698 if (valueOfTarget == null) { 699 valueOfTarget = containerPolicy.containerInstance(); 700 } 701 702 setRealAttributeValueInObject(target, valueOfTarget); 703 } 704 705 710 public void mergeIntoObject(Object target, boolean isTargetUnInitialized, Object source, MergeManager mergeManager) { 711 if (isTargetUnInitialized) { 712 if (mergeManager.shouldMergeWorkingCopyIntoOriginal() && (!isAttributeValueInstantiated(source))) { 714 setAttributeValueInObject(target, getIndirectionPolicy().getOriginalIndirectionObject(getAttributeValueFromObject(source), mergeManager.getSession())); 715 return; 716 } 717 } 718 if (!shouldMergeCascadeReference(mergeManager)) { 719 return; 721 } 722 if (mergeManager.shouldMergeOriginalIntoWorkingCopy()) { 723 if (!isAttributeValueInstantiated(target)) { 724 return; 727 } 728 } else if (!isAttributeValueInstantiated(source)) { 729 return; 732 } 733 734 Object valueOfSource = getRealCollectionAttributeValueFromObject(source, mergeManager.getSession()); 735 736 AbstractSession mergeSession = mergeManager.getSession(); 740 Object valueOfTarget = getRealCollectionAttributeValueFromObject(target, mergeSession); 741 ContainerPolicy containerPolicy = getContainerPolicy(); 742 boolean fireChangeEvents = false; 743 if (! mergeManager.shouldMergeOriginalIntoWorkingCopy()){ 744 Object newContainer = containerPolicy.containerInstance(containerPolicy.sizeFor(valueOfSource)); 748 valueOfTarget = newContainer; 749 }else{ 750 setRealAttributeValueInObject(target, containerPolicy.containerInstance(containerPolicy.sizeFor(valueOfSource))); 753 containerPolicy.clear(valueOfTarget); 754 } 755 756 synchronized(valueOfSource){ 757 Object sourceIterator = containerPolicy.iteratorFor(valueOfSource); 758 while (containerPolicy.hasNext(sourceIterator)) { 759 Object object = containerPolicy.next(sourceIterator, mergeManager.getSession()); 760 if (object == null){ 761 continue; } 763 if (shouldMergeCascadeParts(mergeManager)) { 764 if ((mergeManager.getSession().isUnitOfWork()) && (((UnitOfWorkImpl)mergeManager.getSession()).getUnitOfWorkChangeSet() != null)) { 765 mergeManager.mergeChanges(mergeManager.getObjectToMerge(object), (ObjectChangeSet)((UnitOfWorkImpl)mergeManager.getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object)); 767 } else { 768 mergeManager.mergeChanges(mergeManager.getObjectToMerge(object), null); 769 } 770 } 771 object = getReferenceDescriptor().getObjectBuilder().wrapObject(mergeManager.getTargetVersionOfSourceObject(object), mergeManager.getSession()); 772 synchronized (valueOfTarget){ 773 containerPolicy.addInto(object, valueOfTarget, mergeManager.getSession()); 774 } 775 } 776 } 777 setRealAttributeValueInObject(target, valueOfTarget); 779 } 780 781 785 protected void objectAddedDuringUpdate(ObjectLevelModifyQuery query, Object objectAdded, ObjectChangeSet changeSet) throws DatabaseException, OptimisticLockException { 786 if (!shouldObjectModifyCascadeToParts(query)) { return; 788 } 789 790 if (query.shouldCascadeOnlyDependentParts()) { 792 return; 793 } 794 795 if (isPrivateOwned()) { 798 InsertObjectQuery insertQuery = new InsertObjectQuery(); 799 insertQuery.setObject(objectAdded); 800 insertQuery.setCascadePolicy(query.getCascadePolicy()); 801 query.getSession().executeQuery(insertQuery); 802 } else { 803 UnitOfWorkChangeSet uowChangeSet = null; 805 if ((changeSet == null) && query.getSession().isUnitOfWork() && (((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet() != null)) { 806 uowChangeSet = (UnitOfWorkChangeSet)((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet(); 807 changeSet = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(query.getObject()); 808 } 809 WriteObjectQuery writeQuery = new WriteObjectQuery(); 810 writeQuery.setObject(objectAdded); 811 writeQuery.setObjectChangeSet(changeSet); 812 writeQuery.setCascadePolicy(query.getCascadePolicy()); 813 query.getSession().executeQuery(writeQuery); 814 } 815 } 816 817 821 protected void objectRemovedDuringUpdate(ObjectLevelModifyQuery query, Object objectDeleted) throws DatabaseException, OptimisticLockException { 822 if (isPrivateOwned()) { if (query.shouldCascadeOnlyDependentParts()) { 824 if (query.getSession().isUnitOfWork()) { 826 if (!(((UnitOfWorkImpl)query.getSession()).getDeletedObjects().containsKey(objectDeleted))) { 828 query.getSession().getCommitManager().addObjectToDelete(objectDeleted); 829 } 830 } else { 831 query.getSession().getCommitManager().addObjectToDelete(objectDeleted); 832 } 833 } else { 834 query.getSession().deleteObject(objectDeleted); 835 } 836 } 837 } 838 839 843 protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object) throws DatabaseException, OptimisticLockException { 844 if (!shouldObjectModifyCascadeToParts(query)) { return; 846 } 847 848 if (query.shouldCascadeOnlyDependentParts()) { 850 return; 851 } 852 853 WriteObjectQuery writeQuery = new WriteObjectQuery(); 855 writeQuery.setObject(object); 856 writeQuery.setCascadePolicy(query.getCascadePolicy()); 857 query.getSession().executeQuery(writeQuery); 858 } 859 860 864 protected void prepareTranslationRow(AbstractRecord translationRow, Object object, AbstractSession session) { 865 } 867 868 872 protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Hashtable backupclones, CacheKey keys) throws DatabaseException, OptimisticLockException { 873 objectUnchangedDuringUpdate(query, object); 874 } 875 876 880 protected Object readPrivateOwnedForObject(ObjectLevelModifyQuery modifyQuery) throws DatabaseException { 881 if (modifyQuery.getSession().isUnitOfWork()) { 882 return getRealCollectionAttributeValueFromObject(modifyQuery.getBackupClone(), modifyQuery.getSession()); 883 } else { 884 prepareTranslationRow(modifyQuery.getTranslationRow(), modifyQuery.getObject(), modifyQuery.getSession()); 886 return modifyQuery.getSession().executeQuery(getSelectionQuery(), modifyQuery.getTranslationRow()); 887 } 888 } 889 890 895 public void setContainerPolicy(ContainerPolicy containerPolicy) { 896 this.containerPolicy = containerPolicy; 897 ((ReadAllQuery)getSelectionQuery()).setContainerPolicy(containerPolicy); 898 } 899 900 906 public void setCustomDeleteAllQuery(ModifyQuery query) { 907 setDeleteAllQuery(query); 908 setHasCustomDeleteAllQuery(true); 909 } 910 911 protected void setDeleteAllQuery(ModifyQuery query) { 912 deleteAllQuery = query; 913 } 914 915 925 public void setDeleteAllSQLString(String sqlString) { 926 DataModifyQuery query = new DataModifyQuery(); 927 query.setSQLString(sqlString); 928 setCustomDeleteAllQuery(query); 929 } 930 931 940 public void setDeleteAllCall(Call call) { 941 DataModifyQuery query = new DataModifyQuery(); 942 query.setCall(call); 943 setCustomDeleteAllQuery(query); 944 } 945 946 protected void setHasCustomDeleteAllQuery(boolean bool) { 947 hasCustomDeleteAllQuery = bool; 948 } 949 950 956 public void setSessionName(String name) { 957 getDeleteAllQuery().setSessionName(name); 958 getSelectionQuery().setSessionName(name); 959 } 960 961 967 public void simpleAddToCollectionChangeRecord(Object referenceKey, Object changeSetToAdd, ObjectChangeSet changeSet, AbstractSession session) { 968 CollectionChangeRecord collectionChangeRecord = (CollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName()); 969 if (collectionChangeRecord == null) { 970 collectionChangeRecord = new CollectionChangeRecord(changeSet); 971 collectionChangeRecord.setAttribute(getAttributeName()); 972 collectionChangeRecord.setMapping(this); 973 collectionChangeRecord.getAddObjectList().put(changeSetToAdd, changeSetToAdd); 974 collectionChangeRecord.getOrderedAddObjects().add(changeSetToAdd); 975 changeSet.addChange(collectionChangeRecord); 976 } else { 977 getContainerPolicy().recordAddToCollectionInChangeRecord((ObjectChangeSet)changeSetToAdd, collectionChangeRecord); 978 } 979 if (referenceKey != null){ 980 ((ObjectChangeSet)changeSetToAdd).setNewKey(referenceKey); 981 } 982 } 983 984 990 public void simpleRemoveFromCollectionChangeRecord(Object referenceKey, Object changeSetToRemove, ObjectChangeSet changeSet, AbstractSession session) { 991 CollectionChangeRecord collectionChangeRecord = (CollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName()); 992 if (collectionChangeRecord == null) { 993 collectionChangeRecord = new CollectionChangeRecord(changeSet); 994 collectionChangeRecord.setAttribute(getAttributeName()); 995 collectionChangeRecord.setMapping(this); 996 collectionChangeRecord.getRemoveObjectList().put(changeSetToRemove, changeSetToRemove); 997 changeSet.addChange(collectionChangeRecord); 998 } else { 999 getContainerPolicy().recordRemoveFromCollectionInChangeRecord((ObjectChangeSet)changeSetToRemove, collectionChangeRecord); 1000 } 1001 if (referenceKey != null){ 1002 ((ObjectChangeSet)changeSetToRemove).setOldKey(referenceKey); 1003 } 1004 } 1005 1006 1016 public void updateChangeRecord(Object clone, Object newValue, Object oldValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) { 1017 CollectionChangeRecord collectionChangeRecord = (CollectionChangeRecord)objectChangeSet.getChangesForAttributeNamed(this.getAttributeName()); 1018 if (collectionChangeRecord == null) { 1019 collectionChangeRecord = new CollectionChangeRecord(objectChangeSet); 1020 collectionChangeRecord.setAttribute(getAttributeName()); 1021 collectionChangeRecord.setMapping(this); 1022 objectChangeSet.addChange(collectionChangeRecord); 1023 } 1024 if (collectionChangeRecord.getOriginalCollection() == null){ 1025 collectionChangeRecord.setOriginalCollection(oldValue); 1026 } 1027 collectionChangeRecord.setLatestCollection(newValue); 1028 1029 objectChangeSet.deferredDetectionRequiredOn(getAttributeName()); 1030 } 1031 1032 1039 public void useCollectionClass(Class concreteClass) { 1040 ContainerPolicy policy = ContainerPolicy.buildPolicyFor(concreteClass, hasOrderBy()); 1041 setContainerPolicy(policy); 1042 } 1043 1044 1051 public void useSortedSetClass(Class concreteClass, Comparator comparator) { 1052 try { 1053 SortedCollectionContainerPolicy policy = (SortedCollectionContainerPolicy)ContainerPolicy.buildPolicyFor(concreteClass); 1054 policy.setComparator(comparator); 1055 setContainerPolicy(policy); 1056 } catch (ClassCastException e) { 1057 useCollectionClass(concreteClass); 1058 } 1059 } 1060 1061 1075 public void useMapClass(Class concreteClass, String keyName) { 1076 if (getReferenceClassName() == null) { 1078 throw DescriptorException.referenceClassNotSpecified(this); 1079 } 1080 1081 ContainerPolicy policy = ContainerPolicy.buildPolicyFor(concreteClass); 1082 policy.setKeyName(keyName, getReferenceClassName()); 1083 setContainerPolicy(policy); 1084 } 1085 1086 1096 public void useMapClass(Class concreteClass) { 1097 useMapClass(concreteClass, null); 1098 } 1099 1100 1111 public void useTransparentCollection() { 1112 setIndirectionPolicy(new TransparentIndirectionPolicy()); 1113 useCollectionClass(ClassConstants.IndirectList_Class); 1114 } 1115 1116 1127 public void useTransparentSet() { 1128 setIndirectionPolicy(new TransparentIndirectionPolicy()); 1129 useCollectionClass(IndirectSet.class); 1130 } 1131 1132 1143 public void useTransparentList() { 1144 setIndirectionPolicy(new TransparentIndirectionPolicy()); 1145 useCollectionClass(ClassConstants.IndirectList_Class); 1146 } 1147 1148 1162 public void useTransparentMap(String methodName) { 1163 setIndirectionPolicy(new TransparentIndirectionPolicy()); 1164 useMapClass(ClassConstants.IndirectMap_Class, methodName); 1165 } 1166 1167 1171 public void validateBeforeInitialization(AbstractSession session) throws DescriptorException { 1172 super.validateBeforeInitialization(session); 1173 1174 getIndirectionPolicy().validateContainerPolicy(session.getIntegrityChecker()); 1175 1176 if (getAttributeAccessor() instanceof InstanceVariableAttributeAccessor) { 1177 Class attributeType = ((InstanceVariableAttributeAccessor)getAttributeAccessor()).getAttributeType(); 1178 getIndirectionPolicy().validateDeclaredAttributeTypeForCollection(attributeType, session.getIntegrityChecker()); 1179 } else if (getAttributeAccessor() instanceof MethodAttributeAccessor) { 1180 Class returnType = ((MethodAttributeAccessor)getAttributeAccessor()).getGetMethodReturnType(); 1181 getIndirectionPolicy().validateGetMethodReturnTypeForCollection(returnType, session.getIntegrityChecker()); 1182 1183 Class parameterType = ((MethodAttributeAccessor)getAttributeAccessor()).getSetMethodParameterType(); 1184 getIndirectionPolicy().validateSetMethodParameterTypeForCollection(parameterType, session.getIntegrityChecker()); 1185 } 1186 } 1187 1188 1192 public boolean verifyDelete(Object object, AbstractSession session) throws DatabaseException { 1193 if (isReadOnly()) { 1195 return true; 1196 } 1197 1198 if (isPrivateOwned()) { 1199 Object objects = getRealCollectionAttributeValueFromObject(object, session); 1200 1201 ContainerPolicy containerPolicy = getContainerPolicy(); 1202 for (Object iter = containerPolicy.iteratorFor(objects); containerPolicy.hasNext(iter);) { 1203 if (!session.verifyDelete(containerPolicy.next(iter, session))) { 1204 return false; 1205 } 1206 } 1207 } 1208 1209 AbstractRecord row = getDescriptor().getObjectBuilder().buildRowForTranslation(object, session); 1210 1211 prepareTranslationRow(row, object, session); 1214 Object value = session.executeQuery(getSelectionQuery(), row); 1215 1216 return getContainerPolicy().isEmpty(value); 1217 } 1218 1219 1224 public void addToCollectionChangeRecord(Object newKey, Object newValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) { 1225 if (newValue != null) { 1226 ClassDescriptor descriptor; 1227 if (!getReferenceDescriptor().hasInheritance()) { 1229 descriptor = getReferenceDescriptor(); 1230 } else { 1231 descriptor = uow.getDescriptor(newValue); 1232 } 1233 newValue = descriptor.getObjectBuilder().unwrapObject(newValue, uow); 1234 ObjectChangeSet newSet = descriptor.getObjectBuilder().createObjectChangeSet(newValue, (UnitOfWorkChangeSet)objectChangeSet.getUOWChangeSet(), uow); 1235 simpleAddToCollectionChangeRecord(newKey, newSet, objectChangeSet, uow); 1236 } 1237 } 1238 1239 1243 public boolean isChangeTrackingSupported() { 1244 return true; 1245 } 1246 1247 1252 public void removeFromCollectionChangeRecord(Object newKey, Object newValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) { 1253 if (newValue != null) { 1254 ClassDescriptor descriptor; 1255 1256 if (!getReferenceDescriptor().hasInheritance()) { 1258 descriptor = getReferenceDescriptor(); 1259 } else { 1260 descriptor = uow.getDescriptor(newValue); 1261 } 1262 newValue = descriptor.getObjectBuilder().unwrapObject(newValue, uow); 1263 ObjectChangeSet newSet = descriptor.getObjectBuilder().createObjectChangeSet(newValue, (UnitOfWorkChangeSet)objectChangeSet.getUOWChangeSet(), uow); 1264 simpleRemoveFromCollectionChangeRecord(newKey, newSet, objectChangeSet, uow); 1265 } 1266 } 1267 1268 1272 public ChangeRecord buildChangeRecord(Object clone, ObjectChangeSet owner, AbstractSession session) { 1273 Object cloneAttribute = null; 1274 cloneAttribute = getAttributeValueFromObject(clone); 1275 if ((cloneAttribute != null) && (!getIndirectionPolicy().objectIsInstantiated(cloneAttribute))) { 1276 return null; 1277 } 1278 1279 IdentityHashMap cloneKeyValues = new IdentityHashMap(); 1281 ContainerPolicy cp = getContainerPolicy(); 1282 Object cloneObjectCollection = null; 1283 if (cloneAttribute != null) { 1284 cloneObjectCollection = getRealCollectionAttributeValueFromObject(clone, session); 1285 } else { 1286 cloneObjectCollection = cp.containerInstance(1); 1287 } 1288 Object cloneIter = cp.iteratorFor(cloneObjectCollection); 1289 1290 while (cp.hasNext(cloneIter)) { 1291 Object firstObject = cp.next(cloneIter, session); 1292 if (firstObject != null) { 1293 cloneKeyValues.put(firstObject, firstObject); 1294 } 1295 } 1296 1297 CollectionChangeRecord changeRecord = new CollectionChangeRecord(owner); 1298 changeRecord.setAttribute(getAttributeName()); 1299 changeRecord.setMapping(this); 1300 changeRecord.addAdditionChange(cloneKeyValues, (UnitOfWorkChangeSet)owner.getUOWChangeSet(), session); 1301 if (changeRecord.hasChanges()) { 1302 return changeRecord; 1303 } 1304 return null; 1305 } 1306 1307 1312 protected boolean shouldUseValueFromRowWithJoin(JoinedAttributeManager joinManager) { 1313 return joinManager.getDataResults_()!=null && super.shouldUseValueFromRowWithJoin(joinManager); 1314 } 1315 1316 1322 protected Object valueFromRowInternalWithJoin(AbstractRecord row, JoinedAttributeManager joinManager, AbstractSession executionSession) throws DatabaseException { 1323 List rows = joinManager.getDataResults_(); 1325 Object value = getContainerPolicy().containerInstance(); 1326 1327 ObjectLevelReadQuery nestedQuery = null; 1330 if (joinManager.getJoinedMappingQueries_() != null) { 1331 nestedQuery = (ObjectLevelReadQuery) joinManager.getJoinedMappingQueries_().get(this); 1332 } else { 1333 nestedQuery = prepareNestedJoins(joinManager, executionSession); 1334 } 1335 nestedQuery.setSession(executionSession); 1336 nestedQuery.setQueryId(joinManager.getBaseQuery().getQueryId()); 1338 1339 Vector sourceKey = getDescriptor().getObjectBuilder().extractPrimaryKeyFromRow(row, executionSession); 1341 CacheKey sourceCacheKey = new CacheKey(sourceKey); 1342 1343 Set targetCacheKeys = new HashSet(); 1345 1346 for (int index = 0; index < rows.size(); index++) { 1348 AbstractRecord sourceRow = (AbstractRecord)rows.get(index); 1349 AbstractRecord targetRow = sourceRow; 1350 1351 if (targetRow != null) { 1353 targetRow = trimRowForJoin(targetRow, joinManager, executionSession); 1357 AbstractRecord pkRow = trimRowForJoin(sourceRow, new Integer (joinManager.getParentResultIndex()), executionSession); 1358 nestedQuery.setTranslationRow(targetRow); 1359 1360 Vector rowSourceKey = getDescriptor().getObjectBuilder().extractPrimaryKeyFromRow(pkRow, executionSession); 1362 if(rowSourceKey != null) { 1363 CacheKey rowSourceCacheKey = new CacheKey(rowSourceKey); 1364 1365 if (sourceCacheKey.equals(rowSourceCacheKey)) { 1367 Vector targetKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromRow(targetRow, executionSession); 1370 if (targetKey == null) { 1371 return getIndirectionPolicy().valueFromRow(value); 1373 } 1374 CacheKey targetCacheKey = new CacheKey(targetKey); 1375 1376 if (!targetCacheKeys.contains(targetCacheKey)) { 1378 targetCacheKeys.add(targetCacheKey); 1379 Object targetObject = getReferenceDescriptor().getObjectBuilder().buildObject(nestedQuery, targetRow, nestedQuery.getJoinedAttributeManager()); 1380 nestedQuery.setTranslationRow(null); 1381 getContainerPolicy().addInto(targetObject, value, executionSession); 1382 } 1383 } 1384 } else { 1385 rows.set(index, null); 1387 } 1388 } 1389 } 1390 return getIndirectionPolicy().valueFromRow(value); 1391 } 1392} 1393 | Popular Tags |