1 cananian 1.1 // MethodGenerator.java, created Fri Jul 11 02:53:45 2003 by cananian
 2 cananian 1.1 // Copyright (C) 2003 C. Scott Ananian <cananian@alumni.princeton.edu>
 3 cananian 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
 4 cananian 1.1 package harpoon.Analysis.Transactions;
 5 cananian 1.1 
 6 cananian 1.1 import harpoon.ClassFile.HClass;
 7 cananian 1.1 import harpoon.ClassFile.HClassMutator;
 8 cananian 1.1 import harpoon.ClassFile.HMethod;
 9 cananian 1.1 
10 cananian 1.1 import java.lang.reflect.Modifier;
11 cananian 1.2 import java.util.Collections;
12 cananian 1.1 import java.util.HashMap;
13 cananian 1.1 import java.util.Map;
14 cananian 1.2 import java.util.Set;
15 cananian 1.1 /**
16 cananian 1.1  * A <code>MethodGenerator</code> creates methods with base names and
17 cananian 1.1  * parameters/return types you specify.
18 cananian 1.1  * 
19 cananian 1.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
20 cananian 1.2  * @version $Id: MethodGenerator.java,v 1.2 2003/07/21 21:21:49 cananian Exp $
21 cananian 1.1  */
22 cananian 1.1 class MethodGenerator {
23 cananian 1.1     private final HClassMutator classMutator;
24 cananian 1.1     private static final String separator = "_";
25 cananian 1.1 
26 cananian 1.1     /** Creates a <code>MethodGenerator</code> which creates methods
27 cananian 1.1      *  in the given <code>HClass</code>. */
28 cananian 1.1     public MethodGenerator(HClass baseClass) {
29 cananian 1.1         this.classMutator = baseClass.getMutator();
30 cananian 1.1     }
31 cananian 1.2 
32 cananian 1.1     /** Return the 'name' originally given to lookupMethod (which will
33 cananian 1.1      *  differ from the name reported by the method via getName()). */
34 cananian 1.2     public String baseName(HMethod hm) {
35 cananian 1.2         assert generatedMethodSet.contains(hm);
36 cananian 1.2         return descriptors.get(hm).namePrefix;
37 cananian 1.1     }
38 cananian 1.1     public HMethod lookupMethod(String name, HClass[] argTypes, HClass retType)
39 cananian 1.1     {
40 cananian 1.1         MethodDescriptor md = new MethodDescriptor(name, argTypes, retType);
41 cananian 1.1         HMethod hm = methods.get(md);
42 cananian 1.1         if (hm!=null) return hm;
43 cananian 1.1         // add counter to name to guarantee uniqueness.
44 cananian 1.1         hm = classMutator.addDeclaredMethod
45 cananian 1.1             (name+separator+(counter++), argTypes, retType);
46 cananian 1.2         hm.getMutator().addModifiers(Modifier.FINAL | //Modifier.NATIVE |
47 cananian 1.1                                      Modifier.STATIC | Modifier.PUBLIC);
48 cananian 1.1         methods.put(md, hm);
49 cananian 1.2         descriptors.put(hm, md);
50 cananian 1.1         return hm;
51 cananian 1.1     }
52 cananian 1.1     private final Map<MethodDescriptor,HMethod> methods =
53 cananian 1.1         new HashMap<MethodDescriptor,HMethod>();
54 cananian 1.2     private final Map<HMethod,MethodDescriptor> descriptors =
55 cananian 1.2         new HashMap<HMethod,MethodDescriptor>();
56 cananian 1.1     int counter = 0;
57 cananian 1.2 
58 cananian 1.2     /** The <code>Set</code> of all <code>HMethod</code>s generated
59 cananian 1.2      *  by this <code>MethodGenerator</code>. */
60 cananian 1.2     public final Set<HMethod> generatedMethodSet =
61 cananian 1.2         Collections.unmodifiableSet(descriptors.keySet());
62 cananian 1.1 
63 cananian 1.1     /** The <code>MethodDescriptor</code> is a handy tuple type to serve
64 cananian 1.1      *  as keys in the hashtable. */
65 cananian 1.1     static class MethodDescriptor {
66 cananian 1.1         final String namePrefix;
67 cananian 1.1         final HClass[] argTypes;
68 cananian 1.1         final HClass retType;
69 cananian 1.1         MethodDescriptor(String namePrefix, HClass[] argTypes, HClass retType){
70 cananian 1.1             this.namePrefix = namePrefix;
71 cananian 1.1             this.argTypes = argTypes;
72 cananian 1.1             this.retType = retType;
73 cananian 1.1         }
74 cananian 1.1         public int hashCode() {
75 cananian 1.1             int hash = namePrefix.hashCode() + retType.hashCode();
76 cananian 1.1             hash += argTypes.length;
77 cananian 1.1             for(int i=0; i<argTypes.length; i++)
78 cananian 1.1                 hash += argTypes[i].hashCode();
79 cananian 1.1             return hash;
80 cananian 1.1         }
81 cananian 1.1         public boolean equals(Object o) {
82 cananian 1.1             if (this==o) return true;
83 cananian 1.1             if (!(o instanceof MethodDescriptor)) return false;
84 cananian 1.1             MethodDescriptor md = (MethodDescriptor) o;
85 cananian 1.1             if (!this.namePrefix.equals(md.namePrefix)) return false;
86 cananian 1.1             if (!this.retType.equals(md.retType)) return false;
87 cananian 1.1             if (this.argTypes.length != md.argTypes.length) return false;
88 cananian 1.1             for (int i=0; i<this.argTypes.length; i++)
89 cananian 1.1                 if (!this.argTypes[i].equals(md.argTypes[i])) return false;
90 cananian 1.1             return true; // exactly the same.
91 cananian 1.1         }
92 cananian 1.1     }
93 cananian 1.1 }