KickJava   Java API By Example, From Geeks To Geeks.

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


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.*;
22 import java.util.Arrays JavaDoc;
23 import java.util.Vector JavaDoc;
24
25 /**
26  * This class defines a meta item that corresponds to the
27  * <code>java.lang.reflect.Method</code> and to the
28  * <code>java.lang.reflect.Constructor</code> meta elements.
29  *
30  * <p>It appears that methods and contructors can be seen as
31  * semantically similar (a constructor is nothing else that a special
32  * static method that returns an object that is of the owner class
33  * type). Thus, we decide to wrap those two meta item into a unique
34  * one (on contrary to the Java choice)<p>
35  *
36  * @author Laurent Martelli
37  * @author Renaud Pawlak
38  */

39
40 public abstract class AbstractMethodItem extends MemberItem {
41    
42     /**
43      * Default contructor to create a new abstract method item.<p>
44      *
45      * @param delegate the <code>java.lang.reflect</code> actual
46      * meta item */

47
48     public AbstractMethodItem(Object JavaDoc delegate, ClassItem parent)
49         throws InvalidDelegateException
50     {
51         super(delegate,parent);
52         isStatic = Modifier.isStatic(((Member)delegate).getModifiers());
53     }
54
55     /**
56      * If the field does not have a value for the request attribute,
57      * tries on the superclass.
58      */

59     public final Object JavaDoc getAttribute(String JavaDoc name) {
60         Object JavaDoc value = super.getAttribute(name);
61         if (value==null) {
62             ClassItem parent = ((ClassItem)getParent()).getSuperclass();
63             if (parent!=null) {
64                 try {
65                     AbstractMethodItem parentMethod = parent.getAbstractMethod(getFullName());
66                     value = parentMethod.getAttribute(name);
67                 } catch (NoSuchMethodException JavaDoc e) {
68                     ClassItem[] interfaces = parent.getInterfaceItems();
69                     for (int i=0; i<interfaces.length && value==null;i++) {
70                         if (parent.hasMethod(getFullName())) {
71                             AbstractMethodItem parentMethod = parent.getAbstractMethod(getFullName());
72                             value = parentMethod.getAttribute(name);
73                         }
74                     }
75                 }
76             }
77         }
78         return value;
79     }
80
81     /**
82      * Gets the parameter types of this abstract method item.<p>
83      *
84      * @return the actual method parameter types
85      */

86     public abstract Class JavaDoc[] getParameterTypes();
87     
88     public void setParameter(Object JavaDoc[] params, int i, Object JavaDoc value) {
89         params[i] = value;
90     }
91
92     public Object JavaDoc getParameter(Object JavaDoc[] params, int i) {
93         return params[i];
94     }
95
96     /**
97      * Get the ClassItem of the type of a parameter of the method.
98      * @param n the number of the parameter
99      * @return the ClassItem of the type of the parameter
100      */

101     public ClassItem getParameterTypeItem(int n) {
102         return ClassRepository.get().getClass(getParameterTypes()[n]);
103     }
104
105     /**
106      * Gets the number of parameters
107      *
108      * @return the number of parameters.
109      */

110     public int getParameterCount() {
111         return getParameterTypes().length;
112     }
113
114     boolean isStatic = false;
115
116     public final boolean isStatic() {
117         return isStatic;
118     }
119    
120     private String JavaDoc fullName;
121     /**
122      * Return the full method name, ie with parameter types.
123      *
124      * @return The full method name. For instance myMethod(java.lang.String,int)
125      * @see #getCompactFullName()
126      */

127     public String JavaDoc getFullName() {
128         if (fullName==null) {
129             fullName = getFullName(getName(),getParameterTypes());
130         }
131         return fullName;
132     }
133
134     String JavaDoc realFullName;
135     /**
136      * Return the full method name, ie with parameter types.
137      *
138      * @return The full method name. For instance myMethod(java.lang.String,int)
139      * @see #getCompactFullName()
140      */

141     public String JavaDoc getRealFullName() {
142         if (realFullName==null) {
143             realFullName = getFullName(getName(),((Method)delegate).getParameterTypes());
144         }
145         return realFullName;
146     }
147
148     public static String JavaDoc getFullName(String JavaDoc name, Class JavaDoc[] pts) {
149         StringBuffer JavaDoc ret = new StringBuffer JavaDoc(name.length()+2+pts.length*15);
150         ret.append(name);
151         ret.append('(');
152         for (int i=0; i<pts.length; i++) {
153             ret.append(NamingConventions.getStandardClassName(pts[i]));
154             if (i < pts.length-1)
155                 ret.append(',');
156         }
157         ret.append(')');
158         return ret.toString();
159     }
160
161     /**
162      * Return the full method name, ie with short parameter types.
163      *
164      * @return The full method name. For instance "myMethod(String,int)"
165      * @see #getFullName()
166      */

167     public String JavaDoc getCompactFullName() {
168         //.substring(0, getName().lastIndexOf('.'))
169
Class JavaDoc[] pts = getParameterTypes();
170         StringBuffer JavaDoc ret = new StringBuffer JavaDoc(getName().length()+2+pts.length*15);
171         ret.append(getName());
172         ret.append('(');
173         for (int i=0; i<pts.length; i++) {
174             ret.append(NamingConventions.getShortClassName(pts[i]));
175             if (i < pts.length-1)
176                 ret.append(',');
177         }
178         ret.append(')');
179         return ret.toString();
180     }
181
182     private String JavaDoc longName;
183     public String JavaDoc getLongName() {
184         if (longName==null)
185             longName = parent.getName()+"."+getFullName();
186         return longName;
187     }
188
189     public Object JavaDoc invoke(Object JavaDoc object, Object JavaDoc[] parameters)
190     {
191         if (true) {
192             throw new RuntimeException JavaDoc(
193                 "wrong invocation on an abstract method "+this);
194         }
195         return null;
196     }
197
198     AbstractMethodItem concreteMethod;
199
200     /**
201      * Returns the method item who really holds the byte code.
202      */

203     public AbstractMethodItem getConcreteMethod() {
204         if (concreteMethod==null) {
205             Member m = (Member)delegate;
206             if (parent.getDelegate() == m.getDeclaringClass()) {
207                 return this;
208             }
209             concreteMethod = ClassRepository.get().getClass(m.getDeclaringClass()).
210                 getAbstractMethod(getRealFullName());
211         }
212         return concreteMethod;
213     }
214
215     /**
216      * Returns the owning class of this method.
217      */

218     public ClassItem getOwningClass() {
219         return (ClassItem)parent;
220     }
221
222     public abstract boolean isAdder();
223     public abstract CollectionItem[] getAddedCollections();
224     /**
225      * Get the value of the collection that is added by this
226      * method (the method is the unique adder of the collection).<p>
227      *
228      * @return value of addedCollection.
229      */

230     public final CollectionItem getAddedCollection() {
231         CollectionItem[] colls = getAddedCollections();
232         return ((colls != null) ? colls[0] : null);
233     }
234
235     public abstract boolean isRemover();
236     public abstract CollectionItem[] getRemovedCollections();
237
238     public abstract boolean isAccessor();
239     public abstract boolean isWriter();
240     public abstract boolean isGetter();
241     public abstract boolean isSetter();
242
243     public abstract boolean isCollectionGetter();
244     public abstract boolean isCollectionAccessor();
245     public abstract boolean isCollectionSetter();
246
247     public abstract boolean isFieldGetter();
248     public abstract boolean isFieldSetter();
249
250     public abstract boolean isReferenceGetter();
251     public abstract boolean isReferenceSetter();
252     public abstract boolean isReferenceAccessor();
253
254     public abstract FieldItem getSetField();
255
256     /** Stores the fields that are written by this method.<p> */
257     FieldItem[] writtenFields = null;
258    
259     /**
260      * Gets the value of the fields that are written by this method.<p>
261      *
262      * @return value of writtenFields. */

263
264     public final FieldItem[] getWrittenFields() {
265         ((ClassItem)parent).buildFieldInfo();
266         return writtenFields;
267     }
268    
269     public final boolean hasWrittenFields() {
270         ((ClassItem)parent).buildFieldInfo();
271         return writtenFields!=null && writtenFields.length>0;
272     }
273
274     /**
275      * Sets the value of the fields that are written by this method.<p>
276      *
277      * @param writtenFields value to assign to writtenFields
278      * @see #addWrittenField(FieldItem)
279      */

280
281     public final void setWrittenFields(FieldItem[] writtenFields) {
282         this.writtenFields = writtenFields;
283     }
284
285     /**
286      * Adds a new written field for this method.<p>
287      *
288      * @param writtenField the field to add
289      * @see #setWrittenFields(FieldItem[])
290      * @see #removeWrittenField(FieldItem)
291      */

292     public final void addWrittenField(FieldItem writtenField) {
293         if (writtenFields == null) {
294             writtenFields = new FieldItem[] { writtenField };
295         } else {
296             FieldItem[] tmp = new FieldItem[writtenFields.length + 1];
297             System.arraycopy(writtenFields, 0, tmp, 0, writtenFields.length);
298             tmp[writtenFields.length] = writtenField;
299             writtenFields = tmp;
300         }
301     }
302
303     /**
304      * Removes a new written field for this method.<p>
305      *
306      * @param field the field to remove
307      * @see #addWrittenField(FieldItem)
308      */

309     public final void removeWrittenField(FieldItem field) {
310         if (writtenFields != null) {
311             Vector JavaDoc v = new Vector JavaDoc(Arrays.asList(writtenFields));
312             v.remove(field);
313             writtenFields = new FieldItem[v.size()];
314             System.arraycopy(v.toArray(),0,writtenFields,0,v.size());
315         }
316     }
317
318     /** Stores the number of references read by this method */
319     int numAccessedReferences = 0;
320
321     /** Stores the number of collections read by this method */
322     int numAccessedCollections = 0;
323
324     /** Stores the collections that are modified by this method.<p> */
325     CollectionItem[] modifiedCollections = null;
326    
327     /**
328      * Gets the value of the collections that are modified by this
329      * method.<p>
330      *
331      * @return value of removedCollections. */

332
333     public final CollectionItem[] getModifiedCollections() {
334         ((ClassItem)parent).buildFieldInfo();
335         return modifiedCollections;
336     }
337    
338     /**
339      * Returns true if the method has at least one modified collection
340      */

341
342     public final boolean hasModifiedCollections() {
343         ((ClassItem)parent).buildFieldInfo();
344         return modifiedCollections!=null && modifiedCollections.length>0;
345     }
346
347     /**
348      * Adds a new modified collection for this method.<p>
349      *
350      * @param modifiedCollection the collection to add
351      */

352
353     public final void addModifiedCollection(CollectionItem modifiedCollection) {
354         if ( modifiedCollections == null ) {
355             modifiedCollections = new CollectionItem[] { modifiedCollection };
356         } else {
357             CollectionItem[] tmp = new CollectionItem[modifiedCollections.length + 1];
358             System.arraycopy( modifiedCollections, 0, tmp, 0, modifiedCollections.length );
359             tmp[modifiedCollections.length] = modifiedCollection;
360             modifiedCollections = tmp;
361         }
362     }
363
364     /** Stores the fields that are read by this method.<p> */
365     FieldItem[] accessedFields = null;
366
367     /**
368      * Gets the value of the fields that are written by this method.<p>
369      *
370      * @return value of accessedFields. */

371
372     public final FieldItem[] getAccessedFields() {
373         ((ClassItem)parent).buildFieldInfo();
374         return accessedFields;
375     }
376
377     /**
378      * Sets the value of the fields that are read by this method.<p>
379      *
380      * @param accessedFields value to assign to accessedFields
381      * @see #addAccessedField(FieldItem)
382      */

383
384     public void setAccessedFields(FieldItem[] accessedFields) {
385         this.accessedFields = accessedFields;
386         numAccessedReferences = 0;
387         numAccessedCollections = 0;
388         if (accessedFields!=null) {
389             for(int i=0; i<accessedFields.length; i++) {
390                 if (accessedFields[i].isReference())
391                     numAccessedReferences++;
392                 else if (accessedFields[i] instanceof CollectionItem)
393                     numAccessedCollections++;
394             }
395         }
396     }
397
398     /**
399      * Adds a new accessed field for this method.<p>
400      *
401      * @param accessedField the field to add
402      * @see #setAccessedFields(FieldItem[])
403      * @see #removeAccessedField(FieldItem)
404      */

405
406     public void addAccessedField(FieldItem accessedField) {
407         if (accessedField.isReference())
408             numAccessedReferences++;
409         else if (accessedField instanceof CollectionItem)
410             numAccessedCollections++;
411         if (accessedFields == null) {
412             accessedFields = new FieldItem[] { accessedField };
413         } else {
414             FieldItem[] tmp = new FieldItem[accessedFields.length + 1];
415             System.arraycopy( accessedFields, 0, tmp, 0, accessedFields.length );
416             tmp[accessedFields.length] = accessedField;
417             accessedFields = tmp;
418         }
419     }
420
421     /**
422      * Removes an accessed field for this method.<p>
423      *
424      * @param field the field to remove
425      * @see #addAccessedField(FieldItem)
426      */

427     public void removeAccessedField(FieldItem field) {
428         if (accessedFields != null) {
429             Vector JavaDoc v = new Vector JavaDoc(Arrays.asList(accessedFields));
430             if (v.remove(field)) {
431                 if (field.isReference())
432                     numAccessedReferences--;
433                 else if (field instanceof CollectionItem)
434                     numAccessedCollections--;
435                 accessedFields = new FieldItem[v.size()];
436                 System.arraycopy(v.toArray(),0,accessedFields,0,v.size());
437             }
438         }
439     }
440
441     /**
442      * Gets the value of the fields that are written by this method.<p>
443      *
444      * @return value of accessedFields.
445      */

446     public final FieldItem[] getAccessedReferences() {
447         ((ClassItem)parent).buildFieldInfo();
448         FieldItem[] refs = new FieldItem[numAccessedReferences];
449         int j=0;
450         for (int i=0; i<accessedFields.length; i++) {
451             if (accessedFields[i].isReference())
452                 refs[j++] = accessedFields[i];
453         }
454         return refs;
455     }
456
457     public final CollectionItem[] getAccessedCollections() {
458         ((ClassItem)parent).buildFieldInfo();
459         CollectionItem[] colls = new CollectionItem[numAccessedCollections];
460         int j=0;
461         for (int i=0; i<accessedFields.length; i++) {
462             if (accessedFields[i] instanceof CollectionItem)
463                 colls[j++] = (CollectionItem)accessedFields[i];
464         }
465         return colls;
466     }
467
468     /** Tells wether the method modifies the state of the object */
469     public final boolean isModifier() {
470         ((ClassItem)parent).buildFieldInfo();
471         return (writtenFields!=null && writtenFields.length>0)
472             || (modifiedCollections!=null && modifiedCollections.length>0)
473             || isAdder() || isRemover();
474     }
475
476    public String JavaDoc toString() {
477        return getLongName();
478    }
479 }
480
Popular Tags