001: /*
002: * Spoon - http://spoon.gforge.inria.fr/
003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
004: *
005: * This software is governed by the CeCILL-C License under French law and
006: * abiding by the rules of distribution of free software. You can use, modify
007: * and/or redistribute the software under the terms of the CeCILL-C license as
008: * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
009: *
010: * This program is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
013: *
014: * The fact that you are presently reading this means that you have had
015: * knowledge of the CeCILL-C license and that you accept its terms.
016: */
017:
018: package spoon.reflect.factory;
019:
020: import java.util.ArrayList;
021: import java.util.List;
022:
023: import spoon.reflect.Factory;
024: import spoon.reflect.declaration.CtElement;
025: import spoon.reflect.declaration.CtPackage;
026: import spoon.reflect.declaration.CtSimpleType;
027: import spoon.reflect.declaration.CtType;
028: import spoon.reflect.declaration.CtTypeParameter;
029: import spoon.reflect.reference.CtArrayTypeReference;
030: import spoon.reflect.reference.CtTypeParameterReference;
031: import spoon.reflect.reference.CtTypeReference;
032:
033: /**
034: * The {@link CtType} sub-factory.
035: */
036: public class TypeFactory extends SubFactory {
037:
038: private static final long serialVersionUID = 1L;
039:
040: CtTypeReference<?> nullType;
041:
042: /**
043: * Returns a reference on the null type (type of null).
044: */
045: public CtTypeReference<?> nullType() {
046: if (nullType == null) {
047: nullType = createReference(CtTypeReference.NULL_TYPE_NAME);
048: }
049: return nullType;
050: }
051:
052: /**
053: * Creates a new type sub-factory.
054: *
055: * @param factory
056: * the parent factory
057: */
058: public TypeFactory(Factory factory) {
059: super (factory);
060: }
061:
062: /**
063: * Creates a reference to an array of given type.
064: *
065: * @param <T>
066: * type of array
067: * @param type
068: * type of array values
069: */
070: public <T> CtArrayTypeReference<T[]> createArrayReference(
071: CtSimpleType<T> type) {
072: CtArrayTypeReference<T[]> array = factory.Core()
073: .createArrayTypeReference();
074: array.setComponentType(createReference(type));
075: return array;
076: }
077:
078: /**
079: * Creates a reference to a one-dimension array of given type.
080: */
081: public <T> CtArrayTypeReference<T[]> createArrayReference(
082: CtTypeReference<T> reference) {
083: CtArrayTypeReference<T[]> array = factory.Core()
084: .createArrayTypeReference();
085: array.setComponentType(reference);
086: return array;
087: }
088:
089: /**
090: * Creates a reference to an n-dimension array of given type.
091: */
092: public CtArrayTypeReference<?> createArrayReference(
093: CtTypeReference<?> reference, int n) {
094: CtTypeReference<?> componentType = null;
095: if (n == 1) {
096: return createArrayReference(reference);
097: }
098: componentType = createArrayReference(reference, n - 1);
099: CtArrayTypeReference<?> array = factory.Core()
100: .createArrayTypeReference();
101: array.setComponentType(componentType);
102: return array;
103: }
104:
105: /**
106: * Creates a reference to an array of given type.
107: */
108: @SuppressWarnings("unchecked")
109: public <T> CtArrayTypeReference<T> createArrayReference(
110: String qualifiedName) {
111: CtArrayTypeReference<T> array = factory.Core()
112: .createArrayTypeReference();
113: array.setComponentType(createReference(qualifiedName));
114: return array;
115: }
116:
117: /**
118: * Creates a reference to a simple type
119: */
120: public <T> CtTypeReference<T> createReference(Class<T> type) {
121: if (type.isArray()) {
122: CtArrayTypeReference<T> array = factory.Core()
123: .createArrayTypeReference();
124: array.setComponentType(createReference(type
125: .getComponentType()));
126: return array;
127: }
128: return createReference(type.getName());
129: }
130:
131: /**
132: * Create a reference to a simple type
133: */
134: public <T> CtTypeReference<T> createReference(CtSimpleType<T> type) {
135: CtTypeReference<T> ref = factory.Core().createTypeReference();
136: if (type.isTopLevel()) {
137: ref.setPackage(factory.Package().createReference(
138: type.getPackage()));
139: } else {
140: if (type.getDeclaringType() != null) {
141: ref.setDeclaringType(createReference(type
142: .getDeclaringType()));
143: }
144: }
145: ref.setSimpleName(type.getSimpleName());
146: return ref;
147: }
148:
149: /**
150: * Create a reference to a simple type
151: */
152: @SuppressWarnings("unchecked")
153: public <T> CtTypeReference<T> createReference(String qualifiedName) {
154: if (qualifiedName.endsWith("[]")) {
155: return createArrayReference(qualifiedName.substring(0,
156: qualifiedName.length() - 2));
157: }
158: CtTypeReference ref = factory.Core().createTypeReference();
159: if (hasInnerType(qualifiedName) > 0) {
160: ref
161: .setDeclaringType(createReference(getDeclaringTypeName(qualifiedName)));
162: } else if (hasPackage(qualifiedName) > 0) {
163: ref.setPackage(factory.Package().createReference(
164: getPackageName(qualifiedName)));
165: }
166: ref.setSimpleName(getSimpleName(qualifiedName));
167: return ref;
168: }
169:
170: /**
171: * Gets a created type from its qualified name.
172: *
173: * @return a found type or null if does not exist
174: */
175: @SuppressWarnings("unchecked")
176: public <T> CtSimpleType<T> get(String qualifiedName) {
177: int inertTypeIndex = qualifiedName
178: .lastIndexOf(CtSimpleType.INNERTTYPE_SEPARATOR);
179: if (inertTypeIndex > 0) {
180: String s = qualifiedName.substring(0, inertTypeIndex);
181: CtSimpleType t = get(s);
182: if (t == null) {
183: return null;
184: }
185: return t.getNestedType(qualifiedName
186: .substring(inertTypeIndex + 1));
187: }
188:
189: int packageIndex = qualifiedName
190: .lastIndexOf(CtPackage.PACKAGE_SEPARATOR);
191: CtPackage pack;
192: if (packageIndex > 0) {
193: pack = factory.Package().get(
194: qualifiedName.substring(0, packageIndex));
195: } else {
196: pack = factory.Package().get(
197: CtPackage.TOP_LEVEL_PACKAGE_NAME);
198: }
199:
200: if (pack == null) {
201: return null;
202: }
203:
204: return (CtSimpleType<T>) pack.getType(qualifiedName
205: .substring(packageIndex + 1));
206: }
207:
208: /**
209: * Gets the list of all top-level created types.
210: */
211: public List<CtSimpleType<?>> getAll() {
212: List<CtSimpleType<?>> types = new ArrayList<CtSimpleType<?>>();
213: for (CtPackage pack : factory.Package().getAll()) {
214: types.addAll(pack.getTypes());
215: }
216: return types;
217: }
218:
219: /**
220: * Gets the list of all created types.
221: */
222: public List<CtSimpleType<?>> getAll(boolean includeNestedTypes) {
223: if (!includeNestedTypes) {
224: return getAll();
225: }
226: List<CtSimpleType<?>> types = new ArrayList<CtSimpleType<?>>();
227: for (CtPackage pack : factory.Package().getAll()) {
228: for (CtSimpleType<?> type : pack.getTypes()) {
229: addNestedType(types, type);
230: }
231: }
232: return types;
233: }
234:
235: private void addNestedType(List<CtSimpleType<?>> list,
236: CtSimpleType<?> t) {
237: list.add(t);
238: for (CtSimpleType<?> nt : t.getNestedTypes()) {
239: addNestedType(list, nt);
240: }
241: }
242:
243: /**
244: * Gets a type from its runtime Java class.
245: *
246: * @param <T>
247: * actual type of the class
248: * @param cl
249: * the java class: note that this class should be Class<T> but
250: * it then poses problem when T is a generic type itself
251: */
252: @SuppressWarnings("unchecked")
253: public <T> CtSimpleType<T> get(Class<?> cl) {
254: return (CtSimpleType<T>) get(cl.getName());
255: }
256:
257: /**
258: * Gets the declaring type name for a given Java qualified name.
259: */
260: protected String getDeclaringTypeName(String qualifiedName) {
261: return qualifiedName.substring(0, hasInnerType(qualifiedName));
262: }
263:
264: /**
265: * Creates a collection of type references from a collection of classes.
266: */
267: public List<CtTypeReference<?>> createReferences(
268: List<Class<?>> classes) {
269: List<CtTypeReference<?>> refs = new ArrayList<CtTypeReference<?>>();
270: for (Class<?> c : classes) {
271: refs.add(createReference(c));
272: }
273: return refs;
274: }
275:
276: /**
277: * Gets the package name for a given Java qualified name.
278: */
279: protected String getPackageName(String qualifiedName) {
280: if (hasPackage(qualifiedName) >= 0) {
281: return qualifiedName
282: .substring(0, hasPackage(qualifiedName));
283: }
284: return CtPackage.TOP_LEVEL_PACKAGE_NAME;
285: }
286:
287: /**
288: * Gets the simple name for a given Java qualified name.
289: */
290: protected String getSimpleName(String qualifiedName) {
291: if (hasInnerType(qualifiedName) > 0) {
292: return qualifiedName
293: .substring(hasInnerType(qualifiedName) + 1);
294: } else if (hasPackage(qualifiedName) > 0) {
295: return qualifiedName
296: .substring(hasPackage(qualifiedName) + 1);
297: } else {
298: return qualifiedName;
299: }
300: }
301:
302: /**
303: * Tells if a given Java qualified name is that of an inner type.
304: */
305: protected int hasInnerType(String qualifiedName) {
306: int ret = qualifiedName
307: .lastIndexOf(CtSimpleType.INNERTTYPE_SEPARATOR);
308: // if (ret < 0) {
309: // if (hasPackage(qualifiedName) > 0) {
310: // String buf = qualifiedName.substring(0,
311: // hasPackage(qualifiedName));
312: // int tmp = buf.lastIndexOf(CtPackage.PACKAGE_SEPARATOR);
313: // if (Character.isUpperCase(buf.charAt(tmp + 1))) {
314: // ret = hasPackage(qualifiedName);
315: // }
316: // }
317: // }
318: return ret;
319: }
320:
321: /**
322: * Tells if a given Java qualified name contains a package name.
323: */
324: protected int hasPackage(String qualifiedName) {
325: return qualifiedName.lastIndexOf(CtPackage.PACKAGE_SEPARATOR);
326: }
327:
328: /**
329: * Creates a type parameter with no bounds.
330: *
331: * @param owner
332: * the owning declaration
333: * @param name
334: * the name of the formal parameter
335: */
336: public CtTypeParameter createTypeParameter(CtElement owner,
337: String name) {
338: CtTypeParameter typeParam = factory.Core()
339: .createTypeParameter();
340: typeParam.setParent(owner);
341: typeParam.setName(name);
342: return typeParam;
343: }
344:
345: /**
346: * Creates a type parameter.
347: *
348: * @param owner
349: * the owning declaration
350: * @param name
351: * the name of the formal parameter
352: * @param bounds
353: * the bounds
354: */
355: public CtTypeParameter createTypeParameter(CtElement owner,
356: String name, List<CtTypeReference<?>> bounds) {
357: CtTypeParameter typeParam = factory.Core()
358: .createTypeParameter();
359: typeParam.setParent(owner);
360: typeParam.setName(name);
361: typeParam.setBounds(bounds);
362: return typeParam;
363: }
364:
365: /**
366: * Creates a type parameter reference with no bounds.
367: *
368: * @param name
369: * the name of the formal parameter
370: */
371: public CtTypeParameterReference createTypeParameterReference(
372: String name) {
373: CtTypeParameterReference typeParam = factory.Core()
374: .createTypeParameterReference();
375: typeParam.setSimpleName(name);
376: return typeParam;
377: }
378:
379: /**
380: * Creates a type parameter reference.
381: *
382: * @param name
383: * the name of the formal parameter
384: * @param bounds
385: * the bounds
386: */
387: public CtTypeParameterReference createTypeParameterReference(
388: String name, List<CtTypeReference<?>> bounds) {
389: CtTypeParameterReference typeParam = factory.Core()
390: .createTypeParameterReference();
391: typeParam.setSimpleName(name);
392: typeParam.setBounds(bounds);
393: return typeParam;
394: }
395:
396: }
|