KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > metadata > DescriptorRepository


1 package org.apache.ojb.broker.metadata;
2
3 /* Copyright 2002-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import java.io.Serializable JavaDoc;
19 import java.util.*;
20
21 import org.apache.commons.lang.SystemUtils;
22 import org.apache.commons.lang.builder.ToStringBuilder;
23 import org.apache.commons.lang.builder.ToStringStyle;
24 import org.apache.ojb.broker.OJBRuntimeException;
25 import org.apache.ojb.broker.PersistenceBrokerException;
26 import org.apache.ojb.broker.locking.IsolationLevels;
27 import org.apache.ojb.broker.util.ClassHelper;
28 import org.apache.ojb.broker.util.logging.LoggerFactory;
29 import org.apache.ojb.broker.util.logging.Logger;
30
31 /**
32  * The repository containing all object mapping and manipulation information of
33  * all used persistent objects.
34  * <br>
35  * Note: Be careful when use references of this class or caching instances of this class,
36  * because instances could become invalid (see {@link MetadataManager}).
37  *
38  * @author <a HREF="mailto:thma@apache.org">Thomas Mahler<a>
39  * @author <a HREF="mailto:leandro@ibnetwork.com.br">Leandro Rodrigo Saad Cruz<a>
40  * @version $Id: DescriptorRepository.java,v 1.50.2.9 2005/12/21 22:26:11 tomdz Exp $
41  */

42 public final class DescriptorRepository extends DescriptorBase
43         implements Serializable JavaDoc, XmlCapable, IsolationLevels
44 {
45     static final long serialVersionUID = -1556339982311359524L;
46     private Logger log = LoggerFactory.getLogger(DescriptorRepository.class);
47
48     /**
49      * The version identifier of the Repository.
50      * Used to validate repository.xml against the dtd.
51      */

52     private static final String JavaDoc VERSION = "1.0";
53     /**
54      * the default isolation level used for this repository
55      */

56     private int defaultIsolationLevel = IsolationLevels.IL_DEFAULT;
57     /**
58      * This table holds all known Mapping descriptions.
59      * Key values are the respective Class objects
60      */

61     private final HashMap descriptorTable;
62     /**
63      * We need a lot the extent, to which a class belongs
64      * (@see DescriptorRepository#getExtentClass). To speed up the costy
65      * evaluation, we use this tiny hash map.
66      */

67     private Map extentTable;
68
69     private Map superClassMultipleJoinedTablesMap;
70
71     private transient Map m_multiMappedTableMap;
72     private transient Map m_topLevelClassTable;
73     private transient Map m_firstConcreteClassMap;
74     private transient Map m_allConcreteSubClass;
75
76     /**
77      * Constructor declaration
78      */

79     public DescriptorRepository() throws PersistenceBrokerException
80     {
81         descriptorTable = new HashMap();
82         extentTable = new HashMap();
83         superClassMultipleJoinedTablesMap = new HashMap();
84     }
85
86     public static String JavaDoc getVersion()
87     {
88         return VERSION;
89     }
90
91     /**
92      * Add a pair of extent/classdescriptor to the extentTable to gain speed
93      * while retrieval of extents.
94      * @param classname the name of the extent itself
95      * @param cld the class descriptor, where it belongs to
96      */

97     void addExtent(String JavaDoc classname, ClassDescriptor cld)
98     {
99         synchronized (extentTable)
100         {
101             extentTable.put(classname, cld);
102         }
103     }
104
105     /**
106      * Remove a pair of extent/classdescriptor from the extentTable.
107      * @param classname the name of the extent itself
108      */

109     void removeExtent(String JavaDoc classname)
110     {
111         synchronized (extentTable)
112         {
113             // returns the super class for given extent class name
114
ClassDescriptor cld = (ClassDescriptor) extentTable.remove(classname);
115             if(cld != null && m_topLevelClassTable != null)
116             {
117                 Class JavaDoc extClass = null;
118                 try
119                 {
120                     extClass = ClassHelper.getClass(classname);
121                 }
122                 catch (ClassNotFoundException JavaDoc e)
123                 {
124                     // Should not happen
125
throw new MetadataException("Can't instantiate class object for needed extent remove", e);
126                 }
127                 // remove extent from super class descriptor
128
cld.removeExtentClass(classname);
129                 m_topLevelClassTable.remove(extClass);
130                 // clear map with first concrete classes, because the removed
131
// extent could be such a first found concrete class
132
m_firstConcreteClassMap = null;
133             }
134         }
135     }
136
137     /**
138      * Returns the top level (extent) class to which the given class belongs.
139      * This may be a (abstract) base-class, an interface or the given class
140      * itself if given class is not defined as an extent in other class
141      * descriptors.
142      *
143      * @throws ClassNotPersistenceCapableException if clazz is not persistence capable,
144      * i.e. if clazz is not defined in the DescriptorRepository.
145      */

146     public Class JavaDoc getTopLevelClass(Class JavaDoc clazz) throws ClassNotPersistenceCapableException
147     {
148         if(m_topLevelClassTable == null)
149         {
150             m_topLevelClassTable = new HashMap();
151         }
152         // try to find an extent that contains clazz
153
Class JavaDoc retval = (Class JavaDoc) m_topLevelClassTable.get(clazz);
154         if (retval == null)
155         {
156             synchronized (extentTable)
157             {
158                 ClassDescriptor cld = (ClassDescriptor) extentTable.get(clazz.getName());
159                 if (cld == null)
160                 {
161                     // walk the super-references
162
cld = getDescriptorFor(clazz).getSuperClassDescriptor();
163                 }
164                 
165                 if (cld != null)
166                 {
167                     // fix by Mark Rowell
168
// Changed to call getExtentClass recursively
169
retval = getTopLevelClass(cld.getClassOfObject());
170                     // if such an extent could not be found just return clazz itself.
171
if (retval == null)
172                     {
173                         retval = clazz;
174                     }
175                 }
176                 else
177                 {
178                     // check if class is persistence capable
179
// +
180
// Adam Jenkins: use the class that is associated
181
// with the descriptor instead of the actual class
182
ClassDescriptor temp = getDescriptorFor(clazz);
183                     retval = temp.getClassOfObject();
184                 }
185                 m_topLevelClassTable.put(clazz, retval);
186             }
187         }
188         return retval;
189     }
190
191     /**
192      * @return all field descriptors for a class that belongs to a set of classes mapped
193      * to the same table, otherwise the select queries produced won't contain the necessary
194      * information to materialize extents mapped to the same class.
195      */

196     public synchronized FieldDescriptor[] getFieldDescriptorsForMultiMappedTable(ClassDescriptor targetCld)
197     {
198         if (m_multiMappedTableMap == null)
199         {
200             m_multiMappedTableMap = new HashMap();
201         }
202
203         FieldDescriptor[] retval = (FieldDescriptor[]) m_multiMappedTableMap.get(targetCld.getClassNameOfObject());
204         if (retval == null)
205         {
206             retval = getAllMappedColumns(getClassesMappedToSameTable(targetCld));
207             m_multiMappedTableMap.put(targetCld.getClassNameOfObject(), retval);
208         }
209         return retval;
210     }
211
212     private FieldDescriptor[] getAllMappedColumns(List classDescriptors)
213     {
214         /* mkalen: Use an ordered implementation not to loose individual field ordering.
215             This is especially important for eg Oracle9i platform and LONGVARBINARY columns,
216             see http://download-west.oracle.com/docs/cd/B10501_01/java.920/a96654/basic.htm#1021777
217             "If you do not use the SELECT-list order to access data,
218              then you can lose the stream data."
219         */

220         List allFieldDescriptors = new Vector();
221
222         Set visitedColumns = new HashSet();
223         Iterator it = classDescriptors.iterator();
224         ClassDescriptor temp = null;
225         FieldDescriptor[] fields;
226         while (it.hasNext())
227         {
228             temp = (ClassDescriptor) it.next();
229             fields = temp.getFieldDescriptions();
230             if (fields != null)
231             {
232                 for (int i = 0; i < fields.length; i++)
233                 {
234                     /*
235                     MBAIRD
236                     hashmap will only allow one entry per unique key,
237                     so no need to check contains(fields[i].getColumnName()).
238                     arminw:
239                     use contains to avoid overriding of target class fields by the same
240                     field-descriptor of other classes mapped to the same DB table, because
241                     the other class can use e.g. different FieldConversion.
242                     In #getClassesMappedToSameTable(...) we make sure that target
243                     class has first position in list.
244                      */

245                     final String JavaDoc columnName = fields[i].getColumnName();
246                     if (!visitedColumns.contains(columnName))
247                     {
248                         visitedColumns.add(columnName);
249                         allFieldDescriptors.add(fields[i]);
250                     }
251                 }
252             }
253         }
254         FieldDescriptor[] retval = new FieldDescriptor[allFieldDescriptors.size()];
255         allFieldDescriptors.toArray(retval);
256         return retval;
257     }
258
259     private List getClassesMappedToSameTable(ClassDescriptor targetCld)
260     {
261         /*
262         try to find an extent that contains clazz
263         clone map to avoid synchronization problems, because another thread
264         can do a put(..) operation on descriptor table
265         */

266         Iterator iter = ((HashMap)descriptorTable.clone()).values().iterator();
267         List retval = new ArrayList();
268         // make sure that target class is at first position
269
retval.add(targetCld);
270         while (iter.hasNext())
271         {
272             ClassDescriptor cld = (ClassDescriptor) iter.next();
273             if (cld.getFullTableName() != null)
274             {
275                 if (cld.getFullTableName().equals(targetCld.getFullTableName())
276                         && !targetCld.getClassOfObject().equals(cld.getClassOfObject()))
277                 {
278                     retval.add(cld);
279                 }
280             }
281         }
282         return retval;
283     }
284
285     public Map getDescriptorTable()
286     {
287         return descriptorTable;
288     }
289
290     /**
291      * Return the first found concrete class {@link ClassDescriptor}.
292      * This means a class which is not an interface or an abstract class.
293      * If given class descriptor is a concrete class, given class descriptor
294      * was returned. If no concrete class can be found <code>null</code> will be
295      * returned.
296      */

297     public ClassDescriptor findFirstConcreteClass(ClassDescriptor cld)
298     {
299         if(m_firstConcreteClassMap == null)
300         {
301             m_firstConcreteClassMap = new HashMap();
302         }
303         ClassDescriptor result = (ClassDescriptor) m_firstConcreteClassMap.get(cld.getClassNameOfObject());
304         if (result == null)
305         {
306             if(cld.isInterface() || cld.isAbstract())
307             {
308                 if(cld.isExtent())
309                 {
310                     List extents = cld.getExtentClasses();
311                     for (int i = 0; i < extents.size(); i++)
312                     {
313                         Class JavaDoc ext = (Class JavaDoc) extents.get(i);
314                         result = findFirstConcreteClass(getDescriptorFor(ext));
315                         if(result != null) break;
316                     }
317                 }
318                 else
319                 {
320                     LoggerFactory.getDefaultLogger().error("["+this.getClass().getName()+"] Found interface/abstract class" +
321                             " in metadata declarations without concrete class: "+cld.getClassNameOfObject());
322                 }
323                 m_firstConcreteClassMap.put(cld.getClassNameOfObject(), result);
324             }
325             else
326             {
327                 result = cld;
328             }
329         }
330         return result;
331     }
332
333     /**
334      *
335      * Utility method to discover all concrete subclasses of a given super class. <br>
336      * This method was introduced in order to get Extent Aware Iterators.
337      *
338      * @return a Collection of ClassDescriptor objects
339      */

340     public Collection getAllConcreteSubclassDescriptors(ClassDescriptor aCld)
341     {
342         if(m_allConcreteSubClass == null)
343         {
344             m_allConcreteSubClass = new HashMap();
345         }
346         Collection concreteSubclassClds = (Collection) m_allConcreteSubClass.get(aCld.getClassOfObject());
347
348         if (concreteSubclassClds == null)
349         {
350             // BRJ: As long as we do not have an ordered Set
351
// duplicates have to be prevented manually.
352
// a HashSet should not be used because the order is unpredictable
353
concreteSubclassClds = new ArrayList();
354             Iterator iter = aCld.getExtentClasses().iterator();
355
356             while (iter.hasNext())
357             {
358                 Class JavaDoc extentClass = (Class JavaDoc) iter.next();
359                 ClassDescriptor extCld = getDescriptorFor(extentClass);
360                 if (aCld.equals(extCld))
361                 {
362                     // prevent infinite recursion caused by cyclic references
363
continue;
364                 }
365                 if (!extCld.isInterface() && !extCld.isAbstract())
366                 {
367                     if (!concreteSubclassClds.contains(extCld))
368                     {
369                         concreteSubclassClds.add(extCld);
370                     }
371                 }
372
373                 // recurse
374
Iterator subIter = getAllConcreteSubclassDescriptors(extCld).iterator();
375                 while (subIter.hasNext())
376                 {
377                     ClassDescriptor subCld = (ClassDescriptor)subIter.next();
378                     if (!concreteSubclassClds.contains(subCld))
379                     {
380                         concreteSubclassClds.add(subCld);
381                     }
382                 }
383             }
384             m_allConcreteSubClass.put(aCld.getClassOfObject(), concreteSubclassClds);
385         }
386
387         return concreteSubclassClds;
388     }
389
390
391     /**
392      * Checks if repository contains given class.
393      */

394     public boolean hasDescriptorFor(Class JavaDoc c)
395     {
396         return descriptorTable.containsKey(c.getName());
397     }
398
399     /**
400      * lookup a ClassDescriptor in the internal Hashtable
401      * @param strClassName a fully qualified class name as it is returned by Class.getName().
402      */

403     public ClassDescriptor getDescriptorFor(String JavaDoc strClassName) throws ClassNotPersistenceCapableException
404     {
405         ClassDescriptor result = discoverDescriptor(strClassName);
406         if (result == null)
407         {
408             throw new ClassNotPersistenceCapableException(strClassName + " not found in OJB Repository");
409         }
410         else
411         {
412             return result;
413         }
414     }
415
416     /**
417      * lookup a ClassDescriptor in the internal Hashtable
418      */

419     public ClassDescriptor getDescriptorFor(Class JavaDoc c) throws ClassNotPersistenceCapableException
420     {
421         return this.getDescriptorFor(c.getName());
422     }
423
424     /**
425      * Convenience for {@link #put(Class c, ClassDescriptor cld)}
426      */

427     public void setClassDescriptor(ClassDescriptor cld)
428     {
429         this.put(cld.getClassNameOfObject(), cld);
430     }
431
432     /**
433      * Add a ClassDescriptor to the internal Hashtable<br>
434      * Set the Repository for ClassDescriptor
435      */

436     public void put(Class JavaDoc c, ClassDescriptor cld)
437     {
438         this.put(c.getName(), cld);
439     }
440
441     /**
442      * Add a ClassDescriptor to the internal Hashtable<br>
443      * Set the Repository for ClassDescriptor
444      */

445     public void put(String JavaDoc classname, ClassDescriptor cld)
446     {
447         cld.setRepository(this); // BRJ
448
synchronized (descriptorTable)
449         {
450             descriptorTable.put(classname, cld);
451             List extentClasses = cld.getExtentClasses();
452             for (int i = 0; i < extentClasses.size(); ++i)
453             {
454                 addExtent(((Class JavaDoc) extentClasses.get(i)).getName(), cld);
455             }
456             changeDescriptorEvent();
457         }
458     }
459
460     public void remove(String JavaDoc className)
461     {
462         synchronized (descriptorTable)
463         {
464             ClassDescriptor cld = (ClassDescriptor) descriptorTable.remove(className);
465             if(cld != null)
466             {
467                 // class itself could no longer be a extent
468
Iterator it = descriptorTable.values().iterator();
469                 while (it.hasNext())
470                 {
471                     ((ClassDescriptor) it.next()).removeExtentClass(className);
472                 }
473                 removeExtent(className);
474                 List extentClasses = cld.getExtentClasses();
475                 for (int i = 0; i < extentClasses.size(); ++i)
476                 {
477                     removeExtent(((Class JavaDoc) extentClasses.get(i)).getName());
478                 }
479                 changeDescriptorEvent();
480                 // deregister classes using mapping of classes to multiple joined tables
481
// the registration is done by the class-descriptor itself
482
deregisterSuperClassMultipleJoinedTables(cld);
483             }
484         }
485     }
486
487     public void remove(Class JavaDoc clazz)
488     {
489         remove(clazz.getName());
490     }
491
492     private synchronized void changeDescriptorEvent()
493     {
494         m_multiMappedTableMap = null;
495         m_topLevelClassTable = null;
496         m_firstConcreteClassMap = null;
497         m_allConcreteSubClass = null;
498     }
499
500     /**
501      * Returns an iterator over all managed {@link ClassDescriptor}.
502      */

503     public Iterator iterator()
504     {
505         /*
506         clone map to avoid synchronization problems
507         */

508         return ((HashMap)descriptorTable.clone()).values().iterator();
509     }
510
511     /**
512      * Returns the defaultIsolationLevel.
513      * @return int
514      */

515     public int getDefaultIsolationLevel()
516     {
517         return defaultIsolationLevel;
518     }
519
520     /**
521      * Sets the defaultIsolationLevel.
522      * @param defaultIsolationLevel The defaultIsolationLevel to set
523      */

524     public void setDefaultIsolationLevel(int defaultIsolationLevel)
525     {
526         this.defaultIsolationLevel = defaultIsolationLevel;
527     }
528
529     /**
530      * returns a string representation
531      */

532     public String JavaDoc toString()
533     {
534         Iterator it = descriptorTable.entrySet().iterator();
535         ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE);
536         String JavaDoc className = "class name: ";
537         String JavaDoc tableName = "> table name: ";
538         while (it.hasNext())
539         {
540             Map.Entry me = (Map.Entry) it.next();
541             ClassDescriptor descriptor = (ClassDescriptor) me.getValue();
542             buf.append(className + me.getKey() + " =", tableName + descriptor.getFullTableName());
543         }
544         return buf.toString();
545     }
546
547     /*
548      * @see XmlCapable#toXML()
549      */

550     public String JavaDoc toXML()
551     {
552         String JavaDoc eol = SystemUtils.LINE_SEPARATOR;
553         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
554
555         // write all ClassDescriptors
556
Iterator i = this.iterator();
557         while (i.hasNext())
558         {
559             buf.append(((XmlCapable) i.next()).toXML() + eol);
560         }
561         return buf.toString();
562     }
563
564     /**
565      * returns IsolationLevel literal as matching
566      * to the corresponding id
567      * @return the IsolationLevel literal
568      */

569     protected String JavaDoc getIsolationLevelAsString()
570     {
571         if (defaultIsolationLevel == IL_READ_UNCOMMITTED)
572         {
573             return LITERAL_IL_READ_UNCOMMITTED;
574         }
575         else if (defaultIsolationLevel == IL_READ_COMMITTED)
576         {
577             return LITERAL_IL_READ_COMMITTED;
578         }
579         else if (defaultIsolationLevel == IL_REPEATABLE_READ)
580         {
581             return LITERAL_IL_REPEATABLE_READ;
582         }
583         else if (defaultIsolationLevel == IL_SERIALIZABLE)
584         {
585             return LITERAL_IL_SERIALIZABLE;
586         }
587         else if (defaultIsolationLevel == IL_OPTIMISTIC)
588         {
589             return LITERAL_IL_OPTIMISTIC;
590         }
591         return LITERAL_IL_READ_UNCOMMITTED;
592     }
593
594     /**
595      * Starts by looking to see if the <code>className</code> is
596      * already mapped specifically to the descritpor repository.
597      * If the <code>className</code> is not specifically mapped we
598      * look at the <code>className</code>'s parent class for a mapping.
599      * We do this until the parent class is of the type
600      * <code>java.lang.Object</code>. If no mapping was found,
601      * <code>null</code> is returned. Mappings successfuly discovered
602      * through inheritence are added to the internal table of
603      * class descriptors to improve performance on subsequent requests
604      * for those classes.
605      *
606      * <br/>
607      * author <a HREF="mailto:weaver@apache.org">Scott T. Weaver</a>
608      * @param className name of class whose descriptor we need to find.
609      * @return ClassDescriptor for <code>className</code> or <code>null</code>
610      * if no ClassDescriptor could be located.
611      */

612     protected ClassDescriptor discoverDescriptor(String JavaDoc className)
613     {
614         ClassDescriptor result = (ClassDescriptor) descriptorTable.get(className);
615         if (result == null)
616         {
617             Class JavaDoc clazz;
618             try
619             {
620                 clazz = ClassHelper.getClass(className, true);
621             }
622             catch (ClassNotFoundException JavaDoc e)
623             {
624                 throw new OJBRuntimeException("Class, " + className + ", could not be found.", e);
625             }
626             result = discoverDescriptor(clazz);
627          }
628         return result;
629     }
630
631     /**
632      * Internal method for recursivly searching for a class descriptor that avoids
633      * class loading when we already have a class object.
634      *
635      * @param clazz The class whose descriptor we need to find
636      * @return ClassDescriptor for <code>clazz</code> or <code>null</code>
637      * if no ClassDescriptor could be located.
638      */

639     private ClassDescriptor discoverDescriptor(Class JavaDoc clazz)
640     {
641         ClassDescriptor result = (ClassDescriptor) descriptorTable.get(clazz.getName());
642
643         if (result == null)
644         {
645             Class JavaDoc superClass = clazz.getSuperclass();
646             // only recurse if the superClass is not java.lang.Object
647
if (superClass != null)
648             {
649                 result = discoverDescriptor(superClass);
650             }
651             if (result == null)
652             {
653                 // we're also checking the interfaces as there could be normal
654
// mappings for them in the repository (using factory-class,
655
// factory-method, and the property field accessor)
656
Class JavaDoc[] interfaces = clazz.getInterfaces();
657
658                 if ((interfaces != null) && (interfaces.length > 0))
659                 {
660                     for (int idx = 0; (idx < interfaces.length) && (result == null); idx++)
661                     {
662                         result = discoverDescriptor(interfaces[idx]);
663                     }
664                 }
665             }
666
667             if (result != null)
668             {
669                 descriptorTable.put(clazz.getName(), result);
670             }
671         }
672         return result;
673     }
674
675     /**
676      * Internal used! Register sub-classes of specified class when mapping class to
677      * multiple joined tables is used. Normally this method is called by the {@link ClassDescriptor}
678      * itself.
679      *
680      * @param cld The {@link ClassDescriptor} of the class to register.
681      */

682     protected void registerSuperClassMultipleJoinedTables(ClassDescriptor cld)
683     {
684         /*
685         arminw: Sadly, we can't map to sub class-descriptor, because it's not guaranteed
686         that they exist when this method is called. Thus we map the class instance instead
687         of the class-descriptor.
688         */

689         if(cld.getBaseClass() != null)
690         {
691             try
692             {
693                 Class JavaDoc superClass = ClassHelper.getClass(cld.getBaseClass());
694                 Class JavaDoc currentClass = cld.getClassOfObject();
695                 synchronized(descriptorTable)
696                 {
697                     List subClasses = (List) superClassMultipleJoinedTablesMap.get(superClass);
698                     if(subClasses == null)
699                     {
700                         subClasses = new ArrayList();
701                         superClassMultipleJoinedTablesMap.put(superClass, subClasses);
702                     }
703                     if(!subClasses.contains(currentClass))
704                     {
705                         if(log.isDebugEnabled())
706                         {
707                             log.debug("(MultipleJoinedTables): Register sub-class '" + currentClass
708                                     + "' for class '" + superClass);
709                         }
710                         subClasses.add(currentClass);
711                     }
712                 }
713             }
714             catch(Exception JavaDoc e)
715             {
716                 throw new MetadataException("Can't register super class '" + cld.getBaseClass()
717                         + "' for class-descriptor: " + cld, e);
718             }
719         }
720     }
721
722     /**
723      * Internal used! Deregister sub-classes of specified class when mapping to multiple joined tables
724      * is used. Normally this method is called when {@link #remove(Class)} a class.
725      *
726      * @param cld The {@link ClassDescriptor} of the class to register.
727      */

728     protected void deregisterSuperClassMultipleJoinedTables(ClassDescriptor cld)
729     {
730         try
731         {
732             Class JavaDoc currentClass = cld.getClassOfObject();
733             synchronized(descriptorTable)
734             {
735                 // first remove registered sub-classes for current class
736
List subClasses = (List) superClassMultipleJoinedTablesMap.remove(currentClass);
737                 if(subClasses != null && log.isDebugEnabled())
738                 {
739                     log.debug("(MultipleJoinedTables): Deregister class " + currentClass
740                             + " with sub classes " + subClasses);
741                 }
742                 if(cld.getBaseClass() != null)
743                 {
744                     // then remove sub-class entry of current class for super-class
745
Class JavaDoc superClass = ClassHelper.getClass(cld.getBaseClass());
746                     subClasses = (List) superClassMultipleJoinedTablesMap.get(superClass);
747                     if(subClasses != null)
748                     {
749                         boolean removed = subClasses.remove(currentClass);
750                         if(removed && log.isDebugEnabled())
751                         {
752                             log.debug("(MultipleJoinedTables): Remove sub-class entry '" + currentClass
753                             + "' in mapping for class '" + superClass + "'");
754                         }
755                     }
756                 }
757             }
758         }
759         catch(Exception JavaDoc e)
760         {
761             throw new MetadataException("Can't deregister super class '" + cld.getBaseClass()
762                     + "' for class-descriptor: " + cld, e);
763         }
764     }
765
766     /**
767      * Return <em>sub-classes</em> of the specified class using the
768      * <em>"super"-Reference</em> concept.
769      * @param cld The {@link ClassDescriptor} of the class to search for sub-classes.
770      * @param wholeTree If set <em>true</em>, the whole sub-class tree of the specified
771      * class will be returned. If <em>false</em> only the direct sub-classes of the specified class
772      * will be returned.
773      * @return An array of <em>sub-classes</em> for the specified class.
774      */

775     public Class JavaDoc[] getSubClassesMultipleJoinedTables(ClassDescriptor cld, boolean wholeTree)
776     {
777         ArrayList result = new ArrayList();
778         createResultSubClassesMultipleJoinedTables(result, cld, wholeTree);
779         return (Class JavaDoc[]) result.toArray(new Class JavaDoc[result.size()]);
780     }
781
782     /**
783      * Add all sub-classes using multiple joined tables feature for specified class.
784      * @param result The list to add results.
785      * @param cld The {@link ClassDescriptor} of the class to search for sub-classes.
786      * @param wholeTree If set <em>true</em>, the whole sub-class tree of the specified
787      * class will be returned. If <em>false</em> only the direct sub-classes of the specified class
788      * will be returned.
789      */

790     private void createResultSubClassesMultipleJoinedTables(List result, ClassDescriptor cld, boolean wholeTree)
791     {
792         List tmp = (List) superClassMultipleJoinedTablesMap.get(cld.getClassOfObject());
793         if(tmp != null)
794         {
795             result.addAll(tmp);
796             if(wholeTree)
797             {
798                 for(int i = 0; i < tmp.size(); i++)
799                 {
800                     Class JavaDoc subClass = (Class JavaDoc) tmp.get(i);
801                     ClassDescriptor subCld = getDescriptorFor(subClass);
802                     createResultSubClassesMultipleJoinedTables(result, subCld, wholeTree);
803                 }
804             }
805         }
806     }
807
808     protected void finalize() throws Throwable JavaDoc
809     {
810         log.info("# finalize DescriptorRepository instance #");
811         super.finalize();
812     }
813 }
814
Popular Tags