1 21 package oracle.toplink.essentials.mappings; 23 24 import java.util.*; 25 import oracle.toplink.essentials.exceptions.*; 26 import oracle.toplink.essentials.expressions.*; 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.queryframework.*; 31 import oracle.toplink.essentials.internal.sessions.*; 32 import oracle.toplink.essentials.sessions.DatabaseRecord; 33 import oracle.toplink.essentials.descriptors.DescriptorEvent; 34 import oracle.toplink.essentials.descriptors.DescriptorEventManager; 35 import oracle.toplink.essentials.queryframework.*; 36 import oracle.toplink.essentials.indirection.ValueHolderInterface; 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 52 public class AggregateCollectionMapping extends CollectionMapping implements RelationalMapping { 53 54 55 protected transient Vector targetForeignKeyFields; 56 57 58 protected transient Vector sourceKeyFields; 59 60 61 protected transient Map targetForeignKeyToSourceKeys; 62 63 67 public AggregateCollectionMapping() { 68 this.targetForeignKeyToSourceKeys = new HashMap(5); 69 this.sourceKeyFields = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(1); 70 this.targetForeignKeyFields = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(1); 71 this.deleteAllQuery = new DeleteAllQuery(); 72 this.setCascadeAll(true); 74 } 75 76 79 public boolean isRelationalMapping() { 80 return true; 81 } 82 83 88 public void addTargetForeignKeyFieldName(String targetForeignKey, String sourceKey) { 89 getTargetForeignKeyFields().addElement(new DatabaseField(targetForeignKey)); 90 getSourceKeyFields().addElement(new DatabaseField(sourceKey)); 91 } 92 93 97 public Object buildBackupCloneForPartObject(Object attributeValue, Object clone, Object backup, UnitOfWorkImpl unitOfWork) { 98 ContainerPolicy containerPolicy = getContainerPolicy(); 99 if (attributeValue == null) { 100 return containerPolicy.containerInstance(1); 101 } 102 103 Object clonedAttributeValue = containerPolicy.containerInstance(containerPolicy.sizeFor(attributeValue)); 104 synchronized (attributeValue) { 105 for (Object valuesIterator = containerPolicy.iteratorFor(attributeValue); 106 containerPolicy.hasNext(valuesIterator);) { 107 Object cloneValue = buildElementBackupClone(containerPolicy.next(valuesIterator, unitOfWork), unitOfWork); 108 containerPolicy.addInto(cloneValue, clonedAttributeValue, unitOfWork); 109 } 110 } 111 return clonedAttributeValue; 112 } 113 114 121 public Object buildCloneForPartObject(Object attributeValue, Object original, Object clone, UnitOfWorkImpl unitOfWork, boolean isExisting) { 122 ContainerPolicy containerPolicy = getContainerPolicy(); 123 if (attributeValue == null) { 124 return containerPolicy.containerInstance(1); 125 } 126 Object clonedAttributeValue = containerPolicy.containerInstance(containerPolicy.sizeFor(attributeValue)); 127 128 Object temporaryCollection = null; 133 synchronized (attributeValue) { 134 temporaryCollection = containerPolicy.cloneFor(attributeValue); 135 } 136 for (Object valuesIterator = containerPolicy.iteratorFor(temporaryCollection); 137 containerPolicy.hasNext(valuesIterator);) { 138 Object originalElement = containerPolicy.next(valuesIterator, unitOfWork); 139 140 if (unitOfWork.isOriginalNewObject(original)) { 142 unitOfWork.addNewAggregate(originalElement); 143 } 144 Object cloneValue = buildElementClone(originalElement, unitOfWork, isExisting); 145 containerPolicy.addInto(cloneValue, clonedAttributeValue, unitOfWork); 146 } 147 return clonedAttributeValue; 148 } 149 150 154 protected Object buildElementBackupClone(Object element, UnitOfWorkImpl unitOfWork) { 155 if (unitOfWork.isClassReadOnly(element.getClass())) { 157 return element; 158 } 159 160 ClassDescriptor aggregateDescriptor = getReferenceDescriptor(element.getClass(), unitOfWork); 161 Object clonedElement = aggregateDescriptor.getObjectBuilder().buildBackupClone(element, unitOfWork); 162 163 return clonedElement; 164 } 165 166 170 protected Object buildElementClone(Object element, UnitOfWorkImpl unitOfWork, boolean isExisting) { 171 if (unitOfWork.isClassReadOnly(element.getClass())) { 173 return element; 174 } 175 176 ClassDescriptor aggregateDescriptor = getReferenceDescriptor(element.getClass(), unitOfWork); 177 178 Object clonedElement = aggregateDescriptor.getObjectBuilder().instantiateWorkingCopyClone(element, unitOfWork); 180 aggregateDescriptor.getObjectBuilder().populateAttributesForClone(element, clonedElement, unitOfWork, null); 181 unitOfWork.getCloneToOriginals().put(clonedElement, element); 184 return clonedElement; 185 } 186 187 191 public void cascadeRegisterNewIfRequired(Object object, UnitOfWorkImpl uow, IdentityHashtable visitedObjects){ 192 Object cloneAttribute = null; 194 cloneAttribute = getAttributeValueFromObject(object); 195 if ((cloneAttribute == null) || (!getIndirectionPolicy().objectIsInstantiated(cloneAttribute))) { 196 return; 197 } 198 199 ObjectBuilder builder = null; 200 ContainerPolicy cp = getContainerPolicy(); 201 Object cloneObjectCollection = null; 202 cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow); 203 Object cloneIter = cp.iteratorFor(cloneObjectCollection); 204 while (cp.hasNext(cloneIter)) { 205 Object nextObject = cp.next(cloneIter, uow); 206 if (nextObject != null && (! visitedObjects.contains(nextObject))){ 207 visitedObjects.put(nextObject, nextObject); 208 builder = getReferenceDescriptor(nextObject.getClass(), uow).getObjectBuilder(); 209 builder.cascadeRegisterNewForCreate(nextObject, uow, visitedObjects); 210 } 211 } 212 } 213 214 218 public void cascadePerformRemoveIfRequired(Object object, UnitOfWorkImpl uow, IdentityHashtable visitedObjects){ 219 Object cloneAttribute = null; 221 cloneAttribute = getAttributeValueFromObject(object); 222 if ((cloneAttribute == null)) { 223 return; 224 } 225 226 ObjectBuilder builder = null; 227 ContainerPolicy cp = getContainerPolicy(); 228 Object cloneObjectCollection = null; 229 cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow); 230 Object cloneIter = cp.iteratorFor(cloneObjectCollection); 231 while (cp.hasNext(cloneIter)) { 232 Object nextObject = cp.next(cloneIter, uow); 233 if (nextObject != null && ( ! visitedObjects.contains(nextObject) ) ){ 234 visitedObjects.put(nextObject, nextObject); 235 builder = getReferenceDescriptor(nextObject.getClass(), uow).getObjectBuilder(); 236 builder.cascadePerformRemove(nextObject, uow, visitedObjects); 237 } 238 } 239 } 240 241 245 public Object clone() { 246 AggregateCollectionMapping mappingObject = (AggregateCollectionMapping)super.clone(); 247 248 mappingObject.setTargetForeignKeyToSourceKeys(new HashMap(getTargetForeignKeyToSourceKeys())); 249 250 return mappingObject; 251 } 252 253 258 public ChangeRecord compareForChange(Object clone, Object backUp, ObjectChangeSet owner, AbstractSession session) { 259 Object cloneAttribute = null; 260 Object backUpAttribute = null; 261 262 cloneAttribute = getAttributeValueFromObject(clone); 263 264 if ((cloneAttribute != null) && (!getIndirectionPolicy().objectIsInstantiated(cloneAttribute))) { 265 return null; 267 } 268 if (!owner.isNew()) { 269 backUpAttribute = getAttributeValueFromObject(backUp); 270 if ((backUpAttribute == null) && (cloneAttribute == null)) { 271 return null; 272 } 273 ContainerPolicy cp = getContainerPolicy(); 274 Object backupCollection = null; 275 Object cloneCollection = null; 276 277 cloneCollection = getRealCollectionAttributeValueFromObject(clone, session); 278 backupCollection = getRealCollectionAttributeValueFromObject(backUp, session); 279 280 if (cp.sizeFor(backupCollection) != cp.sizeFor(cloneCollection)) { 281 return convertToChangeRecord(cloneCollection, owner, session); 282 } 283 Object cloneIterator = cp.iteratorFor(cloneCollection); 284 Object backUpIterator = cp.iteratorFor(backupCollection); 285 boolean change = false; 286 287 UnitOfWorkChangeSet uowComparisonChangeSet = new UnitOfWorkChangeSet(); 291 while (cp.hasNext(cloneIterator)) { 292 Object cloneObject = cp.next(cloneIterator, session); 293 294 if (cloneObject == null) { 296 change = true; 297 break; 298 } 299 Object backUpObject = null; 300 if (cp.hasNext(backUpIterator)) { 301 backUpObject = cp.next(backUpIterator, session); 302 } else { 303 change = true; 304 break; 305 } 306 if (cloneObject.getClass().equals(backUpObject.getClass())) { 307 ObjectBuilder builder = getReferenceDescriptor(cloneObject.getClass(), session).getObjectBuilder(); 308 ObjectChangeSet initialChanges = builder.createObjectChangeSet(cloneObject, uowComparisonChangeSet, owner.isNew(), session); 309 310 ObjectChangeSet changes = builder.compareForChange(cloneObject, backUpObject, uowComparisonChangeSet, session); 312 if (changes != null) { 313 change = true; 314 break; 315 } 316 } else { 317 change = true; 318 break; 319 } 320 } 321 if ((change == true) || (cp.hasNext(backUpIterator))) { 322 return convertToChangeRecord(cloneCollection, owner, session); 323 } else { 324 return null; 325 } 326 } 327 328 return convertToChangeRecord(getRealCollectionAttributeValueFromObject(clone, session), owner, session); 329 } 330 331 335 public boolean compareObjects(Object firstObject, Object secondObject, AbstractSession session) { 336 Object firstCollection = getRealCollectionAttributeValueFromObject(firstObject, session); 337 Object secondCollection = getRealCollectionAttributeValueFromObject(secondObject, session); 338 ContainerPolicy containerPolicy = getContainerPolicy(); 339 340 if (containerPolicy.sizeFor(firstCollection) != containerPolicy.sizeFor(secondCollection)) { 341 return false; 342 } 343 344 if (containerPolicy.sizeFor(firstCollection) == 0) { 345 return true; 346 } 347 348 for (Object iterFirst = containerPolicy.iteratorFor(firstCollection); 350 containerPolicy.hasNext(iterFirst);) { 351 Object firstAggregateObject = containerPolicy.next(iterFirst, session); 353 354 for (Object iterSecond = containerPolicy.iteratorFor(secondCollection); true;) { 356 Object secondAggregateObject = containerPolicy.next(iterSecond, session); 358 359 if (getReferenceDescriptor().getObjectBuilder().compareObjects(firstAggregateObject, secondAggregateObject, session)) { 361 break; 362 } 363 364 if (!containerPolicy.hasNext(iterSecond)) { 365 return false; 366 } 367 } 368 } 369 370 return true; 371 } 372 373 382 protected ChangeRecord convertToChangeRecord(Object cloneCollection, ObjectChangeSet owner, AbstractSession session) { 383 ContainerPolicy cp = getContainerPolicy(); 384 Object cloneIter = cp.iteratorFor(cloneCollection); 385 Vector collectionChanges = new Vector(2); 386 while (cp.hasNext(cloneIter)) { 387 Object aggregateObject = cp.next(cloneIter, session); 388 389 if (aggregateObject != null) { 391 ObjectChangeSet changes = getReferenceDescriptor(aggregateObject.getClass(), session).getObjectBuilder().compareForChange(aggregateObject, null, (UnitOfWorkChangeSet)owner.getUOWChangeSet(), session); 392 collectionChanges.addElement(changes); 393 } 394 } 395 396 AggregateCollectionChangeRecord changeRecord = new AggregateCollectionChangeRecord(owner); 398 changeRecord.setAttribute(getAttributeName()); 399 changeRecord.setMapping(this); 400 changeRecord.setChangedValues(collectionChanges); 401 return changeRecord; 402 } 403 404 408 protected void deleteAll(DeleteObjectQuery query) throws DatabaseException { 409 Object referenceObjects = null; 410 if(usesIndirection()) { 411 Object attribute = getAttributeAccessor().getAttributeValueFromObject(query.getObject()); 412 if(attribute == null || !((ValueHolderInterface)attribute).isInstantiated()) { 413 referenceObjects = new Vector(0); 415 } 416 } 417 if(referenceObjects == null) { 418 referenceObjects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession()); 419 } 420 ((DeleteAllQuery)getDeleteAllQuery()).executeDeleteAll(query.getSession().getSessionForClass(getReferenceClass()), query.getTranslationRow(), getContainerPolicy().vectorFor(referenceObjects, query.getSession())); 422 } 423 424 428 protected void executeEvent(int eventCode, ObjectLevelModifyQuery query) { 429 ClassDescriptor referenceDescriptor = getReferenceDescriptor(query.getObject().getClass(), query.getSession()); 430 431 if (referenceDescriptor.getEventManager().hasAnyEventListeners()) { 433 referenceDescriptor.getEventManager().executeEvent(new DescriptorEvent(eventCode, query)); 434 } 435 } 436 437 442 protected Vector extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) { 443 Vector key = new Vector(getTargetForeignKeyFields().size()); 444 445 for (int index = 0; index < getTargetForeignKeyFields().size(); index++) { 446 DatabaseField targetField = (DatabaseField)getTargetForeignKeyFields().elementAt(index); 447 DatabaseField sourceField = (DatabaseField)getSourceKeyFields().elementAt(index); 448 Object value = row.get(targetField); 449 450 try { 452 value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(sourceField)); 453 } catch (ConversionException e) { 454 throw ConversionException.couldNotBeConverted(this, getDescriptor(), e); 455 } 456 457 key.addElement(value); 458 } 459 460 return key; 461 } 462 463 468 protected Vector extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) { 469 Vector key = new Vector(getSourceKeyFields().size()); 470 471 for (Enumeration fieldEnum = getSourceKeyFields().elements(); fieldEnum.hasMoreElements();) { 472 DatabaseField field = (DatabaseField)fieldEnum.nextElement(); 473 Object value = row.get(field); 474 475 try { 477 value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field)); 478 } catch (ConversionException e) { 479 throw ConversionException.couldNotBeConverted(this, getDescriptor(), e); 480 } 481 482 key.addElement(value); 483 } 484 485 return key; 486 } 487 488 492 public AbstractRecord getAggregateRow(ObjectLevelModifyQuery query, Object object) { 493 Vector referenceObjectKeys = getReferenceObjectKeys(query); 494 AbstractRecord aggregateRow = new DatabaseRecord(); 495 Vector keys = getTargetForeignKeyFields(); 496 for (int keyIndex = 0; keyIndex < keys.size(); keyIndex++) { 497 aggregateRow.put(keys.elementAt(keyIndex), referenceObjectKeys.elementAt(keyIndex)); 498 } 499 getReferenceDescriptor(object.getClass(), query.getSession()).getObjectBuilder().buildRow(aggregateRow, object, query.getSession()); 500 501 return aggregateRow; 502 } 503 504 508 protected Expression getDeleteAllCriteria(AbstractSession session) { 509 Expression expression; 510 Expression criteria = null; 511 Expression builder = new ExpressionBuilder(); 512 513 for (Iterator keys = getTargetForeignKeyToSourceKeys().keySet().iterator(); keys.hasNext();) { 514 DatabaseField targetForeignKey = (DatabaseField)keys.next(); 515 DatabaseField sourceKey = (DatabaseField)getTargetForeignKeyToSourceKeys().get(targetForeignKey); 516 517 expression = builder.getField(targetForeignKey).equal(builder.getParameter(sourceKey)); 518 519 criteria = expression.and(criteria); 520 } 521 522 return criteria; 523 } 524 525 529 public ClassDescriptor getReferenceDescriptor(Class theClass, AbstractSession session) { 530 if (getReferenceDescriptor().getJavaClass().equals(theClass)) { 531 return getReferenceDescriptor(); 532 } else { 533 ClassDescriptor subclassDescriptor = session.getDescriptor(theClass); 534 if (subclassDescriptor == null) { 535 throw DescriptorException.noSubClassMatch(theClass, this); 536 } else { 537 return subclassDescriptor; 538 } 539 } 540 } 541 542 546 public Vector getReferenceObjectKeys(ObjectLevelModifyQuery query) throws DatabaseException, OptimisticLockException { 547 Vector referenceObjectKeys = new Vector(getSourceKeyFields().size()); 548 549 AbstractRecord translationRow = query.getTranslationRow(); 551 552 for (Enumeration sourcekeys = getSourceKeyFields().elements(); 553 sourcekeys.hasMoreElements();) { 554 DatabaseField sourceKey = (DatabaseField)sourcekeys.nextElement(); 555 556 Object referenceKey = null; 558 if ((translationRow != null) && (translationRow.containsKey(sourceKey))) { 559 referenceKey = translationRow.get(sourceKey); 560 } else { 561 referenceKey = getDescriptor().getObjectBuilder().extractValueFromObjectForField(query.getObject(), sourceKey, query.getSession()); 562 } 563 referenceObjectKeys.addElement(referenceKey); 564 } 565 566 return referenceObjectKeys; 567 } 568 569 574 public Vector getSourceKeyFieldNames() { 575 Vector fieldNames = new Vector(getSourceKeyFields().size()); 576 for (Enumeration fieldsEnum = getSourceKeyFields().elements(); 577 fieldsEnum.hasMoreElements();) { 578 fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName()); 579 } 580 581 return fieldNames; 582 } 583 584 588 public Vector getSourceKeyFields() { 589 return sourceKeyFields; 590 } 591 592 597 public Vector getTargetForeignKeyFieldNames() { 598 Vector fieldNames = new Vector(getTargetForeignKeyFields().size()); 599 for (Enumeration fieldsEnum = getTargetForeignKeyFields().elements(); 600 fieldsEnum.hasMoreElements();) { 601 fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName()); 602 } 603 604 return fieldNames; 605 } 606 607 611 public Vector getTargetForeignKeyFields() { 612 return targetForeignKeyFields; 613 } 614 615 618 public Map getTargetForeignKeyToSourceKeys() { 619 return targetForeignKeyToSourceKeys; 620 } 621 622 631 public void initialize(AbstractSession session) throws DescriptorException { 632 super.initialize(session); 633 634 if (!getReferenceDescriptor().isAggregateCollectionDescriptor()) { 635 session.getIntegrityChecker().handleError(DescriptorException.referenceDescriptorIsNotAggregateCollection(getReferenceClass().getName(), this)); 636 } 637 638 if (shouldInitializeSelectionCriteria()) { 639 if (isSourceKeySpecified()) { 640 initializeTargetForeignKeyToSourceKeys(session); 641 } else { 642 initializeTargetForeignKeyToSourceKeysWithDefaults(session); 643 } 644 645 initializeSelectionCriteria(session); 646 } 647 648 getSelectionQuery().setShouldMaintainCache(false); 650 651 initializeDeleteAllQuery(session); 652 } 653 654 663 public void initializeChildInheritance(ClassDescriptor parentDescriptor, AbstractSession session) throws DescriptorException { 664 if (parentDescriptor.getInheritancePolicy().hasChildren()) { 666 Vector childDescriptors = parentDescriptor.getInheritancePolicy().getChildDescriptors(); 668 Vector cloneChildDescriptors = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(); 669 for (Enumeration enumtr = childDescriptors.elements(); enumtr.hasMoreElements();) { 670 ClassDescriptor clonedChildDescriptor = (ClassDescriptor)((ClassDescriptor)enumtr.nextElement()).clone(); 671 672 if (!clonedChildDescriptor.isAggregateCollectionDescriptor()) { 673 session.getIntegrityChecker().handleError(DescriptorException.referenceDescriptorIsNotAggregate(clonedChildDescriptor.getJavaClass().getName(), this)); 674 } 675 676 clonedChildDescriptor.getInheritancePolicy().setParentDescriptor(parentDescriptor); 677 clonedChildDescriptor.preInitialize(session); 678 clonedChildDescriptor.initialize(session); 679 cloneChildDescriptors.addElement(clonedChildDescriptor); 680 initializeChildInheritance(clonedChildDescriptor, session); 681 } 682 parentDescriptor.getInheritancePolicy().setChildDescriptors(cloneChildDescriptors); 683 } 684 } 685 686 691 protected void initializeDeleteAllQuery(AbstractSession session) { 692 DeleteAllQuery query = (DeleteAllQuery)getDeleteAllQuery(); 693 query.setReferenceClass(getReferenceClass()); 694 query.setShouldMaintainCache(false); 695 if (!hasCustomDeleteAllQuery()) { 696 if (getSelectionCriteria() == null) { 697 query.setSelectionCriteria(getDeleteAllCriteria(session)); 698 } else { 699 query.setSelectionCriteria(getSelectionCriteria()); 700 } 701 } 702 } 703 704 713 public void initializeParentInheritance(ClassDescriptor parentDescriptor, ClassDescriptor childDescriptor, AbstractSession session) throws DescriptorException { 714 if (!parentDescriptor.isAggregateCollectionDescriptor()) { 715 session.getIntegrityChecker().handleError(DescriptorException.referenceDescriptorIsNotAggregateCollection(parentDescriptor.getJavaClass().getName(), this)); 716 } 717 718 ClassDescriptor clonedParentDescriptor = (ClassDescriptor)parentDescriptor.clone(); 719 720 if (clonedParentDescriptor.getInheritancePolicy().isChildDescriptor()) { 722 ClassDescriptor parentToParentDescriptor = session.getDescriptor(clonedParentDescriptor.getJavaClass()); 723 initializeParentInheritance(parentToParentDescriptor, parentDescriptor, session); 724 } 725 726 Vector childern = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(1); 727 childern.addElement(childDescriptor); 728 clonedParentDescriptor.getInheritancePolicy().setChildDescriptors(childern); 729 clonedParentDescriptor.preInitialize(session); 730 clonedParentDescriptor.initialize(session); 731 } 732 733 738 protected void initializeSelectionCriteria(AbstractSession session) { 739 Expression expression; 740 Expression criteria; 741 Expression builder = new ExpressionBuilder(); 742 743 for (Iterator keys = getTargetForeignKeyToSourceKeys().keySet().iterator(); keys.hasNext();) { 744 DatabaseField targetForeignKey = (DatabaseField)keys.next(); 745 DatabaseField sourceKey = (DatabaseField)getTargetForeignKeyToSourceKeys().get(targetForeignKey); 746 747 expression = builder.getField(targetForeignKey).equal(builder.getParameter(sourceKey)); 748 749 criteria = expression.and(getSelectionCriteria()); 750 setSelectionCriteria(criteria); 751 } 752 } 753 754 758 protected void initializeTargetForeignKeyToSourceKeys(AbstractSession session) throws DescriptorException { 759 if (getTargetForeignKeyFields().isEmpty()) { 760 throw DescriptorException.noTargetForeignKeysSpecified(this); 761 } 762 763 for (Enumeration keys = getTargetForeignKeyFields().elements(); keys.hasMoreElements();) { 764 DatabaseField foreignKeyfield = (DatabaseField)keys.nextElement(); 765 getReferenceDescriptor().buildField(foreignKeyfield); 766 } 767 768 for (Enumeration keys = getSourceKeyFields().elements(); keys.hasMoreElements();) { 769 DatabaseField sourceKeyfield = (DatabaseField)keys.nextElement(); 770 getDescriptor().buildField(sourceKeyfield); 771 } 772 773 if (getTargetForeignKeyFields().size() != getSourceKeyFields().size()) { 774 throw DescriptorException.targetForeignKeysSizeMismatch(this); 775 } 776 777 Enumeration targetForeignKeysEnum = getTargetForeignKeyFields().elements(); 778 Enumeration sourceKeysEnum = getSourceKeyFields().elements(); 779 for (; targetForeignKeysEnum.hasMoreElements();) { 780 getTargetForeignKeyToSourceKeys().put(targetForeignKeysEnum.nextElement(), sourceKeysEnum.nextElement()); 781 } 782 } 783 784 789 protected void initializeTargetForeignKeyToSourceKeysWithDefaults(AbstractSession session) throws DescriptorException { 790 if (getTargetForeignKeyFields().isEmpty()) { 791 throw DescriptorException.noTargetForeignKeysSpecified(this); 792 } 793 794 List sourceKeys = getDescriptor().getPrimaryKeyFields(); 795 setSourceKeyFields(oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(sourceKeys)); 796 for (Enumeration keys = getTargetForeignKeyFields().elements(); keys.hasMoreElements();) { 797 DatabaseField foreignKeyfield = ((DatabaseField)keys.nextElement()); 798 getReferenceDescriptor().buildField(foreignKeyfield); 799 } 800 801 if (getTargetForeignKeyFields().size() != sourceKeys.size()) { 802 throw DescriptorException.targetForeignKeysSizeMismatch(this); 803 } 804 805 for (int index = 0; index < getTargetForeignKeyFields().size(); index++) { 806 getTargetForeignKeyToSourceKeys().put(getTargetForeignKeyFields().get(index), sourceKeys.get(index)); 807 } 808 } 809 810 814 public void iterateOnElement(DescriptorIterator iterator, Object element) { 815 if (element != null) { 818 iterator.iterateForAggregateMapping(element, this, iterator.getSession().getDescriptor(element)); 819 } 820 } 821 822 825 public boolean isAggregateCollectionMapping() { 826 return true; 827 } 828 829 832 public boolean isPrivateOwned() { 833 return true; 834 } 835 836 839 protected boolean isSourceKeySpecified() { 840 return !(getSourceKeyFields().isEmpty()); 841 } 842 843 849 public void mergeChangesIntoObject(Object target, ChangeRecord changeRecord, Object source, MergeManager mergeManager) { 850 if (!isAttributeValueInstantiated(target)) { 852 return; 854 } 855 856 ContainerPolicy containerPolicy = getContainerPolicy(); 857 AbstractSession session = mergeManager.getSession(); 858 Object valueOfTarget = null; 859 860 Object sourceAggregate = null; 863 864 if (mergeManager.shouldMergeChangesIntoDistributedCache()) { 870 ClassDescriptor descriptor = getDescriptor(); 871 AbstractRecord parentRow = descriptor.getObjectBuilder().extractPrimaryKeyRowFromObject(target, session); 872 Object result = getIndirectionPolicy().valueFromQuery(getSelectionQuery(), parentRow, session); setAttributeValueInObject(target, result); 874 return; 875 } 876 877 Vector aggregateObjects = ((AggregateCollectionChangeRecord)changeRecord).getChangedValues(); 879 valueOfTarget = containerPolicy.containerInstance(); 880 ObjectChangeSet objectChanges = null; 882 for (int i = 0; i < aggregateObjects.size(); ++i) { 883 objectChanges = (ObjectChangeSet)aggregateObjects.elementAt(i); 884 Class localClassType = objectChanges.getClassType(session); 885 sourceAggregate = objectChanges.getUnitOfWorkClone(); 886 887 Object targetAggregate = ((UnitOfWorkImpl)mergeManager.getSession()).getCloneToOriginals().get(sourceAggregate); 890 891 if (targetAggregate == null) { 892 targetAggregate = getReferenceDescriptor(localClassType, session).getObjectBuilder().buildNewInstance(); 893 } 894 getReferenceDescriptor(localClassType, session).getObjectBuilder().mergeChangesIntoObject(targetAggregate, objectChanges, sourceAggregate, mergeManager); 895 containerPolicy.addInto(targetAggregate, valueOfTarget, session); 896 } 897 setRealAttributeValueInObject(target, valueOfTarget); 898 } 899 900 904 public void mergeIntoObject(Object target, boolean isTargetUnInitialized, Object source, MergeManager mergeManager) { 905 if (isTargetUnInitialized) { 906 if (mergeManager.shouldMergeWorkingCopyIntoOriginal() && (!isAttributeValueInstantiated(source))) { 908 setAttributeValueInObject(target, getIndirectionPolicy().getOriginalIndirectionObject(getAttributeValueFromObject(source), mergeManager.getSession())); 909 return; 910 } 911 } 912 if (!shouldMergeCascadeReference(mergeManager)) { 913 return; 915 } 916 if (mergeManager.shouldMergeOriginalIntoWorkingCopy()) { 917 if (!isAttributeValueInstantiated(target)) { 918 return; 921 } 922 } else if (!isAttributeValueInstantiated(source)) { 923 return; 926 } 927 928 ContainerPolicy containerPolicy = getContainerPolicy(); 929 Object valueOfSource = getRealCollectionAttributeValueFromObject(source, mergeManager.getSession()); 930 Object valueOfTarget = containerPolicy.containerInstance(containerPolicy.sizeFor(valueOfSource)); 931 for (Object sourceValuesIterator = containerPolicy.iteratorFor(valueOfSource); 932 containerPolicy.hasNext(sourceValuesIterator);) { 933 Object sourceValue = containerPolicy.next(sourceValuesIterator, mergeManager.getSession()); 934 935 Object originalValue = getReferenceDescriptor(sourceValue.getClass(), mergeManager.getSession()).getObjectBuilder().buildNewInstance(); 937 getReferenceDescriptor(sourceValue.getClass(), mergeManager.getSession()).getObjectBuilder().mergeIntoObject(originalValue, true, sourceValue, mergeManager); 938 containerPolicy.addInto(originalValue, valueOfTarget, mergeManager.getSession()); 939 } 940 941 setRealAttributeValueInObject(target, valueOfTarget); 943 } 944 945 949 protected void objectAddedDuringUpdate(ObjectLevelModifyQuery query, Object objectAdded, ObjectChangeSet changeSet) throws DatabaseException, OptimisticLockException { 950 InsertObjectQuery insertQuery = getAndPrepareModifyQueryForInsert(query, objectAdded); 952 query.getSession().executeQuery(insertQuery, insertQuery.getTranslationRow()); 953 } 954 955 959 protected void objectRemovedDuringUpdate(ObjectLevelModifyQuery query, Object objectDeleted) throws DatabaseException, OptimisticLockException { 960 DeleteObjectQuery deleteQuery = new DeleteObjectQuery(); 962 prepareModifyQueryForDelete(query, deleteQuery, objectDeleted); 963 query.getSession().executeQuery(deleteQuery, deleteQuery.getTranslationRow()); 964 } 965 966 970 protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Hashtable backupCloneKeyedCache, CacheKey cachedKey) throws DatabaseException, OptimisticLockException { 971 UpdateObjectQuery updateQuery = new UpdateObjectQuery(); 973 Object backupclone = backupCloneKeyedCache.get(cachedKey); 974 updateQuery.setBackupClone(backupclone); 975 prepareModifyQueryForUpdate(query, updateQuery, object); 976 query.getSession().executeQuery(updateQuery, updateQuery.getTranslationRow()); 977 } 978 979 988 public void postInitialize(AbstractSession session) throws DescriptorException { 989 super.postInitialize(session); 990 getReferenceDescriptor().postInitialize(session); 991 } 992 993 997 public void postInsert(WriteObjectQuery query) throws DatabaseException, OptimisticLockException { 998 if (isReadOnly()) { 999 return; 1000 } 1001 1002 Object objects = getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession()); 1003 1004 ContainerPolicy cp = getContainerPolicy(); 1006 for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) { 1007 Object object = cp.next(iter, query.getSession()); 1008 InsertObjectQuery insertQuery = getAndPrepareModifyQueryForInsert(query, object); 1009 query.getSession().executeQuery(insertQuery, insertQuery.getTranslationRow()); 1010 } 1011 } 1012 1013 1017 public void postUpdate(WriteObjectQuery writeQuery) throws DatabaseException, OptimisticLockException { 1018 if (isReadOnly()) { 1019 return; 1020 } 1021 1022 if (!isAttributeValueInstantiated(writeQuery.getObject())) { 1024 return; 1025 } 1026 1027 Object objects = getRealCollectionAttributeValueFromObject(writeQuery.getObject(), writeQuery.getSession()); 1029 Object currentObjectsInDB = readPrivateOwnedForObject(writeQuery); 1030 if (currentObjectsInDB == null) { 1031 currentObjectsInDB = getContainerPolicy().containerInstance(1); 1032 } 1033 compareObjectsAndWrite(currentObjectsInDB, objects, writeQuery); 1034 } 1035 1036 1040 public void preDelete(DeleteObjectQuery query) throws DatabaseException, OptimisticLockException { 1041 if (isReadOnly()) { 1042 return; 1043 } 1044 1045 if (getReferenceDescriptor().hasDependencyOnParts() || getReferenceDescriptor().usesOptimisticLocking() || (getReferenceDescriptor().hasInheritance() && getReferenceDescriptor().getInheritancePolicy().shouldReadSubclasses()) || getReferenceDescriptor().hasMultipleTables()) { 1048 Object objects = getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession()); 1049 ContainerPolicy containerPolicy = getContainerPolicy(); 1050 for (Object iter = containerPolicy.iteratorFor(objects); containerPolicy.hasNext(iter);) { 1051 Object object = containerPolicy.next(iter, query.getSession()); 1052 DeleteObjectQuery deleteQuery = new DeleteObjectQuery(); 1053 prepareModifyQueryForDelete(query, deleteQuery, object); 1054 query.getSession().executeQuery(deleteQuery, deleteQuery.getTranslationRow()); 1055 } 1056 if (!query.getSession().isUnitOfWork()) { 1057 verifyDeleteForUpdate(query); 1061 } 1062 } else { 1063 deleteAll(query); 1064 } 1065 } 1066 1067 1071 public void preInsert(WriteObjectQuery query) throws DatabaseException, OptimisticLockException { 1072 if (isReadOnly()) { 1073 return; 1074 } 1075 1076 Object objects = getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession()); 1077 1078 ContainerPolicy cp = getContainerPolicy(); 1080 for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) { 1081 Object object = cp.next(iter, query.getSession()); 1082 InsertObjectQuery insertQuery = getAndPrepareModifyQueryForInsert(query, object); 1083 1084 executeEvent(DescriptorEventManager.PreWriteEvent, insertQuery); 1086 executeEvent(DescriptorEventManager.PreInsertEvent, insertQuery); 1087 getReferenceDescriptor().getQueryManager().preInsert(insertQuery); 1088 } 1089 } 1090 1091 1095 protected InsertObjectQuery getInsertObjectQuery(AbstractSession session, ClassDescriptor desc) { 1096 InsertObjectQuery insertQuery = desc.getQueryManager().getInsertQuery(); 1097 if (insertQuery == null) { 1098 insertQuery = new InsertObjectQuery(); 1099 desc.getQueryManager().setInsertQuery(insertQuery); 1100 } 1101 if (insertQuery.getModifyRow() == null) { 1102 AbstractRecord modifyRow = new DatabaseRecord(); 1103 for (int i = 0; i < getTargetForeignKeyFields().size(); i++) { 1104 DatabaseField field = (DatabaseField)getTargetForeignKeyFields().elementAt(i); 1105 modifyRow.put(field, null); 1106 } 1107 desc.getObjectBuilder().buildTemplateInsertRow(session, modifyRow); 1108 insertQuery.setModifyRow(modifyRow); 1109 } 1110 return insertQuery; 1111 } 1112 1113 1117 public InsertObjectQuery getAndPrepareModifyQueryForInsert(ObjectLevelModifyQuery originalQuery, Object object) { 1118 AbstractSession session = originalQuery.getSession(); 1119 ClassDescriptor objReferenceDescriptor = getReferenceDescriptor(object.getClass(), session); 1120 InsertObjectQuery insertQueryFromDescriptor = getInsertObjectQuery(session, objReferenceDescriptor); 1121 insertQueryFromDescriptor.checkPrepare(session, insertQueryFromDescriptor.getModifyRow()); 1122 1123 InsertObjectQuery insertQuery = (InsertObjectQuery)insertQueryFromDescriptor.clone(); 1124 insertQuery.setObject(object); 1125 1126 AbstractRecord targetForeignKeyRow = new DatabaseRecord(); 1127 Vector referenceObjectKeys = getReferenceObjectKeys(originalQuery); 1128 for (int keyIndex = 0; keyIndex < getTargetForeignKeyFields().size(); keyIndex++) { 1129 targetForeignKeyRow.put(getTargetForeignKeyFields().elementAt(keyIndex), referenceObjectKeys.elementAt(keyIndex)); 1130 } 1131 1132 insertQuery.setModifyRow(targetForeignKeyRow); 1133 insertQuery.setTranslationRow(targetForeignKeyRow); 1134 insertQuery.setSession(session); 1135 insertQuery.setCascadePolicy(originalQuery.getCascadePolicy()); 1136 insertQuery.dontMaintainCache(); 1137 1138 if (session.isUnitOfWork()) { 1142 Object backupAttributeValue = getReferenceDescriptor(object.getClass(), session).getObjectBuilder().buildNewInstance(); 1143 insertQuery.setBackupClone(backupAttributeValue); 1144 } 1145 return insertQuery; 1146 } 1147 1148 1152 public void prepareModifyQueryForDelete(ObjectLevelModifyQuery originalQuery, ObjectLevelModifyQuery modifyQuery, Object object) { 1153 AbstractRecord aggregateRow = getAggregateRow(originalQuery, object); 1154 modifyQuery.setObject(object); 1155 modifyQuery.setPrimaryKey(getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromRow(aggregateRow, originalQuery.getSession())); 1156 modifyQuery.setModifyRow(aggregateRow); 1157 modifyQuery.setTranslationRow(aggregateRow); 1158 modifyQuery.setSession(originalQuery.getSession()); 1159 if (originalQuery.shouldCascadeOnlyDependentParts()) { 1160 modifyQuery.setCascadePolicy(DatabaseQuery.CascadeAggregateDelete); 1163 } else { 1164 modifyQuery.setCascadePolicy(originalQuery.getCascadePolicy()); 1165 } 1166 modifyQuery.dontMaintainCache(); 1167 } 1168 1169 1173 public void prepareModifyQueryForUpdate(ObjectLevelModifyQuery originalQuery, ObjectLevelModifyQuery modifyQuery, Object object) { 1174 AbstractRecord aggregateRow = getAggregateRow(originalQuery, object); 1175 modifyQuery.setObject(object); 1176 modifyQuery.setPrimaryKey(getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromRow(aggregateRow, originalQuery.getSession())); 1177 modifyQuery.setTranslationRow(aggregateRow); 1178 modifyQuery.setSession(originalQuery.getSession()); 1179 modifyQuery.setCascadePolicy(originalQuery.getCascadePolicy()); 1180 modifyQuery.dontMaintainCache(); 1181 } 1182 1183 1188 public void setSourceKeyFieldNames(Vector fieldNames) { 1189 Vector fields = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(fieldNames.size()); 1190 for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements();) { 1191 fields.addElement(new DatabaseField((String )fieldNamesEnum.nextElement())); 1192 } 1193 1194 setSourceKeyFields(fields); 1195 } 1196 1197 1201 public void setSourceKeyFields(Vector sourceKeyFields) { 1202 this.sourceKeyFields = sourceKeyFields; 1203 } 1204 1205 1210 public void setTargetForeignKeyFieldNames(Vector fieldNames) { 1211 Vector fields = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(fieldNames.size()); 1212 for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements();) { 1213 fields.addElement(new DatabaseField((String )fieldNamesEnum.nextElement())); 1214 } 1215 1216 setTargetForeignKeyFields(fields); 1217 } 1218 1219 1223 public void setTargetForeignKeyFields(Vector targetForeignKeyFields) { 1224 this.targetForeignKeyFields = targetForeignKeyFields; 1225 } 1226 1227 protected void setTargetForeignKeyToSourceKeys(Map targetForeignKeyToSourceKeys) { 1228 this.targetForeignKeyToSourceKeys = targetForeignKeyToSourceKeys; 1229 } 1230 1231 1235 protected boolean shouldObjectModifyCascadeToParts(ObjectLevelModifyQuery query) { 1236 if (isReadOnly()) { 1237 return false; 1238 } 1239 1240 return true; 1241 } 1242 1243 1249 public void simpleAddToCollectionChangeRecord(Object referenceKey, Object changeSetToAdd, ObjectChangeSet changeSet, AbstractSession session) { 1250 AggregateCollectionChangeRecord collectionChangeRecord = (AggregateCollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName()); 1251 if (collectionChangeRecord == null) { 1252 Object cloneObject = ((UnitOfWorkChangeSet)changeSet.getUOWChangeSet()).getUOWCloneForObjectChangeSet(changeSet); 1255 Object cloneCollection = this.getRealAttributeValueFromObject(cloneObject, session); 1256 collectionChangeRecord = (AggregateCollectionChangeRecord)convertToChangeRecord(cloneCollection, changeSet, session); 1257 changeSet.addChange(collectionChangeRecord); 1258 } else { 1259 collectionChangeRecord.getChangedValues().add(changeSetToAdd); 1260 } 1261 } 1262 1263 1269 public void simpleRemoveFromCollectionChangeRecord(Object referenceKey, Object changeSetToRemove, ObjectChangeSet changeSet, AbstractSession session) { 1270 AggregateCollectionChangeRecord collectionChangeRecord = (AggregateCollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName()); 1271 1272 if (collectionChangeRecord == null) { 1273 Object cloneObject = ((UnitOfWorkChangeSet)changeSet.getUOWChangeSet()).getUOWCloneForObjectChangeSet(changeSet); 1276 Object cloneCollection = this.getRealAttributeValueFromObject(cloneObject, session); 1277 collectionChangeRecord = (AggregateCollectionChangeRecord)convertToChangeRecord(cloneCollection, changeSet, session); 1278 changeSet.addChange(collectionChangeRecord); 1279 } else { 1280 collectionChangeRecord.getChangedValues().remove(changeSetToRemove); 1281 } 1282 } 1283 1284 1288 protected Object valueFromRowInternal(AbstractRecord row, JoinedAttributeManager joinManager, AbstractSession executionSession) throws DatabaseException { 1289 row = (AbstractRecord)row.clone(); 1298 int i = 0; 1299 for (Enumeration sourceKeys = getSourceKeyFields().elements(); 1300 sourceKeys.hasMoreElements(); i++) { 1301 DatabaseField sourceKey = (DatabaseField)sourceKeys.nextElement(); 1302 Object value = null; 1303 1304 int index = row.getFields().indexOf(sourceKey); 1307 if (index == -1) { 1308 value = joinManager.getBaseQuery().getTranslationRow().get(sourceKey); 1310 row.add(sourceKey, value); 1311 } else { 1312 value = row.getValues().elementAt(index); 1313 } 1314 1315 row.add((DatabaseField)getTargetForeignKeyFields().elementAt(i), value); 1318 } 1319 return super.valueFromRowInternal(row, joinManager, executionSession); 1320 } 1321 1322 1326 public boolean verifyDelete(Object object, AbstractSession session) throws DatabaseException { 1327 if (isReadOnly()) { 1329 return true; 1330 } 1331 1332 AbstractRecord row = getDescriptor().getObjectBuilder().buildRowForTranslation(object, session); 1333 Object value = session.executeQuery(getSelectionQuery(), row); 1334 1335 return getContainerPolicy().isEmpty(value); 1336 } 1337 1338 1343 protected void verifyDeleteForUpdate(DeleteObjectQuery query) throws DatabaseException, OptimisticLockException { 1344 Object objects = readPrivateOwnedForObject(query); 1345 1346 ContainerPolicy cp = getContainerPolicy(); 1348 for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) { 1349 query.getSession().deleteObject(cp.next(iter, query.getSession())); 1350 } 1351 } 1352 1353 1358 public void addToCollectionChangeRecord(Object newKey, Object newValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) throws DescriptorException { 1359 throw DescriptorException.invalidMappingOperation(this, "addToCollectionChangeRecord"); 1360 } 1361 1362 1366 public boolean isCascadedLockingSupported() { 1367 return true; 1368 } 1369 1370 1374 public boolean isChangeTrackingSupported() { 1375 return false; 1376 } 1377 1378 1383 public void removeFromCollectionChangeRecord(Object newKey, Object newValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) throws DescriptorException { 1384 throw DescriptorException.invalidMappingOperation(this, "removeFromCollectionChangeRecord"); 1385 } 1386} 1387 | Popular Tags |