KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > spoon > jdiet > InvocationProcessor


1 package spoon.jdiet;
2
3 import java.util.ArrayList JavaDoc;
4 import java.util.Arrays JavaDoc;
5 import java.util.Collection JavaDoc;
6 import java.util.Hashtable JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.List JavaDoc;
9 import java.util.Map JavaDoc;
10 import java.util.Set JavaDoc;
11 import java.util.Vector JavaDoc;
12
13 import spoon.jdiet.rt.Helper;
14 import spoon.processing.AbstractProcessor;
15 import spoon.processing.TraversalStrategy;
16 import spoon.reflect.code.CtExpression;
17 import spoon.reflect.code.CtInvocation;
18 import spoon.reflect.code.CtNewClass;
19 import spoon.reflect.declaration.CtElement;
20 import spoon.reflect.factory.CodeFactory;
21 import spoon.reflect.factory.ExecutableFactory;
22 import spoon.reflect.factory.TypeFactory;
23 import spoon.reflect.reference.CtExecutableReference;
24 import spoon.reflect.reference.CtTypeReference;
25
26 /**
27  * This processor replaces Java API calls which are not in the J2ME API by some
28  * J2ME compliant equivalent calls.
29  *
30  * @author Lionel Seinturier <Lionel.Seinturier@lifl.fr>
31  */

32 public class InvocationProcessor extends AbstractProcessor<CtInvocation> {
33     
34     public TraversalStrategy getTraversalStrategy() {
35         // Let arguments included in the construction be visited first
36
return TraversalStrategy.POST_ORDER;
37     }
38
39     private List JavaDoc<Transformer<CtInvocation>> mits =
40         new ArrayList JavaDoc<Transformer<CtInvocation>>();
41     
42     public InvocationProcessor() {
43         
44         Class JavaDoc objarraycl = new Object JavaDoc[0].getClass();
45         
46         /*
47          * Transforming into methods defined in the Helper class.
48          */

49         mits.add( new HelperClassCtInvTransformer(Arrays JavaDoc.class,"asList",Vector JavaDoc.class,"asList",new Object JavaDoc[0].getClass()) );
50         mits.add( new HelperClassCtInvTransformer(Collection JavaDoc.class,"toArray",objarraycl,"toArray",Vector JavaDoc.class,new Object JavaDoc[0].getClass()) );
51         mits.add( new HelperClassCtInvTransformer(List JavaDoc.class,"add",Boolean JavaDoc.class,"addList",Vector JavaDoc.class,Object JavaDoc.class) );
52         mits.add( new HelperClassCtInvTransformer(List JavaDoc.class,"addAll",Boolean JavaDoc.class,"addAllList",Vector JavaDoc.class,Vector JavaDoc.class) );
53         mits.add( new HelperClassCtInvTransformer(Map JavaDoc.class,"values",Vector JavaDoc.class,"values",Hashtable JavaDoc.class) );
54         mits.add( new HelperClassCtInvTransformer(Map JavaDoc.class,"entrySet",Vector JavaDoc.class,"entrySet",Hashtable JavaDoc.class) );
55         mits.add( new HelperClassCtInvTransformer(Map JavaDoc.class,"keySet",Vector JavaDoc.class,"keySet",Hashtable JavaDoc.class) );
56         mits.add( new HelperClassCtInvTransformer(Set JavaDoc.class,"add",Boolean JavaDoc.class,"addSet",Vector JavaDoc.class,Object JavaDoc.class) );
57         mits.add( new HelperClassCtInvTransformer(Set JavaDoc.class,"addAll",Boolean JavaDoc.class,"addAllSet",Vector JavaDoc.class,Vector JavaDoc.class) );
58         
59         /*
60          * Transforming by replacing method names.
61          */

62         mits.add( new SimpleCtInvTransformer(Collection JavaDoc.class,"iterator","elements") );
63         mits.add( new SimpleCtInvTransformer(Collection JavaDoc.class,"remove","removeElement") );
64         mits.add( new SimpleCtInvTransformer(Iterator JavaDoc.class,"hasNext","hasMoreElements") );
65         mits.add( new SimpleCtInvTransformer(Iterator JavaDoc.class,"next","nextElement") );
66         mits.add( new SimpleCtInvTransformer(List JavaDoc.class,"get","elementAt") );
67     }
68     
69     public void process(CtInvocation inv) {
70         // Perform the replacement for all registered transformers
71
for (Transformer<CtInvocation> t : mits) {
72             if( t.match(inv) ) {
73                 t.transform(inv);
74             }
75         }
76     }
77 }
78
79
80 interface Transformer<T extends CtElement> {
81     boolean match( T element );
82     void transform( T element );
83 }
84
85 /**
86  * Root class for implementing replacements on method invocations
87  * (CtInvocation). The match(CtInvocation) method returns true if the
88  * CtInvocation matches the searched method.
89  *
90  * @author Lionel Seinturier <Lionel.Seinturier@lifl.fr>
91  */

92 abstract class AbstractCtInvTransformer implements Transformer<CtInvocation> {
93     
94     private Class JavaDoc srcType;
95     private String JavaDoc methName;
96     
97     protected Class JavaDoc replMethType;
98     protected String JavaDoc replMethName;
99     protected Class JavaDoc[] replMethParameterTypes;
100     
101     public AbstractCtInvTransformer(
102             Class JavaDoc srcType, String JavaDoc methName,
103             Class JavaDoc replMethType, String JavaDoc replMethName,
104             Class JavaDoc... replMethParameterTypes ) {
105         
106         this.srcType = srcType;
107         this.methName = methName;
108         this.replMethType = replMethType;
109         this.replMethName = replMethName;
110         this.replMethParameterTypes = replMethParameterTypes;
111     }
112     
113     public boolean match( CtInvocation inv ) {
114         
115         TypeFactory tf = inv.getFactory().Type();
116         CtTypeReference srcTypeRef = tf.createReference(srcType);
117         CtTypeReference invokedType = getTargetType(inv);
118         
119         if( invokedType.getQualifiedName().length() == 0 ) {
120             getTargetType(inv);
121         }
122         
123         if( invokedType.isSubtypeOf(srcTypeRef) ) {
124             CtExecutableReference cer = inv.getExecutable();
125             String JavaDoc invokedMethodName = cer.getSimpleName();
126             return invokedMethodName.equals(methName);
127         }
128         
129         return false;
130     }
131     
132     abstract public void transform( CtInvocation inv );
133     
134     protected CtTypeReference getTargetType( CtInvocation inv ) {
135         CtExpression target = inv.getTarget();
136         if( target == null ) {
137             // Static method invocation
138
CtTypeReference ctr = inv.getExecutable().getDeclaringType();
139             return ctr;
140         }
141         else {
142             if( target instanceof CtNewClass ) {
143                 // Invocation on an instance of an anonymous class
144
// e.g. new Runnable(){ public void run(){} }
145
CtNewClass nc = (CtNewClass) target;
146                 CtTypeReference ctr = NewClassProcessor.getType(nc);
147                 return ctr;
148             }
149             else {
150                 // Instance method invocation
151
CtTypeReference ctr = target.getType();
152                 return ctr;
153             }
154         }
155     }
156 }
157
158 /**
159  * This class replaces a given method invocation (CtInvocation) by substituing
160  * method names.
161  *
162  * @author Lionel Seinturier <Lionel.Seinturier@lifl.fr>
163  */

164 class SimpleCtInvTransformer extends AbstractCtInvTransformer {
165     
166     public SimpleCtInvTransformer(
167             Class JavaDoc targetType, String JavaDoc methName, String JavaDoc replMethName ) {
168         
169         super( targetType, methName, null, replMethName, (Class JavaDoc[]) null );
170     }
171     
172     public void transform( CtInvocation inv ) {
173         CtExecutableReference cer = inv.getExecutable();
174         cer.setSimpleName(replMethName);
175     }
176 }
177
178 /**
179  * This class replaces a given method invocation (CtInvocation) into a call to
180  * one of the static methods defined in the {@link Helper} class. The
181  * replacement takes the form of a method name substitution.
182  *
183  * @author Lionel Seinturier <Lionel.Seinturier@lifl.fr>
184  */

185 class HelperClassCtInvTransformer extends AbstractCtInvTransformer {
186     
187     public HelperClassCtInvTransformer(
188             Class JavaDoc targetType, String JavaDoc methName,
189             Class JavaDoc replMethType, String JavaDoc replMethName,
190             Class JavaDoc... replMethParameterTypes ) {
191         
192         super(
193             targetType, methName,
194             replMethType, replMethName, replMethParameterTypes );
195     }
196     
197     public void transform( CtInvocation inv ) {
198         
199         CodeFactory cf = inv.getFactory().Code();
200         ExecutableFactory ef = inv.getFactory().Executable();
201         TypeFactory tf = inv.getFactory().Type();
202         
203         // Construct the signature of the replacement method
204
CtTypeReference[] trs = new CtTypeReference[replMethParameterTypes.length];
205         for (int i = 0; i < replMethParameterTypes.length; i++) {
206             trs[i] = tf.createReference(replMethParameterTypes[i]);
207         }
208         
209         // Get the replacement method
210
CtExecutableReference replmeth =
211             ef.createReference(
212                     tf.createReference(Helper.class),true,replMethName,trs );
213         replmeth.setType( tf.createReference(replMethType) );
214
215         // Construct the array of arguments for the replacement method
216
List JavaDoc<CtExpression<?>> l = inv.getArguments();
217         CtExpression target = inv.getTarget();
218         if( target != null ) {
219             // Instance (i.e. non static) method invocation
220
// Add the target of the call as a first parameter
221
l.add(0,target);
222         }
223         
224         // Construct the method invocation
225
CtInvocation repl = cf.createInvocation( null, replmeth, l );
226         repl.setType( tf.createReference(replMethType) );
227         repl.setTypeCasts(inv.getTypeCasts());
228         
229         // Perform the replacement
230
inv.replace(repl);
231     }
232 }
233
Popular Tags