Source Code Cross Referenced for PersistentObject.java in  » Database-ORM » ODAL » com » completex » objective » components » persistency » 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 » ODAL » com.completex.objective.components.persistency 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         *  Objective Database Abstraction Layer (ODAL)
0003:         *  Copyright (c) 2004, The ODAL Development Group
0004:         *  All rights reserved.
0005:         *  For definition of the ODAL Development Group please refer to LICENCE.txt file
0006:         *
0007:         *  Distributable under LGPL license.
0008:         *  See terms of license at gnu.org.
0009:         */package com.completex.objective.components.persistency;
0010:
0011:        import com.completex.objective.components.persistency.core.impl.LinkDependencyGraph;
0012:        import com.completex.objective.components.persistency.core.impl.LinkIterator;
0013:        import com.completex.objective.components.persistency.core.impl.query.NonCompilingQueryFactory;
0014:        import com.completex.objective.components.persistency.type.TracingCollection;
0015:        import com.completex.objective.components.OdalRuntimeException;
0016:
0017:        import java.io.IOException;
0018:        import java.io.ObjectInput;
0019:        import java.io.ObjectOutput;
0020:        import java.sql.SQLException;
0021:        import java.util.Collection;
0022:        import java.util.Date;
0023:        import java.util.HashMap;
0024:        import java.util.Iterator;
0025:        import java.util.List;
0026:        import java.util.Map;
0027:        import java.util.Set;
0028:
0029:        /**
0030:         * Ancestor of all generated persistent objects. Its descendants can be used as return type
0031:         * as well as in "queries by example". If no "singular result factory" is specified for Query or Call,
0032:         * the retrieved records will be placed into raw PersistentObject instances. In this case
0033:         * field values can be accessed through its Record by calling:
0034:         * <p/>
0035:         * <PRE>
0036:         * persistentObject.record().getXXX();
0037:         * </PRE>
0038:         * methods.
0039:         *
0040:         * @author Gennady Krizhevsky
0041:         * @see Record
0042:         */
0043:        public class PersistentObject extends AbstractPersistentObject
0044:                implements  Compound {
0045:
0046:            public static final StringBuffer NULL_BUFFER = new StringBuffer();
0047:
0048:            private transient boolean _preinitializedComplex;
0049:            private transient boolean _initializedComplex;
0050:            private transient Record _record;
0051:            private transient Boolean _trace;
0052:
0053:            //
0054:            // Links for the master (template) object - only for complex objects
0055:            //
0056:            private transient Link[] _links;
0057:
0058:            //
0059:            // This is a template object:
0060:            //
0061:            private transient PersistentObject _master;
0062:
0063:            public PersistentObject() {
0064:                postInitializeRecord();
0065:            }
0066:
0067:            public PersistentObject(Record record) {
0068:                validate(record);
0069:                this ._record = record;
0070:                if (record != null) {
0071:                    this ._record.setPersistentObject(this );
0072:                }
0073:
0074:                postInitializeRecord();
0075:
0076:                if (complex() && !_preinitializedComplex
0077:                        && !_initializedComplex) {
0078:                    preinitializeComplex();
0079:                }
0080:
0081:                if (compound()) {
0082:                    compoundAttrSetup();
0083:                    setupCompound();
0084:                }
0085:            }
0086:
0087:            /**
0088:             * Returns links that define children of this PersistentObject
0089:             *
0090:             * @param queryFactory
0091:             * @return Link[] - links that define children of this PersistentObject
0092:             */
0093:            public Link[] retrieveLinks(QueryFactory queryFactory) {
0094:                if (this ._links == null) {
0095:                    this ._links = links(queryFactory);
0096:                }
0097:                return this ._links;
0098:            }
0099:
0100:            //
0101:            // Compound begin:
0102:            //
0103:
0104:            /**
0105:             * Sets this object as compound.
0106:             *
0107:             * @param compound
0108:             */
0109:            protected void compound(boolean compound) {
0110:                compound(1);
0111:            }
0112:
0113:            /**
0114:             * Returns true.
0115:             *
0116:             * @return true
0117:             * @see AbstractPersistentObject#selfReferencing()
0118:             */
0119:            public boolean selfReferencing() {
0120:                return true;
0121:            }
0122:
0123:            /**
0124:             * Makes this object the 1st object in PersistentObject[] of compound PersistentObject
0125:             */
0126:            protected void selfReference() {
0127:                if (persistentObjects != null && persistentObjects.length > 0) {
0128:                    persistentObjects[0] = this ;
0129:                }
0130:            }
0131:
0132:            //
0133:            // Compound end.
0134:            //
0135:
0136:            /**
0137:             * Preinitializes complex <tt>PersistentObject</tt>. Creates master <tt>PersistentObject</tt>
0138:             * of this class and assembles it populating its <tt>LinkDependencyGraph</tt>.
0139:             * The master is used down the road as a template object to assemble new instances of this class.
0140:             * Creating and assembling of the master is done once for every
0141:             * specific <tt>Persistency</tt> instance it is used with.
0142:             * Does nothing if the object is not complex.
0143:             *
0144:             * @return itself
0145:             */
0146:            protected PersistentObject preinitializeComplex() {
0147:                //        System.out.println("Enter PersistentObject::preinitialize: " + getClass());
0148:                if (!complex() || _preinitializedComplex) {
0149:                    return this ;
0150:                }
0151:
0152:                QueryFactory queryFactory = NonCompilingQueryFactory
0153:                        .getInstance();
0154:
0155:                PersistentObject master = null;
0156:                instantiateRegisteredMasters();
0157:                if (!classInitialized(queryFactory)) {
0158:                    synchronized (classLock()) {
0159:                        if (!classInitialized(queryFactory)) {
0160:                            String key = registrationKey(queryFactory);
0161:                            registerMaster(key);
0162:                            master = master(queryFactory);
0163:                            registerDependent(queryFactory, master);
0164:                            master.record().setDependencyGraph(
0165:                                    new LinkDependencyGraph(master));
0166:                            this ._master = master;
0167:                        }
0168:                    }
0169:                } else {
0170:                    master = master(queryFactory);
0171:                    this ._master = master;
0172:                }
0173:
0174:                synchronized (this ) {
0175:                    if (!_preinitializedComplex) {
0176:                        newPersistentObjectPreSetup(this , master);
0177:                        _preinitializedComplex = true;
0178:                    }
0179:                }
0180:                return this ;
0181:            }
0182:
0183:            /**
0184:             * Initializes complex <tt>PersistentObject</tt>. Uses the master object
0185:             * as a template to assemble new instance.
0186:             * Does nothing if the object is not complex.
0187:             *
0188:             * @param queryFactory
0189:             * @return itself
0190:             */
0191:            public PersistentObject initializeComplex(QueryFactory queryFactory) {
0192:                if (!complex() || _initializedComplex) {
0193:                    return this ;
0194:                }
0195:
0196:                PersistentObject master;
0197:                if (_preinitializedComplex) {
0198:                    master = master(NonCompilingQueryFactory.getInstance());
0199:                    if (master == null) {
0200:                        throw new IllegalArgumentException(
0201:                                "Cannot find preinitialized master for " + this );
0202:                    }
0203:                } else {
0204:                    throw new IllegalArgumentException(
0205:                            "Cannot initialize class that not preinitialized master: "
0206:                                    + this );
0207:                }
0208:
0209:                if (!classInitialized(queryFactory)) {
0210:                    synchronized (classLock()) {
0211:                        if (!classInitialized(queryFactory)) {
0212:                            LinkDependencyGraph masterDependencyGraph = master
0213:                                    .record().getDependencyGraph();
0214:                            if (masterDependencyGraph != null
0215:                                    && masterDependencyGraph.hasMetaAssembly()) {
0216:                                for (int i = 0; i < masterDependencyGraph
0217:                                        .metaAssemblySize(); i++) {
0218:                                    Link link = masterDependencyGraph
0219:                                            .getMetaAssemblyLink(i);
0220:                                    if (link.getQuery() != null) {
0221:                                        link.getQuery().decompile();
0222:                                        ((QueryCtl) link.getQuery())
0223:                                                .setParentQueryFactory(queryFactory);
0224:                                    }
0225:                                }
0226:                            }
0227:                            reregisterMaster(
0228:                                    registrationKey(NonCompilingQueryFactory
0229:                                            .getInstance()),
0230:                                    registrationKey(queryFactory));
0231:                        }
0232:                    }
0233:                }
0234:
0235:                if (!_initializedComplex) {
0236:                    synchronized (this ) {
0237:                        if (!_initializedComplex) {
0238:                            LinkDependencyGraph linkDependencyGraph;
0239:                            try {
0240:                                linkDependencyGraph = (LinkDependencyGraph) master
0241:                                        .record().getDependencyGraph().clone();
0242:                            } catch (CloneNotSupportedException e) {
0243:                                throw new RuntimeException(e);
0244:                            }
0245:                            newPersistentObjectSetup(this , master);
0246:                            this .record().setDependencyGraph(
0247:                                    linkDependencyGraph);
0248:
0249:                            // Now we go by path and replace values in final assembly:
0250:                            Link parent = toLink();
0251:                            String path = Link.ROOT;
0252:                            linkDependencyGraph.addToAssembly(path, parent);
0253:                            addToAssembly(path, parent, linkDependencyGraph,
0254:                                    queryFactory);
0255:                            _initializedComplex = true;
0256:                        }
0257:                    }
0258:                }
0259:
0260:                return this ;
0261:            }
0262:
0263:            /**
0264:             * Returns master (template) object assuming it was already set for this instance
0265:             * which is done in preinitializeComplex() method
0266:             *
0267:             * @return master object
0268:             */
0269:            protected PersistentObject master() {
0270:                return _master;
0271:            }
0272:
0273:            /**
0274:             * Registers this object as a master.
0275:             *
0276:             * @param registrationKey
0277:             */
0278:            protected void registerMaster(String registrationKey) {
0279:                PersistentObject persistent = (PersistentObject) this .clone();
0280:                registeredMasters().put(registrationKey, persistent);
0281:
0282:            }
0283:
0284:            /**
0285:             * Instantiates Registered Masters (Map) in thread safe manner.
0286:             * Has to be overridden by descendants.
0287:             *
0288:             * @throws UnsupportedOperationException if it is not overridden by descendant
0289:             */
0290:            protected void instantiateRegisteredMasters() {
0291:                throw new UnsupportedOperationException();
0292:            }
0293:
0294:            /**
0295:             * To traverse the graph follow the pattern:
0296:             * <PRE>
0297:             * record.toLink
0298:             * |-> result
0299:             * |-> record.toLink / collection -> record.toLink
0300:             * |-> children <-| (meta-data)
0301:             * </PRE>
0302:             *
0303:             * @param path                link path
0304:             * @param parent              parent link
0305:             * @param linkDependencyGraph LinkDependencyGraph
0306:             * @param queryFactory        QueryFactory
0307:             */
0308:            protected void addToAssembly(String path, Link parent,
0309:                    LinkDependencyGraph linkDependencyGraph,
0310:                    QueryFactory queryFactory) {
0311:                if (parent.hasChildren()) {
0312:                    for (LinkIterator it = parent.linkIterator(); it.hasNext();) {
0313:                        Link link = it.nextLink();
0314:                        if (!link.isAdHoc()) {
0315:                            String linkPath = path + Link.SEP + link.getName();
0316:                            Object result = link.getResult();
0317:                            if (result != null) {
0318:                                if (result instanceof  PersistentObject) {
0319:                                    PersistentObject persistentObject = (PersistentObject) result;
0320:                                    addToAssemblyOne(persistentObject, parent,
0321:                                            linkDependencyGraph, linkPath,
0322:                                            queryFactory);
0323:                                } else if (result instanceof  Collection) {
0324:                                    for (Iterator iterator = ((Collection) result)
0325:                                            .iterator(); iterator.hasNext();) {
0326:                                        PersistentObject persistentObject = (PersistentObject) iterator
0327:                                                .next();
0328:                                        addToAssemblyOne(persistentObject,
0329:                                                parent, linkDependencyGraph,
0330:                                                linkPath, queryFactory);
0331:                                    }
0332:                                } else {
0333:                                    throw new UnsupportedOperationException(
0334:                                            "Unsupported type: " + result);
0335:                                }
0336:                            }
0337:                        }
0338:                    }
0339:                }
0340:            }
0341:
0342:            private void addToAssemblyOne(PersistentObject persistentObject,
0343:                    Link parent, LinkDependencyGraph linkDependencyGraph,
0344:                    String linkPath, QueryFactory queryFactory) {
0345:                persistentObject.toLink().setParentLink(parent);
0346:                linkDependencyGraph.addToAssembly(linkPath, persistentObject
0347:                        .toLink());
0348:                addToAssembly(linkPath, persistentObject.toLink(),
0349:                        linkDependencyGraph, queryFactory);
0350:            }
0351:
0352:            /**
0353:             * Return true if class is initialized.
0354:             *
0355:             * @param queryFactory QueryFactory
0356:             * @return true if class is initialized
0357:             */
0358:            protected boolean classInitialized(QueryFactory queryFactory) {
0359:                if (!complex()) {
0360:                    return false;
0361:                }
0362:                return registeredMasters().containsKey(
0363:                        registrationKey(queryFactory));
0364:            }
0365:
0366:            /**
0367:             * Re-registers master object under different registration key. Re-registration is done once per 1st
0368:             * usage of object of this class with specific Persistency.
0369:             *
0370:             * @param oldRegistrationKey
0371:             * @param newRegistrationKey
0372:             */
0373:            protected void reregisterMaster(String oldRegistrationKey,
0374:                    String newRegistrationKey) {
0375:                PersistentObject master = (PersistentObject) registeredMasters()
0376:                        .get(oldRegistrationKey);
0377:                registeredMasters().put(newRegistrationKey, master);
0378:            }
0379:
0380:            /**
0381:             * Retrieves master object from the registry using QueryFactory to build registration key
0382:             *
0383:             * @param queryFactory QueryFactory
0384:             * @return master PersistentObject
0385:             */
0386:            protected PersistentObject master(QueryFactory queryFactory) {
0387:                return (PersistentObject) registeredMasters().get(
0388:                        registrationKey(this .getClass(), queryFactory));
0389:            }
0390:
0391:            /**
0392:             * Return registeredMasters Map. Has to be overriden in descendants.
0393:             *
0394:             * @return registeredMasters Map
0395:             * @throws UnsupportedOperationException if it is not overridden by descendant
0396:             */
0397:            protected Map registeredMasters() {
0398:                throw new UnsupportedOperationException();
0399:            }
0400:
0401:            /**
0402:             * Returns class lock for objects of this class
0403:             *
0404:             * @return class lock
0405:             */
0406:            protected Object classLock() {
0407:                return this .getClass();
0408:            }
0409:
0410:            /**
0411:             * Adds child links to the master object.
0412:             *
0413:             * @param queryFactory
0414:             * @param master
0415:             */
0416:            protected void registerDependent(QueryFactory queryFactory,
0417:                    PersistentObject master) {
0418:                Map circularCheckSet = new HashMap();
0419:                Link[] links = master.retrieveLinks(queryFactory);
0420:                Link parentLink = master.record().toLink();
0421:                registerDependent(queryFactory, parentLink, links,
0422:                        circularCheckSet);
0423:            }
0424:
0425:            private void registerDependent(QueryFactory queryFactory,
0426:                    Link parentLink, Link[] links, Map circularCheckSet) {
0427:                if (links != null) {
0428:                    for (int i = 0; i < links.length; i++) {
0429:                        Link linkToAdd = links[i];
0430:                        if (linkToAdd.getName() == null) {
0431:                            throw new IllegalArgumentException(
0432:                                    "Link name is null");
0433:                        }
0434:                        //
0435:                        // Check if the link already there:
0436:                        //
0437:                        // Get class:
0438:                        Class parentClazz;
0439:                        PersistentObjectFactory parentFactory;
0440:                        if (parentLink.getQuery() != null
0441:                                && parentLink.getQuery()
0442:                                        .getSingularResultFactory() != null) {
0443:                            parentFactory = parentLink.getQuery()
0444:                                    .getSingularResultFactory();
0445:                            parentClazz = parentFactory.getClass();
0446:                        } else {
0447:                            parentFactory = this ;
0448:                            parentClazz = this .getClass();
0449:                        }
0450:
0451:                        Class childClazz;
0452:                        PersistentObjectFactory childFactory;
0453:                        if (linkToAdd.getQuery() != null
0454:                                && linkToAdd.getQuery()
0455:                                        .getSingularResultFactory() != null) {
0456:                            childFactory = linkToAdd.getQuery()
0457:                                    .getSingularResultFactory();
0458:                            childClazz = childFactory.getClass();
0459:                        } else {
0460:                            throw new IllegalArgumentException(
0461:                                    "Link with no query or Singular result factory ");
0462:                        }
0463:
0464:                        String key;
0465:                        if ((key = circularDependencyKey(parentFactory,
0466:                                childFactory, linkToAdd)) == null) {
0467:                            key = circularDependencyKey(parentClazz,
0468:                                    childClazz, linkToAdd);
0469:                        }
0470:                        if (circularCheckSet.containsKey(key)) {
0471:                            //
0472:                            // Circular dependency now is okay - do not propagate:
0473:                            //
0474:                            Link circularLink = (Link) circularCheckSet
0475:                                    .get(key);
0476:                            circularLink.setEndOfChain(true);
0477:                            return;
0478:                        } else {
0479:                            circularCheckSet.put(key, linkToAdd);
0480:                        }
0481:
0482:                        parentLink.addChild(linkToAdd);
0483:
0484:                        if (linkToAdd.getQuery() != null
0485:                                && linkToAdd.getQuery()
0486:                                        .getSingularResultFactory() != null) {
0487:                            PersistentObject temp = (PersistentObject) links[i]
0488:                                    .getQuery().getSingularResultFactory();
0489:                            if (temp.complex()) {
0490:                                Link[] tempLinks = temp
0491:                                        .retrieveLinks(queryFactory);
0492:                                if (tempLinks != null && tempLinks.length > 0) {
0493:                                    registerDependent(queryFactory, linkToAdd,
0494:                                            tempLinks, circularCheckSet);
0495:                                }
0496:                            }
0497:                        }
0498:                    }
0499:                }
0500:            }
0501:
0502:            private String circularDependencyKey(Class parentClazz,
0503:                    Class childClazz, Link linkToAdd) {
0504:                return parentClazz.getName() + Link.SEP + childClazz.getName()
0505:                        + Link.SEP + linkToAdd.getName();
0506:            }
0507:
0508:            private String circularDependencyKey(
0509:                    PersistentObjectFactory parentFactory,
0510:                    PersistentObjectFactory childFactory, Link linkToAdd) {
0511:                if (parentFactory instanceof  PersistentObject) {
0512:                    PersistentObject parent = (PersistentObject) parentFactory;
0513:                    if (parent.record() != null) {
0514:                        String parentTableName = parent.record().getTableName();
0515:                        String childTableName = ((PersistentObject) childFactory)
0516:                                .record().getTableName();
0517:                        return parentTableName + Link.SEP + childTableName
0518:                                + Link.SEP + linkToAdd.getName();
0519:                    } else {
0520:                        return null;
0521:                    }
0522:                } else {
0523:                    return null;
0524:                }
0525:            }
0526:
0527:            /**
0528:             * Builds master object registration key based on class name and QueryFactory
0529:             *
0530:             * @param queryFactory
0531:             * @return master object registration key
0532:             */
0533:            protected String registrationKey(QueryFactory queryFactory) {
0534:                return registrationKey(this .getClass(), queryFactory);
0535:            }
0536:
0537:            /**
0538:             * Builds master object registration key based on class name and QueryFactory
0539:             *
0540:             * @param clazz        Class
0541:             * @param queryFactory QueryFactory
0542:             * @return master object registration key
0543:             */
0544:            static String registrationKey(Class clazz, QueryFactory queryFactory) {
0545:                Persistency persistency = queryFactory.getPersistency();
0546:                return new StringBuffer(clazz.getName()).append("|").append(
0547:                        persistency.getClass().getName()).append("@").append(
0548:                        Integer.toHexString(persistency.hashCode())).toString();
0549:            }
0550:
0551:            /**
0552:             * Returns links that define children of this <tt>PersistentObject</tt>
0553:             *
0554:             * @param queryFactory
0555:             * @return Link[] - links that define children of this <tt>PersistentObject</tt>
0556:             */
0557:            protected Link[] links(QueryFactory queryFactory) {
0558:                return null;
0559:            }
0560:
0561:            /**
0562:             * Returns <tt>Link</tt> reperesentation of this <tt>PersistentObject</tt>
0563:             *
0564:             * @return Link reperesentation of this Record
0565:             */
0566:            public Link toLink() {
0567:                Link link = _record.toLink();
0568:                link.setResult(this );
0569:                return link;
0570:            }
0571:
0572:            private Record dependencyGraph() {
0573:                if (_record.getDependencyGraph() == null) {
0574:                    LinkDependencyGraph dependencyGraph = new LinkDependencyGraph();
0575:                    _record.setDependencyGraph(dependencyGraph);
0576:                }
0577:                return _record;
0578:            }
0579:
0580:            /**
0581:             * Assembles <tt>LinkDependencyGraph</tt> associated with this <tt>PersistentObject</tt>
0582:             */
0583:            public void assemble() {
0584:                dependencyGraph().assemble(this );
0585:            }
0586:
0587:            private void validate(Record record) {
0588:                if (record == null) {
0589:                    throw new IllegalArgumentException("Record may not be null");
0590:                }
0591:            }
0592:
0593:            /**
0594:             * Returns <tt>Record</tt> associated with this <tt>PersistentObject</tt>
0595:             *
0596:             * @return <tt>Record</tt> associated with this <tt>PersistentObject</tt>
0597:             */
0598:            public Record record() {
0599:                return _record;
0600:            }
0601:
0602:            /**
0603:             * Sets <tt>Record</tt> associated with this <tt>PersistentObject</tt>
0604:             */
0605:            protected void record(Record record) {
0606:                validate(record);
0607:                this ._record = record;
0608:                this ._record.setPersistentObject(this );
0609:            }
0610:
0611:            /**
0612:             * Returns <tt>Record</tt> associated with this <tt>PersistentObject</tt>
0613:             *
0614:             * @return <tt>Record</tt> associated with this <tt>PersistentObject</tt>
0615:             * @throws OdalRuntimePersistencyException
0616:             *          if this object is flattened
0617:             */
0618:            public Record record2() {
0619:                invalidateOnFlattened();
0620:                return _record;
0621:            }
0622:
0623:            /**
0624:             * Sets autoPadChars flag.
0625:             * If set to true, character fields will be right padded with spaces to column length
0626:             *
0627:             * @param autoPadChars if true char fields will be right padded with spaces to column length
0628:             */
0629:            public void autoPadChars(boolean autoPadChars) {
0630:                _record.setAutoPadChars(autoPadChars);
0631:            }
0632:
0633:            /**
0634:             * Factory mathod
0635:             *
0636:             * @return new <tt>PersistentObject</tt>
0637:             */
0638:            public PersistentObject newPersistentObject() {
0639:                try {
0640:                    PersistentObject persistentObject = (PersistentObject) this 
0641:                            .getClass().newInstance();
0642:                    if (persistentObject.record() == null && _record != null) {
0643:                        persistentObject.record(_record.newRecord());
0644:                        persistentObject.toLink();
0645:                    }
0646:                    persistentObject._trace = _trace;
0647:                    persistentObject.postInitializeRecord();
0648:                    return persistentObject;
0649:                } catch (Exception e) {
0650:                    throw new RuntimeException(
0651:                            "Cannot instantiate PersistentObject by class name ["
0652:                                    + this .getClass().getName() + "]", e);
0653:                }
0654:            }
0655:
0656:            /**
0657:             * Performs pre-setup of "to" object based on properties of "from" object.
0658:             * Namely, all results are copied from "from" to "to" excluding those of child objects.
0659:             * Newly created "to" record is linked to "to" PersistentObject.
0660:             *
0661:             * @param to   target <tt>PersistentObject</tt>
0662:             * @param from <tt>PersistentObject</tt> used as a template
0663:             */
0664:            protected static void newPersistentObjectPreSetup(
0665:                    PersistentObject to, PersistentObject from) {
0666:                if (from != null) {
0667:                    Record origRecord = to.record();
0668:                    Record fromRecord = from.record();
0669:                    to.record(fromRecord.newRecord());
0670:                    to.record().copyDirty(origRecord, null);
0671:                    to.record().setPersistentObject(to);
0672:                    Link toLink = to.toLink();
0673:                    Link origToLink = origRecord.toLink();
0674:                    toLink.copyResultsOneLevel(origToLink);
0675:                }
0676:            }
0677:
0678:            /**
0679:             * Performs setup of "to" object based on properties of "from" object.
0680:             * Namely, links structure, served as meta-data, is copied from "from" <tt>PersistentObject</tt>
0681:             * to "to" one.
0682:             *
0683:             * @param to   target <tt>PersistentObject</tt>
0684:             * @param from <tt>PersistentObject</tt> used as a template
0685:             */
0686:            protected static void newPersistentObjectSetup(PersistentObject to,
0687:                    PersistentObject from) {
0688:                if (from != null) {
0689:                    Record origRecord = to.record();
0690:                    to.record(from.record().newRecord());
0691:                    Record.setupPrimitiveFields(origRecord, to.record());
0692:                    to.record().copyPreseveStates(origRecord);
0693:                    Link toLink = to.toLink();
0694:                    Link origToLink = origRecord.toLink();
0695:                    toLink.copyResults(origToLink);
0696:                }
0697:            }
0698:
0699:            /**
0700:             * Returns <tt>PersistentObjectFactory</tt> of this object
0701:             *
0702:             * @return <tt>PersistentObjectFactory</tt> of this object
0703:             */
0704:            protected PersistentObjectFactory factory() {
0705:                return this ;
0706:            }
0707:
0708:            /**
0709:             * @return new instance of this object preserving tracing mode
0710:             * @see PersistentObject#traceOn()
0711:             * @see PersistentObject#traceOff()
0712:             */
0713:            public AbstractPersistentObject newPersistentInstance() {
0714:                return newPersistentObject();
0715:            }
0716:
0717:            /**
0718:             * Returns deep copy of this object
0719:             *
0720:             * @return deep copy of this object
0721:             */
0722:            public Object clone() {
0723:                PersistentObject persistentObject = (PersistentObject) super 
0724:                        .clone();
0725:                try {
0726:                    if (!flattened()) {
0727:                        persistentObject.record((Record) _record.clone());
0728:                        persistentObject._preinitializedComplex = false;
0729:                        persistentObject.toLink();
0730:                        persistentObject.toBeanFields();
0731:                        persistentObject.unmarkInitializedComplex();
0732:                        persistentObject._record
0733:                                .setPersistentObject(persistentObject);
0734:                    }
0735:                    return persistentObject;
0736:                } catch (Exception e) {
0737:                    throw new OdalRuntimePersistencyException(
0738:                            "Cannot clone PersistentObject by class name ["
0739:                                    + this .getClass().getName() + "]", e);
0740:                }
0741:            }
0742:
0743:            /**
0744:             * Copies updateable fields from source record to this record.
0745:             * Only "dirty" fields are copied
0746:             *
0747:             * @param source source <tt>PersistentObject</tt>
0748:             */
0749:            public void copyDirty(PersistentObject source) {
0750:                copyDirty(source, null);
0751:            }
0752:
0753:            /**
0754:             * Copies updateable fields from source record to this record.
0755:             * Only "dirty" fields are copied
0756:             *
0757:             * @param source           source <tt>PersistentObject</tt>
0758:             * @param updateableFields set of updateable column names
0759:             */
0760:            public void copyDirty(PersistentObject source, Set updateableFields) {
0761:                copy(source, updateableFields, true);
0762:            }
0763:
0764:            /**
0765:             * Copies updateable fields from source persistent object to this persistent object.
0766:             * If the persistent objects are compound then all the entries will be copied.
0767:             * If updateableFields Set is null then all dirty fields will be copied.
0768:             * If dirtyFieldsOnly flag is true then only dirty fields are copied
0769:             *
0770:             * @param source           source <tt>PersistentObject</tt>
0771:             * @param updateableFields set of updateable column names
0772:             * @param dirtyFieldsOnly  if true only dirty fields are copied
0773:             */
0774:            public void copy(PersistentObject source, Set updateableFields,
0775:                    boolean dirtyFieldsOnly) {
0776:                copy(source, updateableFields, dirtyFieldsOnly, false);
0777:            }
0778:
0779:            /**
0780:             * Copies updateable fields from source persistent object to this persistent object.
0781:             * If the persistent objects are compound then all the entries will be copied.
0782:             * If updateableFields Set is null then all dirty fields will be copied.
0783:             * If dirtyFieldsOnly flag is true then only dirty fields are copied
0784:             *
0785:             * @param source           source <tt>PersistentObject</tt>
0786:             * @param updateableFields set of updateable column names
0787:             * @param dirtyFieldsOnly  if true only dirty fields are copied
0788:             * @param preserveStates   if true target record "dirty" states are set the same as the source record fields "dirty" states
0789:             *                         even if the values are the same
0790:             */
0791:            public void copy(PersistentObject source, Set updateableFields,
0792:                    boolean dirtyFieldsOnly, boolean preserveStates) {
0793:                if (this .compound() && !source.compound() || !this .compound()
0794:                        && source.compound()) {
0795:                    throw new IllegalArgumentException(
0796:                            "Cannot copy since source and target objects "
0797:                                    + "compound properties are different");
0798:                } else if (this .compound() && source.compound()) {
0799:                    if (this .compoundSize() != source.compoundSize()) {
0800:                        throw new IllegalArgumentException(
0801:                                "Cannot copy since number of compound entries in source and target objects "
0802:                                        + "is different");
0803:                    }
0804:                }
0805:
0806:                if (compound()) {
0807:                    PersistentObject[] this Entries = compoundEntries();
0808:                    for (int i = 0; i < this Entries.length; i++) {
0809:                        PersistentObject this Entry = this Entries[i];
0810:                        PersistentObject sourceEntry = source.compoundEntry(i);
0811:                        copyBasic(sourceEntry, this Entry, updateableFields,
0812:                                dirtyFieldsOnly, preserveStates);
0813:                    }
0814:                } else {
0815:                    copyBasic(source, this , updateableFields, dirtyFieldsOnly,
0816:                            preserveStates);
0817:                }
0818:            }
0819:
0820:            /**
0821:             * Copies updateable fields from source basic persistent object to this  basic persistent object.
0822:             * If updateableFields Set is null then all dirty fields will be copied.
0823:             * If dirtyFieldsOnly flag is true then only dirty fields are copied
0824:             *
0825:             * @param source           source <tt>PersistentObject</tt>
0826:             * @param updateableFields set of updateable column names
0827:             * @param dirtyFieldsOnly  if true only dirty fields are copied
0828:             */
0829:            public void copyBasic(PersistentObject source,
0830:                    Set updateableFields, boolean dirtyFieldsOnly) {
0831:                copyBasic(source, this , updateableFields, dirtyFieldsOnly,
0832:                        false);
0833:            }
0834:
0835:            /**
0836:             * Copies all fields from source basic persistent object to this basic persistent object.
0837:             *
0838:             * @param source source <tt>PersistentObject</tt>
0839:             *               from source record to this record even if the values are the same
0840:             */
0841:            public void copyBasic(PersistentObject source) {
0842:                copyBasic(source, null, false);
0843:            }
0844:
0845:            /**
0846:             * Copies updateable fields from source basic persistent object to this basic persistent object.
0847:             * Only "dirty" fields are copied
0848:             *
0849:             * @param source           source <tt>PersistentObject</tt>
0850:             * @param updateableFields set of updateable column names
0851:             */
0852:            public void copyBasicDirty(PersistentObject source,
0853:                    Set updateableFields) {
0854:                copyBasic(source, updateableFields, true);
0855:            }
0856:
0857:            /**
0858:             * Copies updateable fields from source basic persistent object to this  basic persistent object.
0859:             * If updateableFields Set is null then all dirty fields will be copied.
0860:             * If dirtyFieldsOnly flag is true then only dirty fields are copied
0861:             *
0862:             * @param source           source <tt>PersistentObject</tt>
0863:             * @param target           target <tt>PersistentObject</tt>
0864:             * @param updateableFields set of updateable column names
0865:             * @param dirtyFieldsOnly  if true only dirty fields are copied
0866:             * @param preserveStates   if true target record "dirty" states are set the same as the source record fields "dirty" states
0867:             *                         even if the values are the same
0868:             */
0869:            public static void copyBasic(PersistentObject source,
0870:                    PersistentObject target, Set updateableFields,
0871:                    boolean dirtyFieldsOnly, boolean preserveStates) {
0872:                if (source == null) {
0873:                    throw new IllegalArgumentException("Source object is null");
0874:                }
0875:                if (target == null) {
0876:                    throw new IllegalArgumentException("Target object is null");
0877:                }
0878:                if (preserveStates) {
0879:                    target.record2().copyPreseveStates(source.record(),
0880:                            updateableFields, dirtyFieldsOnly);
0881:                } else {
0882:                    target.record2().copy(source.record(), updateableFields,
0883:                            dirtyFieldsOnly);
0884:                }
0885:                target.toBeanFields();
0886:            }
0887:
0888:            /**
0889:             * Copies all fields from source record to this record.
0890:             *
0891:             * @param source source <tt>PersistentObject</tt>
0892:             *               from source record to this record even if the values are the same
0893:             */
0894:            public void copy(PersistentObject source) {
0895:                copy(source, null, false);
0896:            }
0897:
0898:            /**
0899:             * Copies all fields from source persistent object to this persistent object.
0900:             * Target record "dirty" states are set the same as the source record fields "dirty" states
0901:             * even if the values are the same
0902:             *
0903:             * @param source source <tt>PersistentObject</tt>
0904:             *               from source record to this record even if the values are the same
0905:             */
0906:            public void copyPreserveStates(PersistentObject source) {
0907:                copy(source, null, false, true);
0908:            }
0909:
0910:            /**
0911:             * Right pads character fields to column length with spaces.
0912:             *
0913:             * @param index
0914:             * @param value
0915:             * @return Object
0916:             */
0917:            public String v2c(int index, String value) {
0918:                return (String) _record.v2c(index, value);
0919:            }
0920:
0921:            /**
0922:             * Returns  <tt>Parameters</tt> object based on values and column types of the record for columns with indeces
0923:             * specified with "indeces" parameter. This method will populate parameters regardless of whether they are
0924:             * "dirty" flags or nulls
0925:             *
0926:             * @param indeces
0927:             * @return Parameters object based on values and column types of the record for columns with indeces
0928:             *         specified with "indeces" parameter
0929:             */
0930:            public Parameters toParameters(int[] indeces) {
0931:                return _record.toParameters(indeces);
0932:            }
0933:
0934:            /**
0935:             * Returns <tt>Parameters</tt> object based on values and column types of the record.
0936:             * This method will populate parameters only if corresponding fields are
0937:             * "dirty" and not nulls
0938:             *
0939:             * @param primaryKeyOnly if true only primary key columns are considered
0940:             * @return Parameters object based on values and column types of the record
0941:             */
0942:            public Parameters toNotNullParameters(boolean primaryKeyOnly) {
0943:                return _record.toNotNullParameters(primaryKeyOnly);
0944:            }
0945:
0946:            /**
0947:             * Returns <tt>Parameters</tt> object based on values and column types of the record.
0948:             * This method will populate parameters only if corresponding fields are
0949:             * "dirty" and not nulls
0950:             *
0951:             * @return Parameters object based on values and column types of the record
0952:             */
0953:            public Parameters toNotNullParameters() {
0954:                return _record.toNotNullParameters(false);
0955:            }
0956:
0957:            /**
0958:             * Returns <tt>Parameters</tt> object based on values and column types of the record.
0959:             * This method will populate parameters only if corresponding fields are "dirty"
0960:             *
0961:             * @param primaryKeyOnly if true only primary key columns are considered
0962:             * @return Parameters object based on values and column types of the record
0963:             */
0964:            public Parameters toParameters(boolean primaryKeyOnly) {
0965:                return _record.toParameters(primaryKeyOnly);
0966:            }
0967:
0968:            /**
0969:             * Returns <tt>Parameters</tt> object based on values and column types of the record.
0970:             * This method will populate parameters only if corresponding fields are "dirty"
0971:             *
0972:             * @return Parameters object based on values and column types of the record
0973:             */
0974:            public Parameters toParameters() {
0975:                return _record.toParameters(false);
0976:            }
0977:
0978:            /**
0979:             * Add child link with specific name
0980:             *
0981:             * @param link
0982:             * @throws NullPointerException if link has no name set
0983:             * @see Link
0984:             */
0985:            public void addChild(Link link) {
0986:                _record.addChild(link);
0987:            }
0988:
0989:            /**
0990:             * Add child link with specific name as ad-hoc link.
0991:             * Ad-hoc links are not part of the Link Dependency Graph and hence the objcts they contain
0992:             * cannot be inserted/updated/deleted. It is dynamically added read only data.
0993:             *
0994:             * @param name
0995:             * @param data
0996:             * @return  newly added link
0997:             */
0998:            public Link addAdHocChild(String name, Object data) {
0999:                Link link = new Link(name, data);
1000:                _record.addChild(link);
1001:                return link;
1002:            }
1003:
1004:            /**
1005:             * Returns record <tt>LinkIterator</tt>
1006:             *
1007:             * @return <tt>LinkIterator</tt>
1008:             */
1009:            public LinkIterator linkIterator() {
1010:                return _record.linkIterator();
1011:            }
1012:
1013:            /**
1014:             * Returns child link by name
1015:             *
1016:             * @return child link by name
1017:             */
1018:            public Link child(String name) {
1019:                return _record.getChild(name);
1020:            }
1021:
1022:            /**
1023:             * Returns true if this record has child links
1024:             *
1025:             * @return true if this record has child links
1026:             */
1027:            public boolean hasChildren() {
1028:                return hasChildren0();
1029:            }
1030:
1031:            private boolean hasChildren0() {
1032:                return _record != null && _record.hasChildren();
1033:            }
1034:
1035:            /**
1036:             * Get child link result w/o
1037:             * causing lazy retrieval to fire
1038:             *
1039:             * @param name
1040:             * @return Object
1041:             */
1042:            public Object getChildObjectStraight(String name) {
1043:                return _record.getChildObjectStraight(name);
1044:            }
1045:
1046:            /**
1047:             * Get child link result object
1048:             *
1049:             * @param name
1050:             * @return child link result object
1051:             * @throws OdalRuntimePersistencyException if child retrieval from database failed
1052:             */
1053:            public Object getChildObject(String name) {
1054:                try {
1055:                    return _record.getChildObject(name);
1056:                } catch (SQLException e) {
1057:                    throw new OdalRuntimePersistencyException(
1058:                            "Cannot get child object", e);
1059:                }
1060:            }
1061:
1062:            /**
1063:             * Gets child link result object. If result object is instance of Collection and
1064:             * collection size is greater than zero the 1st collection element is returned.
1065:             * If result object is instance of Collection and collection size is zero then null
1066:             * is returned.
1067:             *
1068:             * @param name
1069:             * @return child link result object. If result object is instance of Collection and
1070:             *         collection size is greater than zero the 1st collection element is returned.
1071:             *         If result object is instance of Collection and collection size is zero then null
1072:             *         is returned.
1073:             * @throws OdalRuntimePersistencyException if child retrieval from database failed
1074:             */
1075:            public Object getFirstChildObject(String name) {
1076:                Object value;
1077:                try {
1078:                    value = _record.getChildObject(name);
1079:                } catch (SQLException e) {
1080:                    throw new OdalRuntimePersistencyException(
1081:                            "Cannot get First Child Object", e);
1082:                }
1083:                return resolveCollection(value);
1084:            }
1085:
1086:            /**
1087:             * Gets child link result object w/o
1088:             * causing lazy retrieval to fire. If result object is instance of Collection and
1089:             * collection size is greater than zero the 1st collection element is returned.
1090:             * If result object is instance of Collection and collection size is zero then null
1091:             * is returned.
1092:             *
1093:             * @param name
1094:             * @return child link result object. If result object is instance of Collection and
1095:             *         collection size is greater than zero the 1st collection element is returned.
1096:             *         If result object is instance of Collection and collection size is zero then null
1097:             *         is returned.
1098:             */
1099:            public Object getFirstChildObjectStraight(String name) {
1100:                Object o = _record.getChildObjectStraight(name);
1101:                return resolveCollection(o);
1102:            }
1103:
1104:            private Object resolveCollection(Object o) {
1105:                if (o instanceof  Collection) {
1106:                    Collection collection = (Collection) o;
1107:                    return collection.size() > 0 ? collection.iterator().next()
1108:                            : null;
1109:                } else {
1110:                    return o;
1111:                }
1112:            }
1113:
1114:            /**
1115:             * Sets result value to link with specific name name
1116:             *
1117:             * @param name  name of child link
1118:             * @param value
1119:             * @see Link#setResult(Object)
1120:             * @see Link#getName()
1121:             */
1122:            public void setChildObject(String name, Object value) {
1123:                _record.setChildObject(name, value);
1124:            }
1125:
1126:            public String toString() {
1127:                StringBuffer buffer = new StringBuffer(super .toString());
1128:                buffer.append(" = { Record = ").append(_record).append("} ");
1129:                return buffer.toString();
1130:            }
1131:
1132:            /**
1133:             * Returns "deep" string reperesentation of this object
1134:             *
1135:             * @param persistentObject
1136:             * @return "deep" string reperesentation of this object
1137:             */
1138:            public static String toGenericString(
1139:                    PersistentObject persistentObject) {
1140:                if (persistentObject == null) {
1141:                    return "null";
1142:                } else {
1143:                    StringBuffer buffer = new StringBuffer(persistentObject
1144:                            .toString());
1145:                    if (persistentObject.compound()) {
1146:                        buffer.append("-> {compoundChildren: ");
1147:                        for (int i = 1; i < persistentObject.compoundSize(); i++) {
1148:                            PersistentObject entry = persistentObject
1149:                                    .compoundEntry(i);
1150:                            buffer.append(toGenericString(entry));
1151:                        }
1152:                        buffer.append("} ");
1153:                    }
1154:
1155:                    if (persistentObject.hasChildren()) {
1156:                        buffer.append("-> {complexChildren: ");
1157:                        for (LinkIterator it = persistentObject.linkIterator(); it
1158:                                .hasNext();) {
1159:                            Link link = it.nextLink();
1160:                            String name = link.getName();
1161:                            Object result = link.getResult();
1162:                            String linkSummary = link.getName() == null ? ""
1163:                                    : link.toSummaryString();
1164:
1165:                            if (result instanceof  PersistentObject) {
1166:                                PersistentObject childObject = (PersistentObject) result;
1167:                                buffer.append("-> {child ").append(linkSummary)
1168:                                        .append("->{").append(
1169:                                                toGenericString(childObject))
1170:                                        .append("}}");
1171:                            } else if (result instanceof  List) {
1172:                                List list = (List) result;
1173:                                buffer.append("-> {child : ").append(
1174:                                        linkSummary).append("->{").append(
1175:                                        " List[").append(list.size()).append(
1176:                                        "]: ").append(name).append(" {[");
1177:
1178:                                for (int i = 0; i < list.size(); i++) {
1179:                                    String comma = i == 0 ? "" : ", ";
1180:                                    PersistentObject childObject = (PersistentObject) list
1181:                                            .get(i);
1182:                                    buffer.append(comma).append(
1183:                                            toGenericString(childObject));
1184:                                }
1185:                                buffer.append("]}}}");
1186:                            } else {
1187:                                buffer.append("; {child ").append(linkSummary)
1188:                                        .append(" {").append("null").append(
1189:                                                "}}");
1190:                            }
1191:                        }
1192:                        buffer.append("}");
1193:                    }
1194:                    return buffer.toString();
1195:                }
1196:            }
1197:
1198:            //
1199:            // Facade to record:
1200:            //
1201:
1202:            /**
1203:             * Returns field value as Object
1204:             *
1205:             * @param index
1206:             * @return field value as Object
1207:             */
1208:            public Object objectValue(int index) {
1209:                return _record.getObject(index);
1210:            }
1211:
1212:            /**
1213:             * Returns field value as String
1214:             *
1215:             * @param index
1216:             * @return field value as String
1217:             */
1218:            public String stringValue(int index) {
1219:                return _record.getString(index);
1220:            }
1221:
1222:            /**
1223:             * Returns field value as Boolean
1224:             *
1225:             * @param index
1226:             * @return field value as Boolean
1227:             */
1228:            public Boolean booleanValue(int index) {
1229:                return _record.getBoolean(index);
1230:            }
1231:
1232:            /**
1233:             * Returns field value as Date
1234:             *
1235:             * @param index
1236:             * @return field value as Date
1237:             */
1238:            public Date dateValue(int index) {
1239:                return _record.getDate(index);
1240:            }
1241:
1242:            /**
1243:             * Returns field value as Object
1244:             *
1245:             * @param columnName
1246:             * @return field value as Object
1247:             */
1248:            public Object objectValue(String columnName) {
1249:                return _record.getObject(columnName);
1250:            }
1251:
1252:            /**
1253:             * Returns field value as String
1254:             *
1255:             * @param columnName
1256:             * @return field value as String
1257:             */
1258:            public String stringValue(String columnName) {
1259:                return _record.getString(columnName);
1260:            }
1261:
1262:            /**
1263:             * Returns field value as Boolean
1264:             *
1265:             * @param columnName
1266:             * @return field value as Boolean
1267:             */
1268:            public Boolean booleanValue(String columnName) {
1269:                return _record.getBoolean(columnName);
1270:            }
1271:
1272:            /**
1273:             * Returns field value as Date
1274:             *
1275:             * @param columnName
1276:             * @return field value as Date
1277:             */
1278:            public Date dateValue(String columnName) {
1279:                return _record.getDate(columnName);
1280:            }
1281:
1282:            /**
1283:             * Return objects key. Its value will be used to identify object in TracingCollection updates.
1284:             *
1285:             * @return objects key
1286:             * @see AbstractPersistentObject#toKey()
1287:             */
1288:            public Object toKey() {
1289:                return super .toKey();
1290:            }
1291:
1292:            /**
1293:             * Marks field as dirty
1294:             *
1295:             * @param index
1296:             */
1297:            public void markFieldDirty(int index) {
1298:                record().markFieldDirty(index);
1299:            }
1300:
1301:            /**
1302:             * Resets dirty flag
1303:             *
1304:             * @param index
1305:             */
1306:            public void unmarkFieldDirty(int index) {
1307:                record().unmarkFieldDirty(index);
1308:            }
1309:
1310:            /**
1311:             * Marks all fields as dirty
1312:             */
1313:            public void markAllFieldsDirty() {
1314:                _record.markAllFieldsDirty();
1315:            }
1316:
1317:            /**
1318:             * Resets dirty flags
1319:             */
1320:            public void unmarkAllFieldsDirty() {
1321:                _record.unmarkAllFieldsDirty();
1322:            }
1323:
1324:            /**
1325:             * Returns true if this is complex object
1326:             *
1327:             * @return true if this is complex object
1328:             */
1329:            public boolean complex() {
1330:                return false;
1331:            }
1332:
1333:            /**
1334:             * Experimental
1335:             */
1336:            public Link[] inlineLinks() {
1337:                return _record.getInlineLinks();
1338:            }
1339:
1340:            /**
1341:             * Marks this object as "InitializedComplex"
1342:             */
1343:            public void markInitializedComplex() {
1344:                if (!_initializedComplex) {
1345:                    synchronized (this ) {
1346:                        _initializedComplex = true;
1347:                    }
1348:                }
1349:            }
1350:
1351:            /**
1352:             * Unmarks this object as "InitializedComplex". Also resets LinkDependencyGraph.
1353:             */
1354:            public void unmarkInitializedComplex() {
1355:                if (_initializedComplex) {
1356:                    synchronized (this ) {
1357:                        _initializedComplex = false;
1358:                        if (_record != null) {
1359:                            _record.setDependencyGraph(null);
1360:                        }
1361:                    }
1362:                }
1363:            }
1364:
1365:            /**
1366:             * Returns true if this object passed "initialization for complex" stage
1367:             *
1368:             * @return true if this object passed "initialization for complex" stage
1369:             */
1370:            public boolean initializedComplex() {
1371:                return _initializedComplex;
1372:            }
1373:
1374:            //
1375:            // For external serialization:
1376:            //
1377:
1378:            /**
1379:             * Implementation of Externalizable interface
1380:             *
1381:             * @param out ObjectOutput
1382:             * @throws IOException
1383:             * @see java.io.Externalizable
1384:             */
1385:            public void writeExternal(ObjectOutput out) throws IOException {
1386:                invalidateOnFlattened();
1387:                _record.writeExternal(out);
1388:                writeExternalDescendant(out);
1389:                if (compound()) {
1390:                    for (int i = 1; i < persistentObjects.length; i++) {
1391:                        PersistentObject persistentObject = persistentObjects[i];
1392:                        persistentObject.writeExternal(out);
1393:                    }
1394:                }
1395:            }
1396:
1397:            /**
1398:             * Implementation of Externalizable interface
1399:             *
1400:             * @param in ObjectInput
1401:             * @throws IOException
1402:             * @throws ClassNotFoundException
1403:             * @see java.io.Externalizable
1404:             */
1405:            public void readExternal(ObjectInput in) throws IOException,
1406:                    ClassNotFoundException {
1407:                invalidateOnFlattened();
1408:                _record.readExternal(in);
1409:                toBeanFields();
1410:                readExternalDescendant(in);
1411:                if (compound()) {
1412:                    for (int i = 1; i < persistentObjects.length; i++) {
1413:                        PersistentObject persistentObject = persistentObjects[i];
1414:                        persistentObject.readExternal(in);
1415:                    }
1416:                }
1417:            }
1418:
1419:            /**
1420:             * Auxilliary serialization
1421:             *
1422:             * @param out ObjectOutput
1423:             * @throws IOException
1424:             */
1425:            public void writeExternalDescendant(ObjectOutput out)
1426:                    throws IOException {
1427:            }
1428:
1429:            /**
1430:             * Auxilliary deserialization
1431:             *
1432:             * @param in ObjectInput
1433:             * @throws IOException
1434:             * @throws ClassNotFoundException
1435:             */
1436:            public void readExternalDescendant(ObjectInput in)
1437:                    throws IOException, ClassNotFoundException {
1438:            }
1439:
1440:            //
1441:            // Bean fields manipuilation
1442:            //
1443:
1444:            /**
1445:             * Populates POJO fields
1446:             */
1447:            public void toBeanFields() {
1448:                toBeanFields(this );
1449:            }
1450:
1451:            /**
1452:             * Populates POJO fields of this PersistentObject from Record fields
1453:             * of sourcePersistentObject passed as parameter
1454:             *
1455:             * @param sourcePersistentObject
1456:             */
1457:            public void toBeanFields(PersistentObject sourcePersistentObject) {
1458:            }
1459:
1460:            public void fromBeanFields() {
1461:                fromBeanFields(this );
1462:            }
1463:
1464:            /**
1465:             * Populates Record fields of this PersistentObject from POJO fields
1466:             * of sourcePersistentObject passed as parameter
1467:             *
1468:             * @param sourcePersistentObject
1469:             */
1470:            public void fromBeanFields(PersistentObject sourcePersistentObject) {
1471:            }
1472:
1473:            /**
1474:             * Sets State.DATA_SAVED to PersistentObject passed as parameter
1475:             *
1476:             * @param persistentObject PersistentObject which state is to be set
1477:             */
1478:            protected void fromBeanFieldsDataSaved(
1479:                    PersistentObject persistentObject) {
1480:                fromBeanFields(persistentObject, State.DATA_SAVED);
1481:            }
1482:
1483:            /**
1484:             * Sets State to PersistentObject passed as parameter
1485:             *
1486:             * @param persistentObject PersistentObject which state is to be set
1487:             * @param state            State to set
1488:             */
1489:            protected void fromBeanFields(PersistentObject persistentObject,
1490:                    State state) {
1491:                persistentObject.record().setState(state);
1492:            }
1493:
1494:            /**
1495:             * Return true if object is flattened (its  record == null)
1496:             *
1497:             * @return true if object is flattened
1498:             */
1499:            public boolean flattened() {
1500:                return _record == null;
1501:            }
1502:
1503:            /**
1504:             * @throws OdalRuntimePersistencyException
1505:             *          if this object is flattened
1506:             */
1507:            protected void invalidateOnFlattened() {
1508:                if (flattened()) {
1509:                    throw new OdalRuntimePersistencyException(
1510:                            "Illegal attempt to use record on flattened object");
1511:                }
1512:            }
1513:
1514:            //
1515:            // Flatten related:
1516:            //
1517:
1518:            /**
1519:             * Override it in descendants to perform children "flattening"
1520:             */
1521:            protected void doFlatten() {
1522:            }
1523:
1524:            /**
1525:             * Override it in descendants to perform children "pre-flattening"
1526:             */
1527:            protected void doPreFlatten() {
1528:            }
1529:
1530:            /**
1531:             * Flattens <tt>PersistentObject</tt> passed as parameter
1532:             *
1533:             * @param persistentObject <tt>PersistentObject</tt> to be flattened
1534:             * @return <tt>PersistentObject</tt> passed as parameter
1535:             */
1536:            protected static PersistentObject flatten(
1537:                    PersistentObject persistentObject) {
1538:                if (persistentObject != null) {
1539:                    persistentObject.flatten();
1540:                }
1541:                return persistentObject;
1542:            }
1543:
1544:            protected void flatten0() {
1545:                doPreFlatten();
1546:                _record = null;
1547:                doFlatten();
1548:                //        return this;
1549:            }
1550:
1551:            //
1552:            // Unflatten related:
1553:            //
1554:
1555:            /**
1556:             * Override it in descendants to perform children "unflattening"
1557:             */
1558:            protected void doUnflatten() {
1559:            }
1560:
1561:            protected void unflatten0() {
1562:                fromBeanFields();
1563:                doUnflatten();
1564:                //        return this;
1565:            }
1566:
1567:            /**
1568:             * Unflattens link.
1569:             *
1570:             * @param parentLink      Link object to be unflattened
1571:             * @param childName       name of child object to be unflattened and set
1572:             * @param childPersistent <tt>PersistentObject</tt> to be unflatten and set to this PersistentObject
1573:             *                        under name specified by <tt>childName</tt> parameter
1574:             */
1575:            protected static PersistentObject unflatten(Link parentLink,
1576:                    String childName, PersistentObject childPersistent) {
1577:                if (childPersistent != null) {
1578:                    childPersistent.unflatten();
1579:                    parentLink.setChildObject(childName, childPersistent);
1580:                }
1581:                return childPersistent;
1582:            }
1583:
1584:            /**
1585:             * Unflattens link.
1586:             *
1587:             * @param parentLink Link object to be unflattened
1588:             * @param childName  name of child object to be unflattened and set
1589:             * @param slaves     Collection<PersistentObject> to be unflatten and set to this PersistentObject
1590:             *                   under name specified by <tt>childName</tt> parameter
1591:             */
1592:            protected static void unflatten(Link parentLink, String childName,
1593:                    Collection slaves) {
1594:                if (slaves != null) {
1595:                    for (Iterator iterator = slaves.iterator(); iterator
1596:                            .hasNext();) {
1597:                        PersistentObject persistent = (PersistentObject) iterator
1598:                                .next();
1599:                        if (persistent != null) {
1600:                            persistent.unflatten();
1601:                        }
1602:                    }
1603:                    parentLink.setChildObject(childName, slaves);
1604:                }
1605:            }
1606:
1607:            /**
1608:             * Flattens collection of persistent objects
1609:             *
1610:             * @param slaves Collection<PersistentObject> to be flattened
1611:             */
1612:            protected static void flatten(Collection slaves) {
1613:                if (slaves != null) {
1614:                    for (Iterator iterator = slaves.iterator(); iterator
1615:                            .hasNext();) {
1616:                        PersistentObject persistent = (PersistentObject) iterator
1617:                                .next();
1618:                        flatten(persistent);
1619:                    }
1620:                }
1621:            }
1622:
1623:            /**
1624:             * If this object is flattened returns value passed as parameter.<br>
1625:             * Otherwise:<br>
1626:             * If this object is not flattened gets child link result object. If result object is instance of Collection and
1627:             * collection size is greater than zero the 1st collection element is returned.
1628:             * If result object is instance of Collection and collection size is zero then null
1629:             * is returned.
1630:             *
1631:             * @param name
1632:             * @return If this object is flattened - value passed as parameter.<br>Otherwise:<br> If child link result object. If result object is instance of Collection and
1633:             *         collection size is greater than zero the 1st collection element is returned.
1634:             *         If result object is instance of Collection and collection size is zero then null
1635:             *         is returned.
1636:             */
1637:            protected Object getFirstChildObject(String name, Object value) {
1638:                if (!flattened()) {
1639:                    value = getFirstChildObject(name);
1640:                }
1641:                return value;
1642:            }
1643:
1644:            /**
1645:             * If this object is flattened returns value passed as parameter.<br>
1646:             * Otherwise:<br>
1647:             * If this object is not flattened gets child link result object w/o
1648:             * causing lazy retrieval to fire. If result object is instance of Collection and
1649:             * collection size is greater than zero the 1st collection element is returned.
1650:             * If result object is instance of Collection and collection size is zero then null
1651:             * is returned.
1652:             *
1653:             * @param name
1654:             * @return If this object is flattened - value passed as parameter.<br>Otherwise:<br> If child link result object. If result object is instance of Collection and
1655:             *         collection size is greater than zero the 1st collection element is returned.
1656:             *         If result object is instance of Collection and collection size is zero then null
1657:             *         is returned.
1658:             */
1659:            protected Object getFirstChildObjectStraight(String name,
1660:                    Object value) {
1661:                if (!flattened()) {
1662:                    value = getFirstChildObjectStraight(name);
1663:                }
1664:                return value;
1665:            }
1666:
1667:            /**
1668:             * If object is flattened then returns value specified by 'value' parameter else
1669:             * retrieves value by getChildObject(name) method
1670:             *
1671:             * @param name  child name
1672:             * @param value default value if object flattened
1673:             * @return If object is flattened - value specified by 'value' parameter else
1674:             *         retrieves value by getChildObject(name) method
1675:             */
1676:            protected Object getChildObject(String name, Object value) {
1677:                if (!flattened()) {
1678:                    value = getChildObject(name);
1679:                }
1680:                return value;
1681:            }
1682:
1683:            /**
1684:             * If object is flattened then returns value specified by 'value' parameter else
1685:             * retrieves value by getChildObject(name) method w/o
1686:             * causing lazy retrieval to fire
1687:             *
1688:             * @param name  child name
1689:             * @param value default value if object flattened
1690:             * @return Object If object is flattened then - value specified by 'value' parameter else
1691:             *         retrieves value by getChildObject(name) method w/o
1692:             *         causing lazy retrieval to fire
1693:             */
1694:            protected Object getChildObjectStraight(String name, Object value) {
1695:                if (!flattened()) {
1696:                    value = getChildObjectStraight(name);
1697:                }
1698:                return value;
1699:            }
1700:
1701:            /**
1702:             * Sets child object value if this <tt>PersistentObject</tt> is not flattened.
1703:             * Always returns newValue passed as parameter
1704:             *
1705:             * @param name
1706:             * @param newValue
1707:             * @return Object newValue parameter
1708:             */
1709:            protected Object setChildObjectSafe(String name, Object newValue) {
1710:                if (!flattened()) {
1711:                    setChildObject(name, newValue);
1712:                }
1713:                return newValue;
1714:            }
1715:
1716:            /**
1717:             * Performs Record post initialization activities.
1718:             */
1719:            protected void postInitializeRecord() {
1720:            }
1721:
1722:            /**
1723:             * Returns Boolean.TRUE if all newly created child Tracing Collections have to be forced to "trace on" mode,
1724:             * Boolean.FALSE if all newly created child Tracing Collections have to be forced to "trace off" mode,
1725:             * null if all newly created child Tracing Collections have to be left in default trace mode.
1726:             *
1727:             * @return Boolean.TRUE if all newly created child Tracing Collections have to be forced to "trace on" mode,
1728:             *         Boolean.FALSE if all newly created child Tracing Collections have to be forced to "trace off" mode,
1729:             *         null if all newly created child Tracing Collections have to be left in default trace mode.
1730:             */
1731:            public Boolean traced() {
1732:                return _trace;
1733:            }
1734:
1735:            /**
1736:             * Indicates that all newly created child Tracing Collections have to be forced to "trace on" mode.
1737:             *
1738:             * @return itself
1739:             */
1740:            public PersistentObject traceOn() {
1741:                this ._trace = Boolean.TRUE;
1742:                return this ;
1743:            }
1744:
1745:            /**
1746:             * Indicates that all newly created child Tracing Collections have to be forced to "trace off" mode.
1747:             * It makes sense to do it when your child objects are from the database and you do not want them
1748:             * to be saved again.
1749:             *
1750:             * @return itself
1751:             */
1752:            public PersistentObject traceOff() {
1753:                this ._trace = Boolean.FALSE;
1754:                return this ;
1755:            }
1756:
1757:            /**
1758:             * Immediately forces all child Tracing Collections have to be forced to "trace on" mode.
1759:             *
1760:             * @return itself
1761:             */
1762:            public PersistentObject traceOnAll() {
1763:                if (complex()) {
1764:                    Link link = toLink();
1765:                    for (LinkIterator it = link.linkIterator(); it.hasNext();) {
1766:                        Link childLink = it.nextLink();
1767:                        Object result = childLink.getResult();
1768:                        if (result instanceof  TracingCollection) {
1769:                            TracingCollection tracingCollection = (TracingCollection) result;
1770:                            tracingCollection.setTrace();
1771:                        }
1772:                    }
1773:                }
1774:                return this ;
1775:            }
1776:
1777:            /**
1778:             * Immediately forces all child Tracing Collections have to be forced to "trace off" mode.
1779:             *
1780:             * @return itself
1781:             */
1782:            public PersistentObject traceOffAll() {
1783:                if (complex()) {
1784:                    Link link = toLink();
1785:                    for (LinkIterator it = link.linkIterator(); it.hasNext();) {
1786:                        Link childLink = it.nextLink();
1787:                        Object result = childLink.getResult();
1788:                        if (result instanceof  TracingCollection) {
1789:                            TracingCollection tracingCollection = (TracingCollection) result;
1790:                            tracingCollection.unsetTrace();
1791:                        }
1792:                    }
1793:                }
1794:                return this ;
1795:            }
1796:
1797:            /**
1798:             * Immediately forces all Tracing Collections passed as paramater have to "trace on" mode,
1799:             * meaning that all object tree collections will trace al the changes to them after.
1800:             *
1801:             * @param collection Collection
1802:             * @return itself
1803:             */
1804:            public static Collection traceOnAll(Collection collection) {
1805:                for (Iterator iterator = collection.iterator(); iterator
1806:                        .hasNext();) {
1807:                    PersistentObject persistent = (PersistentObject) iterator
1808:                            .next();
1809:                    persistent.traceOnAll();
1810:                }
1811:                return collection;
1812:            }
1813:
1814:            /**
1815:             * This method will be called in descendants on lazy collection instanciation.
1816:             * It will set proper tracing mode if needed
1817:             *
1818:             * @param collection
1819:             */
1820:            protected void handleAddCollection(Collection collection) {
1821:                if (traced() != null && collection instanceof  TracingCollection) {
1822:                    TracingCollection tracingCollection = (TracingCollection) collection;
1823:                    boolean setTrace = traced().booleanValue();
1824:                    if (setTrace) {
1825:                        tracingCollection.setTrace();
1826:                    } else {
1827:                        tracingCollection.unsetTrace();
1828:                    }
1829:                }
1830:            }
1831:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.