KickJava   Java API By Example, From Geeks To Geeks.

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


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.metainfo.api.Class;
27 import org.objectweb.jorm.metainfo.api.ClassRef;
28 import org.objectweb.jorm.metainfo.api.GenClassRef;
29 import org.objectweb.jorm.metainfo.api.MetaObject;
30 import org.objectweb.jorm.metainfo.api.NameDef;
31 import org.objectweb.jorm.metainfo.api.PrimitiveElement;
32 import org.objectweb.jorm.metainfo.api.ScalarField;
33 import org.objectweb.jorm.metainfo.api.TypedElement;
34 import org.objectweb.jorm.type.api.PType;
35 import org.objectweb.jorm.type.api.PExceptionTyping;
36 import org.objectweb.jorm.lib.JormPathHelper;
37 import org.objectweb.util.monolog.api.BasicLevel;
38
39 import java.util.ArrayList JavaDoc;
40 import java.util.Collection JavaDoc;
41 import java.util.HashMap JavaDoc;
42 import java.util.Iterator JavaDoc;
43 import java.util.Map JavaDoc;
44 import java.util.List JavaDoc;
45
46 /**
47  * BasicGenClassRef defines a reference to a generic class which is class field.
48  * This object is created by the GenClass object to define its fields.
49  * @author X. Spengler
50  */

51 public class BasicGenClassRef
52         extends BasicMetaObject
53         implements GenClassRef, Comparable JavaDoc {
54
55     private static final String JavaDoc PRIMITIVE_ELEMENT_NAME = "element";
56     /**
57      * the name of the reference field
58      */

59     private String JavaDoc name;
60
61     /**
62      * the name of the generic class
63      */

64     private String JavaDoc genClassName;
65     private String JavaDoc genClassId;
66
67     /**
68      * indexField is an index field for the generic class
69      */

70     private ScalarField indexField;
71
72     /**
73      * the list of the name definition declared by the user in the
74      * current reference to the generic class.
75      * key: the name of the NameDef
76      * value: a NameDef object
77      */

78     private ArrayList JavaDoc refNameDefs;
79
80     /**
81      * the list of the name definition declared by the user in the
82      * current reference to the generic class.
83      * key: the name of the NameDef
84      * value: a NameDef object
85      */

86     private ArrayList JavaDoc idNameDefs;
87
88     /**
89      * hiddenFields defines the list of the hiddenfields.
90      * These fields are scalar fields.
91      * key: the name of the hiddenField object
92      * value: the scalarfield object
93      */

94     private Map JavaDoc hiddenFields;
95
96     /**
97      * indexFields is a list of index fields for the generic class.
98      * key: the name of the index field
99      * value: a PrimitiveElement
100      */

101     private List JavaDoc indexFields;
102
103     /**
104      * if true, the current GenClassRef is a primitive field
105      */

106     private boolean primitive;
107
108     /**
109      * if true, the current GenClassRef is a reference to a class
110      */

111     private boolean classRef;
112
113     /**
114      * if true, the current GenClassRef is a reference to a generic class
115      */

116     private boolean genClassRef;
117
118     /**
119      * currentGenClassRef is the reference to the generic class which defines
120      * the type of the current field
121      */

122     private GenClassRef currentGenClassRef;
123
124     /**
125      * currentClassRef is the reference to the class which defines the type
126      * of the current field
127      */

128     private ClassRef currentClassRef;
129
130     /**
131      * primitiveType defines the type of the current field
132      */

133     private PrimitiveElement primitiveElement;
134
135     private PType type;
136
137     /**
138      * Builds a new BasicGenClassRef object.
139      * This object is defined by its name, the reference to the generic class
140      * and its parent.
141      *
142      * @param genClassName the name of the generic class reference
143      * @param name the string representation of the generic class
144      * field name
145      * @param parent the parent of the current object
146      */

147     public BasicGenClassRef(String JavaDoc genClassName,
148                             String JavaDoc name,
149                             MetaObject parent) {
150         super(parent);
151         this.name = name;
152         this.genClassName = genClassName;
153         indexField = null;
154         hiddenFields = new HashMap JavaDoc();
155         refNameDefs = new ArrayList JavaDoc();
156         idNameDefs = new ArrayList JavaDoc();
157         indexFields = new ArrayList JavaDoc();
158         genClassId = JormPathHelper.getPath(this, false);
159     }
160
161     public int compareTo(Object JavaDoc o) {
162         return name.compareTo(((TypedElement) o).getName());
163     }
164
165     ///////////////////////////////////////////////////////////////////
166
// from GenClassRef interface
167
///////////////////////////////////////////////////////////////////
168
/**
169      * Creates a new PrimitiveElement object, and attach it to the current GenClassRef
170      * This method must be used when the recursion is finished (we are on
171      * final object which is a PrimitiveElement).
172      *
173      * @param type is the PType of the primitive element which will be created
174      * @return PrimitiveElement the primitive element which defines the current
175      * GenClassRef object. This object is the final
176      * object of the recursion.
177      */

178     public PrimitiveElement createPrimitiveElement(PType type, int size, int scale) {
179         primitiveElement = new BasicPrimitiveElement(
180                 PRIMITIVE_ELEMENT_NAME + '_' + type.getJormName(), type, size, scale, this);
181         setLoggingOnChild(primitiveElement);
182
183         // set the flags, primitive to true, the others to false
184
primitive = true;
185         classRef = false;
186         genClassRef = false;
187         return primitiveElement;
188     }
189
190     /**
191      * Returns a new ScalarField object.
192      *
193      * @param indexFieldName the name of the index field
194      * @param type the type of the index field
195      * @return a new ScalarField object for the index field
196      */

197     public ScalarField createIndexField(String JavaDoc indexFieldName,
198                                         PType type, int size, int scale) {
199         if (debug)
200             logger.log(BasicLevel.DEBUG,
201                        "create a new PrimitiveElement (index field (" +
202                        indexFieldName + ")) for the current " + "GenClass (" +
203                        this.genClassName + ")");
204         ScalarField sf = new BasicScalarField(indexFieldName, type, size, scale, this);
205         setLoggingOnChild(sf);
206         return sf;
207     }
208
209     /**
210      * Returns the ScalarField object corresponding to the index field.
211      * @return a ScalarField object.
212      */

213     public ScalarField getIndexField() {
214         return indexField;
215     }
216
217     /**
218      * Creates a new ClassRef object, and attach it to the current GenClassRef
219      * This method must be used when the recursion is finished (we are on
220      * final object which is a ClassRef).
221      *
222      * @param clazz the reference to the Class object which defines the
223      * current GenClassRef object. This object is the final
224      * object of the recursion.
225      * @return ClassRef a new ClassRef object
226      */

227     public ClassRef createClassRef(Class JavaDoc clazz) {
228         String JavaDoc classname = clazz.getName();
229         int idx = classname.lastIndexOf('.');
230         if (idx != -1) {
231             classname = classname.substring(idx + 1, classname.length());
232         }
233         currentClassRef = new BasicClassRef(classname, clazz, this);
234         setLoggingOnChild(currentClassRef);
235         // set the flags, classRef to true, the others to false
236
classRef = true;
237         genClassRef = false;
238         primitive = false;
239
240         return currentClassRef;
241     }
242
243     /**
244      * Creates a new GenClassRef object.
245      * This method must be used when the recursion is not finished (we are on
246      * not final object).
247      *
248      * @param genClassRefName the name of the generic class used to create a
249      * new GenClassRef object
250      * @return a new GenClassRef object
251      */

252     public GenClassRef createGenClassRef(String JavaDoc genClassRefName) {
253         // set the flags, genClassRef to true, the others to false
254
classRef = false;
255         genClassRef = true;
256         primitive = false;
257
258         if (debug)
259             logger.log(BasicLevel.DEBUG, "create a new GenClassRef ("
260                                          + genClassRefName + ") for the current GenClassRef ("
261                                          + name + ")");
262
263         if (currentGenClassRef == null) {
264             currentGenClassRef = new BasicGenClassRef(genClassRefName, null, this);
265             setLoggingOnChild(currentGenClassRef);
266         }
267         return currentGenClassRef;
268     }
269
270     /**
271      * Returns the PrimitiveElement object which defines the current GenClassRef
272      * object.
273      * This method is used after a call to isPrimitive() method, to determine
274      * if the current object is a "basic" type.
275      *
276      * @return the current type of the field. This method always returns a
277      * PType object, and can not return null value because of the
278      * previous test.
279      */

280     public PrimitiveElement getPrimitiveElement() {
281         return primitiveElement;
282     }
283
284     public TypedElement removeTypedElement(String JavaDoc fieldName){
285         TypedElement res = (TypedElement) hiddenFields.remove(fieldName);
286         return res;
287     }
288     
289     /**
290      * Returns the ClassRef object which defines the current GenClassRef object.
291      * This method is used after a call to isClassRef() method, to determine if
292      * the current object is defined by a final class or not.
293      *
294      * @return the final Class which describes the type of the object which
295      * defines the GenClassRef object. This method always returns a
296      * Class, and can not return null value because of the previous
297      * test.
298      */

299     public ClassRef getClassRef() {
300         return currentClassRef;
301     }
302
303     /**
304      * Returns the GenClassRef object which defines the current GenClassRef
305      * object.
306      * This object exists when it is in a recursion. This method is used after a
307      * call to isGenClassRef() method, to determine if the current object is a
308      * reference to a generic class or not.
309      *
310      * @return the underlying reference to the generic class. This method
311      * always returns a GenClassRef, and can not return null value
312      * because of the previous test.
313      */

314     public GenClassRef getGenClassRef() {
315         return currentGenClassRef;
316     }
317
318     /**
319      * Allows to know if the current object is primitive or not (final and
320      * "basic").
321      *
322      * @return true, if the current object is primitive, else false, if the
323      * object is not primitive (either a reference to a Class, or
324      * a reference to a generic class).
325      */

326     public boolean isPrimitive() {
327         return primitive;
328     }
329
330     /**
331      * Allows to know if the current object is a reference to a Class or not.
332      *
333      * @return true, if the object is a reference to a Class, else false, if
334      * the object is not a reference to a Class (either a primitive
335      * object, or a reference to a generic class).
336      */

337     public boolean isClassRef() {
338         return classRef;
339     }
340
341     /**
342      * Allows to know if the current object is a reference to a generic class
343      * or not.
344      *
345      * @return true, if the object is a reference to a generic class, else
346      * false, if the object is not a reference to a generic class
347      * (either a primitive object, or a reference to a class).
348      */

349     public boolean isGenClassRef() {
350         return genClassRef;
351     }
352
353     /**
354      * Creates a new NameDef object for the new GenClassRef object.
355      * If the specified namedef object already exists, it is returned, else
356      * a new NameDef object is created.
357      *
358      * @return a new object used to describe the PName projection for
359      * the current Class, or an existing object if already defined
360      */

361
362     public NameDef createIdNameDef() {
363         if (debug)
364             logger.log(BasicLevel.DEBUG,
365                        "create a new ID NameDef () for the current GenClassRef (" + name + ")");
366         // in the case it does not exist, we create it.
367
NameDef newNameDef = new BasicNameDef(this);
368         setLoggingOnChild(newNameDef);
369         idNameDefs.add(newNameDef);
370         return newNameDef;
371     }
372
373
374     /**
375      * Returns an iterator on existing NameDef of GenClassRef object.
376      * If no NameDef exists, an empty iterator is returned.
377      *
378      * @return an iterator on NameDef object
379      */

380     public Collection JavaDoc getIdNameDef() {
381         return idNameDefs;
382     }
383
384
385     /**
386      * Create a new hidden field for the refgenclass.
387      *
388      * @return the ScalarField
389      */

390     public ScalarField createHiddenField(String JavaDoc fieldName, PType type, int size, int scale) {
391         if (debug)
392             logger.log(BasicLevel.DEBUG,
393                        "create a new HiddenField (" + fieldName + ") for the current refgenclass (" + name + ")");
394
395         // verify if the field is not yet in the database
396
if (hiddenFields.get(fieldName) != null) {
397             if (logger != null) {
398                 logger.log(BasicLevel.WARN,
399                            "attention, try to create an existing HiddenField (" +
400                            fieldName + "), return existing one");
401             }
402             return (ScalarField) hiddenFields.get(fieldName);
403         }
404
405         // else create a new one
406
ScalarField newHiddenField = new BasicScalarField(fieldName, type, size, scale, this);
407         setLoggingOnChild(newHiddenField);
408         hiddenFields.put(fieldName, newHiddenField);
409         return newHiddenField;
410     }
411
412     /**
413      * return an iterator over the hiddenfield of the refgenclass definition.
414      *
415      * @return the iterator containing the hiddenfield.
416      */

417     public Collection JavaDoc getHiddenFields() {
418         return hiddenFields.values();
419     }
420
421
422     /**
423      * retrieve an hiddenfield from its name.
424      *
425      * @return the hiddenfield.
426      */

427     public ScalarField getHiddenField(String JavaDoc fieldName) {
428         if (debug) {
429             logger.log(BasicLevel.DEBUG,
430                        "try to return an hidden field (" + fieldName + ")");
431         }
432         return (ScalarField) hiddenFields.get(fieldName);
433     }
434
435     /**
436      * Returns the name of the GenClass object.
437      *
438      * @return the name of the GenClassRef object
439      */

440     public String JavaDoc getGenClassName() {
441         return genClassName;
442     }
443
444     public String JavaDoc getGenClassId() {
445         return genClassId;
446     }
447
448     /**
449      * Creates a new NameDef object for the current reference class object.
450      * If this NameDef already exists for the current object, it is returned,
451      * in other case, a new NameDef object is created and returned.
452      *
453      * @return a new object used to describe the name projection for
454      * the current reference class, or an existing one if it
455      * already exists
456      */

457
458     public NameDef createRefNameDef() {
459         if (debug)
460             logger.log(BasicLevel.DEBUG,
461                        "create a new REF NameDef () for the current Class (" + name + ")");
462         // in the case it does not exist, we create it.
463
NameDef newNameDef = new BasicNameDef(this);
464         setLoggingOnChild(newNameDef);
465         refNameDefs.add(newNameDef);
466         return newNameDef;
467     }
468
469     /**
470      * Returns a NameDef object.
471      * If the namedef does not exist, null is returned.
472      *
473      * @param name the name of the namedef.
474      * @return an existing namedef object,else null is returned.
475      */

476     public NameDef getRefNameDef(String JavaDoc name) {
477         Iterator JavaDoc iter = refNameDefs.iterator();
478         while (iter.hasNext()) {
479             NameDef nameDef = (NameDef) iter.next();
480             if (nameDef.getName().equals(name)) {
481                 return nameDef;
482             }
483         }
484         return null;
485     }
486
487     /**
488      * Returns a NameDef object.
489      * If the namedef does not exist, null is returned.
490      *
491      * @param name the name of the namedef.
492      * @return an existing namedef object,else null is returned.
493      */

494     public NameDef getIdNameDef(String JavaDoc name) {
495         Iterator JavaDoc iter = idNameDefs.iterator();
496         while (iter.hasNext()) {
497             NameDef nameDef = (NameDef) iter.next();
498             if (nameDef.getName().equals(name)) {
499                 return nameDef;
500             }
501         }
502         return null;
503     }
504
505     /**
506      * Returns an iterator on existing NameDef for the current Class.
507      * This method returns an empty iterator if no namedef exists in this Class.
508      *
509      * @return an iterator on NameDef, or an empty iterator if no namedef is
510      * defined
511      */

512
513     public Collection JavaDoc getRefNameDef() {
514         return refNameDefs;
515     }
516
517     public void addIndexField(String JavaDoc indexFieldName) {
518         indexFields.add(hiddenFields.get(indexFieldName));
519     }
520
521     /**
522      * Allows to know all the existing index field for the current generic
523      * class.
524      * This iterator contains PrimitiveElement objects. If no index field
525      * exists, an empty iterator is returned.
526      *
527      * @return an Iterator on index field (PrimitiveElement). If there is no
528      * index field to return, an empty iterator is returned.
529      */

530     public Collection JavaDoc getIndexFields() {
531         return indexFields;
532     }
533
534     protected Collection JavaDoc getChildren() {
535         ArrayList JavaDoc res = new ArrayList JavaDoc();
536         res.addAll(hiddenFields.values());
537         res.addAll(refNameDefs);
538         res.addAll(idNameDefs);
539         return res;
540     }
541
542     ///////////////////////////////////////////////////////////////////
543
// from TypedElement interface
544
///////////////////////////////////////////////////////////////////
545

546
547     /**
548      * Returns the name of the current typed element.
549      *
550      * @return the string representation of the typed element
551      */

552     public String JavaDoc getName() {
553         return name;
554     }
555
556     /**
557      * Allows to know the type of the field.
558      *
559      * @return a PType object which defines the type of the current field
560      */

561     public PType getType() {
562         if (type != null)
563             return type;
564         try {
565             if (primitive) {
566                 type = getManager().getPTypeSpace().createPType(
567                         new String JavaDoc[]{genClassName}, primitiveElement.getType());
568             } else if (classRef) {
569                 type = getManager().getPTypeSpace().createPType(
570                         new String JavaDoc[]{genClassName}, currentClassRef.getType());
571             } else { //genClassRef
572
ArrayList JavaDoc al = new ArrayList JavaDoc();
573                 GenClassRef gcr = this;
574                 al.add(gcr.getGenClassName());
575                 while (gcr.isGenClassRef()) {
576                     al.add(gcr.getGenClassName());
577                     gcr = gcr.getGenClassRef();
578                 }
579                 PType lasttype = null;
580                 if (gcr.isClassRef())
581                     lasttype = gcr.getClassRef().getType();
582                 else
583                     lasttype = gcr.getPrimitiveElement().getType();
584                 type = getManager().getPTypeSpace().createPType(
585                         (String JavaDoc[]) al.toArray(new String JavaDoc[0]), lasttype);
586             }
587         } catch (PExceptionTyping e) {
588             if (logger != null) {
589                 logger.log(BasicLevel.ERROR,
590                            "Impossible to calculate the type of the GenClassRef field "
591                            + genClassId, e);
592             }
593         }
594         return type;
595     }
596 }
597
Popular Tags