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;
019:
020: import java.io.Serializable;
021: import java.lang.reflect.Array;
022: import java.util.ArrayList;
023: import java.util.Collection;
024:
025: import spoon.processing.Builder;
026: import spoon.processing.Environment;
027: import spoon.reflect.cu.CompilationUnit;
028: import spoon.reflect.declaration.CtAnnotationType;
029: import spoon.reflect.declaration.CtClass;
030: import spoon.reflect.declaration.CtConstructor;
031: import spoon.reflect.declaration.CtEnum;
032: import spoon.reflect.declaration.CtExecutable;
033: import spoon.reflect.declaration.CtField;
034: import spoon.reflect.declaration.CtInterface;
035: import spoon.reflect.declaration.CtMethod;
036: import spoon.reflect.declaration.CtPackage;
037: import spoon.reflect.declaration.CtType;
038: import spoon.reflect.factory.AnnotationFactory;
039: import spoon.reflect.factory.ClassFactory;
040: import spoon.reflect.factory.CodeFactory;
041: import spoon.reflect.factory.CompilationUnitFactory;
042: import spoon.reflect.factory.ConstructorFactory;
043: import spoon.reflect.factory.EnumFactory;
044: import spoon.reflect.factory.EvalFactory;
045: import spoon.reflect.factory.ExecutableFactory;
046: import spoon.reflect.factory.FieldFactory;
047: import spoon.reflect.factory.InterfaceFactory;
048: import spoon.reflect.factory.MethodFactory;
049: import spoon.reflect.factory.PackageFactory;
050: import spoon.reflect.factory.TemplateFactory;
051: import spoon.reflect.factory.TypeFactory;
052: import spoon.reflect.reference.CtExecutableReference;
053: import spoon.reflect.reference.CtFieldReference;
054: import spoon.reflect.reference.CtPackageReference;
055: import spoon.reflect.reference.CtReference;
056: import spoon.reflect.reference.CtTypeReference;
057: import spoon.support.DefaultCoreFactory;
058: import spoon.support.StandardEnvironment;
059: import spoon.support.builder.SpoonBuildingManager;
060:
061: /**
062: * This class defines the entry point API to create and access the program's
063: * model. Element-specific methods are defined in the sub-factories. An instance
064: * of the current factory can be retrieved at any place where a
065: * {@link spoon.processing.FactoryAccessor} instance is available (that is to
066: * say, any processor or model element). Factory methods ensure the model's
067: * consistency and should be always used when creating model elements. The
068: * {@link spoon.reflect.CoreFactory} is used to create raw elements, but model
069: * consistency has to be maintained manually.
070: *
071: * @see spoon.processing.Processor
072: * @see spoon.reflect.declaration.CtElement
073: * @see spoon.reflect.CoreFactory
074: * @see #Core()
075: */
076: public class Factory implements Serializable {
077:
078: private static final long serialVersionUID = 1L;
079:
080: private transient AnnotationFactory Annotation;
081:
082: /**
083: * The {@link CtAnnotationType} sub-factory.
084: */
085: public AnnotationFactory Annotation() {
086: if (Annotation == null) {
087: Annotation = new AnnotationFactory(this );
088: }
089: return Annotation;
090: }
091:
092: private transient ClassFactory Class;
093:
094: /**
095: * The {@link CtClass} sub-factory.
096: */
097: public ClassFactory Class() {
098: if (Class == null) {
099: Class = new ClassFactory(this );
100: }
101: return Class;
102: }
103:
104: private transient CodeFactory Code;
105:
106: /**
107: * The {@link spoon.reflect.code.CtCodeElement} sub-factory.
108: */
109: public CodeFactory Code() {
110: if (Code == null) {
111: Code = new CodeFactory(this );
112: }
113: return Code;
114: }
115:
116: private transient ConstructorFactory Constructor;
117:
118: /**
119: * The {@link CtConstructor} sub-factory.
120: */
121: public ConstructorFactory Constructor() {
122: if (Constructor == null) {
123: Constructor = new ConstructorFactory(this );
124: }
125: return Constructor;
126: }
127:
128: private transient CoreFactory Core;
129:
130: /**
131: * The core factory.
132: */
133: public CoreFactory Core() {
134: if (Core == null) {
135: Core = new DefaultCoreFactory();
136: }
137: return Core;
138: }
139:
140: private transient EnumFactory Enum;
141:
142: /**
143: * The {@link CtEnum} sub-factory.
144: */
145: public EnumFactory Enum() {
146: if (Enum == null) {
147: Enum = new EnumFactory(this );
148: }
149: return Enum;
150: }
151:
152: private transient Environment Environment;
153:
154: /**
155: * Gets the Spoon environment that encloses this factory.
156: */
157: public Environment getEnvironment() {
158: if (Environment == null) {
159: Environment = new StandardEnvironment();
160: }
161: return Environment;
162: }
163:
164: private transient ExecutableFactory Executable;
165:
166: /**
167: * The {@link CtExecutable} sub-factory.
168: */
169: public ExecutableFactory Executable() {
170: if (Executable == null) {
171: Executable = new ExecutableFactory(this );
172: }
173: return Executable;
174: }
175:
176: private transient EvalFactory Eval;
177:
178: /**
179: * The evaluators sub-factory.
180: */
181: public EvalFactory Eval() {
182: if (Eval == null) {
183: Eval = new EvalFactory(this );
184: }
185: return Eval;
186: }
187:
188: private transient FieldFactory Field;
189:
190: /**
191: * The {@link CtField} sub-factory.
192: */
193: public FieldFactory Field() {
194: if (Field == null) {
195: Field = new FieldFactory(this );
196: }
197: return Field;
198: }
199:
200: /**
201: * The {@link CtInterface} sub-factory.
202: */
203: private transient InterfaceFactory Interface;
204:
205: /**
206: * The {@link CtInterface} sub-factory.
207: */
208: public InterfaceFactory Interface() {
209: if (Interface == null) {
210: Interface = new InterfaceFactory(this );
211: }
212: return Interface;
213: }
214:
215: private transient MethodFactory Method;
216:
217: /**
218: * The {@link CtMethod} sub-factory.
219: */
220: public MethodFactory Method() {
221: if (Method == null) {
222: Method = new MethodFactory(this );
223: }
224: return Method;
225: }
226:
227: private PackageFactory Package;
228:
229: /**
230: * The {@link CtPackage} sub-factory.
231: */
232: public PackageFactory Package() {
233: if (Package == null) {
234: Package = new PackageFactory(this );
235: }
236: return Package;
237: }
238:
239: private CompilationUnitFactory CompilationUnit;
240:
241: /**
242: * The {@link CompilationUnit} sub-factory.
243: */
244: public CompilationUnitFactory CompilationUnit() {
245: if (CompilationUnit == null) {
246: CompilationUnit = new CompilationUnitFactory(this );
247: }
248: return CompilationUnit;
249: }
250:
251: private TemplateFactory Template;
252:
253: /**
254: * The {@link CtPackage} sub-factory.
255: */
256: public TemplateFactory Template() {
257: if (Template == null) {
258: Template = new TemplateFactory(this );
259: }
260: return Template;
261: }
262:
263: private transient TypeFactory Type;
264:
265: /**
266: * The {@link CtType} sub-factory.
267: */
268: public TypeFactory Type() {
269: if (Type == null) {
270: Type = new TypeFactory(this );
271: }
272: return Type;
273: }
274:
275: private Factory() {
276: super ();
277: if (launchingFactory == null)
278: launchingFactory = this ;
279: }
280:
281: static Factory launchingFactory;
282:
283: /**
284: * Gets the factory that was created at launching time (the firstly created
285: * factory). This factory is automatically initialized when a factory is
286: * contructed for the first time. Any subsequent constructions will not
287: * affect the launching factory and references to other factories have to be
288: * handled manually, if ever needed.
289: */
290: public static Factory getLauchingFactory() {
291: return launchingFactory;
292: }
293:
294: /**
295: * The constructor.
296: */
297: public Factory(CoreFactory coreFactory, Environment environment) {
298: this ();
299: this .Environment = environment;
300: environment.setFactory(this );
301: this .Core = coreFactory;
302: this .Core.setMainFactory(this );
303: }
304:
305: /**
306: * The builder associated to this factory.
307: */
308: protected transient Builder builder;
309:
310: /**
311: * Returns a builder for this factory (creates it if not existing yet).
312: */
313: public Builder getBuilder() {
314: if (builder == null)
315: builder = new SpoonBuildingManager(this );
316: return builder;
317: }
318:
319: /**
320: * Converts an object <code>o</code> into an object or a
321: * {@link CtReference} of type </code>type<code>.
322: *
323: * @param <T>
324: * the actual type of the object
325: * @param type
326: * the type to convert the object into
327: * @param o
328: * the object to be converted
329: * @return a primitive object of type T, or a reference
330: */
331: @SuppressWarnings("unchecked")
332: public <T> T convert(Class<T> type, Object o) {
333: if (o == null)
334: return null;
335: if (type == boolean.class)
336: return (T) new Boolean(o.toString());
337: if (type == byte.class)
338: return (T) new Byte(o.toString());
339: if (type == char.class)
340: return (T) new Character(o.toString().charAt(0));
341: if (type == double.class)
342: return (T) new Double(o.toString());
343: if (type == float.class)
344: return (T) new Float(o.toString());
345: if (type == int.class)
346: return (T) new Integer(o.toString());
347: if (type == long.class)
348: return (T) new Long(o.toString());
349: if (CtTypeReference.class.isAssignableFrom(type)) {
350: return (T) Type().createReference(o.toString());
351: }
352: if (CtExecutableReference.class.isAssignableFrom(type)) {
353: return (T) Executable().createReference(o.toString());
354: }
355: if (CtFieldReference.class.isAssignableFrom(type)) {
356: return (T) Field().createReference(o.toString());
357: }
358: if (CtPackageReference.class.isAssignableFrom(type)) {
359: return (T) Package().createReference(o.toString());
360: }
361: if (type.isEnum()) {
362: return (T) java.lang.Enum.valueOf((Class<Enum>) type, o
363: .toString());
364: }
365: return (T) o.toString();
366: }
367:
368: /**
369: * Converts a collection of object into an array of type </code>type<code>.
370: *
371: * @param <T>
372: * the actual type of the array
373: * @param type
374: * the type to convert the object into
375: * @param val
376: * the collection to be converted
377: * @return an array of type T
378: */
379: @SuppressWarnings("unchecked")
380: public <T> T convertArray(Class<T> type, Collection<Object> val) {
381: if (type.equals(boolean.class)) {
382: boolean[] ret = new boolean[val.size()];
383: int i = 0;
384: for (Object o : val) {
385: ret[i++] = convert(boolean.class, o);
386: }
387: return (T) ret;
388: } else if (type.equals(byte.class)) {
389: byte[] ret = new byte[val.size()];
390: int i = 0;
391: for (Object o : val) {
392: ret[i++] = convert(byte.class, o);
393: }
394: return (T) ret;
395: } else if (type.equals(char.class)) {
396: char[] ret = new char[val.size()];
397: int i = 0;
398: for (Object o : val) {
399: ret[i++] = convert(char.class, o);
400: }
401: return (T) ret;
402: } else if (type.equals(double.class)) {
403: double[] ret = new double[val.size()];
404: int i = 0;
405: for (Object o : val) {
406: ret[i++] = convert(double.class, o);
407: }
408: return (T) ret;
409: } else if (type.equals(float.class)) {
410: float[] ret = new float[val.size()];
411: int i = 0;
412: for (Object o : val) {
413: ret[i++] = convert(float.class, o);
414: }
415: return (T) ret;
416: } else if (type.equals(int.class)) {
417: int[] ret = new int[val.size()];
418: int i = 0;
419: for (Object o : val) {
420: ret[i++] = convert(int.class, o);
421: }
422: return (T) ret;
423: } else if (type.equals(long.class)) {
424: long[] ret = new long[val.size()];
425: int i = 0;
426: for (Object o : val) {
427: ret[i++] = convert(long.class, o);
428: }
429: return (T) ret;
430: } else if (type.equals(String.class)) {
431: String[] ret = new String[val.size()];
432: int i = 0;
433: for (Object o : val) {
434: ret[i++] = convert(String.class, o);
435: }
436: return (T) ret;
437: } else if (CtPackageReference.class.isAssignableFrom(type)) {
438: CtPackageReference[] ret = new CtPackageReference[val
439: .size()];
440: int i = 0;
441: for (Object o : val) {
442: ret[i++] = convert(CtPackageReference.class, o);
443: }
444: return (T) ret;
445: } else if (CtTypeReference.class.isAssignableFrom(type)) {
446: CtTypeReference[] ret = new CtTypeReference[val.size()];
447: int i = 0;
448: for (Object o : val) {
449: ret[i++] = convert(CtTypeReference.class, o);
450: }
451: return (T) ret;
452: } else if (CtFieldReference.class.isAssignableFrom(type)) {
453: CtFieldReference[] ret = new CtFieldReference[val.size()];
454: int i = 0;
455: for (Object o : val) {
456: ret[i++] = convert(CtFieldReference.class, o);
457: }
458: return (T) ret;
459: } else if (CtExecutableReference.class.isAssignableFrom(type)) {
460: CtExecutableReference[] ret = new CtExecutableReference[val
461: .size()];
462: int i = 0;
463: for (Object o : val) {
464: ret[i++] = convert(CtExecutableReference.class, o);
465: }
466: return (T) ret;
467: } else if (type.isEnum()) {
468: Collection<Enum<?>> ret = new ArrayList<Enum<?>>();
469: for (Object o : val) {
470: ret.add((Enum) convert(type, o));
471: }
472: return (T) ret.toArray((Enum[]) Array.newInstance(type, 0));
473: }
474: return null;
475: }
476:
477: }
|