KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > core > rtti > RttiAC


1 /*
2   Copyright (C) 2001-2003 Renaud Pawlak <renaud@aopsys.com>,
3                           Laurent Martelli <laurent@aopsys.com>
4   
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU Lesser General Public License as
7   published by the Free Software Foundation; either version 2 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   GNU Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

18
19 package org.objectweb.jac.core.rtti;
20
21 import java.lang.reflect.InvocationTargetException JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Hashtable JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Set JavaDoc;
27 import org.apache.log4j.Logger;
28 import org.objectweb.jac.core.AspectComponent;
29 import org.objectweb.jac.core.Wrappee;
30 import java.lang.reflect.Method JavaDoc;
31
32 /**
33  * This class defines the rtti aspect.
34  *
35  * <p>It allows the programmer to add some runtime type informations on
36  * the classes of its applications.
37  *
38  * @see ClassItem
39  * @see MethodItem
40  * @see FieldItem
41  * @see CollectionItem
42  *
43  * @author Renaud Pawlak
44  * @author Laurent Martelli
45  */

46
47 public class RttiAC extends AspectComponent implements RttiConf {
48     static Logger logger = Logger.getLogger("rtti");
49
50     public static final String JavaDoc OPPOSITE_ROLE = "RttiAC.OPPOSITE_ROLE";
51     public static final String JavaDoc FIELD_TYPE = "RttiAC.FIELD_TYPE";
52     public static final String JavaDoc DYNAMIC_FIELD_TYPE = "RttiAC.DYNAMIC_FIELD_TYPE";
53     public static final String JavaDoc PARAMETER_TYPES = "RttiAC.PARAMETERS_TYPES";
54     public static final String JavaDoc CLONED_FIELDS = "RttiAC.CLONED_FIELDS";
55     public static final String JavaDoc REPOSITORY_NAME = "RttiAC.REPOSITORY_NAME";
56     public static final String JavaDoc REPOSITORY_COLLECTION = "RttiAC.REPOSITORY_COLLECTION";
57     public static final String JavaDoc NULL_ALLOWED_PARAMETERS = "RttiAC.NULL_ALOWED_PARAMETERS";
58     public static final String JavaDoc NULL_ALLOWED = "RttiAC.NULL_ALLOWED"; // Boolean
59
public static final String JavaDoc IS_INDEX = "RttiAC.IS_INDEX"; // Boolean
60
public static final String JavaDoc INDEXED_FIELD = "RttiAC.INDEXED_FIELD"; // FieldItem
61
public static final String JavaDoc AUTHORIZED_VALUES = "RttiAC.AUTHORIZED_VALUES";
62     public static final String JavaDoc FORBIDDEN_VALUES = "RttiAC.FORBIDDEN_VALUES";
63     public static final String JavaDoc CONSTRAINTS = "RttiAC.CONSTRAINTS";
64     public static final String JavaDoc PARAMETERS_FIELDS = "RttiAC.PARAMETERS_FIELDS"; // FieldItem[]
65

66     public static final String JavaDoc PRIMARY_KEY = "RttiAC.PRIMARY_KEY";
67
68     public void addWrittenFields(AbstractMethodItem method,
69                                  String JavaDoc[] writtenFields) {
70         ClassItem cl = method.getClassItem();
71         for( int i=0; i<writtenFields.length; i++ ) {
72             FieldItem fi = cl.getField(writtenFields[i]);
73             method.addWrittenField(fi);
74         }
75     }
76
77     public void declareCalculatedField(ClassItem cl, String JavaDoc fieldName,
78                                        String JavaDoc getterName)
79     {
80         MethodItem getter = cl.getMethod(getterName);
81         FieldItem calculatedField;
82         if (RttiAC.isCollectionType(getter.getType()))
83             calculatedField = new CollectionItem(fieldName,getter,cl);
84         else
85             calculatedField = new FieldItem(fieldName,getter,cl);
86         cl.addField(calculatedField);
87         FieldItem[] fields = getter.getAccessedFields();
88         for (int i=0;i<fields.length;i++) {
89             if (fields[i]!=calculatedField) {
90                 logger.debug(calculatedField.getLongName()+" depends on "+fields[i]);
91                 fields[i].addDependentField(calculatedField);
92             }
93         }
94     }
95
96     public void setSetter(FieldItem field, String JavaDoc setterName) {
97         MethodItem setter = field.getClassItem().getMethod(setterName);
98         setter.setSetField(field);
99         field.setSetter(setter);
100     }
101
102     public void setGetter(FieldItem field, String JavaDoc getterName) {
103         MethodItem getter = field.getClassItem().getMethod(getterName);
104         getter.setReturnedField(field);
105         field.setGetter(getter);
106     }
107
108     public void addDependentField(FieldItem field, String JavaDoc dependentField) {
109         field.getClassItem().getField(dependentField).addDependentField(field);
110     }
111
112     public void addFieldDependency(FieldItem field, FieldItem dependentField) {
113         field.addDependentField(dependentField);
114     }
115
116     public void addAdder(CollectionItem collection, String JavaDoc methodName) {
117         MethodItem method = collection.getClassItem().getMethod(methodName);
118         collection.addAddingMethod(method);
119         method.addAddedCollection(collection);
120     }
121
122     public void setAdder(CollectionItem collection, String JavaDoc methodName) {
123         MethodItem method = collection.getClassItem().getMethod(methodName);
124         collection.setAdder(method);
125         method.addAddedCollection(collection);
126     }
127
128     public void addRemover(CollectionItem collection,String JavaDoc methodName) {
129         MethodItem method = collection.getClassItem().getMethod(methodName);
130         collection.addRemovingMethod(method);
131         method.addRemovedCollection(collection);
132     }
133
134     public void setRemover(CollectionItem collection,String JavaDoc methodName) {
135         MethodItem method = collection.getClassItem().getMethod(methodName);
136         collection.setRemover(method);
137         method.addRemovedCollection(collection);
138     }
139
140     public void addAccessedFields(MethodItem method,
141                                   String JavaDoc[] accessedFields) {
142         ClassItem cl = method.getClassItem();
143         for(int i=0; i<accessedFields.length; i++) {
144             FieldItem fi = cl.getField(accessedFields[i]);
145             method.addAccessedField(fi);
146         }
147     }
148
149     public void setFieldType(FieldItem field, String JavaDoc type)
150     {
151         Object JavaDoc cl = ClassRepository.get().getObject(type);
152
153         if (cl == null)
154             throw new RuntimeException JavaDoc("no such type "+type);
155
156         field.setAttribute(FIELD_TYPE, cl);
157     }
158
159     public void setDynamicFieldType(FieldItem field, MethodItem method) {
160         if (!method.isStatic()) {
161             error("Method must be static");
162         } if (!(method.getType()==String JavaDoc.class
163                 || method.getType()==Object JavaDoc.class
164                 || MetaItem.class.isAssignableFrom(method.getType()))) {
165             error("Method must return a String, a MetaItem or an Object");
166         } else {
167             field.setAttribute(DYNAMIC_FIELD_TYPE, method);
168         }
169     }
170
171     public void setComponentType(CollectionItem collection, String JavaDoc type) {
172         collection.setComponentType(currentImports.getClass(type));
173     }
174
175     /**
176      * Gets the type of a field. May return a ClassItem, a
177      * VirtualClassItem or a MethodItem.
178      * @param field a field
179      */

180     public static MetaItem getFieldType(FieldItem field) {
181         return (MetaItem)field.getAttribute(FIELD_TYPE);
182     }
183
184     /**
185      * Gets the type of a field for a given object. May return a
186      * ClassItem, a VirtualClassItem.
187      * @param field a field
188      * @param substance the object holding the field
189      */

190     public static MetaItem getFieldType(FieldItem field, Object JavaDoc substance) {
191         MethodItem dynType = (MethodItem)field.getAttribute(DYNAMIC_FIELD_TYPE);
192         if (dynType!=null) {
193             Object JavaDoc type = dynType.invokeStatic(new Object JavaDoc[] {field,substance});
194             if (type instanceof String JavaDoc)
195                 return cr.getVirtualClass((String JavaDoc)type);
196             else
197                 return (MetaItem)type;
198         } else {
199             return getFieldType(field);
200         }
201     }
202
203     public void setParametersType(AbstractMethodItem method,
204                                   String JavaDoc[] types)
205     {
206         ClassRepository cr = ClassRepository.get();
207         MetaItem[] metaItems = new MetaItem[types.length];
208         for (int i=0; i<types.length;i++) {
209             metaItems[i] = (MetaItem)cr.getObject(types[i]);
210         }
211         method.setAttribute(PARAMETER_TYPES,metaItems);
212     }
213
214     public void newVirtualClass(String JavaDoc className, ClassItem actualType)
215     {
216         logger.info("newVirtualClass("+className+")");
217         ClassRepository.get().register(className,
218                                        new VirtualClassItem(className,actualType));
219     }
220
221     public void defineRepository(ClassItem type,
222                                  String JavaDoc repositoryName,
223                                  CollectionItem repositoryCollection)
224     {
225         type.setAttribute(REPOSITORY_NAME, repositoryName);
226         type.setAttribute(REPOSITORY_COLLECTION, repositoryCollection);
227     }
228
229     public void setClonedFields(String JavaDoc className, String JavaDoc[] fields) {
230         ClassRepository.get().getClass(className)
231             .setAttribute(CLONED_FIELDS,fields);
232     }
233
234     public void whenClone(Wrappee cloned, Wrappee clone) {
235       
236         ClassItem cli = ClassRepository.get().getClass(cloned.getClass());
237         String JavaDoc[] clonedFields = (String JavaDoc[])cli.getAttribute(CLONED_FIELDS);
238       
239         if( clonedFields != null ) {
240             for( int i=0; i<clonedFields.length; i++ ) {
241                 FieldItem fi = cli.getField( clonedFields[i] );
242                 logger.debug("cloning field "+clonedFields[i]);
243                 /*
244                   try {
245                   fi.set(clone,((Wrappee)fi.get(cloned)).clone());
246                   } catch( Exception e ) {}
247                 */

248             }
249         }
250     }
251
252     public void ignoreFields(String JavaDoc packageExpr) {
253         logger.info("ignoreFields"+packageExpr);
254         ClassRepository.get().ignoreFields(packageExpr);
255     }
256
257     void setItemClass(MetaItem item, String JavaDoc className, ClassItem actualType) {
258         MetaItem virtualClass;
259         ClassRepository cr = ClassRepository.get();
260         try {
261             virtualClass = cr.getVirtualClass(className);
262         } catch (NoSuchClassException e) {
263             virtualClass = new VirtualClassItem(className,actualType);
264             cr.register(className,virtualClass);
265         }
266         item.setItemClass(virtualClass);
267     }
268
269     public void setClass(MemberItem member, String JavaDoc className) {
270         setItemClass(member,className,member.getTypeItem());
271     }
272
273     public void setClass(ClassItem cli, String JavaDoc className) {
274         setItemClass(cli,className,cli);
275     }
276
277     /*
278     public void introduce(ClassItem target,ClassItem roleType,
279                           String memeberType,String memberName) {
280     }
281     */

282
283     public void setParametersFields(AbstractMethodItem method,
284                                     FieldItem[] fields) {
285         method.setAttribute(PARAMETERS_FIELDS, fields);
286     }
287
288     public void setNullAllowed(FieldItem field) {
289         setNullAllowed(field,true);
290     }
291
292     public void setNullAllowed(FieldItem field, boolean allowed) {
293         field.setAttribute(NULL_ALLOWED, allowed ? Boolean.TRUE : Boolean.FALSE);
294         logger.info("setNullAllowed("+field.getName()+")");
295     }
296
297     public static boolean isNullAllowed(FieldItem field) {
298         Boolean JavaDoc result = (Boolean JavaDoc) field.getAttribute(NULL_ALLOWED);
299         if (result == null)
300             return false;
301         return result.booleanValue();
302     }
303
304     public void setNullAllowedParameters(AbstractMethodItem method,
305                                          boolean[] nulls) {
306         method.setAttribute(NULL_ALLOWED_PARAMETERS, nulls);
307     }
308
309     public static boolean isNullAllowedParameter(AbstractMethodItem method,
310                                                  int i) {
311         //System.out.println("is null allowed "+method+" "+i);
312
boolean[] nulls=(boolean[])method.getAttribute(NULL_ALLOWED_PARAMETERS);
313         if(nulls==null) return false;
314         //System.out.println("=> "+nulls[i]);
315
return nulls[i];
316     }
317
318     public void setAggregation(FieldItem field, boolean isAggregation) {
319         field.setAggregation(isAggregation);
320     }
321
322     public void setIndexedField(CollectionItem collection,
323                                 FieldItem indexedField) {
324         setIsIndex(collection,true);
325         collection.setAttribute(INDEXED_FIELD, indexedField);
326     }
327
328     public void setIsIndex(CollectionItem collection,
329                            boolean isIndex) {
330         collection.setAttribute(IS_INDEX, isIndex?Boolean.TRUE:Boolean.FALSE);
331     }
332
333     public static FieldItem getIndexFied(CollectionItem collection) {
334         return (FieldItem)collection.getAttribute(INDEXED_FIELD);
335     }
336
337     public static boolean isIndex(CollectionItem collection) {
338         Boolean JavaDoc result = (Boolean JavaDoc) collection.getAttribute(IS_INDEX);
339         if (result == null)
340             return false;
341         return result.booleanValue();
342     }
343
344     public String JavaDoc[] getDefaultConfigs() {
345         return new String JavaDoc[] {"org/objectweb/jac/core/rtti/rtti.acc",
346                              "org/objectweb/jac/aspects/user/rtti.acc"};
347     }
348
349     public void definePrimaryKey(CollectionItem collection,
350                                  String JavaDoc[] fields) {
351         collection.setAttribute(PRIMARY_KEY, fields);
352     }
353
354     /**
355      * Tells wether a given type represents a collection
356      */

357     public static boolean isCollectionType(Class JavaDoc type) {
358         return Collection JavaDoc.class.isAssignableFrom(type) ||
359             Map JavaDoc.class.isAssignableFrom(type) ||
360             (type.isArray() && type.getComponentType()!=byte.class);
361     }
362
363     static Hashtable JavaDoc allowedCasts = new Hashtable JavaDoc();
364     public void addAllowedCast(ClassItem src, ClassItem dest) {
365         Set JavaDoc casts = (Set JavaDoc)allowedCasts.get(src);
366         if (casts == null) {
367             casts = new HashSet JavaDoc();
368             allowedCasts.put(src,casts);
369         }
370         casts.add(dest);
371     }
372
373     public static boolean isCastAllowed(ClassItem src, ClassItem dest) {
374         Set JavaDoc casts = (Set JavaDoc)allowedCasts.get(src);
375         return casts!=null && casts.contains(dest);
376     }
377
378     public static boolean isCastAllowed(Class JavaDoc src, Class JavaDoc dest) {
379         ClassRepository cr = ClassRepository.get();
380         return isCastAllowed(cr.getClass(src),cr.getClass(dest));
381     }
382
383     HashSet JavaDoc classesWithAssociations = new HashSet JavaDoc();
384     public Set JavaDoc getClassesWithAssociations() {
385         return classesWithAssociations;
386     }
387
388     public void setOppositeRole(FieldItem field, FieldItem oppositeRole) {
389         field.setOppositeRole(oppositeRole);
390         classesWithAssociations.add(field.getClassItem());
391     }
392     
393     public void declareAssociation(FieldItem roleA, FieldItem roleB) {
394         roleA.setOppositeRole(roleB);
395         roleB.setOppositeRole(roleA);
396         classesWithAssociations.add(roleA.getClassItem());
397         classesWithAssociations.add(roleB.getClassItem());
398     }
399
400     /**
401      * Tries to convert an object into a given type
402      *
403      * <p>If type is
404      * String, toString() is called on value. If type Integer or Long
405      * (or int or long), and the value is numeric type
406      * (float,Float,double or Double) an Integer or Long is
407      * returned. Otherwise, isCastAllowed() is called, and if it
408      * returns true, we try to invoke a constructor take value as a
409      * parameter.</p>
410      *
411      * @param value the value to convert
412      * @param type the type to convert the value into
413      * @return an instance of type built from value, or value
414      * @see #isCastAllowed(Class,Class)
415      */

416     public static Object JavaDoc convert(Object JavaDoc value, Class JavaDoc type)
417         throws InstantiationException JavaDoc, IllegalAccessException JavaDoc,
418                InvocationTargetException JavaDoc, java.lang.NoSuchMethodException JavaDoc
419     {
420         Class JavaDoc valueType = value.getClass();
421         if ((type==int.class || type==Integer JavaDoc.class)
422             && (valueType==float.class || valueType==Float JavaDoc.class
423                 || valueType==double.class || valueType==Double JavaDoc.class)) {
424             return new Integer JavaDoc(((Number JavaDoc)value).intValue());
425         } else if ((type==long.class || type==Long JavaDoc.class)
426                    && (valueType==float.class || valueType==Float JavaDoc.class
427                        || valueType==double.class || valueType==Double JavaDoc.class)) {
428             return new Long JavaDoc(((Number JavaDoc)value).longValue());
429         } else if (type==String JavaDoc.class) {
430             return value.toString();
431         } else {
432             if (RttiAC.isCastAllowed(valueType,type)) {
433                 return
434                     type.getConstructor(new Class JavaDoc[] {valueType})
435                     .newInstance(new Object JavaDoc[] {value});
436             }
437         }
438         return value;
439     }
440
441     public void addMixinMethod(ClassItem cli, MethodItem method)
442         throws InvalidDelegateException
443     {
444         cli.addMethod(new MixinMethodItem((Method JavaDoc)method.getDelegate(),cli));
445     }
446
447 }
448
Popular Tags