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.reflect.Method;
021: import java.util.ArrayList;
022: import java.util.Arrays;
023: import java.util.Collection;
024: import java.util.List;
025: import java.util.Set;
026:
027: import spoon.reflect.Factory;
028: import spoon.reflect.code.CtBlock;
029: import spoon.reflect.declaration.CtClass;
030: import spoon.reflect.declaration.CtMethod;
031: import spoon.reflect.declaration.CtParameter;
032: import spoon.reflect.declaration.CtSimpleType;
033: import spoon.reflect.declaration.CtType;
034: import spoon.reflect.declaration.ModifierKind;
035: import spoon.reflect.reference.CtExecutableReference;
036: import spoon.reflect.reference.CtTypeReference;
037: import spoon.template.Substitution;
038:
039: /**
040: * The {@link CtMethod} sub-factory.
041: */
042: public class MethodFactory extends ExecutableFactory {
043:
044: private static final long serialVersionUID = 1L;
045:
046: /**
047: * Creates a new method sub-factory.
048: *
049: * @param factory
050: * the parent factory
051: */
052: public MethodFactory(Factory factory) {
053: super (factory);
054: }
055:
056: /**
057: * Creates a method.
058: *
059: * @param target
060: * the class where the method is inserted
061: * @param modifiers
062: * the modifiers
063: * @param returnType
064: * the method's return type
065: * @param name
066: * the method's name
067: * @param parameters
068: * the parameters
069: * @param thrownTypes
070: * the thrown types
071: * @param body
072: * the method's body
073: */
074: public <R, B extends R> CtMethod<R> create(CtClass<?> target,
075: Set<ModifierKind> modifiers, CtTypeReference<R> returnType,
076: String name, List<CtParameter<?>> parameters,
077: Set<CtTypeReference<? extends Throwable>> thrownTypes,
078: CtBlock<B> body) {
079: CtMethod<R> method = create(target, modifiers, returnType,
080: name, parameters, thrownTypes);
081: method.setBody(body);
082: body.setParent(method);
083: return method;
084: }
085:
086: /**
087: * Creates a method by copying an existing method.
088: *
089: * @param <T>
090: * the type of the method
091: * @param target
092: * the target type where the new method has to be inserted to
093: * @param source
094: * the source method to be copied
095: * @param redirectReferences
096: * tells if all the references to the owning type of the source
097: * method should be redirected to the target type (true is
098: * recommended for most uses)
099: * @return the newly created method
100: */
101: public <T> CtMethod<T> create(CtType<?> target, CtMethod<T> source,
102: boolean redirectReferences) {
103: CtMethod<T> newMethod = factory.Core().clone(source);
104: if (redirectReferences && (source.getDeclaringType() != null)) {
105: Substitution.redirectTypeReferences(newMethod, source
106: .getDeclaringType().getReference(), target
107: .getReference());
108: }
109: target.getMethods().add(newMethod);
110: newMethod.setParent(target);
111: return newMethod;
112: }
113:
114: /**
115: * Creates an empty method.
116: *
117: * @param target
118: * the class where the method is inserted
119: * @param modifiers
120: * the modifiers
121: * @param returnType
122: * the method's return type
123: * @param name
124: * the method's name
125: * @param parameters
126: * the parameters
127: * @param thrownTypes
128: * the thrown types
129: */
130: public <T> CtMethod<T> create(CtType<?> target,
131: Set<ModifierKind> modifiers, CtTypeReference<T> returnType,
132: String name, List<CtParameter<?>> parameters,
133: Set<CtTypeReference<? extends Throwable>> thrownTypes) {
134: CtMethod<T> method = factory.Core().createMethod();
135: target.getMethods().add(method);
136: method.setParent(target);
137: if (modifiers != null) {
138: method.setModifiers(modifiers);
139: }
140: method.setType(returnType);
141: method.setSimpleName(name);
142: if (parameters != null) {
143: method.setParameters(parameters);
144: }
145: setParent(method, parameters);
146: if (thrownTypes != null) {
147: method.setThrownTypes(thrownTypes);
148: }
149: return method;
150: }
151:
152: /**
153: * Creates a method reference.
154: */
155: public <T> CtExecutableReference<T> createReference(CtMethod<T> m) {
156: return factory.Executable().createReference(m);
157: }
158:
159: /**
160: * Creates a method reference from an actual method.
161: */
162: @SuppressWarnings("unchecked")
163: public <T> CtExecutableReference<T> createReference(Method method) {
164: return createReference(factory.Type().createReference(
165: method.getDeclaringClass()),
166: (CtTypeReference<T>) factory.Type().createReference(
167: method.getReturnType()), method.getName(),
168: factory.Type().createReferences(
169: Arrays.asList(method.getParameterTypes()))
170: .toArray(new CtTypeReference<?>[0]));
171: }
172:
173: /**
174: * Gets all the main methods stored in this factory.
175: */
176: public Collection<CtMethod<Void>> getMainMethods() {
177: Collection<CtMethod<Void>> methods = new ArrayList<CtMethod<Void>>();
178: for (CtSimpleType<?> t : factory.Type().getAll()) {
179: if (t instanceof CtClass) {
180: CtMethod<Void> m = ((CtClass<?>) t).getMethod(factory
181: .Type().createReference(void.class), "main",
182: factory.Type().createArrayReference(
183: factory.Type().createReference(
184: String.class)));
185: if ((m != null)
186: && m.getModifiers().contains(
187: ModifierKind.STATIC)) {
188: methods.add(m);
189: }
190: }
191: }
192: return methods;
193: }
194:
195: }
|