Source Code Cross Referenced for AggregateMapping.java in  » Database-ORM » toplink » oracle » toplink » essentials » mappings » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » toplink » oracle.toplink.essentials.mappings 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         * 
0004:         * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
0005:         * 
0006:         *
0007:         * The contents of this file are subject to the terms of either the GNU
0008:         * General Public License Version 2 only ("GPL") or the Common Development
0009:         * and Distribution License("CDDL") (collectively, the "License").  You
0010:         * may not use this file except in compliance with the License. You can obtain
0011:         * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
0012:         * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
0013:         * language governing permissions and limitations under the License.
0014:         * 
0015:         * When distributing the software, include this License Header Notice in each
0016:         * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
0017:         * Sun designates this particular file as subject to the "Classpath" exception
0018:         * as provided by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code.  If applicable, add the following below the License
0020:         * Header, with the fields enclosed by brackets [] replaced by your own
0021:         * identifying information: "Portions Copyrighted [year]
0022:         * [name of copyright owner]"
0023:         * 
0024:         * Contributor(s):
0025:         * 
0026:         * If you wish your version of this file to be governed by only the CDDL or
0027:         * only the GPL Version 2, indicate your decision by adding "[Contributor]
0028:         * elects to include this software in this distribution under the [CDDL or GPL
0029:         * Version 2] license."  If you don't indicate a single choice of license, a
0030:         * recipient has the option to distribute your version of this file under
0031:         * either the CDDL, the GPL Version 2 or to extend the choice of license to
0032:         * its licensees as provided above.  However, if you add GPL Version 2 code
0033:         * and therefore, elected the GPL Version 2 license, then the option applies
0034:         * only if the new code is made subject to such option by the copyright
0035:         * holder.
0036:         */
0037:        package oracle.toplink.essentials.mappings;
0038:
0039:        import java.security.AccessController;
0040:        import java.security.PrivilegedActionException;
0041:        import java.util.*;
0042:        import oracle.toplink.essentials.exceptions.*;
0043:        import oracle.toplink.essentials.internal.descriptors.*;
0044:        import oracle.toplink.essentials.internal.security.PrivilegedAccessHelper;
0045:        import oracle.toplink.essentials.internal.security.PrivilegedClassForName;
0046:        import oracle.toplink.essentials.internal.sessions.*;
0047:        import oracle.toplink.essentials.queryframework.*;
0048:        import oracle.toplink.essentials.sessions.ObjectCopyingPolicy;
0049:        import oracle.toplink.essentials.descriptors.DescriptorEventManager;
0050:        import oracle.toplink.essentials.descriptors.DescriptorQueryManager;
0051:        import oracle.toplink.essentials.internal.sessions.AbstractRecord;
0052:        import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
0053:        import oracle.toplink.essentials.internal.sessions.AbstractSession;
0054:        import oracle.toplink.essentials.descriptors.ClassDescriptor;
0055:        import oracle.toplink.essentials.internal.queryframework.JoinedAttributeManager;
0056:
0057:        /**
0058:         * <b>Purpose</b>: Two objects can be considered to be related by aggregation if there is a strict
0059:         * 1:1 relationship between the objects. This means that if the source (parent)object exists, then
0060:         * the target (child or owned) object must exist. This class implements the behavior common to the
0061:         * aggregate object and structure mappings.
0062:         *
0063:         * @author Sati
0064:         * @since TopLink for Java 1.0
0065:         */
0066:        public abstract class AggregateMapping extends DatabaseMapping {
0067:
0068:            /** Stores a reference class */
0069:            protected Class referenceClass;
0070:            protected String referenceClassName;
0071:
0072:            /** The descriptor of the reference class */
0073:            protected ClassDescriptor referenceDescriptor;
0074:
0075:            /**
0076:             * Default constructor.
0077:             */
0078:            public AggregateMapping() {
0079:                super ();
0080:            }
0081:
0082:            /**
0083:             * Make a copy of the sourceQuery for the attribute.
0084:             */
0085:            protected DeleteObjectQuery buildAggregateDeleteQuery(
0086:                    WriteObjectQuery sourceQuery, Object sourceAttributeValue) {
0087:                DeleteObjectQuery aggregateQuery = new DeleteObjectQuery();
0088:                buildAggregateModifyQuery(sourceQuery, aggregateQuery,
0089:                        sourceAttributeValue);
0090:                return aggregateQuery;
0091:            }
0092:
0093:            /**
0094:             * Initialize the aggregate query with the settings from the source query.
0095:             */
0096:            protected void buildAggregateModifyQuery(
0097:                    ObjectLevelModifyQuery sourceQuery,
0098:                    ObjectLevelModifyQuery aggregateQuery,
0099:                    Object sourceAttributeValue) {
0100:                if (sourceQuery.getSession().isUnitOfWork()) {
0101:                    Object backupAttributeValue = getAttributeValueFromBackupClone(sourceQuery
0102:                            .getBackupClone());
0103:                    if (backupAttributeValue == null) {
0104:                        backupAttributeValue = getObjectBuilder(
0105:                                sourceAttributeValue, sourceQuery.getSession())
0106:                                .buildNewInstance();
0107:                    }
0108:                    aggregateQuery.setBackupClone(backupAttributeValue);
0109:                }
0110:                aggregateQuery.setCascadePolicy(sourceQuery.getCascadePolicy());
0111:                aggregateQuery.setObject(sourceAttributeValue);
0112:                aggregateQuery.setTranslationRow(sourceQuery
0113:                        .getTranslationRow());
0114:                aggregateQuery.setSession(sourceQuery.getSession());
0115:                aggregateQuery.setProperties(sourceQuery.getProperties());
0116:            }
0117:
0118:            /**
0119:             * Make a copy of the sourceQuery for the attribute.
0120:             */
0121:            protected WriteObjectQuery buildAggregateWriteQuery(
0122:                    WriteObjectQuery sourceQuery, Object sourceAttributeValue) {
0123:                WriteObjectQuery aggregateQuery = new WriteObjectQuery();
0124:                buildAggregateModifyQuery(sourceQuery, aggregateQuery,
0125:                        sourceAttributeValue);
0126:                return aggregateQuery;
0127:            }
0128:
0129:            /**
0130:             * INTERNAL:
0131:             * Clone the attribute from the clone and assign it to the backup.
0132:             */
0133:            public void buildBackupClone(Object clone, Object backup,
0134:                    UnitOfWorkImpl unitOfWork) {
0135:                Object attributeValue = getAttributeValueFromObject(clone);
0136:                setAttributeValueInObject(backup, buildBackupClonePart(
0137:                        attributeValue, unitOfWork));
0138:            }
0139:
0140:            /**
0141:             * INTERNAL:
0142:             * Build and return a backup clone of the attribute.
0143:             */
0144:            protected Object buildBackupClonePart(Object attributeValue,
0145:                    UnitOfWorkImpl unitOfWork) {
0146:                if (attributeValue == null) {
0147:                    return null;
0148:                }
0149:                return getObjectBuilder(attributeValue, unitOfWork)
0150:                        .buildBackupClone(attributeValue, unitOfWork);
0151:            }
0152:
0153:            /**
0154:             * INTERNAL:
0155:             * Clone the attribute from the original and assign it to the clone.
0156:             */
0157:            public void buildClone(Object original, Object clone,
0158:                    UnitOfWorkImpl unitOfWork,
0159:                    JoinedAttributeManager joinedAttributeManager) {
0160:                Object attributeValue = getAttributeValueFromObject(original);
0161:                setAttributeValueInObject(clone, buildClonePart(original,
0162:                        attributeValue, unitOfWork));
0163:            }
0164:
0165:            /**
0166:             * INTERNAL:
0167:             * A combination of readFromRowIntoObject and buildClone.
0168:             * <p>
0169:             * buildClone assumes the attribute value exists on the original and can
0170:             * simply be copied.
0171:             * <p>
0172:             * readFromRowIntoObject assumes that one is building an original.
0173:             * <p>
0174:             * Both of the above assumptions are false in this method, and actually
0175:             * attempts to do both at the same time.
0176:             * <p>
0177:             * Extract value from the row and set the attribute to this value in the
0178:             * working copy clone.
0179:             * In order to bypass the shared cache when in transaction a UnitOfWork must
0180:             * be able to populate working copies directly from the row.
0181:             */
0182:            public void buildCloneFromRow(AbstractRecord databaseRow,
0183:                    JoinedAttributeManager joinManager, Object clone,
0184:                    ObjectBuildingQuery sourceQuery, UnitOfWorkImpl unitOfWork,
0185:                    AbstractSession executionSession) {
0186:                // automatically returns a uow result from scratch that doesn't need cloning
0187:                Object cloneAttributeValue = valueFromRow(databaseRow,
0188:                        joinManager, sourceQuery, executionSession);
0189:                setAttributeValueInObject(clone, cloneAttributeValue);
0190:            }
0191:
0192:            /**
0193:             * INTERNAL:
0194:             * Build and return a clone of the attribute.
0195:             */
0196:            protected Object buildClonePart(Object original,
0197:                    Object attributeValue, UnitOfWorkImpl unitOfWork) {
0198:                if (attributeValue == null) {
0199:                    return null;
0200:                }
0201:                if (unitOfWork.isOriginalNewObject(original)) {
0202:                    unitOfWork.addNewAggregate(attributeValue);
0203:                }
0204:
0205:                // Do not clone for read-only.
0206:                if (unitOfWork.isClassReadOnly(attributeValue.getClass())) {
0207:                    return attributeValue;
0208:                }
0209:
0210:                ObjectBuilder aggregateObjectBuilder = getObjectBuilder(
0211:                        attributeValue, unitOfWork);
0212:
0213:                // bug 2612602 as we are building the working copy make sure that we call to correct clone method.
0214:                Object clonedAttributeValue = aggregateObjectBuilder
0215:                        .instantiateWorkingCopyClone(attributeValue, unitOfWork);
0216:                aggregateObjectBuilder.populateAttributesForClone(
0217:                        attributeValue, clonedAttributeValue, unitOfWork, null);
0218:
0219:                return clonedAttributeValue;
0220:            }
0221:
0222:            /**
0223:             * INTERNAL:
0224:             * Copy of the attribute of the object.
0225:             * This is NOT used for unit of work but for templatizing an object.
0226:             */
0227:            public void buildCopy(Object copy, Object original,
0228:                    ObjectCopyingPolicy policy) {
0229:                Object attributeValue = getAttributeValueFromObject(original);
0230:                setAttributeValueInObject(copy, buildCopyOfAttributeValue(
0231:                        attributeValue, policy));
0232:            }
0233:
0234:            /**
0235:             * Copy of the attribute of the object.
0236:             * This is NOT used for unit of work but for templatizing an object.
0237:             */
0238:            protected Object buildCopyOfAttributeValue(Object attributeValue,
0239:                    ObjectCopyingPolicy policy) {
0240:                if (attributeValue == null) {
0241:                    return null;
0242:                }
0243:                return getObjectBuilder(attributeValue, policy.getSession())
0244:                        .copyObject(attributeValue, policy);
0245:            }
0246:
0247:            /**
0248:             * INTERNAL:
0249:             * Build and return a new instance of the specified attribute.
0250:             * This will be populated by a merge.
0251:             */
0252:            protected Object buildNewMergeInstanceOf(
0253:                    Object sourceAttributeValue, AbstractSession session) {
0254:                return getObjectBuilder(sourceAttributeValue, session)
0255:                        .buildNewInstance();
0256:            }
0257:
0258:            /**
0259:             * INTERNAL:
0260:             * Cascade perform delete through mappings that require the cascade
0261:             */
0262:            //    public void cascadePerformDeleteIfRequired(Object object, UnitOfWork uow, IdentityHashtable visitedObjects){
0263:            //objects referenced by this mapping are not registered as they have
0264:            // no identity, this is a no-op.
0265:            //    }
0266:            /**
0267:             * INTERNAL:
0268:             * Cascade registerNew for Create through mappings that require the cascade
0269:             */
0270:            //    public void cascadeRegisterNewIfRequired(Object object, UnitOfWork uow, IdentityHashtable visitedObjects){
0271:            //aggregate objects are not registeres as they have no identity, this is a no-op.
0272:            //    }
0273:            /**
0274:             * INTERNAL:
0275:             * Compare the attributes. Return true if they are alike.
0276:             */
0277:            protected boolean compareAttributeValues(Object attributeValue1,
0278:                    Object attributeValue2, AbstractSession session) {
0279:                if ((attributeValue1 == null) && (attributeValue2 == null)) {
0280:                    return true;
0281:                }
0282:                if ((attributeValue1 == null) || (attributeValue2 == null)) {
0283:                    return false;
0284:                }
0285:                if (attributeValue1.getClass() != attributeValue2.getClass()) {
0286:                    return false;
0287:                }
0288:                return getObjectBuilder(attributeValue1, session)
0289:                        .compareObjects(attributeValue1, attributeValue2,
0290:                                session);
0291:            }
0292:
0293:            /**
0294:             * INTERNAL:
0295:             * Compare the changes between two aggregates.
0296:             * Return a change record holding the changes.
0297:             */
0298:            public ChangeRecord compareForChange(Object clone, Object backup,
0299:                    ObjectChangeSet owner, AbstractSession session) {
0300:                Object cloneAttribute = getAttributeValueFromObject(clone);
0301:                Object backupAttribute = null;
0302:
0303:                if (!owner.isNew()) {
0304:                    backupAttribute = getAttributeValueFromObject(backup);
0305:                    if ((cloneAttribute == null) && (backupAttribute == null)) {
0306:                        return null;// no change
0307:                    }
0308:                    if ((cloneAttribute != null)
0309:                            && (backupAttribute != null)
0310:                            && (!cloneAttribute.getClass().equals(
0311:                                    backupAttribute.getClass()))) {
0312:                        backupAttribute = null;
0313:                    }
0314:                }
0315:
0316:                AggregateChangeRecord changeRecord = new AggregateChangeRecord(
0317:                        owner);
0318:                changeRecord.setAttribute(getAttributeName());
0319:                changeRecord.setMapping(this );
0320:
0321:                if (cloneAttribute == null) {// the attribute was set to null
0322:                    changeRecord.setChangedObject(null);
0323:                    return changeRecord;
0324:                }
0325:
0326:                ObjectBuilder builder = getObjectBuilder(cloneAttribute,
0327:                        session);
0328:
0329:                //if the owner is new then the backup will be null, if the owner is new then the aggregate is new
0330:                //if the backup is null but the owner is not new then this aggregate is new
0331:                ObjectChangeSet initialChanges = builder.createObjectChangeSet(
0332:                        cloneAttribute, (UnitOfWorkChangeSet) owner
0333:                                .getUOWChangeSet(), (backupAttribute == null),
0334:                        session);
0335:                ObjectChangeSet changeSet = builder.compareForChange(
0336:                        cloneAttribute, backupAttribute,
0337:                        (UnitOfWorkChangeSet) owner.getUOWChangeSet(), session);
0338:                if (changeSet == null) {
0339:                    if (initialChanges.isNew()) {
0340:                        // This happens if original aggregate is of class A, the new aggregate
0341:                        // is of class B (B inherits from A) - and neither A nor B has any mapped attributes.
0342:                        // CR3664
0343:                        changeSet = initialChanges;
0344:                    } else {
0345:                        return null;// no change
0346:                    }
0347:                }
0348:                changeRecord.setChangedObject(changeSet);
0349:                return changeRecord;
0350:            }
0351:
0352:            /**
0353:             * INTERNAL:
0354:             * Compare the attributes belonging to this mapping for the objects.
0355:             */
0356:            public boolean compareObjects(Object firstObject,
0357:                    Object secondObject, AbstractSession session) {
0358:                return compareAttributeValues(
0359:                        getAttributeValueFromObject(firstObject),
0360:                        getAttributeValueFromObject(secondObject), session);
0361:            }
0362:
0363:            /**
0364:             * INTERNAL:
0365:             * Convert all the class-name-based settings in this mapping to actual class-based
0366:             * settings. This method is used when converting a project that has been built
0367:             * with class names to a project with classes.
0368:             * @param classLoader 
0369:             */
0370:            public void convertClassNamesToClasses(ClassLoader classLoader) {
0371:                Class referenceClass = null;
0372:                try {
0373:                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
0374:                        try {
0375:                            referenceClass = (Class) AccessController
0376:                                    .doPrivileged(new PrivilegedClassForName(
0377:                                            getReferenceClassName(), true,
0378:                                            classLoader));
0379:                        } catch (PrivilegedActionException exception) {
0380:                            throw ValidationException
0381:                                    .classNotFoundWhileConvertingClassNames(
0382:                                            getReferenceClassName(), exception
0383:                                                    .getException());
0384:                        }
0385:                    } else {
0386:                        referenceClass = oracle.toplink.essentials.internal.security.PrivilegedAccessHelper
0387:                                .getClassForName(getReferenceClassName(), true,
0388:                                        classLoader);
0389:                    }
0390:                } catch (ClassNotFoundException exc) {
0391:                    throw ValidationException
0392:                            .classNotFoundWhileConvertingClassNames(
0393:                                    getReferenceClassName(), exc);
0394:                }
0395:                setReferenceClass(referenceClass);
0396:            };
0397:
0398:            /**
0399:             * INTERNAL:
0400:             * Execute a descriptor event for the specified event code.
0401:             */
0402:            protected void executeEvent(int eventCode,
0403:                    ObjectLevelModifyQuery query) {
0404:                ClassDescriptor referenceDescriptor = getReferenceDescriptor(
0405:                        query.getObject(), query.getSession());
0406:
0407:                // PERF: Avoid events if no listeners.
0408:                if (referenceDescriptor.getEventManager()
0409:                        .hasAnyEventListeners()) {
0410:                    referenceDescriptor
0411:                            .getEventManager()
0412:                            .executeEvent(
0413:                                    new oracle.toplink.essentials.descriptors.DescriptorEvent(
0414:                                            eventCode, query));
0415:                }
0416:            }
0417:
0418:            /**
0419:             * Return the appropriate attribute value.
0420:             * This method is a hack to allow the aggregate collection
0421:             * subclass to override....
0422:             */
0423:            protected Object getAttributeValueFromBackupClone(Object backupClone) {
0424:                return getAttributeValueFromObject(backupClone);
0425:            }
0426:
0427:            /**
0428:             * Convenience method
0429:             */
0430:            protected ObjectBuilder getObjectBuilderForClass(Class javaClass,
0431:                    AbstractSession session) {
0432:                return getReferenceDescriptor(javaClass, session)
0433:                        .getObjectBuilder();
0434:            }
0435:
0436:            /**
0437:             * Convenience method
0438:             */
0439:            protected ObjectBuilder getObjectBuilder(Object attributeValue,
0440:                    AbstractSession session) {
0441:                return getReferenceDescriptor(attributeValue, session)
0442:                        .getObjectBuilder();
0443:            }
0444:
0445:            /**
0446:             * Convenience method
0447:             */
0448:            protected DescriptorQueryManager getQueryManager(
0449:                    Object attributeValue, AbstractSession session) {
0450:                return getReferenceDescriptor(attributeValue, session)
0451:                        .getQueryManager();
0452:            }
0453:
0454:            /**
0455:             * PUBLIC:
0456:             * Returns the reference class
0457:             */
0458:            public Class getReferenceClass() {
0459:                return referenceClass;
0460:            }
0461:
0462:            /**
0463:             * INTERNAL:
0464:             * Used by MW.
0465:             */
0466:            public String getReferenceClassName() {
0467:                if ((referenceClassName == null) && (referenceClass != null)) {
0468:                    referenceClassName = referenceClass.getName();
0469:                }
0470:                return referenceClassName;
0471:            }
0472:
0473:            /**
0474:             * INTERNAL:
0475:             * Return the referenceDescriptor. This is a descriptor which is associated with the reference class.
0476:             * NOTE: If you are looking for the descriptor for a specific aggregate object, use
0477:             * #getReferenceDescriptor(Object). This will ensure you get the right descriptor if the object's
0478:             * descriptor is part of an inheritance tree.
0479:             */
0480:            public ClassDescriptor getReferenceDescriptor() {
0481:                return referenceDescriptor;
0482:            }
0483:
0484:            /**
0485:             * INTERNAL:
0486:             * For inheritance purposes.
0487:             */
0488:            protected ClassDescriptor getReferenceDescriptor(Class theClass,
0489:                    AbstractSession session) {
0490:                if (getReferenceDescriptor().getJavaClass().equals(theClass)) {
0491:                    return getReferenceDescriptor();
0492:                }
0493:
0494:                ClassDescriptor subclassDescriptor = session
0495:                        .getDescriptor(theClass);
0496:                if (subclassDescriptor == null) {
0497:                    throw DescriptorException.noSubClassMatch(theClass, this );
0498:                } else {
0499:                    return subclassDescriptor;
0500:                }
0501:            }
0502:
0503:            /**
0504:             * Convenience method
0505:             */
0506:            protected ClassDescriptor getReferenceDescriptor(
0507:                    Object attributeValue, AbstractSession session) {
0508:                if (attributeValue == null) {
0509:                    return getReferenceDescriptor();
0510:                } else {
0511:                    return getReferenceDescriptor(attributeValue.getClass(),
0512:                            session);
0513:                }
0514:            }
0515:
0516:            /**
0517:             * INTERNAL:
0518:             * Initialize the reference descriptor.
0519:             */
0520:            public void initialize(AbstractSession session)
0521:                    throws DescriptorException {
0522:                super .initialize(session);
0523:
0524:                if (getReferenceClass() == null) {
0525:                    throw DescriptorException.referenceClassNotSpecified(this );
0526:                }
0527:
0528:                setReferenceDescriptor(session
0529:                        .getDescriptor(getReferenceClass()));
0530:
0531:                ClassDescriptor refDescriptor = this .getReferenceDescriptor();
0532:                if (refDescriptor == null) {
0533:                    session.getIntegrityChecker().handleError(
0534:                            DescriptorException.descriptorIsMissing(
0535:                                    getReferenceClass().getName(), this ));
0536:                }
0537:                if (refDescriptor.isAggregateDescriptor()) {
0538:                    refDescriptor.checkInheritanceTreeAggregateSettings(
0539:                            session, this );
0540:                } else {
0541:                    session.getIntegrityChecker()
0542:                            .handleError(
0543:                                    DescriptorException
0544:                                            .referenceDescriptorIsNotAggregate(
0545:                                                    getReferenceClass()
0546:                                                            .getName(), this ));
0547:                }
0548:            }
0549:
0550:            /**
0551:             * INTERNAL:
0552:             * Related mapping should implement this method to return true.
0553:             */
0554:            public boolean isAggregateMapping() {
0555:                return true;
0556:            }
0557:
0558:            /**
0559:             * INTERNAL:
0560:             * Iterate on the appropriate attribute value.
0561:             */
0562:            public void iterate(DescriptorIterator iterator) {
0563:                iterateOnAttributeValue(
0564:                        iterator,
0565:                        getAttributeValueFromObject(iterator.getVisitedParent()));
0566:            }
0567:
0568:            /**
0569:             * Iterate on the specified attribute value.
0570:             */
0571:            protected void iterateOnAttributeValue(DescriptorIterator iterator,
0572:                    Object attributeValue) {
0573:                iterator.iterateForAggregateMapping(attributeValue, this ,
0574:                        getReferenceDescriptor(attributeValue, iterator
0575:                                .getSession()));
0576:            }
0577:
0578:            /**
0579:             * Merge the attribute values.
0580:             */
0581:            protected void mergeAttributeValue(Object targetAttributeValue,
0582:                    boolean isTargetUnInitialized, Object sourceAttributeValue,
0583:                    MergeManager mergeManager) {
0584:                // don't merge read-only attributes
0585:                if (mergeManager.getSession().isClassReadOnly(
0586:                        sourceAttributeValue.getClass())) {
0587:                    return;
0588:                }
0589:                if (mergeManager.getSession().isClassReadOnly(
0590:                        targetAttributeValue.getClass())) {
0591:                    return;
0592:                }
0593:
0594:                getObjectBuilder(sourceAttributeValue,
0595:                        mergeManager.getSession()).mergeIntoObject(
0596:                        targetAttributeValue, isTargetUnInitialized,
0597:                        sourceAttributeValue, mergeManager);
0598:            }
0599:
0600:            /**
0601:             * INTERNAL:
0602:             * Merge changes from the source to the target object.
0603:             * With aggregates the merge must cascade to the object changes for the aggregate object
0604:             * because aggregate objects have no identity outside of themselves.
0605:             * The actual aggregate object does not need to be replaced, because even if the clone references
0606:             * another aggregate it appears the same to TopLink
0607:             */
0608:            public void mergeChangesIntoObject(Object target,
0609:                    ChangeRecord changeRecord, Object source,
0610:                    MergeManager mergeManager) {
0611:                ObjectChangeSet aggregateChangeSet = (ObjectChangeSet) ((AggregateChangeRecord) changeRecord)
0612:                        .getChangedObject();
0613:                if (aggregateChangeSet == null) {// the change was to set the value to null
0614:                    setAttributeValueInObject(target, null);
0615:                    return;
0616:                }
0617:
0618:                Object sourceAggregate = null;
0619:                if (source != null) {
0620:                    sourceAggregate = getAttributeValueFromObject(source);
0621:                }
0622:                ObjectBuilder objectBuilder = getObjectBuilderForClass(
0623:                        aggregateChangeSet.getClassType(mergeManager
0624:                                .getSession()), mergeManager.getSession());
0625:                //Bug#4719341  Always obtain aggregate attribute value from the target object regardless of new or not
0626:                Object targetAggregate = getAttributeValueFromObject(target);
0627:                if (targetAggregate == null) {
0628:                    targetAggregate = objectBuilder.buildNewInstance();
0629:                } else {
0630:                    if ((sourceAggregate != null)
0631:                            && (sourceAggregate.getClass() != targetAggregate
0632:                                    .getClass())) {
0633:                        targetAggregate = objectBuilder.buildNewInstance();
0634:                    }
0635:                }
0636:                objectBuilder.mergeChangesIntoObject(targetAggregate,
0637:                        aggregateChangeSet, sourceAggregate, mergeManager);
0638:                setAttributeValueInObject(target, targetAggregate);
0639:            }
0640:
0641:            /**
0642:             * INTERNAL:
0643:             * Merge changes from the source to the target object. This merge is only called when a changeSet for the target
0644:             * does not exist or the target is uninitialized
0645:             */
0646:            public void mergeIntoObject(Object target,
0647:                    boolean isTargetUnInitialized, Object source,
0648:                    MergeManager mergeManager) {
0649:                Object sourceAttributeValue = getAttributeValueFromObject(source);
0650:                if (sourceAttributeValue == null) {
0651:                    setAttributeValueInObject(target, null);
0652:                    return;
0653:                }
0654:
0655:                Object targetAttributeValue = getAttributeValueFromObject(target);
0656:                if (targetAttributeValue == null) {
0657:                    // avoid null-pointer/nothing to merge to - create a new instance
0658:                    // (a new clone cannot be used as all changes must be merged)
0659:                    targetAttributeValue = buildNewMergeInstanceOf(
0660:                            sourceAttributeValue, mergeManager.getSession());
0661:                    mergeAttributeValue(targetAttributeValue, true,
0662:                            sourceAttributeValue, mergeManager);
0663:                    // setting new instance so fire event as if set was called by user.
0664:                    // this call will eventually get passed to updateChangeRecord which will 
0665:                    //ensure this new aggregates is fully initilized with listeners.
0666:                    this .getDescriptor().getObjectChangePolicy()
0667:                            .raiseInternalPropertyChangeEvent(target,
0668:                                    getAttributeName(),
0669:                                    getAttributeValueFromObject(target),
0670:                                    targetAttributeValue);
0671:
0672:                } else {
0673:                    mergeAttributeValue(targetAttributeValue,
0674:                            isTargetUnInitialized, sourceAttributeValue,
0675:                            mergeManager);
0676:                }
0677:
0678:                // allow setter to re-morph any changes...
0679:                setAttributeValueInObject(target, targetAttributeValue);
0680:            }
0681:
0682:            /**
0683:             * INTERNAL:
0684:             * The message is passed to its reference class descriptor.
0685:             */
0686:            public void postDelete(WriteObjectQuery query)
0687:                    throws DatabaseException, OptimisticLockException {
0688:                if (!isReadOnly()) {
0689:                    postDeleteAttributeValue(query,
0690:                            getAttributeValueFromObject(query.getObject()));
0691:                }
0692:            }
0693:
0694:            /**
0695:             * INTERNAL:
0696:             * The message is passed to its reference class descriptor.
0697:             */
0698:            protected void postDeleteAttributeValue(WriteObjectQuery query,
0699:                    Object attributeValue) throws DatabaseException,
0700:                    OptimisticLockException {
0701:                if (attributeValue == null) {
0702:                    return;
0703:                }
0704:                DeleteObjectQuery aggregateQuery = buildAggregateDeleteQuery(
0705:                        query, attributeValue);
0706:                getQueryManager(attributeValue, query.getSession()).postDelete(
0707:                        aggregateQuery);
0708:                executeEvent(DescriptorEventManager.PostDeleteEvent,
0709:                        aggregateQuery);
0710:            }
0711:
0712:            /**
0713:             * INTERNAL:
0714:             * The message is passed to its reference class descriptor.
0715:             */
0716:            public void postInsert(WriteObjectQuery query)
0717:                    throws DatabaseException, OptimisticLockException {
0718:                if (!isReadOnly()) {
0719:                    postInsertAttributeValue(query,
0720:                            getAttributeValueFromObject(query.getObject()));
0721:                }
0722:            }
0723:
0724:            /**
0725:             * INTERNAL:
0726:             * The message is passed to its reference class descriptor.
0727:             */
0728:            protected void postInsertAttributeValue(WriteObjectQuery query,
0729:                    Object attributeValue) throws DatabaseException,
0730:                    OptimisticLockException {
0731:                if (attributeValue == null) {
0732:                    return;
0733:                }
0734:                WriteObjectQuery aggregateQuery = buildAggregateWriteQuery(
0735:                        query, attributeValue);
0736:                getQueryManager(attributeValue, query.getSession()).postInsert(
0737:                        aggregateQuery);
0738:                executeEvent(DescriptorEventManager.PostInsertEvent,
0739:                        aggregateQuery);
0740:                // aggregates do not actually use a query to write to the database so the post write must be called here
0741:                executeEvent(DescriptorEventManager.PostWriteEvent,
0742:                        aggregateQuery);
0743:            }
0744:
0745:            /**
0746:             * INTERNAL:
0747:             * The message is passed to its reference class descriptor.
0748:             */
0749:            public void postUpdate(WriteObjectQuery query)
0750:                    throws DatabaseException, OptimisticLockException {
0751:                if (!isReadOnly()) {
0752:                    postUpdateAttributeValue(query,
0753:                            getAttributeValueFromObject(query.getObject()));
0754:                }
0755:            }
0756:
0757:            /**
0758:             * INTERNAL:
0759:             * The message is passed to its reference class descriptor.
0760:             */
0761:            protected void postUpdateAttributeValue(WriteObjectQuery query,
0762:                    Object attributeValue) throws DatabaseException,
0763:                    OptimisticLockException {
0764:                if (attributeValue == null) {
0765:                    return;
0766:                }
0767:                ObjectChangeSet changeSet = null;
0768:                UnitOfWorkChangeSet uowChangeSet = null;
0769:                if (query.getSession().isUnitOfWork()
0770:                        && (((UnitOfWorkImpl) query.getSession())
0771:                                .getUnitOfWorkChangeSet() != null)) {
0772:                    uowChangeSet = (UnitOfWorkChangeSet) ((UnitOfWorkImpl) query
0773:                            .getSession()).getUnitOfWorkChangeSet();
0774:                    changeSet = (ObjectChangeSet) uowChangeSet
0775:                            .getObjectChangeSetForClone(attributeValue);
0776:                }
0777:                WriteObjectQuery aggregateQuery = buildAggregateWriteQuery(
0778:                        query, attributeValue);
0779:                aggregateQuery.setObjectChangeSet(changeSet);
0780:                getQueryManager(attributeValue, query.getSession()).postUpdate(
0781:                        aggregateQuery);
0782:                executeEvent(DescriptorEventManager.PostUpdateEvent,
0783:                        aggregateQuery);
0784:                // aggregates do not actually use a query to write to the database so the post write must be called here
0785:                executeEvent(DescriptorEventManager.PostWriteEvent,
0786:                        aggregateQuery);
0787:            }
0788:
0789:            /**
0790:             * INTERNAL:
0791:             * The message is passed to its reference class descriptor.
0792:             */
0793:            public void preDelete(WriteObjectQuery query)
0794:                    throws DatabaseException, OptimisticLockException {
0795:                if (!isReadOnly()) {
0796:                    preDeleteAttributeValue(query,
0797:                            getAttributeValueFromObject(query.getObject()));
0798:                }
0799:            }
0800:
0801:            /**
0802:             * INTERNAL:
0803:             * The message is passed to its reference class descriptor.
0804:             */
0805:            protected void preDeleteAttributeValue(WriteObjectQuery query,
0806:                    Object attributeValue) throws DatabaseException,
0807:                    OptimisticLockException {
0808:                if (attributeValue == null) {
0809:                    return;
0810:                }
0811:                DeleteObjectQuery aggregateQuery = buildAggregateDeleteQuery(
0812:                        query, attributeValue);
0813:                executeEvent(DescriptorEventManager.PreDeleteEvent,
0814:                        aggregateQuery);
0815:                getQueryManager(attributeValue, query.getSession()).preDelete(
0816:                        aggregateQuery);
0817:            }
0818:
0819:            /**
0820:             * INTERNAL:
0821:             * The message is passed to its reference class descriptor.
0822:             */
0823:            public void preInsert(WriteObjectQuery query)
0824:                    throws DatabaseException, OptimisticLockException {
0825:                if (!isReadOnly()) {
0826:                    preInsertAttributeValue(query,
0827:                            getAttributeValueFromObject(query.getObject()));
0828:                }
0829:            }
0830:
0831:            /**
0832:             * INTERNAL:
0833:             * The message is passed to its reference class descriptor.
0834:             */
0835:            protected void preInsertAttributeValue(WriteObjectQuery query,
0836:                    Object attributeValue) throws DatabaseException,
0837:                    OptimisticLockException {
0838:                if (attributeValue == null) {
0839:                    return;
0840:                }
0841:                WriteObjectQuery aggregateQuery = buildAggregateWriteQuery(
0842:                        query, attributeValue);
0843:                getQueryManager(attributeValue, query.getSession()).preInsert(
0844:                        aggregateQuery);
0845:            }
0846:
0847:            /**
0848:             * INTERNAL:
0849:             * The message is passed to its reference class descriptor.
0850:             */
0851:            public void preUpdate(WriteObjectQuery query)
0852:                    throws DatabaseException, OptimisticLockException {
0853:                if (!isReadOnly()) {
0854:                    preUpdateAttributeValue(query,
0855:                            getAttributeValueFromObject(query.getObject()));
0856:                }
0857:            }
0858:
0859:            /**
0860:             * INTERNAL:
0861:             * The message is passed to its reference class descriptor.
0862:             */
0863:            protected void preUpdateAttributeValue(WriteObjectQuery query,
0864:                    Object attributeValue) throws DatabaseException,
0865:                    OptimisticLockException {
0866:                if (attributeValue == null) {
0867:                    return;
0868:                }
0869:                WriteObjectQuery aggregateQuery = buildAggregateWriteQuery(
0870:                        query, attributeValue);
0871:                ObjectChangeSet changeSet = null;
0872:                UnitOfWorkChangeSet uowChangeSet = null;
0873:                if (query.getSession().isUnitOfWork()
0874:                        && (((UnitOfWorkImpl) query.getSession())
0875:                                .getUnitOfWorkChangeSet() != null)) {
0876:                    uowChangeSet = (UnitOfWorkChangeSet) ((UnitOfWorkImpl) query
0877:                            .getSession()).getUnitOfWorkChangeSet();
0878:                    changeSet = (ObjectChangeSet) uowChangeSet
0879:                            .getObjectChangeSetForClone(aggregateQuery
0880:                                    .getObject());
0881:                }
0882:
0883:                aggregateQuery.setObjectChangeSet(changeSet);
0884:                // aggregates do not actually use a query to write to the database so the pre-write must be called here
0885:                if (changeSet == null) {// then we didn't fire events at calculations
0886:                    executeEvent(DescriptorEventManager.PreWriteEvent,
0887:                            aggregateQuery);
0888:                    executeEvent(DescriptorEventManager.PreUpdateEvent,
0889:                            aggregateQuery);
0890:                }
0891:                getQueryManager(attributeValue, query.getSession()).preUpdate(
0892:                        aggregateQuery);
0893:            }
0894:
0895:            /**
0896:             * PUBLIC:
0897:             * This is a reference class whose instances this mapping will store in the domain objects.
0898:             */
0899:            public void setReferenceClass(Class aClass) {
0900:                referenceClass = aClass;
0901:            }
0902:
0903:            /**
0904:             * INTERNAL:
0905:             * Used by MW.
0906:             */
0907:            public void setReferenceClassName(String aClassName) {
0908:                referenceClassName = aClassName;
0909:            }
0910:
0911:            /**
0912:             * INTERNAL:
0913:             * Set the referenceDescriptor. This is a descriptor which is associated with
0914:             * the reference class.
0915:             */
0916:            protected void setReferenceDescriptor(ClassDescriptor aDescriptor) {
0917:                referenceDescriptor = aDescriptor;
0918:            }
0919:
0920:            /**
0921:             * INTERNAL:
0922:             * Either create a new change record or update the change record with the new value.
0923:             * This is used by attribute change tracking.  Only call this method if a different aggregate
0924:             * is being set in the object, if the aggregate itself is being updated then call the
0925:             * update on the corresponding mapping within the aggregate.
0926:             */
0927:            public void updateChangeRecord(Object sourceClone, Object newValue,
0928:                    Object oldValue, ObjectChangeSet objectChangeSet,
0929:                    UnitOfWorkImpl uow) throws DescriptorException {
0930:                //This method will be called when either the referenced aggregate has 
0931:                //been changed or a component of the referenced aggregate has been changed
0932:                //this case is determined by the value of the sourceClone 
0933:
0934:                AggregateChangeRecord changeRecord = (AggregateChangeRecord) objectChangeSet
0935:                        .getChangesForAttributeNamed(this .getAttributeName());
0936:                if (changeRecord == null) {
0937:                    changeRecord = new AggregateChangeRecord(objectChangeSet);
0938:                    changeRecord.setAttribute(this .getAttributeName());
0939:                    changeRecord.setMapping(this );
0940:                    objectChangeSet.addChange(changeRecord);
0941:                }
0942:
0943:                if (sourceClone.getClass().equals(
0944:                        objectChangeSet.getClassType(uow))) {
0945:                    // event was fired on the parent to the aggregate, the attribute value changed.
0946:                    ClassDescriptor referenceDescriptor = getReferenceDescriptor(
0947:                            newValue, uow);
0948:                    if (newValue == null) { // attribute set to null
0949:                        changeRecord.setChangedObject(null);
0950:                        return;
0951:                    } else { // attribute set to new aggregate
0952:                        UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet) objectChangeSet
0953:                                .getUOWChangeSet();
0954:                        //force comparison change detection to build changeset.
0955:                        ObjectChangeSet aggregateChangeSet = (ObjectChangeSet) uowChangeSet
0956:                                .getObjectChangeSetForClone(newValue);
0957:                        if (aggregateChangeSet != null) {
0958:                            aggregateChangeSet.clear(); // old differences must be thrown away because difference is between old value and new value
0959:                        }
0960:                        //force comparison change detection to build changeset.
0961:                        changeRecord.setChangedObject(referenceDescriptor
0962:                                .getObjectChangePolicy()
0963:                                .createObjectChangeSetThroughComparison(
0964:                                        newValue, oldValue, uowChangeSet,
0965:                                        (oldValue == null), uow,
0966:                                        referenceDescriptor));
0967:                        referenceDescriptor.getObjectChangePolicy()
0968:                                .setChangeSetOnListener(
0969:                                        (ObjectChangeSet) changeRecord
0970:                                                .getChangedObject(), newValue);
0971:
0972:                    }
0973:                } else {
0974:                    // not tracked at attribute level, lets force build a changeset then.
0975:                    changeRecord.setChangedObject(referenceDescriptor
0976:                            .getObjectChangePolicy()
0977:                            .createObjectChangeSetThroughComparison(
0978:                                    sourceClone,
0979:                                    null,
0980:                                    (UnitOfWorkChangeSet) objectChangeSet
0981:                                            .getUOWChangeSet(), true, uow,
0982:                                    referenceDescriptor));
0983:                }
0984:            }
0985:
0986:            /**
0987:             * INTERNAL:
0988:             * Return whether the specified object and all its components have been deleted.
0989:             */
0990:            public boolean verifyDelete(Object object, AbstractSession session)
0991:                    throws DatabaseException {
0992:                return verifyDeleteOfAttributeValue(
0993:                        getAttributeValueFromObject(object), session);
0994:            }
0995:
0996:            /**
0997:             * INTERNAL:
0998:             * Return whether the specified object and all its components have been deleted.
0999:             */
1000:            protected boolean verifyDeleteOfAttributeValue(
1001:                    Object attributeValue, AbstractSession session)
1002:                    throws DatabaseException {
1003:                if (attributeValue == null) {
1004:                    return true;
1005:                }
1006:                for (Enumeration mappings = getReferenceDescriptor(
1007:                        attributeValue, session).getMappings().elements(); mappings
1008:                        .hasMoreElements();) {
1009:                    DatabaseMapping mapping = (DatabaseMapping) mappings
1010:                            .nextElement();
1011:                    if (!mapping.verifyDelete(attributeValue, session)) {
1012:                        return false;
1013:                    }
1014:                }
1015:                return true;
1016:            }
1017:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.