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.lang.annotation.Annotation;
021: import java.lang.reflect.Method;
022: import java.util.Arrays;
023: import java.util.Collection;
024: import java.util.List;
025:
026: import spoon.reflect.Factory;
027: import spoon.reflect.declaration.CtAnnotation;
028: import spoon.reflect.declaration.CtAnnotationType;
029: import spoon.reflect.declaration.CtElement;
030: import spoon.reflect.declaration.CtField;
031: import spoon.reflect.declaration.CtPackage;
032: import spoon.reflect.reference.CtArrayTypeReference;
033: import spoon.reflect.reference.CtTypeReference;
034:
035: /**
036: * The {@link CtAnnotationType} sub-factory.
037: */
038: public class AnnotationFactory extends TypeFactory {
039:
040: private static final long serialVersionUID = 1L;
041:
042: /**
043: * Creates an annotation sub-factory.
044: *
045: * @param factory
046: * the parent factory
047: */
048: public AnnotationFactory(Factory factory) {
049: super (factory);
050: }
051:
052: /**
053: * Creates an annotation type.
054: *
055: * @param owner
056: * the package of the annotation type
057: * @param simpleName
058: * the name of annotation
059: */
060: public <T extends Annotation> CtAnnotationType<?> create(
061: CtPackage owner, String simpleName) {
062: CtAnnotationType<T> t = factory.Core().createAnnotationType();
063: t.setSimpleName(simpleName);
064: owner.getTypes().add(t);
065: t.setParent(owner);
066: return t;
067: }
068:
069: /**
070: * Creates an annotation type.
071: *
072: * @param qualifiedName
073: * the fully qualified name of the annotation type.
074: */
075: public CtAnnotationType<?> create(String qualifiedName) {
076: return create(factory.Package().getOrCreate(
077: getPackageName(qualifiedName)),
078: getSimpleName(qualifiedName));
079: }
080:
081: /**
082: * Gets a annotation type from its name.
083: */
084: @SuppressWarnings("unchecked")
085: public <T extends Annotation> CtAnnotationType<T> getAnnotationType(
086: String qualifiedName) {
087: return (CtAnnotationType) super .get(qualifiedName);
088: }
089:
090: /**
091: * Creates/updates an element's annotation value.
092: *
093: * @param element
094: * the program element to annotate
095: * @param annotationType
096: * the annotation type
097: * @param annotationElementName
098: * the annotation element name
099: * @param value
100: * the value of the annotation element
101: * @return the created/updated annotation
102: */
103: @SuppressWarnings("unchecked")
104: public <A extends Annotation> CtAnnotation<A> annotate(
105: CtElement element, CtTypeReference<A> annotationType,
106: String annotationElementName, Object value) {
107: return annotate(element, annotationType.getActualClass(),
108: annotationElementName, value);
109: }
110:
111: /**
112: * Creates/updates an element's annotation value.
113: *
114: * @param element
115: * the program element to annotate
116: * @param annotationType
117: * the annotation type
118: * @param annotationElementName
119: * the annotation element name
120: * @param value
121: * the value of the annotation element
122: * @return the created/updated annotation
123: */
124: @SuppressWarnings("unchecked")
125: public <A extends Annotation> CtAnnotation<A> annotate(
126: CtElement element, Class<A> annotationType,
127: String annotationElementName, Object value) {
128: CtAnnotation annotation = element.getAnnotation(factory.Type()
129: .createReference(annotationType));
130: if (annotation == null) {
131: annotation = factory.Core().createAnnotation();
132: annotation.setAnnotationType(factory.Type()
133: .createReference(annotationType));
134: element.getAnnotations().add(annotation);
135: annotation.setParent(element);
136: }
137: boolean isArray;
138:
139: // try with CT reflexion
140: CtAnnotationType annotationtype = ((CtAnnotationType) annotation
141: .getAnnotationType().getDeclaration());
142: if (annotationtype != null) {
143: CtField e = annotationtype.getField(annotationElementName);
144: isArray = (e.getType() instanceof CtArrayTypeReference);
145: } else {
146: Method m = null;
147: try {
148: m = annotation.getAnnotationType().getActualClass()
149: .getMethod(annotationElementName, new Class[0]);
150: } catch (Exception ex) {
151: throw new RuntimeException("undefined element '"
152: + annotationElementName + "' for annotation '"
153: + annotationType.getName() + "'");
154: }
155: isArray = m.getReturnType().isArray();
156: }
157: if (isArray == ((value instanceof Collection) || value
158: .getClass().isArray())) {
159: if (value.getClass().isArray()) {
160: value = Arrays.asList(value);
161: }
162: annotation.getElementValues().put(annotationElementName,
163: value);
164: } else {
165: if (isArray) {
166: ((List) annotation
167: .getElementValue(annotationElementName))
168: .add(value);
169: } else {
170: throw new RuntimeException(
171: "cannot assing an array to a non-array annotation element");
172: }
173:
174: }
175: return annotation;
176: }
177:
178: /**
179: * Adds an annotation to an element.
180: *
181: * @param element
182: * the program element to annotate
183: * @param annotationType
184: * the annotation type
185: * @return the concerned annotation
186: */
187: public <A extends Annotation> CtAnnotation<A> annotate(
188: CtElement element, CtTypeReference<A> annotationType) {
189: return annotate(element, annotationType.getActualClass());
190: }
191:
192: /**
193: * Adds an annotation to an element.
194: *
195: * @param element
196: * the program element to annotate
197: * @param annotationType
198: * the annotation type
199: * @return the concerned annotation
200: */
201: public <A extends Annotation> CtAnnotation<A> annotate(
202: CtElement element, Class<A> annotationType) {
203: CtAnnotation<A> annotation = element.getAnnotation(factory
204: .Type().createReference(annotationType));
205: if (annotation == null) {
206: annotation = factory.Core().createAnnotation();
207: annotation.setAnnotationType(factory.Type()
208: .createReference(annotationType));
209: element.getAnnotations().add(annotation);
210: annotation.setParent(element);
211: }
212: return annotation;
213: }
214:
215: }
|