1 package org.springframework.roo.model;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11 import java.util.TreeMap;
12 import java.util.Vector;
13
14 import org.springframework.roo.support.util.Assert;
15 import org.springframework.roo.support.util.StringUtils;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public final class JavaType implements Comparable<JavaType>, Cloneable {
33 private List<JavaType> parameters = new ArrayList<JavaType>();
34 private JavaSymbolName argName = null;
35 private int array = 0;
36 private boolean defaultPackage;
37 private DataType dataType;
38 private String fullyQualifiedTypeName;
39 private String simpleTypeName;
40 public static final JavaType BOOLEAN_OBJECT = new JavaType("java.lang.Boolean", 0, DataType.TYPE, null, null);
41 public static final JavaType CHAR_OBJECT = new JavaType("java.lang.Character", 0, DataType.TYPE, null, null);
42 public static final JavaType STRING_OBJECT = new JavaType("java.lang.String", 0, DataType.TYPE, null, null);
43 public static final JavaType BYTE_OBJECT = new JavaType("java.lang.Byte", 0, DataType.TYPE, null, null);
44 public static final JavaType SHORT_OBJECT = new JavaType("java.lang.Short", 0, DataType.TYPE, null, null);
45 public static final JavaType INT_OBJECT = new JavaType("java.lang.Integer", 0, DataType.TYPE, null, null);
46 public static final JavaType LONG_OBJECT = new JavaType("java.lang.Long", 0, DataType.TYPE, null, null);
47 public static final JavaType FLOAT_OBJECT = new JavaType("java.lang.Float", 0, DataType.TYPE, null, null);
48 public static final JavaType DOUBLE_OBJECT = new JavaType("java.lang.Double", 0, DataType.TYPE, null, null);
49 public static final JavaType VOID_OBJECT = new JavaType("java.lang.Void", 0, DataType.TYPE, null, null);
50 public static final JavaType BOOLEAN_PRIMITIVE = new JavaType("java.lang.Boolean", 0, DataType.PRIMITIVE, null, null);
51 public static final JavaType CHAR_PRIMITIVE = new JavaType("java.lang.Character", 0, DataType.PRIMITIVE, null, null);
52 public static final JavaType BYTE_PRIMITIVE = new JavaType("java.lang.Byte", 0, DataType.PRIMITIVE, null, null);
53 public static final JavaType SHORT_PRIMITIVE = new JavaType("java.lang.Short", 0, DataType.PRIMITIVE, null, null);
54 public static final JavaType INT_PRIMITIVE = new JavaType("java.lang.Integer", 0, DataType.PRIMITIVE, null, null);
55 public static final JavaType LONG_PRIMITIVE = new JavaType("java.lang.Long", 0, DataType.PRIMITIVE, null, null);
56 public static final JavaType FLOAT_PRIMITIVE = new JavaType("java.lang.Float", 0, DataType.PRIMITIVE, null, null);
57 public static final JavaType DOUBLE_PRIMITIVE = new JavaType("java.lang.Double", 0, DataType.PRIMITIVE, null, null);
58 public static final JavaType VOID_PRIMITIVE = new JavaType("java.lang.Void", 0, DataType.PRIMITIVE, null, null);
59
60 private static final Set<String> commonCollectionTypes = new HashSet<String>();
61
62 static {
63 commonCollectionTypes.add(Collection.class.getName());
64 commonCollectionTypes.add(List.class.getName());
65 commonCollectionTypes.add(Set.class.getName());
66 commonCollectionTypes.add(Map.class.getName());
67 commonCollectionTypes.add(HashMap.class.getName());
68 commonCollectionTypes.add(TreeMap.class.getName());
69 commonCollectionTypes.add(ArrayList.class.getName());
70 commonCollectionTypes.add(Vector.class.getName());
71 commonCollectionTypes.add(HashSet.class.getName());
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 public JavaType(String fullyQualifiedTypeName) {
91 this(fullyQualifiedTypeName, 0, DataType.TYPE, null, null);
92 }
93
94
95
96
97
98
99
100
101
102
103
104 public JavaType(String fullyQualifiedTypeName, int array, DataType primitive, JavaSymbolName argName, List<JavaType> parameters) {
105 if (fullyQualifiedTypeName == null || fullyQualifiedTypeName.length() == 0) {
106 throw new IllegalArgumentException("Fully qualified type name required");
107 }
108 JavaSymbolName.assertJavaNameLegal(fullyQualifiedTypeName);
109 this.fullyQualifiedTypeName = fullyQualifiedTypeName;
110 this.defaultPackage = !fullyQualifiedTypeName.contains(".");
111 if (defaultPackage) {
112 simpleTypeName = fullyQualifiedTypeName;
113 } else {
114 int offset = fullyQualifiedTypeName.lastIndexOf(".");
115 simpleTypeName = fullyQualifiedTypeName.substring(offset+1);
116 }
117 if (!Character.isUpperCase(simpleTypeName.charAt(0))) {
118
119 if (simpleTypeName.length() < 2 || !Character.isUpperCase(simpleTypeName.charAt(1)) || '_' != simpleTypeName.charAt(0)) {
120 throw new IllegalArgumentException("The first letter of the type name portion must be uppercase (attempted '" + fullyQualifiedTypeName + "')");
121 }
122 }
123
124 this.array = array;
125 this.dataType = primitive;
126 if (parameters != null) {
127 this.parameters = parameters;
128 }
129 this.argName = argName;
130 }
131
132
133
134
135 public String getSimpleTypeName() {
136 return simpleTypeName;
137 }
138
139
140
141
142 public String getFullyQualifiedTypeName() {
143 return fullyQualifiedTypeName;
144 }
145
146
147 public static final JavaSymbolName WILDCARD_EXTENDS = new JavaSymbolName("_ROO_WILDCARD_EXTENDS_");
148 public static final JavaSymbolName WILDCARD_SUPER = new JavaSymbolName("_ROO_WILDCARD_SUPER_");
149 public static final JavaSymbolName WILDCARD_NEITHER = new JavaSymbolName("_ROO_WILDCARD_NEITHER_");
150
151
152
153
154
155
156
157 public String getNameIncludingTypeParameters() {
158 return getNameIncludingTypeParameters(false, null, new HashMap<String, String>());
159 }
160
161
162
163
164
165
166
167
168
169
170 public String getNameIncludingTypeParameters(boolean staticForm, ImportRegistrationResolver resolver) {
171 return getNameIncludingTypeParameters(staticForm, resolver, new HashMap<String, String>());
172 }
173
174 private String getNameIncludingTypeParameters(boolean staticForm, ImportRegistrationResolver resolver, Map<String, String> types) {
175 if (DataType.PRIMITIVE == dataType) {
176 Assert.isTrue(parameters.size() == 0, "A primitive cannot have parameters");
177 if (this.fullyQualifiedTypeName.equals(Integer.class.getName())) {
178 return "int" + getArraySuffix();
179 } else if (this.fullyQualifiedTypeName.equals(Character.class.getName())) {
180 return "char" + getArraySuffix();
181 } else if (this.fullyQualifiedTypeName.equals(Void.class.getName())) {
182 return "void";
183 }
184 return StringUtils.uncapitalize(this.getSimpleTypeName() + getArraySuffix());
185 }
186
187 StringBuilder sb = new StringBuilder();
188
189 if (WILDCARD_EXTENDS.equals(argName)) {
190 sb.append("?");
191 if (dataType == DataType.TYPE || !staticForm) {
192 sb.append(" extends ");
193 } else if (types.containsKey(fullyQualifiedTypeName)) {
194 sb.append(" extends ").append(types.get(fullyQualifiedTypeName));
195 }
196 } else if (WILDCARD_SUPER.equals(argName)) {
197 sb.append("?");
198 if (dataType == DataType.TYPE || !staticForm) {
199 sb.append(" super ");
200 } else if (types.containsKey(fullyQualifiedTypeName)) {
201 sb.append(" extends ").append(types.get(fullyQualifiedTypeName));
202 }
203 } else if (WILDCARD_NEITHER.equals(argName)) {
204 sb.append("?");
205 } else if (argName != null && !staticForm) {
206 sb.append(argName);
207 if (dataType == DataType.TYPE) {
208 sb.append(" extends ");
209 }
210 }
211
212 if (!WILDCARD_NEITHER.equals(argName)) {
213
214
215 if (dataType == DataType.TYPE || !staticForm) {
216
217 if (resolver != null) {
218 if (resolver.isFullyQualifiedFormRequiredAfterAutoImport(this)) {
219 sb.append(fullyQualifiedTypeName);
220 } else {
221 sb.append(getSimpleTypeName());
222 }
223 } else {
224 sb.append(fullyQualifiedTypeName);
225 }
226 }
227
228 if (this.parameters.size() > 0 && (dataType == DataType.TYPE || !staticForm)) {
229 sb.append("<");
230 int counter = 0;
231 for (JavaType param : this.parameters) {
232 counter++;
233 if (counter > 1) {
234 sb.append(", ");
235 }
236 sb.append(param.getNameIncludingTypeParameters(staticForm, resolver, types));
237 counter++;
238 }
239 sb.append(">");
240 }
241
242 sb.append(getArraySuffix());
243 }
244
245 if (argName != null && !argName.equals(WILDCARD_EXTENDS) && !argName.equals(WILDCARD_SUPER) && !argName.equals(WILDCARD_NEITHER)) {
246 types.put(this.argName.getSymbolName(), sb.toString());
247 }
248
249 return sb.toString();
250 }
251
252
253
254
255 public JavaPackage getPackage() {
256 if (isDefaultPackage()) {
257 return new JavaPackage("");
258 }
259
260 JavaType enclosingType = getEnclosingType();
261 if (enclosingType != null) {
262 return enclosingType.getPackage();
263 }
264
265 int offset = fullyQualifiedTypeName.lastIndexOf(".");
266 return new JavaPackage(fullyQualifiedTypeName.substring(0, offset));
267 }
268
269
270
271
272 public JavaType getEnclosingType() {
273 int offset = fullyQualifiedTypeName.lastIndexOf(".");
274 if (offset == -1) {
275
276 return null;
277 }
278 String possibleName = fullyQualifiedTypeName.substring(0, offset);
279 int offset2 = possibleName.lastIndexOf(".");
280
281
282 String enclosedWithinPackage = null;
283 String enclosedWithinTypeName = possibleName;
284
285
286 if (offset2 > -1) {
287 enclosedWithinPackage = possibleName.substring(0, offset2);
288 enclosedWithinTypeName = possibleName.substring(offset2+1);
289 }
290 if (enclosedWithinTypeName.charAt(0) == enclosedWithinTypeName.toUpperCase().charAt(0)) {
291
292 String preTypeNamePortion = enclosedWithinPackage == null ? "" : (enclosedWithinPackage + ".");
293 return new JavaType(preTypeNamePortion + enclosedWithinTypeName);
294 }
295 return null;
296 }
297
298 public boolean isDefaultPackage() {
299 return defaultPackage;
300 }
301
302 public final int hashCode() {
303 return this.fullyQualifiedTypeName.hashCode();
304 }
305
306 public boolean isPrimitive() {
307 return DataType.PRIMITIVE == dataType;
308 }
309
310 public boolean isCommonCollectionType() {
311 return commonCollectionTypes.contains(this.fullyQualifiedTypeName);
312 }
313
314 public List<JavaType> getParameters() {
315 return Collections.unmodifiableList(this.parameters);
316 }
317
318 public boolean isArray() {
319 return array > 0;
320 }
321
322 public int getArray() {
323 return array;
324 }
325
326 private String getArraySuffix() {
327 if (array == 0) {
328 return "";
329 }
330 StringBuilder sb = new StringBuilder();
331 for (int i = 0; i < array; i++) {
332 sb.append("[]");
333 }
334 return sb.toString();
335 }
336
337 public final boolean equals(Object obj) {
338
339 return obj != null && obj instanceof JavaType && this.fullyQualifiedTypeName.equals(((JavaType)obj).fullyQualifiedTypeName) && this.dataType == ((JavaType)obj).dataType;
340 }
341
342 public final int compareTo(JavaType o) {
343
344 if (o == null) return -1;
345 return this.fullyQualifiedTypeName.compareTo(o.fullyQualifiedTypeName);
346 }
347
348 public final String toString() {
349 return getNameIncludingTypeParameters();
350 }
351
352 public JavaSymbolName getArgName() {
353 return argName;
354 }
355
356 public DataType getDataType() {
357 return dataType;
358 }
359
360
361
362
363
364
365
366
367 }