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.support.reflect.reference;
019:
020: import java.lang.annotation.Annotation;
021: import java.lang.reflect.Constructor;
022: import java.lang.reflect.Field;
023: import java.lang.reflect.Method;
024: import java.util.ArrayList;
025: import java.util.Collection;
026: import java.util.List;
027: import java.util.Set;
028: import java.util.TreeSet;
029:
030: import spoon.reflect.declaration.CtClass;
031: import spoon.reflect.declaration.CtConstructor;
032: import spoon.reflect.declaration.CtField;
033: import spoon.reflect.declaration.CtMethod;
034: import spoon.reflect.declaration.CtPackage;
035: import spoon.reflect.declaration.CtSimpleType;
036: import spoon.reflect.declaration.CtType;
037: import spoon.reflect.declaration.ModifierKind;
038: import spoon.reflect.reference.CtArrayTypeReference;
039: import spoon.reflect.reference.CtExecutableReference;
040: import spoon.reflect.reference.CtFieldReference;
041: import spoon.reflect.reference.CtPackageReference;
042: import spoon.reflect.reference.CtTypeParameterReference;
043: import spoon.reflect.reference.CtTypeReference;
044: import spoon.reflect.visitor.CtVisitor;
045: import spoon.support.util.RtHelper;
046:
047: public class CtTypeReferenceImpl<T> extends CtReferenceImpl implements
048: CtTypeReference<T> {
049: private static final long serialVersionUID = 1L;
050:
051: List<CtTypeReference<?>> actualTypeArguments = new ArrayList<CtTypeReference<?>>();
052:
053: CtTypeReference<?> declaringType;
054:
055: CtPackageReference pack;
056:
057: public CtTypeReferenceImpl() {
058: super ();
059: }
060:
061: public void accept(CtVisitor visitor) {
062: visitor.visitCtTypeReference(this );
063: }
064:
065: public CtTypeReference<?> box() {
066: if (!isPrimitive()) {
067: return this ;
068: }
069: if (getSimpleName().equals("int")) {
070: return factory.Type().createReference(Integer.class);
071: }
072: if (getSimpleName().equals("float")) {
073: return factory.Type().createReference(Float.class);
074: }
075: if (getSimpleName().equals("long")) {
076: return factory.Type().createReference(Long.class);
077: }
078: if (getSimpleName().equals("char")) {
079: return factory.Type().createReference(Character.class);
080: }
081: if (getSimpleName().equals("double")) {
082: return factory.Type().createReference(Double.class);
083: }
084: if (getSimpleName().equals("boolean")) {
085: return factory.Type().createReference(Boolean.class);
086: }
087: if (getSimpleName().equals("short")) {
088: return factory.Type().createReference(Short.class);
089: }
090: if (getSimpleName().equals("byte")) {
091: return factory.Type().createReference(Byte.class);
092: }
093: if (getSimpleName().equals("void")) {
094: return factory.Type().createReference(Void.class);
095: }
096: return this ;
097: }
098:
099: @SuppressWarnings("unchecked")
100: public Class<T> getActualClass() {
101: if (isPrimitive()) {
102: String simpleN = getSimpleName();
103: if (simpleN.equals("boolean")) {
104: return (Class<T>) boolean.class;
105: } else if (simpleN.equals("byte")) {
106: return (Class<T>) byte.class;
107: } else if (simpleN.equals("double")) {
108: return (Class<T>) double.class;
109: } else if (simpleN.equals("int")) {
110: return (Class<T>) int.class;
111: } else if (simpleN.equals("short")) {
112: return (Class<T>) short.class;
113: } else if (simpleN.equals("char")) {
114: return (Class<T>) char.class;
115: } else if (simpleN.equals("long")) {
116: return (Class<T>) long.class;
117: } else if (simpleN.equals("float")) {
118: return (Class<T>) float.class;
119: } else if (simpleN.equals("void")) {
120: return (Class<T>) void.class;
121: }
122: }
123: try {
124: return (Class<T>) Thread.currentThread()
125: .getContextClassLoader().loadClass(
126: getQualifiedName());
127: } catch (Exception e) {
128: throw new RuntimeException(e);
129: }
130: }
131:
132: public List<CtTypeReference<?>> getActualTypeArguments() {
133: return actualTypeArguments;
134: }
135:
136: @Override
137: public <A extends Annotation> A getAnnotation(
138: Class<A> annotationType) {
139: A a = super .getAnnotation(annotationType);
140: if (a == null) {
141: return getActualClass().getAnnotation(annotationType);
142: }
143: return a;
144: }
145:
146: @Override
147: public Annotation[] getAnnotations() {
148: Annotation[] a = super .getAnnotations();
149: if (a == null) {
150: return getActualClass().getAnnotations();
151: }
152: return a;
153: }
154:
155: @SuppressWarnings("unchecked")
156: public CtSimpleType<T> getDeclaration() {
157: if (!isPrimitive() && (getQualifiedName().length() > 0)) {
158: if (getFactory().Template().isTemplate(this )) {
159: return (CtSimpleType<T>) getFactory().Template().get(
160: getQualifiedName());
161: }
162: return (CtSimpleType<T>) getFactory().Type().get(
163: getQualifiedName());
164: }
165: return null;
166: }
167:
168: public CtTypeReference<?> getDeclaringType() {
169: return declaringType;
170: }
171:
172: public CtPackageReference getPackage() {
173: return pack;
174: }
175:
176: public String getQualifiedName() {
177: if (getDeclaringType() != null) {
178: return getDeclaringType().getQualifiedName()
179: + CtSimpleType.INNERTTYPE_SEPARATOR
180: + getSimpleName();
181: } else if (getPackage() != null) {
182: return getPackage().getSimpleName()
183: + CtPackage.PACKAGE_SEPARATOR + getSimpleName();
184: } else {
185: return getSimpleName();
186: }
187: }
188:
189: public boolean isAssignableFrom(CtTypeReference<?> type) {
190: if (type != null) {
191: return type.isSubtypeOf(this );
192: }
193: return false;
194: }
195:
196: public boolean isPrimitive() {
197: return (getSimpleName().equals("boolean")
198: || getSimpleName().equals("byte")
199: || getSimpleName().equals("double")
200: || getSimpleName().equals("int")
201: || getSimpleName().equals("short")
202: || getSimpleName().equals("char")
203: || getSimpleName().equals("long")
204: || getSimpleName().equals("float") || getSimpleName()
205: .equals("void"));
206: }
207:
208: public boolean isSubtypeOf(CtTypeReference<?> type) {
209: if (type instanceof CtTypeParameterReference) {
210: return false;
211: }
212: if (isPrimitive() || type.isPrimitive()) {
213: return equals(type);
214: }
215: CtSimpleType<?> t2 = type.getDeclaration();
216: CtSimpleType<?> t1 = getDeclaration();
217: if ((t1 == null) && (t2 == null)) {
218: try {
219: if (((this instanceof CtArrayTypeReference) || (type instanceof CtArrayTypeReference))) {
220: return ((CtArrayTypeReference<?>) this )
221: .getComponentType().isSubtypeOf(
222: ((CtArrayTypeReference<?>) type)
223: .getComponentType());
224: }
225: Class<?> c1 = getActualClass();
226: // Class.forName(this.getQualifiedName());
227: Class<?> c2 = type.getActualClass();
228: // Class.forName(type.getQualifiedName());
229: return c2.isAssignableFrom(c1);
230: } catch (Exception e) {
231: return false;
232: }
233: }
234: if (getQualifiedName().equals(type.getQualifiedName())) {
235: return true;
236: }
237: if (t1 != null) {
238: if (t1 instanceof CtType) {
239: for (CtTypeReference<?> ref : ((CtType<?>) t1)
240: .getSuperInterfaces()) {
241: if (ref.isSubtypeOf(type)) {
242: return true;
243: }
244: }
245: if (t1 instanceof CtClass) {
246: if (getFactory().Type().createReference(
247: Object.class).equals(type)) {
248: return true;
249: }
250: if (((CtClass<?>) t1).getSuperclass() != null) {
251: if (((CtClass<?>) t1).getSuperclass().equals(
252: type)) {
253: return true;
254: }
255: return ((CtClass<?>) t1).getSuperclass()
256: .isSubtypeOf(type);
257: }
258: }
259: }
260: return false;
261: }
262: try {
263: Class<?> c = getActualClass();
264: // Class.forName(getQualifiedName());
265: Class<?> candidate = type.getActualClass();
266: // Class.forName(type.getQualifiedName());
267: return candidate.isAssignableFrom(c);
268: } catch (Exception e) {
269: return false;
270: }
271: }
272:
273: public void setActualTypeArguments(
274: List<CtTypeReference<?>> actualTypeArguments) {
275: this .actualTypeArguments = actualTypeArguments;
276: }
277:
278: public void setDeclaringType(CtTypeReference<?> declaringType) {
279: this .declaringType = declaringType;
280: }
281:
282: public void setPackage(CtPackageReference pack) {
283: this .pack = pack;
284: }
285:
286: public CtTypeReference<?> unbox() {
287: if (!isPrimitive()) {
288: return this ;
289: }
290: if (getActualClass() == Integer.class) {
291: return factory.Type().createReference(int.class);
292: }
293: if (getActualClass() == Float.class) {
294: return factory.Type().createReference(float.class);
295: }
296: if (getActualClass() == Long.class) {
297: return factory.Type().createReference(long.class);
298: }
299: if (getActualClass() == Character.class) {
300: return factory.Type().createReference(char.class);
301: }
302: if (getActualClass() == Double.class) {
303: return factory.Type().createReference(double.class);
304: }
305: if (getActualClass() == Boolean.class) {
306: return factory.Type().createReference(boolean.class);
307: }
308: if (getActualClass() == Short.class) {
309: return factory.Type().createReference(short.class);
310: }
311: if (getActualClass() == Byte.class) {
312: return factory.Type().createReference(byte.class);
313: }
314: if (getActualClass() == Void.class) {
315: return factory.Type().createReference(void.class);
316: }
317: return this ;
318: }
319:
320: public Collection<CtFieldReference<?>> getDeclaredFields() {
321: Collection<CtFieldReference<?>> l = new ArrayList<CtFieldReference<?>>();
322: CtSimpleType<?> t = getDeclaration();
323: if (t == null) {
324: for (Field f : getActualClass().getDeclaredFields()) {
325: l.add(getFactory().Field().createReference(f));
326: }
327: if (getActualClass().isAnnotation()) {
328: for (Method m : getActualClass().getDeclaredMethods()) {
329: CtTypeReference<?> retRef = getFactory().Type()
330: .createReference(m.getReturnType());
331: CtFieldReference<?> fr = getFactory().Field()
332: .createReference(this , retRef, m.getName());
333: // fr.
334: l.add(fr);
335: }
336: }
337:
338: } else {
339: for (CtField<?> f : t.getFields()) {
340: l.add(f.getReference());
341: }
342: }
343: return l;
344: }
345:
346: public Collection<CtExecutableReference<?>> getDeclaredExecutables() {
347: Collection<CtExecutableReference<?>> l = new ArrayList<CtExecutableReference<?>>();
348: CtSimpleType<T> t = getDeclaration();
349: if (t == null) {
350: for (Method m : getActualClass().getDeclaredMethods()) {
351: l.add(getFactory().Method().createReference(m));
352: }
353: for (Constructor<?> c : getActualClass()
354: .getDeclaredConstructors()) {
355: l.add(getFactory().Constructor().createReference(c));
356: }
357: } else {
358: if (t instanceof CtType) {
359: for (CtMethod<?> m : ((CtType<?>) t).getMethods()) {
360: l.add(m.getReference());
361: }
362: }
363: if (t instanceof CtClass) {
364: for (CtConstructor<T> c : ((CtClass<T>) t)
365: .getConstructors()) {
366: l.add(c.getReference());
367: }
368: }
369: }
370: return l;
371: }
372:
373: public Collection<CtFieldReference<?>> getAllFields() {
374: Collection<CtFieldReference<?>> l = new ArrayList<CtFieldReference<?>>();
375: CtSimpleType<?> t = getDeclaration();
376: if (t == null) {
377: Class<?> c = getActualClass();
378: if (c != null) {
379: for (Field f : c.getDeclaredFields()) {
380: l.add(getFactory().Field().createReference(f));
381: }
382: Class<?> sc = c.getSuperclass();
383: if (sc != null) {
384: l.addAll(getFactory().Type().createReference(sc)
385: .getAllFields());
386: }
387: }
388: } else {
389: for (CtField<?> f : t.getFields()) {
390: l.add(f.getReference());
391: }
392: if (t instanceof CtClass) {
393: CtTypeReference<?> st = ((CtClass<?>) t)
394: .getSuperclass();
395: if (st != null) {
396: l.addAll(st.getAllFields());
397: }
398: }
399: }
400: return l;
401: }
402:
403: public Collection<CtExecutableReference<?>> getAllExecutables() {
404: Collection<CtExecutableReference<?>> l = new ArrayList<CtExecutableReference<?>>();
405: CtSimpleType<T> t = getDeclaration();
406: if (t == null) {
407: Class<?> c = getActualClass();
408: for (Method m : c.getDeclaredMethods()) {
409: l.add(getFactory().Method().createReference(m));
410: }
411: Class<?> sc = c.getSuperclass();
412: if (sc != null) {
413: l.addAll(getFactory().Type().createReference(sc)
414: .getAllExecutables());
415: }
416: } else {
417: if (t instanceof CtType) {
418: for (CtMethod<?> m : ((CtType<?>) t).getMethods()) {
419: l.add(m.getReference());
420: }
421: }
422: if (t instanceof CtClass) {
423: for (CtConstructor<T> c : ((CtClass<T>) t)
424: .getConstructors()) {
425: l.add(c.getReference());
426: }
427: CtTypeReference<?> st = ((CtClass<?>) t)
428: .getSuperclass();
429: if (st != null) {
430: l.addAll(st.getAllExecutables());
431: }
432: }
433: }
434: return l;
435: }
436:
437: //
438: // public Set<CtMethod<?>> getAllMethods() {
439: // Set<CtMethod<?>> ret = new TreeSet<CtMethod<?>>();
440: // ret.addAll(getMethods());
441: //
442: // for (CtTypeReference<?> ref : getSuperInterfaces()) {
443: // if (ref.getDeclaration() != null) {
444: // CtType<?> t = (CtType<?>) ref.getDeclaration();
445: // ret.addAll(t.getAllMethods());
446: // }
447: // }
448: // return ret;
449: // }
450:
451: public Set<ModifierKind> getModifiers() {
452: CtSimpleType<T> t = getDeclaration();
453: if (t != null) {
454: return t.getModifiers();
455: }
456: Class<T> c = getActualClass();
457: if (c != null) {
458: return RtHelper.getModifiers(c.getModifiers());
459: }
460: return new TreeSet<ModifierKind>();
461: }
462:
463: public CtTypeReference<?> getSuperclass() {
464: CtSimpleType<T> t = getDeclaration();
465: if (t != null) {
466: if (t instanceof CtClass) {
467: return ((CtClass<T>) t).getSuperclass();
468: }
469: } else {
470: Class<T> c = getActualClass();
471: if (c != null) {
472: Class<?> sc = c.getSuperclass();
473: if (sc != null) {
474: return getFactory().Type().createReference(sc);
475: }
476: }
477: }
478: return null;
479: }
480:
481: public Set<CtTypeReference<?>> getSuperInterfaces() {
482: CtSimpleType<?> t = getDeclaration();
483: if (t != null) {
484: if (t instanceof CtType) {
485: return ((CtType<?>) t).getSuperInterfaces();
486: }
487: } else {
488: Class<?> c = getActualClass();
489: if (c != null) {
490: Class<?>[] sis = c.getInterfaces();
491: if ((sis != null) && (sis.length > 0)) {
492: Set<CtTypeReference<?>> set = new TreeSet<CtTypeReference<?>>();
493: for (Class<?> si : sis) {
494: set
495: .add(getFactory().Type()
496: .createReference(si));
497: }
498: return set;
499: }
500: }
501: }
502: return new TreeSet<CtTypeReference<?>>();
503: }
504:
505: }
|