/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("myMethod", t1);
19 * generateNext("myMethod", t2);
20 * generateNext("myMethod", 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