KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jorm > type > lib > PTypeSpacePAAH


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.type.lib;
25
26 import org.objectweb.jorm.type.api.PExceptionTyping;
27 import org.objectweb.jorm.type.api.PType;
28 import org.objectweb.jorm.type.api.PTypeSpace;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Arrays JavaDoc;
34 import java.io.Serializable JavaDoc;
35
36 /*
37  * This implementation of the PTypeSpace considers that this is the PType which
38  * contains its ancestor. Then class contains only a simple list of PType
39  * defined in this PType space. The PAAH letters mean PType As Ancestor Holder.
40  * This implementation uses the PTypePAAH class to create PType of jorm class.
41  * @author Pascal D?chamboux, Sebastien Chassande-Barrioz
42  */

43
44 public class PTypeSpacePAAH implements PTypeSpace {
45
46     /**
47      * This hash map contains the list of PType defined in this PType space.
48      * keys = the jorm names of PType
49      * values = The PTypeHashMapEntry corresponding to the class name
50      */

51     private HashMap JavaDoc types = null;
52
53     public PTypeSpacePAAH() {
54         types = new HashMap JavaDoc();
55         // Puts basic JORM types into the types map (for GC support purpose)
56
for (int i = 0; i < PTypeSpace.PREDEFINEDPTYPES.length; i++)
57             types.put(PTypeSpace.PREDEFINEDPTYPES[i].getJormName(),
58                       new PTypeHashMapEntry(PTypeSpace.PREDEFINEDPTYPES[i], this));
59     }
60
61     /**
62      * It creates a new PType for a JORM class that has no inherited class.
63      * @param classname The name of the JORM class.
64      * @return The created PType or the existing one if it has the same
65      * definition (same name and same super types).
66      * @exception PExceptionTyping Raised when a PType with this class name
67      * exists with a different array of super
68      * types.
69      */

70     public synchronized PType createPType(String JavaDoc classname)
71             throws PExceptionTyping {
72         if (isConflict(classname, NULLSUPERCLASSNAMES))
73             throw new PExceptionTyping("Cannot create type <" + classname
74                                        + ">: it conflicts with existing types.");
75         return definePType(classname, NULLSUPERCLASSNAMES).entryPType;
76     }
77
78     /**
79      * It creates a new PType for a JORM class. It is defined by its name and
80      * its inheritance hierarchy. For example, if "Engineer" inherits from
81      * "Employee" that inherits from "Person", then the following stands:
82      * <bl>
83      * <li>classname = "schm1.Engineer"</li>
84      * <li>superclassnames = {{"schm1.Engineer", "schm2.Employee"},
85      * {"schm2.Employee", "schm3.Person"}}</li>
86      * </bl>
87      * @param classname The name of the JORM class to be defined.
88      * @param superclassnames The hierarchy of of classes inherited by the
89      * previous class (defined by classname) if any.
90      * @return The created PType or the existing one if it has the same
91      * definition (same name and same super types).
92      * @exception PExceptionTyping Raised when a PType with this class name
93      * exists with a different array of super
94      * types.
95      */

96     public synchronized PType createPType(String JavaDoc classname,
97                                           String JavaDoc[][] superclassnames)
98             throws PExceptionTyping {
99         if (isConflict(classname, superclassnames))
100             throw new PExceptionTyping("Cannot create type <" + classname
101                                        + ">: it conflicts with existing types.");
102         return definePType(classname, superclassnames).entryPType;
103     }
104
105     /**
106      * It creates a new PType for a JORM generic class instance. Such an
107      * instance may have a nested structure like
108      * "list<array<set<int>>>", which means that:
109      * <bl>
110      * <li>gcnames = {"list", "array", "set"}</li>
111      * <li>ptypename = INT</li>
112      * </bl>
113      * @param gcnames The array of names of the nested generic classes.
114      * @param ptype The PType of the type of the elements contained
115      * within this generic class, which is one of those
116      * defined inside PREDEFINEDPTYPES.
117      * @return The created PType or the existing one if it has the same
118      * definition (same name and same element type).
119      * @exception PExceptionTyping Raised when a PType with this class name
120      * exists with a different inner PType
121      */

122     public PType createPType(String JavaDoc[] gcnames, PType ptype)
123             throws PExceptionTyping {
124         return ((PTypeHashMapEntry) types.get(ptype.getJormName()))
125                 .addGcPType(gcnames, (short) (gcnames.length - 1));
126     }
127
128     /**
129      * It creates a new PType for a JORM generic class instance. Such an
130      * instance may have a nested structure like
131      * "list<array<set<schm1.Engineer>>>", which means that:
132      * <bl>
133      * <li>gcnames = {"list", "array", "set"}</li>
134      * <li>typename = "schm1.Engineer"</li>
135      * <li>superclassnames = {{"schm1.Engineer", "schm2.Employee"},
136      * {"schm2.Employee", "schm3.Person"}}</li>
137      * </bl>
138      * @param gcnames The array of names of the nested generic
139      * classes.
140      * @param typename The name of the type of the elements contained
141      * within this generic class.
142      * @param superclassnames The hierarchy of of classes inherited by the
143      * previous class (defined by typename) if any.
144      * @return The created PType or the existing one if it has the same
145      * definition (same name and same element type).
146      * @exception PExceptionTyping Raised when a PType with this class name
147      * exists with a different inner PType
148      */

149     public synchronized PType createPType(String JavaDoc[] gcnames, String JavaDoc typename,
150                                           String JavaDoc[][] superclassnames)
151             throws PExceptionTyping {
152         if (isConflict(typename, superclassnames))
153             throw new PExceptionTyping("Cannot create type <" + typename
154                                        + ">: it conflicts with existing types.");
155         return defineGcPType(gcnames, typename, superclassnames);
156     }
157
158     /**
159      * It tries to retrieve a PType representing a JORM class with the given
160      * class name.
161      * @param classname The name of a JORM class the PType is looking for.
162      * @return The relevant PType if one has been found or null if none found.
163      */

164     public PType getPType(String JavaDoc classname) {
165         synchronized (types) {
166             PTypeHashMapEntry entry = (PTypeHashMapEntry) types.get(classname);
167             if (entry == null) {
168                 return null;
169             } else {
170                 return entry.entryPType;
171             }
172         }
173     }
174
175     /**
176      * Retrieves all subtypes of this PType defined within its PTypeSpace.
177      * @param pt The concerned PType.
178      * @return The array of PType containing all these subtypes.
179      */

180     public PType[] getSubTypes(PType pt) {
181         ArrayList JavaDoc subtypes = new ArrayList JavaDoc();
182         Iterator JavaDoc it = types.values().iterator();
183         while (it.hasNext()) {
184             PTypeHashMapEntry entry = (PTypeHashMapEntry) it.next();
185             if ((entry.entryPType != pt) && entry.entryPType.isa(pt)) {
186                 subtypes.add(entry.entryPType);
187             }
188         }
189         return (PType[]) subtypes.toArray(new PType[subtypes.size()]);
190     }
191
192     /**
193      * It compares to PType representing JORM classes. It verifies if the first
194      * one conforms to the second one.
195      * @param pt1 The first JORM class PType.
196      * @param pt2 The second JORM class PType.
197      * @return It returns true if pt1 conforms to pt2.
198      */

199     public boolean isa(PType pt1, PType pt2) {
200         if ((pt1 == null) || (pt2 == null))
201             return false;
202         if (pt1 == pt2)
203             return true;
204         if ((pt1 instanceof PTypePAAH) && (pt2 instanceof PTypePAAH)) {
205             return ((PTypePAAH) pt1).belongsToInherited(pt2);
206         } else if ((pt1 instanceof PTypeGenClass) && (pt2 instanceof PTypeGenClass)) {
207             if (pt1.getJormName().equals(pt2.getJormName()))
208                 return isa(pt1.getNestedPType(), pt2.getNestedPType());
209         }
210         return false;
211     }
212
213     /**
214      *
215      */

216     private boolean isConflict(String JavaDoc classname, String JavaDoc[][] superclasses) {
217         PTypeHashMapEntry entry = (PTypeHashMapEntry) types.get(classname);
218         if (entry == null)
219             return false;
220         short i = 0;
221         while ((i < superclasses.length) &&
222                 !(superclasses[i][0].equals(classname)))
223             i++;
224         // This a ROOT PType (no inheritance)
225
if (i == superclasses.length) {
226             if (((PTypePAAH) entry.entryPType).superTypes.length == 0)
227                 return false;
228             return true;
229         }
230         if (((PTypePAAH) entry.entryPType).superTypes.length
231                 != (superclasses[i].length -1))
232             return true;
233         short j;
234         for (short k = 0; k < ((PTypePAAH) entry.entryPType).superTypes.length;
235              k++) {
236             j = 1;
237             while (j < superclasses[i].length) {
238                 if (((PTypePAAH) entry.entryPType).superTypes[k].getJormName()
239                         .equals(superclasses[i][j])) {
240                     if (isConflict(superclasses[i][j], superclasses))
241                         return true;
242                     break;
243                 }
244                 j++;
245             }
246             if (j == superclasses[i].length)
247                 return true;
248         }
249         return false;
250     }
251
252     /**
253      *
254      */

255     private PTypeHashMapEntry definePType(String JavaDoc classname,
256                                           String JavaDoc[][] superclasses) {
257         PTypeHashMapEntry entry = (PTypeHashMapEntry) types.get(classname);
258         if (entry != null)
259             return entry;
260         short i = 0;
261         while ((i < superclasses.length) &&
262                 !(superclasses[i][0].equals(classname))) {
263             i++;
264         }
265         // This is a ROOT PType (no inheritance)
266
if (i == superclasses.length) {
267             entry = new PTypeHashMapEntry(
268                     new PTypePAAH(classname, this, NULLSUPERTYPES), this);
269         } else {
270             PType[] supertypes = new PType[superclasses[i].length - 1];
271             for (short j = 1; j < superclasses[i].length; j++) {
272                 supertypes[j - 1]
273                         = definePType(superclasses[i][j], superclasses).entryPType;
274             }
275             entry = new PTypeHashMapEntry(new PTypePAAH(classname, this, supertypes), this);
276         }
277         types.put(classname, entry);
278         return entry;
279     }
280
281     /**
282      *
283      */

284     private PType defineGcPType(String JavaDoc[] gcnames, String JavaDoc typename,
285                                 String JavaDoc[][] superclasses) {
286         PTypeHashMapEntry typeentry = (PTypeHashMapEntry) types.get(typename);
287         if (typeentry == null) {
288             typeentry = definePType(typename, superclasses);
289         }
290         return typeentry.addGcPType(gcnames, (short) (gcnames.length - 1));
291     }
292 }
293
294 /**
295  * This class represents a PType and defines a tree of PType. A instance is
296  * node of PTypeHashMapEntry tree. A Path in this tree defines a PType. Be
297  * carefull the path is reversed: for example the PType array(set(String)) will
298  * be stored in the following tree:<br/>
299  * String <br/>
300  * \--set <br/>
301  * \--array <br/>
302  *
303  * If after you add the PType array(String) the tree will be completed as here:
304  * String <br/>
305  * |--set <br/>
306  * | \--array <br/>
307  * \--array <br/>
308  *
309  * To optimize the adding operation, a PTypeHashMapEntry manages an array of
310  * several childrens. This array is increased by increment.
311  *
312  * @author Pascal D?chamboux, Sebastien Chassande-Barrioz
313  */

314 class PTypeHashMapEntry implements Serializable JavaDoc {
315     /**
316      * The size of the increment.
317      */

318     public final static int INCREMENT = 5;
319
320     /**
321      * The current PType defined by the reverse path from the root
322      */

323     PType entryPType;
324     PTypeSpace pTypeSpace;
325
326     /**
327      * The children of the current PTypeHashMapEntry
328      */

329     private PTypeHashMapEntry[] gcInstances = null;
330
331     public PTypeHashMapEntry(PType ptype, PTypeSpace ptypespace) {
332         entryPType = ptype;
333         pTypeSpace = ptypespace;
334     }
335
336     /**
337      * It Adds a PType in the tree.
338      * @param gcnames is the list of the gen class names which must be inserted
339      * @param curgc is an index into the gcnames array. It is used to go all
340      * over elements of the array. The gcnames placed before the index, have
341      * been already inserted in the tree.
342      * @return The PType inserted or found in the tree.
343      */

344     public PType addGcPType(String JavaDoc[] gcnames, short curgc) {
345         if (curgc < 0) {
346             // The searched element is the current.
347
return entryPType;
348         }
349
350         // No GC already associated to this type
351
if (gcInstances == null) {
352             gcInstances = new PTypeHashMapEntry[INCREMENT];
353             for (short i = 1; i < INCREMENT; i++)
354                 gcInstances[i] = null;
355             gcInstances[0] = new PTypeHashMapEntry(
356                     new PTypeGenClass(gcnames[curgc], entryPType, pTypeSpace),
357                     pTypeSpace);
358             return gcInstances[0].addGcPType(gcnames, (short) (curgc - 1));
359         }
360
361         // Looks if the currrent GC already exists
362
int i = 0;
363         while ((i < gcInstances.length)
364                 && gcInstances[i] != null
365                 && !gcInstances[i++].entryPType.getJormName().equals(gcnames[curgc]))
366             ;
367
368         if (i == gcInstances.length) {
369             // It does not exist and no free slot exists: increases size
370
if (i == gcInstances.length) {
371                 PTypeHashMapEntry[] newgcinstances
372                         = new PTypeHashMapEntry[gcInstances.length + INCREMENT];
373                 System.arraycopy(gcInstances, 0, newgcinstances, 0, gcInstances.length);
374                 Arrays.fill(newgcinstances, gcInstances.length, newgcinstances.length, null);
375                 gcInstances = newgcinstances;
376             }
377         }
378         if (gcInstances[i] == null) {
379             gcInstances[i] = new PTypeHashMapEntry(
380                     new PTypeGenClass(gcnames[curgc], entryPType, pTypeSpace),
381                     pTypeSpace);
382         }
383
384         // In all cases recall with the next gcnames
385
return gcInstances[i].addGcPType(gcnames, (short) (curgc - 1));
386     }
387 }
388
Popular Tags