Source Code Cross Referenced for LinkDependencyGraph.java in  » Database-ORM » ODAL » com » completex » objective » components » persistency » core » impl » 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.core.impl 
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.core.impl;
0010:
0011:        import com.completex.objective.components.persistency.AbstractPersistentObject;
0012:        import com.completex.objective.components.persistency.Cloneable;
0013:        import com.completex.objective.components.persistency.LifeCycleController;
0014:        import com.completex.objective.components.persistency.Link;
0015:        import com.completex.objective.components.persistency.OdalPersistencyException;
0016:        import com.completex.objective.components.persistency.OdalRuntimePersistencyException;
0017:        import com.completex.objective.components.persistency.PersistentObject;
0018:        import com.completex.objective.components.persistency.core.CircularDependencyError;
0019:        import com.completex.objective.components.persistency.type.Tracer;
0020:        import com.completex.objective.components.persistency.type.TracingCollection;
0021:
0022:        import java.util.ArrayList;
0023:        import java.util.Collection;
0024:        import java.util.Iterator;
0025:        import java.util.LinkedHashMap;
0026:        import java.util.LinkedHashSet;
0027:        import java.util.List;
0028:        import java.util.Map;
0029:        import java.util.Set;
0030:        import java.util.Collections;
0031:
0032:        /**
0033:         * Class that determines order of inserts/updates/deletes/selects for complex persistent objects
0034:         *
0035:         * @author Gennady Krizhevsky
0036:         */
0037:        public class LinkDependencyGraph implements  Cloneable {
0038:
0039:            private LinkHolder linkHolder;
0040:            private boolean print = false;
0041:
0042:            public LinkDependencyGraph() {
0043:            }
0044:
0045:            /**
0046:             *
0047:             * @param parent persistent object
0048:             */
0049:            public LinkDependencyGraph(AbstractPersistentObject parent) {
0050:                assemble(parent);
0051:            }
0052:
0053:            /**
0054:             * Assemble LinkDependencyGraph ordering links by dependecies
0055:             *
0056:             * @param parent
0057:             */
0058:            public void assemble(AbstractPersistentObject parent) {
0059:                assemble(parent, false);
0060:            }
0061:
0062:            /**
0063:             * Assemble LinkDependencyGraph ordering links by dependecies
0064:             *
0065:             * @param parent
0066:             * @param reset indicator when set true re-assembling is performed
0067:             */
0068:            public void assemble(AbstractPersistentObject parent, boolean reset) {
0069:                if (!reset && hasMetaAssembly()) {
0070:                    return;
0071:                }
0072:                Context context = new Context();
0073:                assembleLocal(parent, context);
0074:                assemblySecondPass(context);
0075:            }
0076:
0077:            /**
0078:             * Get meta assembly Link by index
0079:             * @param index
0080:             * @return meta assembly Link
0081:             */
0082:            public Link getMetaAssemblyLink(int index) {
0083:                return linkHolder == null ? null : linkHolder
0084:                        .getMetaAssemblyLink(index);
0085:            }
0086:
0087:            /**
0088:             * 
0089:             * @return metaAssemblySize
0090:             */
0091:            public int metaAssemblySize() {
0092:                return linkHolder == null ? 0 : linkHolder.metaAssemblySize();
0093:            }
0094:
0095:            public boolean hasMetaAssembly() {
0096:                return linkHolder != null && linkHolder.hasMetaAssembly();
0097:            }
0098:
0099:            private void assembleLocal(AbstractPersistentObject parent,
0100:                    Context context) {
0101:                try {
0102:                    Link rootLink = parent.toLink().setCascadeAll();
0103:                    if (parent.hasChildren()) {
0104:                        assemble0(rootLink, parent.linkIterator(), context);
0105:                    }
0106:                    println(metaAssemblyToString(context.metaAssemblyMap));
0107:                    assembleOne(null, rootLink, context.metaAssemblyMap);
0108:                } catch (StackOverflowError e) {
0109:                    String message = "\n";
0110:                    message += "   StackOverflowError is caught probably due to circular dependency, look at following current parent & child links which are probably circularly dependent: \n";
0111:                    message += "   currParentLink = " + context.currParentLink
0112:                            + "\n";
0113:                    message += "   currChildLink = " + context.currChildLink
0114:                            + "\n";
0115:                    throw new CircularDependencyError(message);
0116:                }
0117:            }
0118:
0119:            private void assemble0(Link parentLink, LinkIterator it,
0120:                    Context context) {
0121:                context.currParentLink = parentLink;
0122:                for (; it.hasNext();) {
0123:                    Link childLink = it.nextLink();
0124:                    context.currChildLink = childLink;
0125:                    assemble007(parentLink, childLink, context);
0126:                }
0127:            }
0128:
0129:            private void assemble007(Link parentLink, Link childLink,
0130:                    Context context) {
0131:                assembleOne(parentLink, childLink, context.metaAssemblyMap);
0132:                if (childLink.hasChildren()) {
0133:                    assemble0(childLink, childLink.linkIterator(), context);
0134:                }
0135:            }
0136:
0137:            /**
0138:             * Creates map keys of which are all the persistent objects in the graph,
0139:             * values - List of objects the key object depends on
0140:             *
0141:             * @param parent
0142:             */
0143:            void assembleOne(Link parent, Link child, LinkedHashMap assembly) {
0144:                if (child.isInsertBeforeParent()) {
0145:                    addDependant(parent, child, assembly);
0146:                } else {
0147:                    addDependant(child, parent, assembly);
0148:                }
0149:            }
0150:
0151:            private void addDependant(Link dependant, Link depender,
0152:                    LinkedHashMap assembly) {
0153:                Set dependsOn = (Set) assembly.get(dependant);
0154:                if (dependsOn == null) {
0155:                    dependsOn = new LinkedHashSet();
0156:                    println("Put dependant " + dependant);
0157:                    println("    Put depender " + depender);
0158:                    if (depender != null && !dependant.isCascadeDelete()) {
0159:                        // If dependant (for insert) is excluded from delete -
0160:                        // exclude the depender also: for deletes
0161:                        // the dependency order is opposite
0162:                        depender.setCascadeDelete(false);
0163:                    }
0164:
0165:                    if (depender != null && !depender.isCascadeInsert()) {
0166:                        dependant.setCascadeInsert(false);
0167:                    }
0168:
0169:                    if (depender != null && !depender.isCascadeUpdate()) {
0170:                        dependant.setCascadeUpdate(false);
0171:                    }
0172:
0173:                    assembly.put(dependant, dependsOn);
0174:                }
0175:                if (depender != null) {
0176:                    dependsOn.add(depender);
0177:                }
0178:            }
0179:
0180:            //
0181:            //
0182:            // Assembly 2nd pass:
0183:            //
0184:            //
0185:
0186:            /**
0187:             * 1) Cycle by dependant
0188:             * 2) find all the dependers
0189:             * 3) cycle by dependers
0190:             * 4) from each depender find if it is in the dependants
0191:             * 5) if yes do 1)
0192:             * 6) if not - add depender to final assembly
0193:             * 7) add dependant to final assembly
0194:             */
0195:            private void assemblySecondPass(Context context) {
0196:                LinkedHashSet finalAssemblySet = new LinkedHashSet();
0197:                for (Iterator ait = context.metaAssemblyMap.keySet().iterator(); ait
0198:                        .hasNext();) {
0199:                    Link dependant = (Link) ait.next();
0200:                    assemblySecondPass0(dependant, finalAssemblySet,
0201:                            context.metaAssemblyMap, 0);
0202:                    finalAssemblySet.add(dependant);
0203:                }
0204:
0205:                ArrayList finalAssemblyList = new ArrayList(finalAssemblySet
0206:                        .size());
0207:                for (Iterator it = finalAssemblySet.iterator(); it.hasNext();) {
0208:                    Link link = (Link) it.next();
0209:                    finalAssemblyList.add(link);
0210:                }
0211:                context.metaAssembly = new Link[finalAssemblyList.size()];
0212:                finalAssemblyList.toArray(context.metaAssembly);
0213:                for (int i = 0; i < context.metaAssembly.length; i++) {
0214:                    context.metaAssembly[i].setDependencyIndex(i);
0215:                }
0216:                linkHolder = new LinkHolder(context.metaAssembly);
0217:            }
0218:
0219:            private boolean assemblySecondPass0(Link dependant,
0220:                    LinkedHashSet finalAssemblySet, LinkedHashMap assembly,
0221:                    int level) {
0222:                level++;
0223:                boolean rc = false;
0224:                Set dependers = (Set) assembly.get(dependant);
0225:                if (dependers != null && dependers.size() > 0) {
0226:                    for (Iterator it = dependers.iterator(); it.hasNext();) {
0227:                        Link depender = (Link) it.next();
0228:                        println("depender[" + level + "] = " + depender);
0229:                        if (assembly.containsKey(depender)) {
0230:                            rc = assemblySecondPass0(depender,
0231:                                    finalAssemblySet, assembly, level);
0232:                        }
0233:                        if (!finalAssemblySet.contains(depender)) {
0234:                            finalAssemblySet.add(depender);
0235:                        }
0236:                    }
0237:                } else {
0238:                    finalAssemblySet.add(dependant);
0239:                    rc = true;
0240:                }
0241:                return rc;
0242:            }
0243:
0244:            //
0245:            //
0246:            // Walk is simple now -
0247:            //
0248:            //
0249:
0250:            /**
0251:             * @param reverseOrder - process tree from bottom to top 
0252:             *  (as opposed to from top to bottom) - false for inserts/updates, true for deletes
0253:             * @param visitor
0254:             */
0255:            public int walk(boolean reverseOrder, Visitor visitor)
0256:                    throws OdalPersistencyException {
0257:                LinkAssemblyMeta meta = linkHolder.getMeta();
0258:
0259:                //
0260:                // calculate starting point of the graph for delete or insert:
0261:                // it's determined by the break in cascade delete or insert:
0262:                //
0263:                boolean complexDirty = complexDirty(visitor);
0264:
0265:                ArrayList[] finalAssemblies = getFinalAssemblies();
0266:                ExtraParents extraParents = new ExtraParents();
0267:                int rc = 0;
0268:                Set visited = new LinkedHashSet();
0269:                int size = finalAssemblies.length;
0270:                for (int i = 0; i < size; i++) {
0271:                    int k = reverseOrder ? (size - i - 1) : i;
0272:                    ArrayList links = finalAssemblies[k];
0273:                    Link metaLink = meta.getLink(k);
0274:                    if (links != null) {
0275:                        boolean bypassForDelete = ModifyVisitorType
0276:                                .isDeleteType(visitor)
0277:                                && !metaLink.isCascadeDelete();
0278:                        boolean bypassForInsert = ModifyVisitorType
0279:                                .isInsertType(visitor)
0280:                                && !metaLink.isCascadeInsert();
0281:                        boolean bypassForUpdate = ModifyVisitorType
0282:                                .isUpdateType(visitor)
0283:                                && !metaLink.isCascadeUpdate();
0284:                        boolean bypass = (bypassForDelete || bypassForInsert || bypassForUpdate);
0285:                        if (!bypass) {
0286:                            for (Iterator iterator = links.iterator(); iterator
0287:                                    .hasNext();) {
0288:                                Link link = (Link) iterator.next();
0289:                                resetTracingOnInsertOrDelete(link, visitor);
0290:
0291:                                //
0292:                                // populate link with meta data:
0293:                                //
0294:                                link.setParentIndeces(metaLink
0295:                                        .getParentIndeces());
0296:                                link.setThisIndeces(metaLink.getThisIndeces());
0297:                                try {
0298:
0299:                                    rc += walk007(link, visitor, visited,
0300:                                            complexDirty, finalAssemblies,
0301:                                            extraParents);
0302:                                } catch (OdalPersistencyException e) {
0303:                                    throw e;
0304:                                }
0305:                            }
0306:                        }
0307:                    }
0308:                }
0309:                visited.clear();
0310:                return rc;
0311:            }
0312:
0313:            private boolean complexDirty(Visitor visitor) {
0314:                boolean complexDirty = false;
0315:                if (visitor.getType() == ModifyVisitorType.UPDATE) {
0316:                    complexDirty = dirty();
0317:                }
0318:                return complexDirty;
0319:            }
0320:
0321:            private void resetTracingOnInsertOrDelete(Link link, Visitor visitor) {
0322:                if (link != null && ModifyVisitorType.isInsertOrDelete(visitor)
0323:                        && link.hasChildren()) {
0324:                    for (LinkIterator it = link.linkIterator(); it.hasNext();) {
0325:                        Link childLink = it.nextLink();
0326:                        if (childLink != null
0327:                                && childLink.getResult() != null
0328:                                && (childLink.getResult() instanceof  TracingCollection)) {
0329:                            TracingCollection tracingCollection = (TracingCollection) childLink
0330:                                    .getResult();
0331:                            tracingCollection.clearTrace();
0332:                        }
0333:                    }
0334:                }
0335:            }
0336:
0337:            private ArrayList[] getFinalAssemblies() {
0338:                LinkedHashMap finalAssemblyMap = linkHolder
0339:                        .getDataAssemblyMap();
0340:                Collection collection = finalAssemblyMap.values();
0341:                ArrayList[] finalAssemblies = new ArrayList[collection.size()];
0342:
0343:                int m = 0;
0344:                for (Iterator mapIterator = collection.iterator(); mapIterator
0345:                        .hasNext(); m++) {
0346:                    finalAssemblies[m] = (ArrayList) mapIterator.next();
0347:                    for (int i = 0; i < finalAssemblies[m].size(); i++) {
0348:                        Link link = (Link) finalAssemblies[m].get(i);
0349:                        if (link != null) {
0350:                            link.setDependencyIndex(m);
0351:                        }
0352:
0353:                    }
0354:                }
0355:                return finalAssemblies;
0356:            }
0357:
0358:            private int walk007(Link link, Visitor visitor, Set visited,
0359:                    boolean complexDirty, ArrayList[] finalAssemblies,
0360:                    ExtraParents extraParents) throws OdalPersistencyException {
0361:                int rc = 0;
0362:                Object result = link.getResult();
0363:                LifeCycleController controller = link.getLifeCycleController();
0364:                if (result != null) {
0365:                    if (result instanceof  AbstractPersistentObject) {
0366:                        rc += visit0((AbstractPersistentObject) result,
0367:                                visitor, visited, controller, link,
0368:                                complexDirty, finalAssemblies, extraParents);
0369:                    } else if (result instanceof  TracingCollection) {
0370:                        //
0371:                        // If this is tracing collections then operation is generalixzed update.
0372:                        // To exclude those entries that has been deleted or just inserted -
0373:                        // check if the entry is traced. If so - it is deleted or inserted - skip it:
0374:                        //
0375:                        TracingCollection list = (TracingCollection) result;
0376:                        for (Iterator iterator = list.iterator(); iterator
0377:                                .hasNext();) {
0378:                            PersistentObject persistentObject = (PersistentObject) iterator
0379:                                    .next();
0380:                            if (!list.containsEntry(persistentObject)) {
0381:                                rc += visit0(persistentObject, visitor,
0382:                                        visited, controller, link,
0383:                                        complexDirty, finalAssemblies,
0384:                                        extraParents);
0385:                            }
0386:                        }
0387:                    } else if (result instanceof  Collection) {
0388:                        Collection list = (Collection) result;
0389:                        for (Iterator iterator = list.iterator(); iterator
0390:                                .hasNext();) {
0391:                            AbstractPersistentObject persistentObject = (AbstractPersistentObject) iterator
0392:                                    .next();
0393:                            rc += visit0(persistentObject, visitor, visited,
0394:                                    controller, link, complexDirty,
0395:                                    finalAssemblies, extraParents);
0396:                        }
0397:                    } else {
0398:                        throw new IllegalArgumentException("Unknown type "
0399:                                + result.getClass().getName());
0400:                    }
0401:
0402:                }
0403:                return rc;
0404:            }
0405:
0406:            private int visit0(AbstractPersistentObject persistent,
0407:                    Visitor visitor, Set visited,
0408:                    LifeCycleController controller, Link link,
0409:                    boolean complexDirty, ArrayList[] finalAssemblies,
0410:                    ExtraParents extraParents) throws OdalPersistencyException {
0411:                int rc = 0;
0412:                if (!visited.contains(persistent)) {
0413:                    insertDependentIndices(visitor, link,
0414:                            (PersistentObject) persistent, finalAssemblies,
0415:                            extraParents);
0416:                    rc = visitor.visit(persistent, controller,
0417:                            persistent == visitor.getRoot(), complexDirty);
0418:                    visited.add(persistent);
0419:                }
0420:                return rc;
0421:            }
0422:
0423:            /**
0424:             * Populate indeces in dependent object if there are no values. it will take care of autogenerated parent
0425:             * fields - children's ones will be populated automatically
0426:             *
0427:             * @param visitor
0428:             * @param link
0429:             * @param persistent
0430:             * @param finalAssemblies
0431:             * @param extraParents
0432:             */
0433:            private void insertDependentIndices(Visitor visitor, Link link,
0434:                    PersistentObject persistent, ArrayList[] finalAssemblies,
0435:                    ExtraParents extraParents) {
0436:                if (visitor.getType() == ModifyVisitorType.INSERT) {
0437:                    if (link.getParentLink() != null
0438:                            && link.getDependencyIndex() > 0
0439:                            && link.getParentIndeces() != null
0440:                            && link.getParentLink().getResult() != null) {
0441:                        insertDependentIndicesDirect(link, persistent,
0442:                                finalAssemblies, extraParents);
0443:                    } else { // Case of reversed dependency - slave is root object ...
0444:                        insertDependentIndicesReversed(persistent, link,
0445:                                extraParents);
0446:                    }
0447:                }
0448:            }
0449:
0450:            private void insertDependentIndicesReversed(
0451:                    PersistentObject persistent, Link link,
0452:                    ExtraParents extraParents) {
0453:                if (persistent != null
0454:                        && persistent.toLink() != null
0455:                        && persistent.toLink().getResult() instanceof  PersistentObject) {
0456:                    Link parentLink = ((PersistentObject) persistent.toLink()
0457:                            .getResult()).toLink();
0458:                    if (parentLink.hasChildren()) {
0459:                        for (LinkIterator it = parentLink.linkIterator(); it
0460:                                .hasNext();) {
0461:                            Link childLink = it.nextLink();
0462:                            if (childLink.getDependencyIndex() < link
0463:                                    .getDependencyIndex()) {
0464:                                Object result = childLink.getResult();
0465:                                PersistentObject childPersistentObject = null;
0466:                                // It can be collection of size 1:
0467:                                if (result instanceof  Collection) {
0468:                                    Collection collection = (Collection) result;
0469:                                    if (!collection.isEmpty()) {
0470:                                        childPersistentObject = (PersistentObject) collection
0471:                                                .iterator().next();
0472:                                    }
0473:                                } else if (result instanceof  PersistentObject) {
0474:                                    childPersistentObject = ((PersistentObject) result);
0475:                                } else if (result != null) {
0476:                                    throw new OdalRuntimePersistencyException(
0477:                                            "Unsupported result type " + result);
0478:                                }
0479:                                if (childPersistentObject != null) {
0480:                                    int[] parentIndeces = childPersistentObject
0481:                                            .toLink().getParentIndeces();
0482:                                    int[] this Indeces = childPersistentObject
0483:                                            .toLink().getThisIndeces();
0484:
0485:                                    for (int i = 0; i < this Indeces.length; i++) {
0486:                                        int this Index = this Indeces[i];
0487:                                        int parentIndex = parentIndeces[i];
0488:                                        persistent.record().setObject(
0489:                                                parentIndex,
0490:                                                childPersistentObject.record()
0491:                                                        .getObject(this Index));
0492:                                    }
0493:                                }
0494:                            }
0495:                        }
0496:                    }
0497:                }
0498:            }
0499:
0500:            private void insertDependentIndicesDirect(Link link,
0501:                    PersistentObject persistent, ArrayList[] finalAssemblies,
0502:                    ExtraParents extraParents) {
0503:                if (link.getParentLink().getResult() instanceof  PersistentObject) {
0504:                    Link parentLink = link.getParentLink();
0505:                    PersistentObject parentObject = (PersistentObject) parentLink
0506:                            .getResult();
0507:                    insertIndicesOne(link, persistent, parentObject);
0508:                    // New stuff to populate extra indices
0509:                    insertExtraDependentIndicesDirect(parentLink,
0510:                            finalAssemblies, link, persistent, extraParents);
0511:                }
0512:
0513:                //
0514:                // Insert extra parent indices:
0515:                //
0516:                List extraParentLinks = extraParents.getExtraParents(link);
0517:                for (int i = 0; i < extraParentLinks.size(); i++) {
0518:                    Link parentLink = (Link) extraParentLinks.get(i);
0519:                    if (parentLink.getResult() instanceof  PersistentObject) {
0520:                        PersistentObject parentObject = (PersistentObject) parentLink
0521:                                .getResult();
0522:                        insertIndicesOne(parentLink, parentObject, persistent);
0523:                    }
0524:                }
0525:            }
0526:
0527:            private void insertExtraDependentIndicesDirect(Link parentLink,
0528:                    ArrayList[] finalAssemblies, Link link,
0529:                    PersistentObject persistent, ExtraParents extraParents) {
0530:                int dependencyIndex = parentLink.getDependencyIndex();
0531:                ArrayList links = finalAssemblies[dependencyIndex];
0532:                for (int i = 0; i < links.size(); i++) {
0533:                    Link dependentLink = (Link) links.get(i);
0534:                    if (dependentLink.hasChildren()
0535:                            && dependentLink.getResult() instanceof  PersistentObject) {
0536:                        PersistentObject extraParentObject = (PersistentObject) dependentLink
0537:                                .getResult();
0538:                        for (LinkIterator it = dependentLink.linkIterator(); it
0539:                                .hasNext();) {
0540:                            Link extraParentLink = it.nextLink();
0541:                            if (extraParentLink != link.getParentLink()
0542:                                    && extraParentLink.getResult() == persistent) {
0543:                                //                        insertIndicesOne(link, persistent, extraParentObject);
0544:                                if (link.getResult() != null) {
0545:                                    extraParents.addExtraParent(dependentLink,
0546:                                            link);
0547:                                }
0548:                            }
0549:                        }
0550:                    }
0551:
0552:                }
0553:            }
0554:
0555:            private void insertIndicesOne(Link link,
0556:                    PersistentObject childObject, PersistentObject parentObject) {
0557:                setDependentKeys(link, childObject, parentObject);
0558:            }
0559:
0560:            /**
0561:             * Utility method that set dependent values from child to parent or from parent to child PersistentObject
0562:             * based on Link.isInsertBeforeParent(), Link.getDependencyIndex(), Link.getThisIndeces() != null,
0563:             * Link.getParentIndeces() methods. Dependent values usually
0564:             * those based on primary/foreign keys relations
0565:             *
0566:             * @param link one of the parentObject links establishing relationship to childObject
0567:             * @param childObject
0568:             * @param parentObject
0569:             */
0570:            public static void setDependentKeys(Link link,
0571:                    PersistentObject childObject, PersistentObject parentObject) {
0572:                if (link.getThisIndeces() != null
0573:                        && link.getParentIndeces() != null) {
0574:                    for (int i = 0; i < link.getParentIndeces().length; i++) {
0575:                        int childIndex = link.getThisIndeces()[i];
0576:                        int parentIndex = link.getParentIndeces()[i];
0577:                        if (!link.isInsertBeforeParent()
0578:                                && link.getDependencyIndex() > link
0579:                                        .getParentLink().getDependencyIndex()) {
0580:                            setDependentIndex(parentObject, parentIndex,
0581:                                    childObject, childIndex);
0582:                        } else {
0583:                            setDependentIndex(childObject, childIndex,
0584:                                    parentObject, parentIndex);
0585:                        }
0586:                    }
0587:                }
0588:            }
0589:
0590:            static void setDependentIndex(PersistentObject parentObject,
0591:                    int parentIndex, PersistentObject persistentObject,
0592:                    int this Index) {
0593:                Object parentValue = parentObject.record().getObject(
0594:                        parentIndex);
0595:                persistentObject.record().setObject(this Index, parentValue);
0596:            }
0597:
0598:            public String toString() {
0599:                return super .toString() + ": {\n" + metaAssemblyToString()
0600:                        + "}";
0601:            }
0602:
0603:            /**
0604:             * 
0605:             * @param metaAssemblyMap
0606:             * @return metaAssemblyMap as String
0607:             */
0608:            public String metaAssemblyToString(LinkedHashMap metaAssemblyMap) {
0609:                if (metaAssemblyMap == null) {
0610:                    return "null";
0611:                }
0612:                String indent = "    ";
0613:                StringBuffer buffer = new StringBuffer();
0614:                int count = 0;
0615:                for (Iterator it = metaAssemblyMap.keySet().iterator(); it
0616:                        .hasNext();) {
0617:                    Object key = it.next();
0618:                    Object value = metaAssemblyMap.get(key);
0619:                    buffer.append(indent).append("Assembly line[").append(
0620:                            ++count).append("]; <dependant> = ").append(key)
0621:                            .append("; <dependsOn> = ").append(value).append(
0622:                                    "\n");
0623:                }
0624:                return buffer.toString();
0625:            }
0626:
0627:            /**
0628:             * 
0629:             * @return meta assembly as string
0630:             */
0631:            public String metaAssemblyToString() {
0632:                return linkHolder.metaAssemblyToString();
0633:            }
0634:
0635:            private void println(String s) {
0636:                if (print) {
0637:                    System.err.println(s);
0638:                }
0639:            }
0640:
0641:            /**
0642:             * 
0643:             * @return copy of this object
0644:             * @throws CloneNotSupportedException
0645:             */
0646:            public Object clone() throws CloneNotSupportedException {
0647:                LinkDependencyGraph graph = (LinkDependencyGraph) super .clone();
0648:                graph.linkHolder = (LinkHolder) linkHolder.clone();
0649:                return graph;
0650:            }
0651:
0652:            /**
0653:             * Add link addToAssembly at specific path
0654:             * 
0655:             * @param linkPath
0656:             * @param link
0657:             */
0658:            public void addToAssembly(String linkPath, Link link) {
0659:                linkHolder.addLink(linkPath, link);
0660:            }
0661:
0662:            /**
0663:             * Traverses the dependecy graph and determines if any of NON-BYPASSED link entries is dirty
0664:             *
0665:             * @return true if at least one of non-bypassed entries is dirty
0666:             */
0667:            public boolean dirty() {
0668:                LinkedHashMap map = linkHolder.getDataAssemblyMap();
0669:                for (Iterator it = map.keySet().iterator(); it.hasNext();) {
0670:                    String key = (String) it.next();
0671:                    List links = (List) map.get(key);
0672:                    for (Iterator iterator = links.iterator(); iterator
0673:                            .hasNext();) {
0674:                        Link link = (Link) iterator.next();
0675:                        Link metaLink = linkHolder.getMeta().getLink(key);
0676:                        boolean bypassForDelete = !metaLink.isCascadeDelete();
0677:                        boolean bypassForInsert = !metaLink.isCascadeInsert();
0678:                        boolean bypassForUpdate = !metaLink.isCascadeUpdate();
0679:                        boolean bypass = bypassForDelete && bypassForInsert
0680:                                && bypassForUpdate;
0681:                        if (!bypass) {
0682:                            Object result = link.getResult();
0683:                            if (result != null
0684:                                    && result instanceof  AbstractPersistentObject
0685:                                    && !bypassForUpdate) {
0686:                                if (((AbstractPersistentObject) result).dirty()) {
0687:                                    return true;
0688:                                }
0689:                            } else if (result instanceof  TracingCollection) {
0690:                                TracingCollection tracingCollection = (TracingCollection) result;
0691:                                int[] ops = tracingCollection
0692:                                        .performedOperations();
0693:                                bypassForDelete = Tracer.Util.isDeleteOnly(ops)
0694:                                        && bypassForDelete;
0695:                                bypassForInsert = Tracer.Util.isInsertOnly(ops)
0696:                                        && bypassForInsert;
0697:                                bypassForUpdate = Tracer.Util.isUpdateOnly(ops)
0698:                                        && bypassForUpdate;
0699:                                bypass = bypassForDelete || bypassForInsert
0700:                                        || bypassForUpdate;
0701:                                if (!bypass && tracingCollection.dirty()) {
0702:                                    return true;
0703:                                }
0704:                            } else if (result instanceof  Collection
0705:                                    && !bypassForUpdate) {
0706:                                Collection collection = (Collection) result;
0707:                                for (Iterator iterator1 = collection.iterator(); iterator1
0708:                                        .hasNext();) {
0709:                                    Object o1 = iterator1.next();
0710:                                    if (((AbstractPersistentObject) o1).dirty()) {
0711:                                        return true;
0712:                                    }
0713:                                }
0714:                            }
0715:                        }
0716:                    }
0717:                }
0718:
0719:                return false;
0720:            }
0721:
0722:            //
0723:            //
0724:            //  Util classes:
0725:            //
0726:            //
0727:
0728:            /**
0729:             * Modify Visitor Type holder
0730:             */
0731:            public static class ModifyVisitorType {
0732:
0733:                private String name;
0734:
0735:                public ModifyVisitorType(String name) {
0736:                    this .name = name;
0737:                }
0738:
0739:                public static final ModifyVisitorType NULL = new ModifyVisitorType(
0740:                        "NULL");
0741:                public static final ModifyVisitorType INSERT = new ModifyVisitorType(
0742:                        "INSERT");
0743:                public static final ModifyVisitorType UPDATE = new ModifyVisitorType(
0744:                        "UPDATE");
0745:                public static final ModifyVisitorType DELETE = new ModifyVisitorType(
0746:                        "DELETE");
0747:
0748:                public String toString() {
0749:                    return name;
0750:                }
0751:
0752:                public static boolean isNullType(Visitor visitor) {
0753:                    return visitor.getType() == NULL;
0754:                }
0755:
0756:                public static boolean isInsertType(Visitor visitor) {
0757:                    return visitor.getType() == INSERT;
0758:                }
0759:
0760:                public static boolean isUpdateType(Visitor visitor) {
0761:                    return visitor.getType() == UPDATE;
0762:                }
0763:
0764:                public static boolean isDeleteType(Visitor visitor) {
0765:                    return visitor.getType() == DELETE;
0766:                }
0767:
0768:                public static boolean isInsertOrDelete(Visitor visitor) {
0769:                    return isInsertType(visitor) || isDeleteType(visitor);
0770:                }
0771:            }
0772:
0773:            /**
0774:             * Interface to traverse AbstractPersistentObject trees 
0775:             */
0776:            public static interface Visitor {
0777:                /**
0778:                 * 
0779:                 * @param persistentObject
0780:                 * @param controller
0781:                 * @param root set true if persistentObject parameter is the root of traversed tree
0782:                 * @param complexDirty set true if the object tree is "dirty" in generalized sense
0783:                 * @return indicator of how many objects are processed
0784:                 * @throws OdalPersistencyException
0785:                 */
0786:                int visit(AbstractPersistentObject persistentObject,
0787:                        LifeCycleController controller, boolean root,
0788:                        boolean complexDirty) throws OdalPersistencyException;
0789:
0790:                /**
0791:                 * @see ModifyVisitorType
0792:                 * 
0793:                 * @return ModifyVisitorType
0794:                 */
0795:                ModifyVisitorType getType();
0796:
0797:                /**
0798:                 * 
0799:                 * @return root object
0800:                 */
0801:                PersistentObject getRoot();
0802:            }
0803:
0804:            private static class Context {
0805:                private Link currParentLink;
0806:                private Link currChildLink;
0807:                private LinkedHashMap metaAssemblyMap = new LinkedHashMap();
0808:                private Link[] metaAssembly;
0809:            }
0810:
0811:            private static class ExtraParents {
0812:                private LinkedHashMap extraParents; /* LinkedHashMap<Link, List<Link>> */
0813:
0814:                public void addExtraParent(Link child, Link extraParent) {
0815:                    List parents = (List) lazyExtraParents().get(child);
0816:                    if (parents == null) {
0817:                        parents = new ArrayList();
0818:                        lazyExtraParents().put(child, parents);
0819:                    }
0820:                    parents.add(extraParent);
0821:                }
0822:
0823:                private Map lazyExtraParents() {
0824:                    if (extraParents == null) {
0825:                        extraParents = new LinkedHashMap();
0826:                    }
0827:                    return extraParents;
0828:                }
0829:
0830:                public List getExtraParents(Link child) {
0831:                    List result = null;
0832:                    if (extraParents != null) {
0833:                        result = (List) extraParents.get(child);
0834:                    }
0835:
0836:                    return result == null ? Collections.EMPTY_LIST : result;
0837:                }
0838:            }
0839:
0840:            /**
0841:             * Contains Link Assembly Meta data and dataAssemblyMap - 
0842:             * map of links lists with slink path as a key
0843:             */
0844:            static class LinkHolder implements  Cloneable {
0845:
0846:                private LinkedHashMap dataAssemblyMap; /* LinkedHashMap<String, List<Link>> */
0847:                private LinkAssemblyMeta meta;
0848:
0849:                LinkHolder(Link[] metaAssembly) {
0850:                    this .meta = new LinkAssemblyMeta(metaAssembly);
0851:                    setDataAssemblyMap(this );
0852:                }
0853:
0854:                private LinkHolder() {
0855:                }
0856:
0857:                private LinkHolder newLinkHolder() {
0858:                    LinkHolder holder = new LinkHolder();
0859:                    holder.meta = meta;
0860:                    setDataAssemblyMap(holder);
0861:                    return holder;
0862:                }
0863:
0864:                /**
0865:                 * 
0866:                 * @return dataAssemblyMap
0867:                 */
0868:                public LinkedHashMap getDataAssemblyMap() {
0869:                    return dataAssemblyMap;
0870:                }
0871:
0872:                private void setDataAssemblyMap(LinkHolder holder) {
0873:                    holder.dataAssemblyMap = meta.newDataAssemblyMap();
0874:                }
0875:
0876:                /**
0877:                 * Add Link to dataAssemblyMap
0878:                 * 
0879:                 * @param linkPath
0880:                 * @param link
0881:                 */
0882:                public void addLink(String linkPath, Link link) {
0883:                    if (!link.isAdHoc()) {
0884:                        List links = (List) dataAssemblyMap.get(linkPath);
0885:                        if (links == null) {
0886:                            throw new OdalRuntimePersistencyException(
0887:                                    "Cannot get links by linkPath " + linkPath);
0888:                        }
0889:                        links.add(link);
0890:                    }
0891:                }
0892:
0893:                /**
0894:                 * 
0895:                 * @return copy of LinkHolder
0896:                 * @throws CloneNotSupportedException
0897:                 */
0898:                public Object clone() throws CloneNotSupportedException {
0899:                    return newLinkHolder();
0900:                }
0901:
0902:                /**
0903:                 * 
0904:                 * @return Link assembly meta data
0905:                 */
0906:                public LinkAssemblyMeta getMeta() {
0907:                    return meta;
0908:                }
0909:
0910:                /**
0911:                 * 
0912:                 * @return metaAssemblySize
0913:                 */
0914:                public int metaAssemblySize() {
0915:                    return meta == null ? 0 : meta.size();
0916:                }
0917:
0918:                /**
0919:                 * 
0920:                 * @return true if LinkHolder meta assembly is empty
0921:                 */
0922:                public boolean isMetaAssemblyEmpty() {
0923:                    return metaAssemblySize() == 0;
0924:                }
0925:
0926:                /**
0927:                 * 
0928:                 * @return true if LinkHolder has meta assembly
0929:                 */
0930:                public boolean hasMetaAssembly() {
0931:                    return !isMetaAssemblyEmpty();
0932:                }
0933:
0934:                public String toString() {
0935:                    return super .toString() + "{" + dataAssemblyMap + "}";
0936:                }
0937:
0938:                public String metaAssemblyToString() {
0939:                    if (isMetaAssemblyEmpty()) {
0940:                        return "null";
0941:                    }
0942:                    String indent = "    ";
0943:                    StringBuffer buffer = new StringBuffer();
0944:                    int count = 0;
0945:
0946:                    for (int i = 0; i < metaAssemblySize(); i++) {
0947:                        Link key = meta.getLink(i);
0948:                        buffer.append(indent).append("Final Assembly line[")
0949:                                .append(++count).append("]; <link> = ").append(
0950:                                        key).append("\n");
0951:                    }
0952:                    return buffer.toString();
0953:                }
0954:
0955:                public Link getMetaAssemblyLink(int index) {
0956:                    return meta == null ? null : meta.getLink(index);
0957:                }
0958:            }
0959:
0960:            /**
0961:             * Link Assembly Meta data. Contains link array and map of links with path as key and
0962:             * Link as value 
0963:             */
0964:            static class LinkAssemblyMeta {
0965:                private Map metaAssemblyMap;
0966:                private Link[] metaAssembly;
0967:
0968:                /**
0969:                 * 
0970:                 * @param metaAssembly
0971:                 */
0972:                public LinkAssemblyMeta(Link[] metaAssembly) {
0973:                    this .metaAssembly = metaAssembly;
0974:                    this .metaAssemblyMap = newMetaAssemblyMap(metaAssembly);
0975:                }
0976:
0977:                private Map newMetaAssemblyMap(Link[] finalAssembly) {
0978:                    LinkedHashMap finalAssemblyMap = new LinkedHashMap(
0979:                            finalAssembly.length);
0980:                    for (int i = 0; i < finalAssembly.length; i++) {
0981:                        finalAssembly[i].setDependencyIndex(i);
0982:                        finalAssemblyMap.put(finalAssembly[i].getPathString(),
0983:                                finalAssembly[i]);
0984:                    }
0985:                    return finalAssemblyMap;
0986:                }
0987:
0988:                public Link getLink(int index) {
0989:                    return metaAssembly[index];
0990:                }
0991:
0992:                public Link getLink(String path) {
0993:                    return (Link) metaAssemblyMap.get(path);
0994:                }
0995:
0996:                public int size() {
0997:                    return metaAssembly != null ? metaAssembly.length : 0;
0998:                }
0999:
1000:                /**
1001:                 * Creates new Data Assembly Map which has Link path as a key 
1002:                 * and empty List as value. The list gets populated in  
1003:                 * LinkDependencyGraph.addToAssembly() method
1004:                 * 
1005:                 * @return new Data Assembly Map
1006:                 */
1007:                public LinkedHashMap newDataAssemblyMap() {
1008:                    LinkedHashMap dataAssemblyMap = new LinkedHashMap(
1009:                            metaAssembly.length);
1010:                    for (int i = 0; i < metaAssembly.length; i++) {
1011:                        dataAssemblyMap.put(metaAssembly[i].getPathString(),
1012:                                new ArrayList());
1013:                    }
1014:                    return dataAssemblyMap;
1015:                }
1016:
1017:                public String toString() {
1018:                    return super.toString();
1019:                }
1020:
1021:            }
1022:        }
w__w__w___.___j_av_a__2s.co___m__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.