/Users/lyon/j4p/src/classUtils/pack/util/codegen/VariableNameGenerator.java

1    package classUtils.pack.util.codegen; 
2     
3    import java.util.HashMap; 
4    import java.util.HashSet; 
5    import java.util.Map; 
6    import java.util.Set; 
7     
8    /** 
9     * 
10    * A class to generate variable names depending on types.  
11    * <p> 
12    * Given a method name and a Java type, the {@link #generateNext(java.lang.String, java.lang.Class) generateNext()}  
13    * method produces  valid (i.e. compilable) sequences of variable names, depending on the passed type, 
14    * until either a different method name is passed or the {@link #reset() reset()} method is invoked. 
15    * <p> 
16    * For example, the invocations: 
17    * <pre> 
18    *  generateNext(&quot;myMethod&quot;, t1); 
19    *  generateNext(&quot;myMethod&quot;, t2); 
20    *  generateNext(&quot;myMethod&quot;, t3); 
21    * </pre> 
22    * where t1=<tt>String</tt>, t2=<tt>int</tt>, t3=<tt>String</tt> will produce  
23    * <tt>string1, i1, string2</tt>. 
24    * <p> 
25    * This generator supports both JDK1.3 and JDK1.4 keywords. 
26    *  
27    * @version 1.0 
28    * @author Cristiano Sadun 
29    */ 
30   public class VariableNameGenerator { 
31    
32       /** 
33        * Constant to use at construction to indicate JDK1_3 keyword compliance. 
34        */  
35       public static final int JDK1_3=0; 
36        
37       /** 
38        * Constant to use at construction to indicate JDK1_4 keyword compliance. 
39        */  
40       public static final int JDK1_4=1; 
41        
42       private Map prefixMap; 
43       private String currentMethodName = null; 
44       private int jdkRelease; 
45    
46       private static Set reservedNames; 
47       private static Set jdk14reservedNames; 
48    
49       /** 
50        * Create a variable name generator for the given target compiler (see class constants). 
51        * @param jdkRelease one of the JDK_x constants. 
52        */ 
53       public VariableNameGenerator(int jdkRelease) { 
54           if (jdkRelease != JDK1_3 && 
55               jdkRelease != JDK1_4) throw new IllegalArgumentException("jdk release parameter incorrect - use the constants defined by this class");   
56           this.jdkRelease=jdkRelease; 
57           this.prefixMap = new HashMap(); 
58       } 
59        
60       /** 
61        * Create a variable name generator for the JDK1_4 target compiler (see class constants). 
62        */ 
63       public VariableNameGenerator() { 
64           this(JDK1_4); 
65       } 
66    
67       /** 
68        * Reset the name generator 
69        */ 
70       public void reset() { 
71           prefixMap = new HashMap(); 
72       } 
73    
74       public String generateNext(String methodName, Class type) { 
75           if (!methodName.equals(currentMethodName)) { 
76               currentMethodName = methodName; 
77               reset(); 
78           } 
79           if (type.isPrimitive()) 
80               return generateForPrimitiveType(methodName, type); 
81           else if (type.isArray()) { 
82               String s = generateNext(methodName, type.getComponentType()); 
83               if (!s.endsWith("Array")) 
84                   s += "Array"; 
85               return s; 
86           } 
87           return generateForObjectType(methodName, type); 
88       } 
89    
90       /** 
91        * Method generateForObjectType. 
92        * @param methodName 
93        * @param type 
94        * @return String 
95        */ 
96       private String generateForObjectType(String methodName, Class type) { 
97           int i = type.getName().lastIndexOf("."); 
98           if (i == -1) 
99               return pickNext(getCanonicalName(type.getName())); 
100          else 
101              return pickNext(getCanonicalName(type.getName().substring(i + 1))); 
102      } 
103   
104      private String getCanonicalName(String name) { 
105   
106          if (name.length() == 1) 
107              return name.toLowerCase(); 
108          if (Character.isUpperCase(name.charAt(0))) 
109              name = Character.toLowerCase(name.charAt(0)) + name.substring(1); 
110   
111          if (isReservedIdentifier(name)) 
112              return "_" + name; 
113          return name; 
114      } 
115   
116      /** 
117       * Method isReservedIdentifier. To be implemented. 
118       * @param name 
119       * @return boolean 
120       */ 
121      private boolean isReservedIdentifier(String name) { 
122          if (jdkRelease==JDK1_4) { 
123              if (jdk14reservedNames.contains(name)) return true; 
124          } 
125          return reservedNames.contains(name); 
126      } 
127   
128      /** 
129       * Method generateForPrimitiveType. 
130       * @param type 
131       */ 
132      private String generateForPrimitiveType(String methodName, Class type) { 
133          return pickNext(type.getName().substring(0, 1)); 
134      } 
135   
136      /** 
137       * Method pickNext. 
138       * @param string 
139       * @return String 
140       */ 
141      private String pickNext(String s) { 
142          Integer next = (Integer) prefixMap.get(s); 
143          if (next == null) { 
144              next = new Integer(0); 
145          } 
146          int n = next.intValue(); 
147          prefixMap.put(s, new Integer(n + 1)); 
148          return s + n; 
149      } 
150   
151      static { 
152          String[] reservedKeywords = 
153              { 
154                  "abstract", 
155                  "boolean", 
156                  "break", 
157                  "byte", 
158                  "case", 
159                  "catch", 
160                  "char", 
161                  "class", 
162                  "continue", 
163                  "default", 
164                  "delegate", 
165                  "do", 
166                  "double", 
167                  "else", 
168                  "extends", 
169                  "false", 
170                  "final", 
171                  "finally", 
172                  "float", 
173                  "for", 
174                  "if", 
175                  "implements", 
176                  "import", 
177                  "instanceof", 
178                  "int", 
179                  "interface", 
180                  "long", 
181                  "multicast", 
182                  "native", 
183                  "new", 
184                  "null", 
185                  "object", 
186                  "package", 
187                  "private", 
188                  "protected", 
189                  "public", 
190                  "return", 
191                  "short", 
192                  "static", 
193                  "super", 
194                  "switch", 
195                  "synchronized", 
196                  "this", 
197                  "throw", 
198                  "throws", 
199                  "transient", 
200                  "true", 
201                  "try", 
202                  "void", 
203                  "volatile", 
204                  "while" }; 
205   
206          reservedNames = new HashSet(); 
207          for (int i = 0; i < reservedKeywords.length; i++) 
208              reservedNames.add(reservedKeywords[i]); 
209           
210          String[] jdk14reservedKeywords = 
211              { "assert" }; 
212               
213          jdk14reservedNames = new HashSet(); 
214          for (int i = 0; i < jdk14reservedKeywords.length; i++) 
215              jdk14reservedNames .add(jdk14reservedKeywords[i]);   
216      } 
217  } 
218