Source Code Cross Referenced for FetchPlan.java in  » Database-ORM » JPOX » org » jpox » 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 » JPOX » org.jpox 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**********************************************************************
002:        Copyright (c) 2007 Andy Jefferson and others. All rights reserved.
003:        Licensed under the Apache License, Version 2.0 (the "License");
004:        you may not use this file except in compliance with the License.
005:        You may obtain a copy of the License at
006:
007:            http://www.apache.org/licenses/LICENSE-2.0
008:
009:        Unless required by applicable law or agreed to in writing, software
010:        distributed under the License is distributed on an "AS IS" BASIS,
011:        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012:        See the License for the specific language governing permissions and
013:        limitations under the License.
014:
015:        Contributors:
016:            ...
017:         **********************************************************************/package org.jpox;
018:
019:        import java.io.Serializable;
020:        import java.util.ArrayList;
021:        import java.util.BitSet;
022:        import java.util.Collection;
023:        import java.util.Collections;
024:        import java.util.HashMap;
025:        import java.util.HashSet;
026:        import java.util.Iterator;
027:        import java.util.Map;
028:        import java.util.Set;
029:
030:        import org.jpox.exceptions.JPOXUserException;
031:        import org.jpox.metadata.AbstractClassMetaData;
032:        import org.jpox.metadata.AbstractMemberMetaData;
033:        import org.jpox.metadata.FetchGroupMetaData;
034:        import org.jpox.metadata.FieldPersistenceModifier;
035:        import org.jpox.util.Localiser;
036:
037:        /**
038:         * FetchPlan for fields for use within JPOX Core.
039:         * A FetchPlan has a series of FetchPlanForClass objects being the fetch plan for particular classes.
040:         * Each FetchPlanForClass defines a series of fields of that class that are part of the fetch plan.
041:         * There are two types of fetch groups under consideration here.
042:         * <ul>
043:         * <li>Static fetch groups, defined in MetaData (XML/Annotations).</li>
044:         * <li>Dynamic fetch groups, defined via an API.</li>
045:         * </ul>
046:         * 
047:         * @version $Revision: 1.11 $
048:         */
049:        public class FetchPlan implements  Serializable {
050:            /** Localisation utility for output messages */
051:            protected static final Localiser LOCALISER = Localiser
052:                    .getInstance("org.jpox.Localisation");
053:
054:            /** Constant defining the fields in the default fetch group. */
055:            public static final String DEFAULT = "default";
056:
057:            /** Constant defining all fields */
058:            public static final String ALL = "all";
059:
060:            /** Constant defing no fields. */
061:            public static final String NONE = "none";
062:
063:            /** Specify that fields that are loaded but not in the current fetch plan should be unloaded prior to detachment. */
064:            public static final int DETACH_UNLOAD_FIELDS = 2;
065:
066:            /** Specify that fields that are not loaded but are in the current fetch plan should be loaded prior to detachment. */
067:            public static final int DETACH_LOAD_FIELDS = 1;
068:
069:            /** Fetch size to load all possible. */
070:            public static final int FETCH_SIZE_GREEDY = -1;
071:
072:            /** Fetch size for the implementation to decide how many to load. */
073:            public static final int FETCH_SIZE_OPTIMAL = 0;
074:
075:            /** ObjectManagerFactory. */
076:            transient final ObjectManagerFactoryImpl omf; // Defined as transient to avoid Serializable problems
077:
078:            /** ClassLoader resolver. */
079:            transient final ClassLoaderResolver clr; // Defined as transient to avoid Serializable problems
080:
081:            /** The "defined" fetch groups in the current FetchPlan. */
082:            final Set groups = new HashSet();
083:
084:            /** The "dynamic" fetch groups in the current FetchPlan. */
085:            transient Set dynamicGroups = null; // Defined as transient to avoid Serializable problems
086:
087:            /** The Fetch size. For use when using large result sets. */
088:            int fetchSize = FETCH_SIZE_OPTIMAL;
089:
090:            /** Options to be used during detachment. Spec 12.7 says that the default is DETACH_LOAD_FIELDS. */
091:            int detachmentOptions = FetchPlan.DETACH_LOAD_FIELDS;
092:
093:            /** Managed class keyed by ClassMetaData **/
094:            final transient Map managedClass = new HashMap();
095:
096:            /** Maximum depth to fetch from the root object. */
097:            int maxFetchDepth = 1;
098:
099:            /** The classes used as the roots for detachment (DetachAllOnCommit). */
100:            Class[] detachmentRootClasses = null;
101:
102:            /** The instances used as the roots for detachment (DetachAllOnCommit). */
103:            Collection detachmentRoots = null;
104:
105:            /**
106:             * Constructor. Initially has the default fetch group.
107:             * @param omf ObjectManagerFactory
108:             * @param clr ClassLoader Resolver
109:             */
110:            public FetchPlan(ObjectManagerFactoryImpl omf,
111:                    ClassLoaderResolver clr) {
112:                this .omf = omf;
113:                this .clr = clr;
114:                groups.add(FetchPlan.DEFAULT);
115:            }
116:
117:            /**
118:             * Manage the fetch plan for the class
119:             * @param cmd AbstractClassMetaData for the class to manage
120:             * @return the FetchPlanForClass
121:             */
122:            public FetchPlanForClass manageFetchPlanForClass(
123:                    AbstractClassMetaData cmd) {
124:                FetchPlanForClass fetchPlanForClass = (FetchPlanForClass) managedClass
125:                        .get(cmd);
126:                if (fetchPlanForClass == null) {
127:                    fetchPlanForClass = new FetchPlanForClass(cmd, this );
128:                    managedClass.put(cmd, fetchPlanForClass);
129:                }
130:                return fetchPlanForClass;
131:            }
132:
133:            /**
134:             * Mark all managed fetch plans to be dirty, so the active fields need to be recomputed.
135:             */
136:            private void markDirty() {
137:                Iterator it = managedClass.values().iterator();
138:                while (it.hasNext()) {
139:                    ((FetchPlanForClass) it.next()).markDirty();
140:                }
141:            }
142:
143:            /**
144:             * Access the fetch plan for the class
145:             * @param cmd the AbstractClassMetaData
146:             * @return the FetchPlanForClass
147:             */
148:            public synchronized FetchPlanForClass getFetchPlanForClass(
149:                    AbstractClassMetaData cmd) {
150:                return (FetchPlanForClass) managedClass.get(cmd);
151:            }
152:
153:            /**
154:             * Method to add a group to the fetch plan.
155:             * @param fetchGroupName The fetch group to add
156:             * @return Updated Fetch Plan
157:             */
158:            public synchronized FetchPlan addGroup(String fetchGroupName) {
159:                if (fetchGroupName != null) {
160:                    boolean changed = groups.add(fetchGroupName);
161:                    boolean dynChanged = addDynamicGroup(fetchGroupName);
162:                    if (changed || dynChanged) {
163:                        markDirty();
164:                    }
165:                }
166:                return this ;
167:            }
168:
169:            /**
170:             * Method to remove a group from the fetch plan.
171:             * @param fetchGroupName The fetch group to remove
172:             * @return Updated Fetch Plan
173:             */
174:            public synchronized FetchPlan removeGroup(String fetchGroupName) {
175:                if (fetchGroupName != null) {
176:                    boolean changed = false;
177:                    changed = groups.remove(fetchGroupName);
178:                    if (dynamicGroups != null) {
179:                        Iterator iter = dynamicGroups.iterator();
180:                        while (iter.hasNext()) {
181:                            FetchGroupImpl grp = (FetchGroupImpl) iter.next();
182:                            if (grp.getName().equals(fetchGroupName)) {
183:                                grp.deregisterListener(this ); // Deregister us from this group
184:                                changed = true;
185:                                iter.remove();
186:                            }
187:                        }
188:                    }
189:                    if (changed) {
190:                        markDirty();
191:                    }
192:                }
193:
194:                return this ;
195:            }
196:
197:            /**
198:             * Method to clear the current groups and activate the DFG.
199:             * @return The FetchPlan
200:             */
201:            public synchronized FetchPlan clearGroups() {
202:                clearDynamicGroups();
203:                groups.clear();
204:                markDirty();
205:                return this ;
206:            }
207:
208:            /**
209:             * Accessor for the static groups for this FetchPlan.
210:             * Doesn't return the dynamic groups.
211:             * @return The fetch plan groups (unmodifiable)
212:             */
213:            public synchronized Set getGroups() {
214:                return Collections.unmodifiableSet(new HashSet(groups));
215:            }
216:
217:            /**
218:             * Method to set the groups of the fetch plan.
219:             * @param fetchGroupNames The fetch groups
220:             * @return Updated Fetch Plan
221:             */
222:            public synchronized FetchPlan setGroups(Collection fetchGroupNames) {
223:                clearDynamicGroups();
224:                groups.clear();
225:
226:                if (fetchGroupNames != null) {
227:                    Set g = new HashSet(fetchGroupNames);
228:                    groups.addAll(g);
229:
230:                    Iterator iter = fetchGroupNames.iterator();
231:                    while (iter.hasNext()) {
232:                        String fetchGroupName = (String) iter.next();
233:                        addDynamicGroup(fetchGroupName);
234:                    }
235:                }
236:
237:                markDirty();
238:                return this ;
239:            }
240:
241:            /**
242:             * Method to set the groups using an array.
243:             * @param fetchGroupNames Names of the fetch groups
244:             * @return The Fetch Plan
245:             */
246:            public synchronized FetchPlan setGroups(String[] fetchGroupNames) {
247:                clearDynamicGroups();
248:                groups.clear();
249:
250:                if (fetchGroupNames != null) {
251:                    for (int i = 0; i < fetchGroupNames.length; i++) {
252:                        groups.add(fetchGroupNames[i]);
253:                    }
254:                    for (int i = 0; i < fetchGroupNames.length; i++) {
255:                        addDynamicGroup(fetchGroupNames[i]);
256:                    }
257:                }
258:
259:                markDirty();
260:                return this ;
261:            }
262:
263:            /**
264:             * Method to set the fetch group.
265:             * @param fetchGroupName Name of the fetch group
266:             * @return The Fetch Plan
267:             */
268:            public synchronized FetchPlan setGroup(String fetchGroupName) {
269:                clearDynamicGroups();
270:                groups.clear();
271:
272:                if (fetchGroupName != null) {
273:                    groups.add(fetchGroupName);
274:                    addDynamicGroup(fetchGroupName);
275:                }
276:
277:                markDirty();
278:                return this ;
279:            }
280:
281:            /**
282:             * Convenience method to clear all dynamic groups.
283:             */
284:            private void clearDynamicGroups() {
285:                if (dynamicGroups != null) {
286:                    Iterator iter = dynamicGroups.iterator();
287:                    while (iter.hasNext()) {
288:                        FetchGroupImpl grp = (FetchGroupImpl) iter.next();
289:                        grp.deregisterListener(this );
290:                    }
291:                    dynamicGroups.clear();
292:                }
293:            }
294:
295:            /**
296:             * Convenience method to add dynamic fetch groups for the specified name.
297:             * @param fetchGroupName Name of fetch group
298:             * @return Whether the groups were changed
299:             */
300:            private boolean addDynamicGroup(String fetchGroupName) {
301:                boolean changed = false;
302:                FetchGroup[] dynGroups = omf.getFetchGroups(fetchGroupName);
303:                if (dynGroups != null) {
304:                    for (int i = 0; i < dynGroups.length; i++) {
305:                        if (dynamicGroups == null) {
306:                            dynamicGroups = new HashSet();
307:                        }
308:                        dynamicGroups.add(dynGroups[i]);
309:                        ((FetchGroupImpl) dynGroups[i]).registerListener(this ); // Register us with this group
310:                    }
311:                    changed = true;
312:                }
313:                return changed;
314:            }
315:
316:            /**
317:             * Method to notify this FetchPlan that the specified FetchGroup has been updated.
318:             * <B>JPOX dynamic fetch groups extension</B>
319:             * @param group The dynamic FetchGroup
320:             * @since 1.2
321:             */
322:            public void notifyFetchGroupChange(FetchGroup group) {
323:                Collection fpClasses = managedClass.values();
324:                Iterator iter = fpClasses.iterator();
325:                while (iter.hasNext()) {
326:                    FetchPlanForClass fpClass = (FetchPlanForClass) iter.next();
327:                    Class cls = clr
328:                            .classForName(fpClass.cmd.getFullClassName());
329:                    FetchGroupImpl grp = (FetchGroupImpl) group;
330:                    if (cls.isAssignableFrom(grp.getFetchGroupClass())
331:                            || grp.getFetchGroupClass().isAssignableFrom(cls)) {
332:                        // Mark all potentially related fetch plans dirty so they recalculate
333:                        fpClass.markDirty();
334:                    }
335:                }
336:            }
337:
338:            /**
339:             * Method to notify this FetchPlan that the specified FetchGroup has been updated.
340:             * <B>JPOX dynamic fetch groups extension</B>
341:             * @param group The dynamic FetchGroup
342:             * @since 1.2
343:             */
344:            public void notifyFetchGroupRemove(FetchGroup group) {
345:                dynamicGroups.remove(group); // Remove the group
346:                notifyFetchGroupChange(group); // Recalculate all groups fields
347:            }
348:
349:            /**
350:             * Set the roots for DetachAllOnCommit
351:             * @param roots The roots of the detachment graph.
352:             * @return The fetch plan with these roots
353:             */
354:            public FetchPlan setDetachmentRoots(Collection roots) {
355:                if (detachmentRootClasses != null || detachmentRoots != null) {
356:                    throw new JPOXUserException(LOCALISER.msg("006003"));
357:                }
358:
359:                if (roots == null) {
360:                    detachmentRoots = null;
361:                }
362:
363:                detachmentRoots = new ArrayList();
364:                detachmentRoots.addAll(roots);
365:                return this ;
366:            }
367:
368:            /**
369:             * Accessor for the roots of the detachment graph for DetachAllOnCommit.
370:             * @return The roots of the detachment graph.
371:             */
372:            public Collection getDetachmentRoots() {
373:                if (detachmentRoots == null) {
374:                    return Collections.EMPTY_LIST;
375:                }
376:                return Collections.unmodifiableCollection(detachmentRoots);
377:            }
378:
379:            /**
380:             * Set the classes used for roots of the detachment graph for DetachAllOnCommit.
381:             * @param rootClasses Classes to be used as roots of the detachment graph
382:             * @return The fetch plan with these roots
383:             */
384:            public FetchPlan setDetachmentRootClasses(Class[] rootClasses) {
385:                if (detachmentRootClasses != null || detachmentRoots != null) {
386:                    throw new JPOXUserException(LOCALISER.msg("006003"));
387:                }
388:
389:                if (rootClasses == null) {
390:                    detachmentRootClasses = null;
391:                    return this ;
392:                }
393:
394:                detachmentRootClasses = new Class[rootClasses.length];
395:                for (int i = 0; i < rootClasses.length; i++) {
396:                    detachmentRootClasses[i] = rootClasses[i];
397:                }
398:
399:                return this ;
400:            }
401:
402:            /**
403:             * Accessor for the root classes of the detachment graph for DetachAllOnCommit.
404:             * @return The classes to be used as the root of the detachment graph.
405:             */
406:            public Class[] getDetachmentRootClasses() {
407:                if (detachmentRootClasses == null) {
408:                    return new Class[0];
409:                }
410:
411:                return detachmentRootClasses;
412:            }
413:
414:            /**
415:             * Method called at commit() to clear out the detachment roots.
416:             */
417:            void resetDetachmentRoots() {
418:                detachmentRootClasses = null;
419:                detachmentRoots = null;
420:            }
421:
422:            /**
423:             * Mutator for the maximum fetch depth where
424:             * -1 implies no restriction on the fetch depth and
425:             * 0 is invalid and throws a JDOUserException.
426:             * @param max The maximum fetch depth to fetch to
427:             */
428:            public synchronized FetchPlan setMaxFetchDepth(int max) {
429:                if (max == 0) {
430:                    throw new JPOXUserException(LOCALISER.msg("006002", max));
431:                }
432:                this .maxFetchDepth = max;
433:                return this ;
434:            }
435:
436:            /**
437:             * Accessor for the maximum fetch depth.
438:             * @return The maximum fetch depth
439:             */
440:            public synchronized int getMaxFetchDepth() {
441:                return maxFetchDepth;
442:            }
443:
444:            /**
445:             * Method to set the fetch size when using large result sets.
446:             * @param fetchSize the size
447:             * @return Updated Fetch Plan
448:             */
449:            public synchronized FetchPlan setFetchSize(int fetchSize) {
450:                if (fetchSize != FETCH_SIZE_GREEDY
451:                        && fetchSize != FETCH_SIZE_OPTIMAL && fetchSize < 0) {
452:                    // Invalid fetch size so just return
453:                    return this ;
454:                }
455:                this .fetchSize = fetchSize;
456:                return this ;
457:            }
458:
459:            /**
460:             * Accessor for the fetch size when using large result sets.
461:             * @return The size
462:             */
463:            public synchronized int getFetchSize() {
464:                return fetchSize;
465:            }
466:
467:            /**
468:             * Return the options to be used at detachment.
469:             * @return Detachment options
470:             */
471:            public int getDetachmentOptions() {
472:                return detachmentOptions;
473:            }
474:
475:            /**
476:             * Set the options to be used at detachment.
477:             * @param options The options
478:             * @return The updated fetch plan.
479:             */
480:            public FetchPlan setDetachmentOptions(int options) {
481:                detachmentOptions = options;
482:                return this ;
483:            }
484:
485:            /*
486:             * (non-Javadoc)
487:             * @see java.lang.Object#toString()
488:             */
489:            public String toString() {
490:                return groups.toString();
491:            }
492:
493:            /**
494:             * Returns a copy of this FetchPlan with all settings initialized
495:             * @return the FetchPlan
496:             */
497:            public synchronized FetchPlan getCopy() {
498:                FetchPlan fp = new FetchPlan(omf, clr); // Includes DEFAULT
499:                fp.maxFetchDepth = maxFetchDepth;
500:                fp.groups.remove(FetchPlan.DEFAULT);
501:                fp.groups.addAll(this .groups);
502:                if (dynamicGroups != null) {
503:                    fp.dynamicGroups = new HashSet(dynamicGroups);
504:                }
505:
506:                for (Iterator it = this .managedClass.entrySet().iterator(); it
507:                        .hasNext();) {
508:                    Map.Entry entry = (Map.Entry) it.next();
509:                    AbstractClassMetaData cmd = (AbstractClassMetaData) entry
510:                            .getKey();
511:                    FetchPlanForClass fpcls = (FetchPlanForClass) entry
512:                            .getValue();
513:                    fp.managedClass.put(cmd, fpcls.getCopy(fp));
514:                }
515:                fp.fetchSize = this .fetchSize;
516:                return fp;
517:            }
518:
519:            /**
520:             * Class managing the fetch plan for a particular class.
521:             * This should not use the fields of the enclosing FetchPlan directly, always referring
522:             * to them using the "plan" field.
523:             */
524:            public class FetchPlanForClass {
525:                /** Parent FetchPlan. */
526:                final FetchPlan plan;
527:
528:                /** MetaData for the class that this represents. */
529:                final AbstractClassMetaData cmd;
530:
531:                /** Fields in the fetch plan for this class. */
532:                int[] fieldsInActualFetchPlan;
533:
534:                /** Whether the record is dirty and needs the fields recalculating. */
535:                boolean dirty = true;
536:
537:                /**
538:                 * Constructor
539:                 * @param cmd the ClassMetaData
540:                 * @param fetchPlan the FetchPlan
541:                 */
542:                public FetchPlanForClass(final AbstractClassMetaData cmd,
543:                        FetchPlan fetchPlan) {
544:                    super ();
545:                    this .cmd = cmd;
546:                    this .plan = fetchPlan;
547:                }
548:
549:                /**
550:                 * Accessor for the FetchPlan that this classes plan relates to.
551:                 * @return The FetchPlan
552:                 */
553:                public final FetchPlan getFetchPlan() {
554:                    return plan;
555:                }
556:
557:                /**
558:                 * Accessor for the ClassMetaData for this classes plan.
559:                 * @return ClassMetaData for the class represented here
560:                 */
561:                public final AbstractClassMetaData getAbstractClassMetaData() {
562:                    return cmd;
563:                }
564:
565:                void markDirty() {
566:                    dirty = true;
567:                }
568:
569:                FetchPlanForClass getCopy(FetchPlan impl) {
570:                    FetchPlanForClass fp = new FetchPlanForClass(cmd, impl);
571:                    if (this .fieldsInActualFetchPlan != null) {
572:                        fp.fieldsInActualFetchPlan = new int[this .fieldsInActualFetchPlan.length];
573:                        for (int i = 0; i < fp.fieldsInActualFetchPlan.length; i++) {
574:                            fp.fieldsInActualFetchPlan[i] = this .fieldsInActualFetchPlan[i];
575:                        }
576:                    }
577:                    fp.dirty = this .dirty;
578:                    return fp;
579:                }
580:
581:                /**
582:                 * Return whether the specified field is in the fetch plan
583:                 * @param fieldNumber The field number
584:                 * @return Whether it is in the FetchPlan
585:                 */
586:                public boolean isFieldInActualFetchPlan(int fieldNumber) {
587:                    if (dirty) {
588:                        BitSet fieldsNumber = getFieldsInActualFetchPlanByBitSet();
589:                        return fieldsNumber.get(fieldNumber);
590:                    }
591:                    if (fieldsInActualFetchPlan != null) {
592:                        for (int i = 0; i < fieldsInActualFetchPlan.length; i++) {
593:                            if (fieldsInActualFetchPlan[i] == fieldNumber) {
594:                                return true;
595:                            }
596:                        }
597:                    }
598:
599:                    return false;
600:                }
601:
602:                /**
603:                 * Get all fields in the actual fetch plan
604:                 * @return an array with the absolute position of the fields
605:                 */
606:                public int[] getFieldsInActualFetchPlan() {
607:                    if (dirty) {
608:                        dirty = false;
609:                        BitSet fieldsNumber = getFieldsInActualFetchPlanByBitSet();
610:                        int countFieldsInFP = 0;
611:                        for (int i = 0; i < fieldsNumber.length(); i++) {
612:                            if (fieldsNumber.get(i)) {
613:                                countFieldsInFP++;
614:                            }
615:                        }
616:
617:                        fieldsInActualFetchPlan = new int[countFieldsInFP];
618:                        int nextField = 0;
619:                        for (int i = 0; i < fieldsNumber.length(); i++) {
620:                            if (fieldsNumber.get(i)) {
621:                                fieldsInActualFetchPlan[nextField++] = i;
622:                            }
623:                        }
624:                    }
625:                    return fieldsInActualFetchPlan;
626:                }
627:
628:                /**
629:                 * Method to return the effective depth of this field number in the overall fetch plan.
630:                 * @param fieldNumber Number of field in this class
631:                 * @return The (max) recursion depth
632:                 */
633:                public int getMaxRecursionDepthForFieldInCurrentFetchPlan(
634:                        int fieldNumber) {
635:                    // prepare array of FetchGroupMetaData from current fetch plan
636:                    Set currentGroupNames = new HashSet(plan.getGroups());
637:                    FetchGroupMetaData[] fgmds = cmd
638:                            .getFetchGroupMetaData(currentGroupNames);
639:
640:                    // find FetchGroupMetaDatas that contain the field in question
641:                    Set fetchGroupsContainingField = getFetchGroupsForFieldAbsoluteNumber(
642:                            fgmds, fieldNumber);
643:
644:                    // find recursion depth for field in its class <field> definition
645:                    int recursionDepth = cmd
646:                            .getMetaDataForManagedMemberAtAbsolutePosition(
647:                                    fieldNumber).getRecursionDepth();
648:                    if (recursionDepth == AbstractMemberMetaData.UNDEFINED_RECURSION_DEPTH) {
649:                        recursionDepth = AbstractMemberMetaData.DEFAULT_RECURSION_DEPTH;
650:                    }
651:
652:                    // find if it has been overridden in a <fetch-group> definition
653:                    String fieldName = cmd
654:                            .getMetaDataForManagedMemberAtAbsolutePosition(
655:                                    fieldNumber).getName();
656:                    for (Iterator iter = fetchGroupsContainingField.iterator(); iter
657:                            .hasNext();) {
658:                        FetchGroupMetaData fgmd = (FetchGroupMetaData) iter
659:                                .next();
660:                        AbstractMemberMetaData[] fmds = fgmd
661:                                .getMemberMetaData();
662:                        for (int i = 0; i < fmds.length; i++) {
663:                            AbstractMemberMetaData fmd = fmds[i];
664:                            if (fmd.getName().equals(fieldName)) {
665:                                if (fmd.getRecursionDepth() != AbstractMemberMetaData.UNDEFINED_RECURSION_DEPTH) {
666:                                    recursionDepth = fmd.getRecursionDepth();
667:                                }
668:                            }
669:                        }
670:                    }
671:                    return recursionDepth;
672:                }
673:
674:                /**
675:                 * Get all fields in the actual fetch plan.
676:                 * This is public for unit testing purposes only
677:                 * @return an BitSet with the bits set in the absolute position of the fields
678:                 */
679:                public BitSet getFieldsInActualFetchPlanByBitSet() {
680:                    return getFieldsInActualFetchPlanByBitSet(cmd);
681:                }
682:
683:                /**
684:                 * Get all fields in the actual fetch plan for this class and superclasses
685:                 * @param cmd this AbstractClassMetaData
686:                 * @return an BitSet with the bits set in the absolute position of the fields
687:                 */
688:                private BitSet getFieldsInActualFetchPlanByBitSet(
689:                        AbstractClassMetaData cmd) {
690:                    BitSet bitSet = plan.getFetchPlanForClass(cmd)
691:                            .getFieldsAbsoluteNumber(
692:                                    cmd.getFetchGroupMetaData());
693:                    if (cmd.getPersistenceCapableSuperclass() != null) {
694:                        plan.manageFetchPlanForClass(cmd
695:                                .getSuperAbstractClassMetaData());
696:                        bitSet.or(plan.getFetchPlanForClass(
697:                                cmd.getSuperAbstractClassMetaData())
698:                                .getFieldsInActualFetchPlanByBitSet(
699:                                        cmd.getSuperAbstractClassMetaData()));
700:                    } else {
701:                        // Make sure that we always have the PK fields in the fetch plan = FetchPlanImpl.NONE
702:                        setNoneFieldNumbers(bitSet);
703:                    }
704:
705:                    if (plan.dynamicGroups != null) {
706:                        // JPOX dynamic fetch groups extension
707:                        Iterator iter = plan.dynamicGroups.iterator();
708:                        while (iter.hasNext()) {
709:                            FetchGroup grp = (FetchGroup) iter.next();
710:                            if (grp.getClassName().equals(
711:                                    cmd.getFullClassName())) {
712:                                // Dynamic fetch group applies
713:                                String[] fields = grp.getFieldNames();
714:                                for (int i = 0; i < fields.length; i++) {
715:                                    int fieldPos = cmd
716:                                            .getAbsolutePositionOfMember(fields[i]);
717:                                    if (fieldPos >= 0) {
718:                                        bitSet.set(fieldPos);
719:                                    }
720:                                }
721:                            }
722:                        }
723:                    }
724:                    return bitSet;
725:                }
726:
727:                /**
728:                 * Get the absolute number of the fields for an array of Fetch Group
729:                 * @param fgmds The Fetch Groups
730:                 * @return a BitSet with flags set to true in the field number positions
731:                 */
732:                private BitSet getFieldsAbsoluteNumber(
733:                        FetchGroupMetaData[] fgmds) {
734:                    BitSet fieldsNumber = new BitSet(0);
735:                    if (fgmds != null) {
736:                        for (int i = 0; i < fgmds.length; i++) {
737:                            if (plan.groups.contains(fgmds[i].getName())) {
738:                                fieldsNumber
739:                                        .or(getFieldsAbsoluteNumberInFetchGroup(fgmds[i]));
740:                            }
741:                        }
742:                    }
743:
744:                    if (plan.groups.contains(FetchPlan.DEFAULT)) {
745:                        setDefaultFieldNumbers(fieldsNumber);
746:                    }
747:                    if (plan.groups.contains(FetchPlan.ALL)) {
748:                        setAllFieldNumbers(fieldsNumber);
749:                    }
750:                    if (plan.groups.contains(FetchPlan.NONE)) {
751:                        setNoneFieldNumbers(fieldsNumber);
752:                    }
753:                    return fieldsNumber;
754:                }
755:
756:                /**
757:                 * Sets the given list of field numbers to include all the fields defined in the DEFAULT FetchPlan.
758:                 * @param fieldsNumber list of field numbers
759:                 */
760:                private void setDefaultFieldNumbers(BitSet fieldsNumber) {
761:                    for (int i = 0; i < cmd.getDFGMemberPositions().length; i++) {
762:                        fieldsNumber.set(cmd.getDFGMemberPositions()[i]);
763:                    }
764:                }
765:
766:                /**
767:                 * Sets the given list of field numbers to include all the fields defined in the ALL FetchPlan.
768:                 * @param fieldsNumber list of field numbers
769:                 */
770:                private void setAllFieldNumbers(BitSet fieldsNumber) {
771:                    for (int i = 0; i < cmd.getNoOfManagedMembers(); i++) {
772:                        if (cmd.getMetaDataForManagedMemberAtPosition(i)
773:                                .getPersistenceModifier() != FieldPersistenceModifier.NONE) {
774:                            fieldsNumber
775:                                    .set(cmd
776:                                            .getAbsoluteMemberPositionForRelativePosition(i));
777:                        }
778:                    }
779:                }
780:
781:                /**
782:                 * Sets the given list of field numbers to include all the fields defined in the NONE FetchPlan.
783:                 * @param fieldsNumber list of field numbers
784:                 */
785:                private void setNoneFieldNumbers(BitSet fieldsNumber) {
786:                    for (int i = 0; i < cmd.getNoOfManagedMembers(); i++) {
787:                        AbstractMemberMetaData fmd = cmd
788:                                .getMetaDataForMemberAtRelativePosition(i);
789:                        if (fmd.isPrimaryKey()) {
790:                            fieldsNumber.set(fmd.getAbsoluteFieldNumber());
791:                        }
792:                    }
793:                }
794:
795:                /**
796:                 * Get the absolute field number for a particular Fetch Group
797:                 * @param fgmd The Fetch Group
798:                 * @return a list of field numbers
799:                 */
800:                private BitSet getFieldsAbsoluteNumberInFetchGroup(
801:                        FetchGroupMetaData fgmd) {
802:                    BitSet fieldsNumber = new BitSet(0);
803:                    for (int i = 0; i < fgmd.getMemberMetaData().length; i++) {
804:                        int fieldNumber = getFieldNumber(cmd, fgmd
805:                                .getMemberMetaData()[i].getName());
806:                        if (fieldNumber == -1) {
807:                            throw new JPOXUserException(LOCALISER.msg("006000",
808:                                    fgmd.getMemberMetaData()[i].getName(), fgmd
809:                                            .getName(), cmd.getFullClassName()))
810:                                    .setFatal();
811:                        }
812:                        fieldsNumber.set(fieldNumber);
813:                    }
814:                    // fields in nested fetch-groups
815:                    for (int i = 0; i < fgmd.getFetchGroupMetaData().length; i++) {
816:                        String nestedGroupName = fgmd.getFetchGroupMetaData()[i]
817:                                .getName();
818:                        if (nestedGroupName.equals(FetchPlan.DEFAULT)) {
819:                            setDefaultFieldNumbers(fieldsNumber);
820:                        } else if (nestedGroupName.equals(FetchPlan.ALL)) {
821:                            setAllFieldNumbers(fieldsNumber);
822:                        } else if (nestedGroupName.equals(FetchPlan.NONE)) {
823:                            setNoneFieldNumbers(fieldsNumber);
824:                        } else {
825:                            FetchGroupMetaData nestedFGMD = getFetchGroupMetaData(
826:                                    cmd, nestedGroupName);
827:                            if (nestedFGMD == null) {
828:                                throw new JPOXUserException(LOCALISER.msg(
829:                                        "006001",
830:                                        fgmd.getFetchGroupMetaData()[i]
831:                                                .getName(), fgmd.getName(), cmd
832:                                                .getFullClassName()))
833:                                        .setFatal();
834:                            }
835:                            fieldsNumber
836:                                    .or(getFieldsAbsoluteNumberInFetchGroup(nestedFGMD));
837:                        }
838:                    }
839:                    return fieldsNumber;
840:                }
841:
842:                /**
843:                 * Find the FetchGroupMetaData with the specified name for the class.
844:                 * @param cmd the AbstractClassMetaData
845:                 * @param fetchGroupName the fetch group name
846:                 * @return the FetchGroup MetaData declaration or null if not found
847:                 */
848:                private FetchGroupMetaData getFetchGroupMetaData(
849:                        AbstractClassMetaData cmd, String fetchGroupName) {
850:                    FetchGroupMetaData nestedFGMD = null;
851:                    nestedFGMD = cmd.getFetchGroupMetaData(fetchGroupName);
852:                    return nestedFGMD;
853:                }
854:
855:                /**
856:                 * gets the field number for a fieldname in this or superclasses
857:                 * @param cmd this AbstractClassMetaData
858:                 * @param fieldName the field Name
859:                 * @return the field number. -1 if not found
860:                 */
861:                private int getFieldNumber(AbstractClassMetaData cmd,
862:                        String fieldName) {
863:                    int fieldNumber = cmd
864:                            .getAbsolutePositionOfMember(fieldName);
865:                    if (fieldNumber == -1
866:                            && cmd.getPersistenceCapableSuperclass() != null) {
867:                        fieldNumber = getFieldNumber(cmd
868:                                .getSuperAbstractClassMetaData(), fieldName);
869:                    }
870:                    return fieldNumber;
871:                }
872:
873:                /**
874:                 * Get all the fetch groups this field is included
875:                 * @param fgmds The Fetch Groups
876:                 * @param absoluteFieldNumber the field absolute number
877:                 * @return The Fetch Groups
878:                 */
879:                private Set getFetchGroupsForFieldAbsoluteNumber(
880:                        FetchGroupMetaData[] fgmds, int absoluteFieldNumber) {
881:                    Set fetchGroups = new HashSet();
882:                    if (fgmds != null) {
883:                        for (int i = 0; i < fgmds.length; i++) {
884:                            for (int j = 0; j < fgmds[i].getMemberMetaData().length; j++) {
885:                                if (fgmds[i].getMemberMetaData()[j]
886:                                        .getName()
887:                                        .equals(
888:                                                cmd
889:                                                        .getMetaDataForManagedMemberAtAbsolutePosition(
890:                                                                absoluteFieldNumber)
891:                                                        .getName())) {
892:                                    fetchGroups.add(fgmds[i]);
893:                                }
894:                            }
895:                            for (int j = 0; j < fgmds[i]
896:                                    .getFetchGroupMetaData().length; j++) {
897:                                fetchGroups
898:                                        .addAll(getFetchGroupsForFieldAbsoluteNumber(
899:                                                fgmds[i]
900:                                                        .getFetchGroupMetaData(),
901:                                                absoluteFieldNumber));
902:                            }
903:                        }
904:                    }
905:                    return fetchGroups;
906:                }
907:
908:                /** 
909:                 * Cache fetch groups by field number, as calculating them in getFetchGroupsForFieldAbsoluteNumber() 
910:                 * is O(n^2) Map<Integer, Set<FetchGroupMetaData>>
911:                 */
912:                Map fetchGroupsByFieldNumber = new HashMap();
913:
914:                /**
915:                 * Whether to call the post load or not. Checks if fields in actual FetchPlan where not previouly loaded 
916:                 * and the post-load is enabled in the metadata
917:                 * @param loadedFields alredy loaded fields
918:                 * @return if is to call the postLoad
919:                 */
920:                public boolean isToCallPostLoadFetchPlan(boolean[] loadedFields) {
921:                    int[] fieldsInActualFetchPlan = getFieldsInActualFetchPlan();
922:                    for (int i = 0; i < fieldsInActualFetchPlan.length; i++) {
923:                        final int fieldNumber = fieldsInActualFetchPlan[i];
924:                        String fieldName = cmd
925:                                .getMetaDataForManagedMemberAtAbsolutePosition(
926:                                        fieldNumber).getFullFieldName();
927:                        // if field in actual fetch plan was not previously loaded
928:                        if (!loadedFields[fieldNumber]) {
929:                            if (cmd
930:                                    .getMetaDataForManagedMemberAtAbsolutePosition(
931:                                            fieldNumber).isDefaultFetchGroup()
932:                                    && groups.contains(FetchPlan.DEFAULT)) {
933:                                // to call jdoPostLoad, field must be in default-fetch-group when DFG is active
934:                                return true;
935:                            } else {
936:                                // field must be in a fetch-group which has post-load set to true
937:                                Integer fieldNumberInteger = new Integer(
938:                                        fieldNumber);
939:                                Set fetchGroups = (Set) fetchGroupsByFieldNumber
940:                                        .get(fieldNumberInteger);
941:                                if (fetchGroups == null) {
942:                                    fetchGroups = getFetchGroupsForFieldAbsoluteNumber(
943:                                            cmd.getFetchGroupMetaData(),
944:                                            fieldNumber);
945:                                    // cache those precious results from expensive invocation
946:                                    fetchGroupsByFieldNumber.put(
947:                                            fieldNumberInteger, fetchGroups);
948:                                }
949:                                for (Iterator it = fetchGroups.iterator(); it
950:                                        .hasNext();) {
951:                                    FetchGroupMetaData fgmd = (FetchGroupMetaData) it
952:                                            .next();
953:                                    if (fgmd.getPostLoad().booleanValue()) {
954:                                        return true;
955:                                    }
956:                                }
957:
958:                                if (plan.dynamicGroups != null) {
959:                                    Class cls = plan.clr.classForName(cmd
960:                                            .getFullClassName());
961:                                    for (Iterator it = plan.dynamicGroups
962:                                            .iterator(); it.hasNext();) {
963:                                        FetchGroupImpl group = (FetchGroupImpl) it
964:                                                .next();
965:                                        if (group.getFetchGroupClass()
966:                                                .isAssignableFrom(cls)
967:                                                && group.hasField(fieldName)
968:                                                && group.getPostLoad()) {
969:                                            return true;
970:                                        }
971:                                    }
972:                                }
973:                            }
974:                        }
975:                    }
976:                    return false;
977:                }
978:            }
979:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.