KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jorm > metainfo > lib > BasicClass


1 /**
2  * JORM: an implementation of a generic mapping system for persistent Java
3  * objects. Two mapping are supported: to RDBMS and to binary files.
4  * Copyright (C) 2001-2003 France Telecom R&D - INRIA
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * Contact: jorm-team@objectweb.org
21  *
22  */

23
24 package org.objectweb.jorm.metainfo.lib;
25
26 import org.objectweb.jorm.api.PException;
27 import org.objectweb.jorm.metainfo.api.*;
28 import org.objectweb.jorm.metainfo.api.Class;
29 import org.objectweb.jorm.metainfo.api.Package;
30 import org.objectweb.jorm.metainfo.lib.BasicMetaObject;
31 import org.objectweb.jorm.type.api.PType;
32 import org.objectweb.util.monolog.api.BasicLevel;
33 import org.objectweb.medor.api.MedorException;
34 import org.objectweb.medor.expression.api.Expression;
35 import org.objectweb.medor.expression.api.MalformedExpressionException;
36 import org.objectweb.medor.expression.api.ExpressionException;
37 import org.objectweb.medor.expression.api.Operator;
38 import org.objectweb.medor.expression.api.ParameterOperand;
39 import org.objectweb.medor.expression.parser.string.ExpressionParser;
40 import org.objectweb.medor.expression.parser.api.ParameterTypeProvider;
41
42 import java.util.ArrayList JavaDoc;
43 import java.util.Collection JavaDoc;
44 import java.util.Iterator JavaDoc;
45 import java.util.HashMap JavaDoc;
46 import java.util.Map JavaDoc;
47 import java.util.Collections JavaDoc;
48 import java.util.List JavaDoc;
49
50 /**
51  * BasicClass is an implementation of the Class interface defined
52  * in the meta information system. This object is defined by a list
53  * of fields, a name, a list of mapping.
54  * @author X. Spengler
55  */

56 public class BasicClass extends BasicMetaObject implements Class JavaDoc {
57     /**
58      * abstractClass boolean defines if the current class is an abstract
59      * class or not.
60      */

61     private boolean abstractClass;
62     private String JavaDoc fileName;
63
64     /**
65      * name is the name of the current class object.
66      */

67     private String JavaDoc name;
68
69     /**
70      * nameDefs defines a list of NameDef that the user can potentially
71      * used for the mapping.
72      * key: the name of the NameDef object
73      * value: a NameDef object
74      */

75
76     private ArrayList JavaDoc nameDefs;
77     private HashMap JavaDoc nd2Exp;
78     private HashMap JavaDoc nd2Key;
79
80     /**
81      * classRefs defines the list of the fields reprensented by
82      * a reference to a Class.
83      * key: the name of the ClassRef object
84      * value: the ClassRef object
85      */

86     private Map JavaDoc classRefs;
87
88     /**
89      * genClassRefs defines the list of the fields which are defined
90      * by a Generic Class.
91      * key: the name of the GenClassRef object
92      * value: the GenClassRef object
93      */

94     private Map JavaDoc genClassRefs;
95
96     /**
97      * primitiveElements defines the list of the fields with a primitive type.
98      * key: the name of the PrimitiveElement object
99      * value: the PrimitiveElement object
100      */

101     private Map JavaDoc primitiveElements;
102
103     /**
104      * hiddenFields defines the list of the hiddenfields.
105      * These fields are scalar fields.
106      * key: the name of the hiddenField object
107      * value: the scalarfield object
108      */

109     private Map JavaDoc hiddenFields;
110
111     /**
112      * pe2Value defines the constant values of PrimitiveElements which are
113      * constant.
114      */

115     private Map JavaDoc pe2Value;
116     /**
117      * derivedClasses represents the list of the classes derived from
118      * the current class object.
119      * element: a Class MetaObject object
120      */

121     private ArrayList JavaDoc derivedClasses;
122
123     /**
124      * This hashmap associates a full qualified class name with
125      * an Class object.
126      */

127     private Map JavaDoc superClasses;
128
129     /**
130      * This HashMap associates a project name with a vector of ClassProject
131      * objects.
132      * The notion of project allows the developer to define multiple mappings
133      * for a class per mapper type.
134      */

135     private HashMap JavaDoc classProjects;
136
137     /**
138      * Builds a new Class object.
139      * This object is mainly defined by its name, if the class is abstract or
140      * not, and its parent (a schema).
141      *
142      * @param className the name of the current class
143      * @param parent the parent of the current object
144      */

145     public BasicClass(String JavaDoc className,
146                       MetaObject parent) {
147         super(parent);
148         this.name = className;
149         this.abstractClass = false;
150         classRefs = new HashMap JavaDoc();
151         genClassRefs = new HashMap JavaDoc();
152         nameDefs = new ArrayList JavaDoc();
153         primitiveElements = new HashMap JavaDoc();
154         hiddenFields = new HashMap JavaDoc();
155         derivedClasses = new ArrayList JavaDoc();
156         superClasses = new HashMap JavaDoc();
157         classProjects = new HashMap JavaDoc();
158         this.fileName = getFQName().replace('.',
159             System.getProperty("file.separator").charAt(0)) + ".pd";
160     }
161
162     protected Collection JavaDoc getChildren() {
163         ArrayList JavaDoc res = new ArrayList JavaDoc();
164         res.addAll(nameDefs);
165         res.addAll(classProjects.values());
166         res.addAll(superClasses.values());
167         res.addAll(getAllFields());
168         res.addAll(getAllHiddenFields());
169         return res;
170     }
171
172     ///////////////////////////////////////////////////////////////////
173
// from Class interface
174
///////////////////////////////////////////////////////////////////
175

176     /**
177      * Allows to retrieve the file name of this class MO.
178      * @return The file name.
179      */

180     public String JavaDoc getFileName() {
181         return fileName;
182     }
183
184     /**
185      * Allows to assign the file name of this class MO.
186      * @param filename The file name.
187      */

188     public void setFileName(String JavaDoc filename) {
189         this.fileName = filename;
190     }
191
192     /**
193      * Allows to know if the current class is an abstract class or not.
194      *
195      * @return true, if the current class is an abstract class, and false,
196      * if the current class is not abstract
197      */

198     public boolean isAbstract() {
199         return abstractClass;
200     }
201
202     public void setAbstract(boolean isAbstract) {
203         abstractClass = isAbstract;
204     }
205
206     /**
207      * Allows to know the name of the current class object.
208      * @return the string representation of the class name
209      */

210     public String JavaDoc getName() {
211         return name;
212     }
213
214     public String JavaDoc getFQName() {
215         String JavaDoc packName = null;
216         MetaObject parent = getParent();
217         if (parent instanceof Package JavaDoc)
218             packName = ((Package JavaDoc) parent).getName();
219         if (packName == null || packName.length() == 0)
220             return name;
221         else
222             return packName + "." + name;
223     }
224
225     /**
226      * Allows to obtain an existing Field.
227      * A TypedElement is a class field, and this method finds a field with its
228      * name (fieldName). This method is a generic method to return a
229      * TypedElement object. The field can be hidden or not.
230      *
231      * @param fieldName the name of the class field
232      * @return a field object. If the field does not exist, null is returned.
233      */

234     public TypedElement getTypedElement(String JavaDoc fieldName) {
235         if (debug)
236             logger.log(BasicLevel.DEBUG, "try to return field (" + fieldName + ")");
237
238         TypedElement res = null;
239         // this method finds in the 3 structures where is the field
240
// fieldName could be a PrimitiveElement
241
res = (TypedElement) primitiveElements.get(fieldName);
242         if (res != null) {
243             if (debug)
244                 logger.log(BasicLevel.DEBUG, "the field is a PrimitiveElement object");
245             return res;
246         }
247         res = (TypedElement) hiddenFields.get(fieldName);
248         if (res != null) {
249             if (debug)
250                 logger.log(BasicLevel.DEBUG, "the field is an hiddenfield object");
251             return res;
252         }
253         res = (TypedElement) classRefs.get(fieldName);
254         // fieldName could be a reference to a class
255
if (classRefs.get(fieldName) != null) {
256             if (debug)
257                 logger.log(BasicLevel.DEBUG, "the field is a ClassRef object");
258             return res;
259         }
260         res = (TypedElement) genClassRefs.get(fieldName);
261         // fieldName could be a reference to a generic class
262
if (res != null) {
263             if (debug)
264                 logger.log(BasicLevel.DEBUG, "the field is a GenClassRef object");
265             return (GenClassRef) genClassRefs.get(fieldName);
266         }
267         Iterator JavaDoc it = getSuperClasses().iterator();
268         while (it.hasNext() && res == null) {
269             res = ((Class JavaDoc) it.next()).getTypedElement(fieldName);
270         }
271         // attention, the fieldname does not exist. where is it ?
272
if (res == null && debug)
273             logger.log(BasicLevel.DEBUG, "the field (" + fieldName
274                 + ") is not defined in the current class");
275         return res;
276     }
277
278     /**
279      * Removes a typed element.
280      * @param fieldName is the name of the field to be removed
281      * @return the removed element or null if the field has not been found.
282      */

283     public TypedElement removeTypedElement(String JavaDoc fieldName) {
284         TypedElement res = (TypedElement) primitiveElements.remove(fieldName);
285         if (res != null) {
286             return res;
287         }
288         res = (TypedElement) hiddenFields.remove(fieldName);
289         if (res != null) {
290             return res;
291         }
292         res = (TypedElement) classRefs.remove(fieldName);
293         // fieldName could be a reference to a class
294
if (classRefs.get(fieldName) != null) {
295             return res;
296         }
297         res = (TypedElement) genClassRefs.remove(fieldName);
298         return res;
299     }
300
301     /**
302      * Creates a new NameDef object for the current Class object.
303      * Here we can define if the namedef is defined outside jorm or not.
304      * In the case where the namedef is already defined for the current class,
305      * the old one is used and returned.
306      *
307      * @return a new object used to describe the PName projection for
308      * the current Class
309      */

310     public NameDef createNameDef() {
311         if (debug)
312             logger.log(BasicLevel.DEBUG,
313                        "create a new NameDef () for the current Class '" + name + "'");
314         NameDef newNameDef = new BasicNameDef(this);
315         setLoggingOnChild(newNameDef);
316         nameDefs.add(newNameDef);
317         return newNameDef;
318     }
319
320
321     /**
322      * Returns a NameDef object.
323      * If the namedef does not exist, null is returned.
324      *
325      * @param name the name of a NameDef object.
326      * @return a namedef object, else null is returned.
327      */

328     public NameDef getNameDef(String JavaDoc name) {
329         Iterator JavaDoc iter = nameDefs.iterator();
330         while (iter.hasNext()) {
331             NameDef nameDef = (NameDef) iter.next();
332             if (nameDef.getName().equals(name)) {
333                 return nameDef;
334             }
335         }
336         return null;
337     }
338
339     public Collection JavaDoc getNameDefs() {
340         return nameDefs;
341     }
342
343     public synchronized Expression getInheritanceFilter(NameDef nd) throws ExpressionException {
344         Object JavaDoc filter = (nd2Exp == null ? null : nd2Exp.get(nd));
345         if (filter instanceof String JavaDoc) {
346             filter = parseInheritanceFilter((String JavaDoc) filter, nd);
347             nd2Exp.put(nd, filter);
348         }
349         //if filter is null, try the parents
350
if (filter == null && !superClasses.isEmpty()) {
351             Iterator JavaDoc it = getSuperClasses().iterator();
352             while (it.hasNext() && filter == null) {
353                 Class JavaDoc cl = (Class JavaDoc) it.next();
354                 filter = cl.getInheritanceFilter(nd);
355             }
356         }
357         return (Expression) filter;
358     }
359
360     public Object JavaDoc getInheritanceNamingKey(NameDef nd) {
361         return (nd2Key == null ? null : nd2Key.get(nd));
362     }
363
364     public void setInheritanceFilter(NameDef nd, Expression e) {
365         if (nd == null || e == null) {
366             return;
367         }
368         if (nd2Exp == null) {
369             nd2Exp = new HashMap JavaDoc(5);
370         }
371         nd2Exp.put(nd, e);
372     }
373
374     public void setInheritanceFilter(NameDef nd, String JavaDoc filter) {
375         if (nd == null || filter == null) {
376             return;
377         }
378         if (nd2Exp == null) {
379             nd2Exp = new HashMap JavaDoc(5);
380         }
381         nd2Exp.put(nd, filter);
382     }
383
384     public void setInheritanceNamingKey(NameDef nd, Object JavaDoc key) {
385         if (nd == null) {
386             return;
387         }
388         if (nd2Key == null) {
389             nd2Key = new HashMap JavaDoc(5);
390         }
391         nd2Key.put(nd, key);
392     }
393
394     /**
395      * Allows to obtain a new PrimitiveElement from a class field name an its
396      * type.
397      * A PrimitiveElement is a Class field. If the class field already exists,
398      * it is returned.
399      *
400      * @param fieldName the name of the primitive field
401      * @param type the PType of the primitive field
402      * @return a new PrimitiveElement object, or the existing one if already
403      * defined
404      */

405     public PrimitiveElement createPrimitiveElement(String JavaDoc fieldName,
406                                                    PType type,
407                                                    int size, int scale) {
408         if (debug)
409             logger.log(BasicLevel.DEBUG, "create a new PrimitiveElement (" +
410                                          fieldName + ") for the current Class (" + name + ")");
411
412         // try to get the fieldname from the current structure
413
PrimitiveElement result = (PrimitiveElement)
414                 primitiveElements.get(fieldName);
415         if (result != null) {
416             // be careful, the primitive element already exists, we return it.
417
if (logger != null) {
418                 logger.log(BasicLevel.WARN,
419                        "Try to create an existing PrimitiveElement (" +
420                        fieldName + "), return existing one");
421             }
422         } else {
423             // oh, the primitive element does not exist, we must create it.
424
result = new BasicPrimitiveElement(fieldName, type, size, scale, this);
425             setLoggingOnChild(result);
426             primitiveElements.put(fieldName, result);
427         }
428         return result;
429     }
430
431     public void setConstantValue(String JavaDoc fieldName, String JavaDoc cv) {
432         if (pe2Value == null) {
433             pe2Value = new HashMap JavaDoc();
434         }
435         pe2Value.put(fieldName, cv);
436     }
437
438     public String JavaDoc getConstantValue(String JavaDoc fieldName) {
439         return (pe2Value == null ? null : (String JavaDoc) pe2Value.get(fieldName));
440     }
441
442     /**
443      * Creates a new scalar field and adds it to the list of hidden fields.
444      * If the field already exists, it is returned, else a new one is built.
445      *
446      * @param fieldName the name of the field to create
447      * @param type the type of the field to create
448      * @return a new ScalarField object if this object does not already exist
449      */

450     public ScalarField createHiddenField(String JavaDoc fieldName, PType type, int size, int scale) {
451         if (debug)
452             logger.log(BasicLevel.DEBUG,
453                        "create a new HiddenField (" + fieldName + ") for the current class (" + name + ")");
454
455         // verify if the field is not yet in the database
456
ScalarField result = (ScalarField) hiddenFields.get(fieldName);
457         if (result != null) {
458             if (logger != null) {
459                 logger.log(BasicLevel.WARN,
460                        "Try to create an existing HiddenField (" +
461                        fieldName + "), return existing one");
462             }
463         } else {
464             // else create a new one
465
result = new BasicScalarField(fieldName, type, size, scale, this);
466             setLoggingOnChild(result);
467             hiddenFields.put(fieldName, result);
468         }
469         return result;
470     }
471
472     /**
473      * Allows to obtain a new ClassRef from a field name an its class.
474      * A ClassRef object is a field which is represented by a reference to a
475      * Class. If the field already exists, it is returned.
476      *
477      * @param fieldName the name of the field
478      * @param class_ the string representation of the class which represents
479      * the reference of the field
480      * @return a new ClassRef object, or the existing one if already defined
481      */

482     public ClassRef createClassRef(String JavaDoc fieldName, Class JavaDoc class_) {
483         if (debug)
484             logger.log(BasicLevel.DEBUG, "create a new ClassRef (" + fieldName +
485                                          ") for the current Class (" + name + ")");
486
487         // just verify if the fielname does not exist in the current structure.
488
ClassRef result = (ClassRef) classRefs.get(fieldName);
489         if (result != null) {
490             // be careful, the object exists, we return it
491
if (logger != null) {
492                 logger.log(BasicLevel.WARN,
493                        "attention, try to create an existing ClassRef (" +
494                        fieldName + "), return existing one");
495             }
496         } else {
497             // we have to create a new object
498
result = new BasicClassRef(fieldName, class_, this);
499             setLoggingOnChild(result);
500             classRefs.put(fieldName, result);
501         }
502         return result;
503     }
504
505     /**
506      * Allows to obtain a new GenClassRef from a field name an its generic
507      * class.
508      * A GenClassRef object is a field which is represented by a
509      * reference to a generic class. If the field already exists,
510      * it is returned.
511      *
512      * @param fieldName the name of the field
513      * @param genName the GenClass object which represents the reference of
514      * the field
515      * @return a new GenClassRef object, or the existing one if already
516      * defined
517      */

518     public GenClassRef createGenClassRef(String JavaDoc fieldName, String JavaDoc genName) {
519         if (debug)
520             logger.log(BasicLevel.DEBUG, "create a new GenClassRef (" +
521                                          genName + ") from field (" + fieldName + ") from Class (" +
522                                          name + ")");
523
524         // verify if the fieldname already exists
525
GenClassRef result = (GenClassRef) genClassRefs.get(fieldName);
526         if (result != null) {
527             // be careful, the object already exists, we return it
528
if (logger != null) {
529                 logger.log(BasicLevel.WARN,
530                        "attention, try to create an existing GenClassRef (" + fieldName +
531                        "), return existing one");
532             }
533         } else {
534             // we have to create a new object and return it
535
result = new BasicGenClassRef(genName, fieldName, this);
536             setLoggingOnChild(result);
537             genClassRefs.put(fieldName, result);
538         }
539         return result;
540     }
541
542     /**
543      * returns an ArrayList which contains the current fields.
544      * @return a list of current fields
545      */

546     protected List JavaDoc listField() {
547         return listField(new ArrayList JavaDoc());
548     }
549     protected List JavaDoc listField(List JavaDoc allFields) {
550         allFields.addAll(primitiveElements.values());
551         allFields.addAll(classRefs.values());
552         allFields.addAll(genClassRefs.values());
553         Collections.sort(allFields, FieldComparator.instance);
554         return allFields;
555     }
556     protected List JavaDoc listAllFields(List JavaDoc allFields) {
557         listField(allFields);
558         // and add the fields from the inherited classes
559
Iterator JavaDoc iter = getSuperClasses().iterator();
560         while (iter.hasNext())
561             ((BasicClass) iter.next()).listAllFields(allFields);
562         return allFields;
563     }
564
565     public Collection JavaDoc getFields() {
566         List JavaDoc fields = listField(new ArrayList JavaDoc());
567         Collections.sort(fields, FieldComparator.instance);
568         return fields;
569     }
570
571     public Collection JavaDoc getAllFields() {
572         List JavaDoc allFields = listAllFields(new ArrayList JavaDoc());
573         Collections.sort(allFields, FieldComparator.instance);
574         return allFields;
575     }
576
577     protected List JavaDoc listHiddenFields(List JavaDoc allFields) {
578         allFields.addAll(hiddenFields.values());
579         return allFields;
580     }
581
582     protected List JavaDoc listAllHiddenField(List JavaDoc allFields) {
583         listHiddenFields(allFields);
584         Iterator JavaDoc iter = getSuperClasses().iterator();
585         while (iter.hasNext())
586             ((BasicClass) iter.next()).listAllHiddenField(allFields);
587         return allFields;
588     }
589
590     public Collection JavaDoc getHiddenFields() {
591         List JavaDoc hiddenFields = listHiddenFields(new ArrayList JavaDoc());
592         Collections.sort(hiddenFields, FieldComparator.instance);
593         return hiddenFields;
594     }
595
596     public Collection JavaDoc getAllHiddenFields() {
597         List JavaDoc allFields = listAllHiddenField(new ArrayList JavaDoc());
598         Collections.sort(allFields, FieldComparator.instance);
599         return allFields;
600     }
601
602     /**
603      * retrieve an hiddenfield from its name.
604      *
605      * @return the hiddenfield or null if the field does not exist.
606      */

607     public ScalarField getHiddenField(String JavaDoc fieldName) {
608         if (debug)
609             logger.log(BasicLevel.DEBUG,
610                        "try to return an hidden field (" + fieldName + ")");
611         // this method finds in the 3 structures where is the field
612
return (ScalarField) hiddenFields.get(fieldName);
613     }
614
615     public Collection JavaDoc getSubClasses() {
616         return derivedClasses;
617     }
618
619     /**
620      * Returns a collection of Class objects.
621      * Returns only the direct super classes of this class.
622      * In the following graph,
623      * A
624      * ---------
625      * | |
626      * B C
627      * -----
628      * |
629      * D
630      * superclass of D is C.
631      * The s in superclasses comes from the fact that in JORM a class can have many superclasses.
632      *
633      * @return a collection.
634      */

635     public Collection JavaDoc getSuperClasses() {
636         return superClasses.values();
637     }
638
639     public Class JavaDoc getSuperClass(String JavaDoc fqcn) {
640         return (Class JavaDoc) superClasses.get(fqcn);
641     }
642
643     /**
644      * Adds a new inherited class to the list of the inherited classes for the
645      * current class object.
646      * If the class already exists, nothing is done.
647      *
648      * @param class_ the inherited class to add to inherited classes list
649      *
650      */

651     public void addSuperClass(Class JavaDoc class_) {
652         if ((class_ != null) &&
653             (!superClasses.containsKey(class_.getFQName()))) {
654             superClasses.put(class_.getFQName(), class_);
655             class_.addSubClass(this);
656         }
657     }
658
659     public void addSubClass(Class JavaDoc class_) {
660         if ((class_ != null) &&
661                 (!derivedClasses.contains(class_))) {
662             derivedClasses.add(class_);
663             class_.addSuperClass(this);
664         }
665     }
666
667     /**
668      * Returns the number of inherited classes for the current Class object.
669      *
670      * @return the number of inherited classes
671      */

672     public int getInheritedClassNumber() {
673         return superClasses.size();
674     }
675
676     /**
677      * Returns all the ancestors of the class, i.e.:
678      * A
679      * ---------
680      * | |
681      * B C
682      * -----
683      * |
684      * D
685      * all ancestors of D are C and A.
686      *
687      */

688     public List JavaDoc getAllAncestors() {
689         if (superClasses.isEmpty()) {
690             return Collections.EMPTY_LIST;
691         }
692         List JavaDoc ancestors = new ArrayList JavaDoc();
693         ancestors.add(this); //init the algorithm
694
int i=0;
695         while(i < ancestors.size()) {
696             Class JavaDoc clazz = (Class JavaDoc) ancestors.get(i);
697             Collection JavaDoc c = clazz.getSuperClasses();
698             // Add super classes which have not already been listed
699
for(Iterator JavaDoc it = c.iterator(); it.hasNext();) {
700                 Class JavaDoc superClass = (Class JavaDoc) it.next();
701                 if (!ancestors.contains(superClass)) {
702                     ancestors.add(superClass);
703                 }
704             }
705             i++; // treat the next element in the list
706
}
707         ancestors.remove(0);
708         return ancestors;
709     }
710
711     /**
712      * Return the list (most often with only one element) of ancestors.
713      * In the following graph,
714      * A
715      * ---------
716      * | |
717      * B C
718      * -----
719      * |
720      * D
721      * ancestor of D is A.
722      * The s of ancestors comes from the fact that with JORM a class can have many superclasses.
723      */

724     public List JavaDoc getAncestors() {
725         if (superClasses.isEmpty()) {
726             return Collections.EMPTY_LIST;
727         }
728         List JavaDoc ancestors = new ArrayList JavaDoc();
729         List JavaDoc roots = new ArrayList JavaDoc();
730         ancestors.add(this); //init the algorithm
731
while(!ancestors.isEmpty()) {
732             Class JavaDoc clazz = (Class JavaDoc) ancestors.remove(0);
733             Collection JavaDoc c = clazz.getSuperClasses();
734             if (c.isEmpty()) {
735                 if (!roots.contains(clazz)) {
736                     roots.add(clazz);
737                 }
738             } else {
739                 // Add super classes which have not already listed
740
for(Iterator JavaDoc it = c.iterator(); it.hasNext();) {
741                     Class JavaDoc superClass = (Class JavaDoc) it.next();
742                     if (!ancestors.contains(superClass)) {
743                         ancestors.add(superClass);
744                     }
745                 }
746             }
747         }
748         return roots;
749     }
750
751     public boolean isPolymorphic() {
752         return (!getSubClasses().isEmpty() || !getSuperClasses().isEmpty());
753     }
754
755     public PType getPType() {
756         try {
757             PType type = getManager().getPTypeSpace().getPType(getFQName());
758             if (type != null) {
759                 return type;
760             }
761             if (superClasses.isEmpty()) {
762                 return getManager().getPTypeSpace().createPType(getFQName());
763             } else {
764                 List JavaDoc ancestors = getAllAncestors();
765                 List JavaDoc couples = new ArrayList JavaDoc(ancestors.size());
766                 for(int i=0; i<ancestors.size(); i++) {
767                     Class JavaDoc clazz = (Class JavaDoc) ancestors.get(i);
768                     Collection JavaDoc superClasses = clazz.getSuperClasses();
769                     for(Iterator JavaDoc it = superClasses.iterator(); it.hasNext();) {
770                         Class JavaDoc superClass = (Class JavaDoc) it.next();
771                         couples.add(new String JavaDoc[] {clazz.getFQName(), superClass.getFQName()});
772                     }
773                 }
774                 return getManager().getPTypeSpace().createPType(
775                             getFQName(),
776                             (String JavaDoc[][]) couples.toArray(new String JavaDoc[couples.size()][]));
777             }
778         } catch(Exception JavaDoc e) {
779             logger.log(BasicLevel.ERROR,
780                 "impossible to compute the PType of the class "
781                 + getFQName(), e);
782             return null;
783         }
784     }
785
786     /**
787      * Returns the number of fields which are references to classes.
788      *
789      * @return the number of fieldRef
790      */

791     public int getFieldRefNumber() {
792         return classRefs.size();
793     }
794
795     /**
796      * Returns a ClassProject object.
797      *
798      * @param projectName a project name.
799      * @return a ClassProject object.
800      */

801     public ClassProject getClassProject(String JavaDoc projectName) {
802         return (ClassProject) classProjects.get(projectName);
803     }
804
805     /**
806      * Returns a ClassMapping object.
807      *
808      * @param projectName a project name,
809      * mappername a mapper name.
810      * @return a ClassMapping object.
811      */

812     public ClassMapping getClassMapping(String JavaDoc projectName, String JavaDoc mapperName) {
813         ClassProject cp = (ClassProject) classProjects.get(projectName);
814         if (cp == null) return null;
815         Mapping mapping = cp.getMapping(mapperName);
816         if (mapping == null) return null;
817         return mapping.getClassMapping();
818     }
819
820     /**
821      * Returns a collection of ClassProject objects.
822      * @return a collection.
823      */

824     public Collection JavaDoc getClassProjects() {
825         return classProjects.values();
826     }
827
828     /**
829      * Adds a ClassProject object.
830      *
831      * @param projectName a project name,
832      * classProject a ClassProject object.
833      */

834     public void addClassProject(String JavaDoc projectName, ClassProject classProject) {
835         if (!classProjects.containsKey(projectName)) {
836             classProjects.put(projectName, classProject);
837         }
838     }
839
840     /**
841      * Creates a new ClassProject object.
842      *
843      * @param projectName the name of the project.
844      * @return a new ClassProject object, or an existing one.
845      */

846     public ClassProject createClassProject(String JavaDoc projectName) {
847         if (debug)
848             logger.log(BasicLevel.DEBUG,
849                        "create a new ClassProject for the current Class (" + name +
850                        ") projectName=<" + projectName + ">");
851
852         // verifies whether the classProject already exists
853
ClassProject cp = (ClassProject) classProjects.get(projectName);
854         if (cp == null) {
855             cp = new BasicClassProject(projectName, this);
856             classProjects.put(projectName, cp);
857             return cp;
858         } else {
859             if (debug) {
860                 logger.log(BasicLevel.DEBUG,
861                        "return the existing ClassProject " + projectName);
862             }
863             return cp;
864         }
865     }
866
867     /**
868      * Removes a ClassProject instance.
869      * @param projectname is the name of removed ClassProject
870      * @return The removed ClassProject
871      */

872     public ClassProject removeClassProject(String JavaDoc projectname) {
873         return (ClassProject) classProjects.remove(projectname);
874     }
875
876     public Expression parseInheritanceFilter(String JavaDoc filter, NameDef nd)
877         throws ExpressionException {
878         return new ExpressionParser()
879             .parse(filter, new BasicParameterTypeProvider());
880     }
881
882     /**
883      * Determine if we need to generate the kfpnc.
884      */

885     public boolean generateKFPNC() throws ExpressionException {
886         Expression exp = null;
887         //for each namedef
888
for (int i = 0; i < nameDefs.size(); i++) {
889             NameDef nd = (NameDef) nameDefs.get(i);
890             exp = getInheritanceFilter(nd);
891             //if only one is false, then we need to generate the kfpnc
892
if(!detectFilterElementNotInPK(exp, nd))
893                 return true;
894         }
895         return false;
896     }
897     
898     public boolean detectFilterElementNotInPK(Expression exp, NameDef nd) throws ExpressionException {
899         if (exp instanceof Operator) {
900             Operator operator = (Operator) exp;
901             int nb = operator.getOperandNumber();
902             if (nb == 1) {
903                 return detectFilterElementNotInPK(operator.getExpression(0), nd);
904             } else if (nb == 2) {
905                 return (detectFilterElementNotInPK(operator.getExpression(0), nd)
906                         || detectFilterElementNotInPK(operator.getExpression(1), nd));
907             } else {
908                 throw new ExpressionException("Operators with more than 2 operands are not supported: " + exp);
909             }
910         } else if (exp instanceof ParameterOperand) {
911             ParameterOperand po = (ParameterOperand) exp;
912             if (nd.isNameRef()) {
913                 //get the list of fields of the composite namedef
914
Collection JavaDoc fields = nd.getNameRef().getProjection().values();
915                 return !(fields.contains(po.getName()));
916             } else {
917                 return !(po.getName().equals(nd.getFieldName()));
918             }
919         }
920         return false;
921     }
922     
923     private class BasicParameterTypeProvider implements ParameterTypeProvider {
924         public PType getParameterPType(String JavaDoc s) throws MalformedExpressionException {
925             TypedElement te = getTypedElement(s);
926             return (te == null ? null : te.getType());
927         }
928     }
929
930 }
931
932
Popular Tags