Source Code Cross Referenced for DescriptorRepository.java in  » Database-ORM » db-ojb » org » apache » ojb » broker » metadata » 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 » db ojb » org.apache.ojb.broker.metadata 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.apache.ojb.broker.metadata;
002:
003:        /* Copyright 2002-2005 The Apache Software Foundation
004:         *
005:         * Licensed under the Apache License, Version 2.0 (the "License");
006:         * you may not use this file except in compliance with the License.
007:         * You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:
018:        import java.io.Serializable;
019:        import java.util.*;
020:
021:        import org.apache.commons.lang.SystemUtils;
022:        import org.apache.commons.lang.builder.ToStringBuilder;
023:        import org.apache.commons.lang.builder.ToStringStyle;
024:        import org.apache.ojb.broker.OJBRuntimeException;
025:        import org.apache.ojb.broker.PersistenceBrokerException;
026:        import org.apache.ojb.broker.locking.IsolationLevels;
027:        import org.apache.ojb.broker.util.ClassHelper;
028:        import org.apache.ojb.broker.util.logging.LoggerFactory;
029:        import org.apache.ojb.broker.util.logging.Logger;
030:
031:        /**
032:         * The repository containing all object mapping and manipulation information of
033:         * all used persistent objects.
034:         * <br>
035:         * Note: Be careful when use references of this class or caching instances of this class,
036:         * because instances could become invalid (see {@link MetadataManager}).
037:         *
038:         * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
039:         * @author <a href="mailto:leandro@ibnetwork.com.br">Leandro Rodrigo Saad Cruz<a>
040:         * @version $Id: DescriptorRepository.java,v 1.50.2.9 2005/12/21 22:26:11 tomdz Exp $
041:         */
042:        public final class DescriptorRepository extends DescriptorBase
043:                implements  Serializable, XmlCapable, IsolationLevels {
044:            static final long serialVersionUID = -1556339982311359524L;
045:            private Logger log = LoggerFactory
046:                    .getLogger(DescriptorRepository.class);
047:
048:            /**
049:             * The version identifier of the Repository.
050:             * Used to validate repository.xml against the dtd.
051:             */
052:            private static final String VERSION = "1.0";
053:            /**
054:             * the default isolation level used for this repository
055:             */
056:            private int defaultIsolationLevel = IsolationLevels.IL_DEFAULT;
057:            /**
058:             * This table holds all known Mapping descriptions.
059:             * Key values are the respective Class objects
060:             */
061:            private final HashMap descriptorTable;
062:            /**
063:             * We need a lot the extent, to which a class belongs
064:             * (@see DescriptorRepository#getExtentClass). To speed up the costy
065:             * evaluation, we use this tiny hash map.
066:             */
067:            private Map extentTable;
068:
069:            private Map super ClassMultipleJoinedTablesMap;
070:
071:            private transient Map m_multiMappedTableMap;
072:            private transient Map m_topLevelClassTable;
073:            private transient Map m_firstConcreteClassMap;
074:            private transient Map m_allConcreteSubClass;
075:
076:            /**
077:             * Constructor declaration
078:             */
079:            public DescriptorRepository() throws PersistenceBrokerException {
080:                descriptorTable = new HashMap();
081:                extentTable = new HashMap();
082:                super ClassMultipleJoinedTablesMap = new HashMap();
083:            }
084:
085:            public static String getVersion() {
086:                return VERSION;
087:            }
088:
089:            /**
090:             * Add a pair of extent/classdescriptor to the extentTable to gain speed
091:             * while retrieval of extents.
092:             * @param classname the name of the extent itself
093:             * @param cld the class descriptor, where it belongs to
094:             */
095:            void addExtent(String classname, ClassDescriptor cld) {
096:                synchronized (extentTable) {
097:                    extentTable.put(classname, cld);
098:                }
099:            }
100:
101:            /**
102:             * Remove a pair of extent/classdescriptor from the extentTable.
103:             * @param classname the name of the extent itself
104:             */
105:            void removeExtent(String classname) {
106:                synchronized (extentTable) {
107:                    // returns the super class for given extent class name
108:                    ClassDescriptor cld = (ClassDescriptor) extentTable
109:                            .remove(classname);
110:                    if (cld != null && m_topLevelClassTable != null) {
111:                        Class extClass = null;
112:                        try {
113:                            extClass = ClassHelper.getClass(classname);
114:                        } catch (ClassNotFoundException e) {
115:                            // Should not happen
116:                            throw new MetadataException(
117:                                    "Can't instantiate class object for needed extent remove",
118:                                    e);
119:                        }
120:                        // remove extent from super class descriptor
121:                        cld.removeExtentClass(classname);
122:                        m_topLevelClassTable.remove(extClass);
123:                        // clear map with first concrete classes, because the removed
124:                        // extent could be such a first found concrete class
125:                        m_firstConcreteClassMap = null;
126:                    }
127:                }
128:            }
129:
130:            /**
131:             * Returns the top level (extent) class to which the given class belongs.
132:             * This may be a (abstract) base-class, an interface or the given class
133:             * itself if given class is not defined as an extent in other class
134:             * descriptors.
135:             *
136:             * @throws ClassNotPersistenceCapableException if clazz is not persistence capable,
137:             * i.e. if clazz is not defined in the DescriptorRepository.
138:             */
139:            public Class getTopLevelClass(Class clazz)
140:                    throws ClassNotPersistenceCapableException {
141:                if (m_topLevelClassTable == null) {
142:                    m_topLevelClassTable = new HashMap();
143:                }
144:                // try to find an extent that contains clazz
145:                Class retval = (Class) m_topLevelClassTable.get(clazz);
146:                if (retval == null) {
147:                    synchronized (extentTable) {
148:                        ClassDescriptor cld = (ClassDescriptor) extentTable
149:                                .get(clazz.getName());
150:                        if (cld == null) {
151:                            // walk the super-references
152:                            cld = getDescriptorFor(clazz)
153:                                    .getSuperClassDescriptor();
154:                        }
155:
156:                        if (cld != null) {
157:                            // fix by Mark Rowell
158:                            // Changed to call getExtentClass recursively
159:                            retval = getTopLevelClass(cld.getClassOfObject());
160:                            // if such an extent could not be found just return clazz itself.
161:                            if (retval == null) {
162:                                retval = clazz;
163:                            }
164:                        } else {
165:                            // check if class is persistence capable
166:                            // +
167:                            // Adam Jenkins: use the class that is associated
168:                            // with the descriptor instead of the actual class
169:                            ClassDescriptor temp = getDescriptorFor(clazz);
170:                            retval = temp.getClassOfObject();
171:                        }
172:                        m_topLevelClassTable.put(clazz, retval);
173:                    }
174:                }
175:                return retval;
176:            }
177:
178:            /**
179:             * @return all field descriptors for a class that belongs to a set of classes mapped
180:             * to the same table, otherwise the select queries produced won't contain the necessary
181:             * information to materialize extents mapped to the same class.
182:             */
183:            public synchronized FieldDescriptor[] getFieldDescriptorsForMultiMappedTable(
184:                    ClassDescriptor targetCld) {
185:                if (m_multiMappedTableMap == null) {
186:                    m_multiMappedTableMap = new HashMap();
187:                }
188:
189:                FieldDescriptor[] retval = (FieldDescriptor[]) m_multiMappedTableMap
190:                        .get(targetCld.getClassNameOfObject());
191:                if (retval == null) {
192:                    retval = getAllMappedColumns(getClassesMappedToSameTable(targetCld));
193:                    m_multiMappedTableMap.put(targetCld.getClassNameOfObject(),
194:                            retval);
195:                }
196:                return retval;
197:            }
198:
199:            private FieldDescriptor[] getAllMappedColumns(List classDescriptors) {
200:                /* mkalen: Use an ordered implementation not to loose individual field ordering.
201:                    This is especially important for eg Oracle9i platform and LONGVARBINARY columns,
202:                    see http://download-west.oracle.com/docs/cd/B10501_01/java.920/a96654/basic.htm#1021777
203:                    "If you do not use the SELECT-list order to access data,
204:                     then you can lose the stream data."
205:                 */
206:                List allFieldDescriptors = new Vector();
207:
208:                Set visitedColumns = new HashSet();
209:                Iterator it = classDescriptors.iterator();
210:                ClassDescriptor temp = null;
211:                FieldDescriptor[] fields;
212:                while (it.hasNext()) {
213:                    temp = (ClassDescriptor) it.next();
214:                    fields = temp.getFieldDescriptions();
215:                    if (fields != null) {
216:                        for (int i = 0; i < fields.length; i++) {
217:                            /*
218:                            MBAIRD
219:                            hashmap will only allow one entry per unique key,
220:                            so no need to check contains(fields[i].getColumnName()).
221:                            arminw:
222:                            use contains to avoid overriding of target class fields by the same
223:                            field-descriptor of other classes mapped to the same DB table, because
224:                            the other class can use e.g. different FieldConversion.
225:                            In #getClassesMappedToSameTable(...) we make sure that target
226:                            class has first position in list.
227:                             */
228:                            final String columnName = fields[i].getColumnName();
229:                            if (!visitedColumns.contains(columnName)) {
230:                                visitedColumns.add(columnName);
231:                                allFieldDescriptors.add(fields[i]);
232:                            }
233:                        }
234:                    }
235:                }
236:                FieldDescriptor[] retval = new FieldDescriptor[allFieldDescriptors
237:                        .size()];
238:                allFieldDescriptors.toArray(retval);
239:                return retval;
240:            }
241:
242:            private List getClassesMappedToSameTable(ClassDescriptor targetCld) {
243:                /*
244:                try to find an extent that contains clazz
245:                clone map to avoid synchronization problems, because another thread
246:                can do a put(..) operation on descriptor table
247:                 */
248:                Iterator iter = ((HashMap) descriptorTable.clone()).values()
249:                        .iterator();
250:                List retval = new ArrayList();
251:                // make sure that target class is at first position
252:                retval.add(targetCld);
253:                while (iter.hasNext()) {
254:                    ClassDescriptor cld = (ClassDescriptor) iter.next();
255:                    if (cld.getFullTableName() != null) {
256:                        if (cld.getFullTableName().equals(
257:                                targetCld.getFullTableName())
258:                                && !targetCld.getClassOfObject().equals(
259:                                        cld.getClassOfObject())) {
260:                            retval.add(cld);
261:                        }
262:                    }
263:                }
264:                return retval;
265:            }
266:
267:            public Map getDescriptorTable() {
268:                return descriptorTable;
269:            }
270:
271:            /**
272:             * Return the first found concrete class {@link ClassDescriptor}.
273:             * This means a class which is not an interface or an abstract class.
274:             * If given class descriptor is a concrete class, given class descriptor
275:             * was returned. If no concrete class can be found <code>null</code> will be
276:             * returned.
277:             */
278:            public ClassDescriptor findFirstConcreteClass(ClassDescriptor cld) {
279:                if (m_firstConcreteClassMap == null) {
280:                    m_firstConcreteClassMap = new HashMap();
281:                }
282:                ClassDescriptor result = (ClassDescriptor) m_firstConcreteClassMap
283:                        .get(cld.getClassNameOfObject());
284:                if (result == null) {
285:                    if (cld.isInterface() || cld.isAbstract()) {
286:                        if (cld.isExtent()) {
287:                            List extents = cld.getExtentClasses();
288:                            for (int i = 0; i < extents.size(); i++) {
289:                                Class ext = (Class) extents.get(i);
290:                                result = findFirstConcreteClass(getDescriptorFor(ext));
291:                                if (result != null)
292:                                    break;
293:                            }
294:                        } else {
295:                            LoggerFactory
296:                                    .getDefaultLogger()
297:                                    .error(
298:                                            "["
299:                                                    + this .getClass().getName()
300:                                                    + "] Found interface/abstract class"
301:                                                    + " in metadata declarations without concrete class: "
302:                                                    + cld
303:                                                            .getClassNameOfObject());
304:                        }
305:                        m_firstConcreteClassMap.put(cld.getClassNameOfObject(),
306:                                result);
307:                    } else {
308:                        result = cld;
309:                    }
310:                }
311:                return result;
312:            }
313:
314:            /**
315:             *
316:             * Utility method to discover all concrete subclasses of a given super class. <br>
317:             * This method was introduced in order to get Extent Aware Iterators.
318:             *
319:             * @return a Collection of ClassDescriptor objects
320:             */
321:            public Collection getAllConcreteSubclassDescriptors(
322:                    ClassDescriptor aCld) {
323:                if (m_allConcreteSubClass == null) {
324:                    m_allConcreteSubClass = new HashMap();
325:                }
326:                Collection concreteSubclassClds = (Collection) m_allConcreteSubClass
327:                        .get(aCld.getClassOfObject());
328:
329:                if (concreteSubclassClds == null) {
330:                    // BRJ: As long as we do not have an ordered Set
331:                    // duplicates have to be prevented manually.
332:                    // a HashSet should not be used because the order is unpredictable
333:                    concreteSubclassClds = new ArrayList();
334:                    Iterator iter = aCld.getExtentClasses().iterator();
335:
336:                    while (iter.hasNext()) {
337:                        Class extentClass = (Class) iter.next();
338:                        ClassDescriptor extCld = getDescriptorFor(extentClass);
339:                        if (aCld.equals(extCld)) {
340:                            // prevent infinite recursion caused by cyclic references
341:                            continue;
342:                        }
343:                        if (!extCld.isInterface() && !extCld.isAbstract()) {
344:                            if (!concreteSubclassClds.contains(extCld)) {
345:                                concreteSubclassClds.add(extCld);
346:                            }
347:                        }
348:
349:                        // recurse
350:                        Iterator subIter = getAllConcreteSubclassDescriptors(
351:                                extCld).iterator();
352:                        while (subIter.hasNext()) {
353:                            ClassDescriptor subCld = (ClassDescriptor) subIter
354:                                    .next();
355:                            if (!concreteSubclassClds.contains(subCld)) {
356:                                concreteSubclassClds.add(subCld);
357:                            }
358:                        }
359:                    }
360:                    m_allConcreteSubClass.put(aCld.getClassOfObject(),
361:                            concreteSubclassClds);
362:                }
363:
364:                return concreteSubclassClds;
365:            }
366:
367:            /**
368:             * Checks if repository contains given class.
369:             */
370:            public boolean hasDescriptorFor(Class c) {
371:                return descriptorTable.containsKey(c.getName());
372:            }
373:
374:            /**
375:             * lookup a ClassDescriptor in the internal Hashtable
376:             * @param strClassName a fully qualified class name as it is returned by Class.getName().
377:             */
378:            public ClassDescriptor getDescriptorFor(String strClassName)
379:                    throws ClassNotPersistenceCapableException {
380:                ClassDescriptor result = discoverDescriptor(strClassName);
381:                if (result == null) {
382:                    throw new ClassNotPersistenceCapableException(strClassName
383:                            + " not found in OJB Repository");
384:                } else {
385:                    return result;
386:                }
387:            }
388:
389:            /**
390:             * lookup a ClassDescriptor in the internal Hashtable
391:             */
392:            public ClassDescriptor getDescriptorFor(Class c)
393:                    throws ClassNotPersistenceCapableException {
394:                return this .getDescriptorFor(c.getName());
395:            }
396:
397:            /**
398:             * Convenience for {@link #put(Class c, ClassDescriptor cld)}
399:             */
400:            public void setClassDescriptor(ClassDescriptor cld) {
401:                this .put(cld.getClassNameOfObject(), cld);
402:            }
403:
404:            /**
405:             * Add a ClassDescriptor to the internal Hashtable<br>
406:             * Set the Repository for ClassDescriptor
407:             */
408:            public void put(Class c, ClassDescriptor cld) {
409:                this .put(c.getName(), cld);
410:            }
411:
412:            /**
413:             * Add a ClassDescriptor to the internal Hashtable<br>
414:             * Set the Repository for ClassDescriptor
415:             */
416:            public void put(String classname, ClassDescriptor cld) {
417:                cld.setRepository(this ); // BRJ
418:                synchronized (descriptorTable) {
419:                    descriptorTable.put(classname, cld);
420:                    List extentClasses = cld.getExtentClasses();
421:                    for (int i = 0; i < extentClasses.size(); ++i) {
422:                        addExtent(((Class) extentClasses.get(i)).getName(), cld);
423:                    }
424:                    changeDescriptorEvent();
425:                }
426:            }
427:
428:            public void remove(String className) {
429:                synchronized (descriptorTable) {
430:                    ClassDescriptor cld = (ClassDescriptor) descriptorTable
431:                            .remove(className);
432:                    if (cld != null) {
433:                        // class itself could no longer be a extent
434:                        Iterator it = descriptorTable.values().iterator();
435:                        while (it.hasNext()) {
436:                            ((ClassDescriptor) it.next())
437:                                    .removeExtentClass(className);
438:                        }
439:                        removeExtent(className);
440:                        List extentClasses = cld.getExtentClasses();
441:                        for (int i = 0; i < extentClasses.size(); ++i) {
442:                            removeExtent(((Class) extentClasses.get(i))
443:                                    .getName());
444:                        }
445:                        changeDescriptorEvent();
446:                        // deregister classes using mapping of classes to multiple joined tables
447:                        // the registration is done by the class-descriptor itself
448:                        deregisterSuperClassMultipleJoinedTables(cld);
449:                    }
450:                }
451:            }
452:
453:            public void remove(Class clazz) {
454:                remove(clazz.getName());
455:            }
456:
457:            private synchronized void changeDescriptorEvent() {
458:                m_multiMappedTableMap = null;
459:                m_topLevelClassTable = null;
460:                m_firstConcreteClassMap = null;
461:                m_allConcreteSubClass = null;
462:            }
463:
464:            /**
465:             * Returns an iterator over all managed {@link ClassDescriptor}.
466:             */
467:            public Iterator iterator() {
468:                /*
469:                clone map to avoid synchronization problems
470:                 */
471:                return ((HashMap) descriptorTable.clone()).values().iterator();
472:            }
473:
474:            /**
475:             * Returns the defaultIsolationLevel.
476:             * @return int
477:             */
478:            public int getDefaultIsolationLevel() {
479:                return defaultIsolationLevel;
480:            }
481:
482:            /**
483:             * Sets the defaultIsolationLevel.
484:             * @param defaultIsolationLevel The defaultIsolationLevel to set
485:             */
486:            public void setDefaultIsolationLevel(int defaultIsolationLevel) {
487:                this .defaultIsolationLevel = defaultIsolationLevel;
488:            }
489:
490:            /**
491:             * returns a string representation
492:             */
493:            public String toString() {
494:                Iterator it = descriptorTable.entrySet().iterator();
495:                ToStringBuilder buf = new ToStringBuilder(this ,
496:                        ToStringStyle.MULTI_LINE_STYLE);
497:                String className = "class name: ";
498:                String tableName = "> table name: ";
499:                while (it.hasNext()) {
500:                    Map.Entry me = (Map.Entry) it.next();
501:                    ClassDescriptor descriptor = (ClassDescriptor) me
502:                            .getValue();
503:                    buf.append(className + me.getKey() + " =", tableName
504:                            + descriptor.getFullTableName());
505:                }
506:                return buf.toString();
507:            }
508:
509:            /*
510:             * @see XmlCapable#toXML()
511:             */
512:            public String toXML() {
513:                String eol = SystemUtils.LINE_SEPARATOR;
514:                StringBuffer buf = new StringBuffer();
515:
516:                // write all ClassDescriptors
517:                Iterator i = this .iterator();
518:                while (i.hasNext()) {
519:                    buf.append(((XmlCapable) i.next()).toXML() + eol);
520:                }
521:                return buf.toString();
522:            }
523:
524:            /**
525:             * returns IsolationLevel literal as matching
526:             * to the corresponding id
527:             * @return the IsolationLevel literal
528:             */
529:            protected String getIsolationLevelAsString() {
530:                if (defaultIsolationLevel == IL_READ_UNCOMMITTED) {
531:                    return LITERAL_IL_READ_UNCOMMITTED;
532:                } else if (defaultIsolationLevel == IL_READ_COMMITTED) {
533:                    return LITERAL_IL_READ_COMMITTED;
534:                } else if (defaultIsolationLevel == IL_REPEATABLE_READ) {
535:                    return LITERAL_IL_REPEATABLE_READ;
536:                } else if (defaultIsolationLevel == IL_SERIALIZABLE) {
537:                    return LITERAL_IL_SERIALIZABLE;
538:                } else if (defaultIsolationLevel == IL_OPTIMISTIC) {
539:                    return LITERAL_IL_OPTIMISTIC;
540:                }
541:                return LITERAL_IL_READ_UNCOMMITTED;
542:            }
543:
544:            /**
545:             * Starts by looking to see if the <code>className</code> is
546:             * already mapped specifically to the descritpor repository.
547:             * If the <code>className</code> is not specifically mapped we
548:             * look at the <code>className</code>'s parent class for a mapping.
549:             * We do this until the parent class is of the type
550:             * <code>java.lang.Object</code>.  If no mapping was found,
551:             * <code>null</code> is returned.  Mappings successfuly discovered
552:             * through inheritence are added to the internal table of
553:             * class descriptors to improve performance on subsequent requests
554:             * for those classes.
555:             *
556:             * <br/>
557:             * author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
558:             * @param className name of class whose descriptor we need to find.
559:             * @return ClassDescriptor for <code>className</code> or <code>null</code>
560:             * if no ClassDescriptor could be located.
561:             */
562:            protected ClassDescriptor discoverDescriptor(String className) {
563:                ClassDescriptor result = (ClassDescriptor) descriptorTable
564:                        .get(className);
565:                if (result == null) {
566:                    Class clazz;
567:                    try {
568:                        clazz = ClassHelper.getClass(className, true);
569:                    } catch (ClassNotFoundException e) {
570:                        throw new OJBRuntimeException("Class, " + className
571:                                + ", could not be found.", e);
572:                    }
573:                    result = discoverDescriptor(clazz);
574:                }
575:                return result;
576:            }
577:
578:            /**
579:             * Internal method for recursivly searching for a class descriptor that avoids
580:             * class loading when we already have a class object.
581:             *
582:             * @param clazz The class whose descriptor we need to find
583:             * @return ClassDescriptor for <code>clazz</code> or <code>null</code>
584:             *         if no ClassDescriptor could be located.
585:             */
586:            private ClassDescriptor discoverDescriptor(Class clazz) {
587:                ClassDescriptor result = (ClassDescriptor) descriptorTable
588:                        .get(clazz.getName());
589:
590:                if (result == null) {
591:                    Class super Class = clazz.getSuperclass();
592:                    // only recurse if the superClass is not java.lang.Object
593:                    if (super Class != null) {
594:                        result = discoverDescriptor(super Class);
595:                    }
596:                    if (result == null) {
597:                        // we're also checking the interfaces as there could be normal
598:                        // mappings for them in the repository (using factory-class,
599:                        // factory-method, and the property field accessor)
600:                        Class[] interfaces = clazz.getInterfaces();
601:
602:                        if ((interfaces != null) && (interfaces.length > 0)) {
603:                            for (int idx = 0; (idx < interfaces.length)
604:                                    && (result == null); idx++) {
605:                                result = discoverDescriptor(interfaces[idx]);
606:                            }
607:                        }
608:                    }
609:
610:                    if (result != null) {
611:                        descriptorTable.put(clazz.getName(), result);
612:                    }
613:                }
614:                return result;
615:            }
616:
617:            /**
618:             * Internal used! Register sub-classes of specified class when mapping class to
619:             * multiple joined tables is used. Normally this method is called by the {@link ClassDescriptor}
620:             * itself.
621:             *
622:             * @param cld The {@link ClassDescriptor} of the class to register.
623:             */
624:            protected void registerSuperClassMultipleJoinedTables(
625:                    ClassDescriptor cld) {
626:                /*
627:                arminw: Sadly, we can't map to sub class-descriptor, because it's not guaranteed
628:                that they exist when this method is called. Thus we map the class instance instead
629:                of the class-descriptor.
630:                 */
631:                if (cld.getBaseClass() != null) {
632:                    try {
633:                        Class super Class = ClassHelper.getClass(cld
634:                                .getBaseClass());
635:                        Class currentClass = cld.getClassOfObject();
636:                        synchronized (descriptorTable) {
637:                            List subClasses = (List) super ClassMultipleJoinedTablesMap
638:                                    .get(super Class);
639:                            if (subClasses == null) {
640:                                subClasses = new ArrayList();
641:                                super ClassMultipleJoinedTablesMap.put(
642:                                        super Class, subClasses);
643:                            }
644:                            if (!subClasses.contains(currentClass)) {
645:                                if (log.isDebugEnabled()) {
646:                                    log
647:                                            .debug("(MultipleJoinedTables): Register sub-class '"
648:                                                    + currentClass
649:                                                    + "' for class '"
650:                                                    + super Class);
651:                                }
652:                                subClasses.add(currentClass);
653:                            }
654:                        }
655:                    } catch (Exception e) {
656:                        throw new MetadataException(
657:                                "Can't register super class '"
658:                                        + cld.getBaseClass()
659:                                        + "' for class-descriptor: " + cld, e);
660:                    }
661:                }
662:            }
663:
664:            /**
665:             * Internal used! Deregister sub-classes of specified class when mapping to multiple joined tables
666:             * is used. Normally this method is called when {@link #remove(Class)} a class.
667:             *
668:             * @param cld The {@link ClassDescriptor} of the class to register.
669:             */
670:            protected void deregisterSuperClassMultipleJoinedTables(
671:                    ClassDescriptor cld) {
672:                try {
673:                    Class currentClass = cld.getClassOfObject();
674:                    synchronized (descriptorTable) {
675:                        // first remove registered sub-classes for current class
676:                        List subClasses = (List) super ClassMultipleJoinedTablesMap
677:                                .remove(currentClass);
678:                        if (subClasses != null && log.isDebugEnabled()) {
679:                            log
680:                                    .debug("(MultipleJoinedTables): Deregister class "
681:                                            + currentClass
682:                                            + " with sub classes " + subClasses);
683:                        }
684:                        if (cld.getBaseClass() != null) {
685:                            // then remove sub-class entry of current class for super-class
686:                            Class super Class = ClassHelper.getClass(cld
687:                                    .getBaseClass());
688:                            subClasses = (List) super ClassMultipleJoinedTablesMap
689:                                    .get(super Class);
690:                            if (subClasses != null) {
691:                                boolean removed = subClasses
692:                                        .remove(currentClass);
693:                                if (removed && log.isDebugEnabled()) {
694:                                    log
695:                                            .debug("(MultipleJoinedTables): Remove sub-class entry '"
696:                                                    + currentClass
697:                                                    + "' in mapping for class '"
698:                                                    + super Class + "'");
699:                                }
700:                            }
701:                        }
702:                    }
703:                } catch (Exception e) {
704:                    throw new MetadataException(
705:                            "Can't deregister super class '"
706:                                    + cld.getBaseClass()
707:                                    + "' for class-descriptor: " + cld, e);
708:                }
709:            }
710:
711:            /**
712:             * Return <em>sub-classes</em> of the specified class using the
713:             * <em>"super"-Reference</em> concept.
714:             * @param cld The {@link ClassDescriptor} of the class to search for sub-classes.
715:             * @param wholeTree If set <em>true</em>, the whole sub-class tree of the specified
716:             * class will be returned. If <em>false</em> only the direct sub-classes of the specified class
717:             * will be returned.
718:             * @return An array of <em>sub-classes</em> for the specified class.
719:             */
720:            public Class[] getSubClassesMultipleJoinedTables(
721:                    ClassDescriptor cld, boolean wholeTree) {
722:                ArrayList result = new ArrayList();
723:                createResultSubClassesMultipleJoinedTables(result, cld,
724:                        wholeTree);
725:                return (Class[]) result.toArray(new Class[result.size()]);
726:            }
727:
728:            /**
729:             * Add all sub-classes using multiple joined tables feature for specified class.
730:             * @param result The list to add results.
731:             * @param cld The {@link ClassDescriptor} of the class to search for sub-classes.
732:             * @param wholeTree If set <em>true</em>, the whole sub-class tree of the specified
733:             * class will be returned. If <em>false</em> only the direct sub-classes of the specified class
734:             * will be returned.
735:             */
736:            private void createResultSubClassesMultipleJoinedTables(
737:                    List result, ClassDescriptor cld, boolean wholeTree) {
738:                List tmp = (List) super ClassMultipleJoinedTablesMap.get(cld
739:                        .getClassOfObject());
740:                if (tmp != null) {
741:                    result.addAll(tmp);
742:                    if (wholeTree) {
743:                        for (int i = 0; i < tmp.size(); i++) {
744:                            Class subClass = (Class) tmp.get(i);
745:                            ClassDescriptor subCld = getDescriptorFor(subClass);
746:                            createResultSubClassesMultipleJoinedTables(result,
747:                                    subCld, wholeTree);
748:                        }
749:                    }
750:                }
751:            }
752:
753:            protected void finalize() throws Throwable {
754:                log.info("# finalize DescriptorRepository instance #");
755:                super.finalize();
756:            }
757:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.