diff --git a/src/main/java/spoon/template/AbstractTemplate.java b/src/main/java/spoon/template/AbstractTemplate.java index 6e7f9e68cd0..a95402e267d 100644 --- a/src/main/java/spoon/template/AbstractTemplate.java +++ b/src/main/java/spoon/template/AbstractTemplate.java @@ -19,7 +19,6 @@ import java.lang.reflect.Field; import spoon.SpoonException; -import spoon.processing.FactoryAccessor; import spoon.reflect.declaration.CtElement; import spoon.reflect.factory.Factory; import spoon.support.template.Parameters; @@ -56,16 +55,6 @@ public boolean isValid() { * returns a Spoon factory object from the first template parameter that contains one */ public Factory getFactory() { - try { - for (Field f : Parameters.getAllTemplateParameterFields(this.getClass())) { - if (f.get(this) != null && f.get(this) instanceof FactoryAccessor) { - return ((FactoryAccessor) f.get(this)).getFactory(); - } - } - } catch (Exception e) { - throw new SpoonException(e); - } - throw new TemplateException("no factory found in this template"); + return Substitution.getFactory(this); } - } diff --git a/src/main/java/spoon/template/BlockTemplate.java b/src/main/java/spoon/template/BlockTemplate.java index 8e0e6c58deb..e62ef09a1e9 100644 --- a/src/main/java/spoon/template/BlockTemplate.java +++ b/src/main/java/spoon/template/BlockTemplate.java @@ -47,8 +47,7 @@ public BlockTemplate() { } public CtBlock apply(CtType targetType) { - CtClass c; - c = targetType.getFactory().Class().get(this.getClass()); + CtClass c = Substitution.getTemplateCtClass(targetType, this); return Substitution.substitute(targetType, this, getBlock(c)); } diff --git a/src/main/java/spoon/template/ExpressionTemplate.java b/src/main/java/spoon/template/ExpressionTemplate.java index 62e42a0e053..bcc38c98a6e 100644 --- a/src/main/java/spoon/template/ExpressionTemplate.java +++ b/src/main/java/spoon/template/ExpressionTemplate.java @@ -63,10 +63,8 @@ public ExpressionTemplate() { @SuppressWarnings("unchecked") public CtExpression apply(CtType targetType) { - CtClass> c; - CtBlock b; - c = targetType.getFactory().Class().get(this.getClass()); - b = Substitution.substitute(targetType, this, getExpressionBlock(c)); + CtClass> c = Substitution.getTemplateCtClass(targetType, this); + CtBlock b = Substitution.substitute(targetType, this, getExpressionBlock(c)); return ((CtReturn) b.getStatements().get(0)).getReturnedExpression(); } diff --git a/src/main/java/spoon/template/StatementTemplate.java b/src/main/java/spoon/template/StatementTemplate.java index ecfcb96c5ad..1de5b20693c 100644 --- a/src/main/java/spoon/template/StatementTemplate.java +++ b/src/main/java/spoon/template/StatementTemplate.java @@ -16,11 +16,9 @@ */ package spoon.template; -import spoon.SpoonException; import spoon.reflect.code.CtStatement; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtType; -import spoon.reflect.factory.Factory; import spoon.support.template.SubstitutionVisitor; /** @@ -42,25 +40,10 @@ public StatementTemplate() { } public CtStatement apply(CtType targetType) { - CtClass c; - Factory factory; - - // we first need a factory - if (targetType != null) { - // if it's template with reference replacement - factory = targetType.getFactory(); - } else { - // else we have at least one template parameter with a factory - factory = getFactory(); - } - - c = factory.Class().get(this.getClass()); - if (c.isShadow()) { - throw new SpoonException("The template " + this.getClass().getName() + " is not part of model. Add template sources to spoon template path."); - } + CtClass c = Substitution.getTemplateCtClass(targetType, this); // we substitute the first statement of method statement CtStatement result = c.getMethod("statement").getBody().getStatements().get(0).clone(); - new SubstitutionVisitor(factory, targetType, this).scan(result); + new SubstitutionVisitor(c.getFactory(), targetType, this).scan(result); return result; } diff --git a/src/main/java/spoon/template/Substitution.java b/src/main/java/spoon/template/Substitution.java index ef012db9767..1d6f6feee4b 100644 --- a/src/main/java/spoon/template/Substitution.java +++ b/src/main/java/spoon/template/Substitution.java @@ -16,6 +16,8 @@ */ package spoon.template; +import spoon.SpoonException; +import spoon.processing.FactoryAccessor; import spoon.reflect.code.CtBlock; import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtStatement; @@ -29,6 +31,7 @@ import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.CtTypeMember; +import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtPackageReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.Query; @@ -36,6 +39,7 @@ import spoon.support.template.Parameters; import spoon.support.template.SubstitutionVisitor; +import java.lang.reflect.Field; import java.util.List; /** @@ -60,7 +64,7 @@ private Substitution() { */ public static > void insertAll(CtType targetType, T template) { - CtClass templateClass = targetType.getFactory().Class().get(template.getClass()); + CtClass templateClass = getTemplateCtClass(targetType, template); // insert all the interfaces for (CtTypeReference t : templateClass.getSuperInterfaces()) { if (!t.equals(targetType.getFactory().Type().createReference(Template.class))) { @@ -154,7 +158,7 @@ public static > void insertAll(CtType targetType, T tem */ public static void insertAllSuperInterfaces(CtType targetType, Template template) { - CtClass> sourceClass = targetType.getFactory().Class().get(template.getClass()); + CtClass> sourceClass = getTemplateCtClass(targetType, template); // insert all the interfaces for (CtTypeReference t : sourceClass.getSuperInterfaces()) { if (!t.equals(targetType.getFactory().Type().createReference(Template.class))) { @@ -195,7 +199,7 @@ public static void insertAllSuperInterfaces(CtType targetType, Template te */ public static void insertAllMethods(CtType targetType, Template template) { - CtClass sourceClass = targetType.getFactory().Class().get(template.getClass()); + CtClass sourceClass = getTemplateCtClass(targetType, template); // insert all the methods for (CtMethod m : sourceClass.getMethods()) { if (m.getAnnotation(Local.class) != null) { @@ -220,7 +224,7 @@ public static void insertAllMethods(CtType targetType, Template template) */ public static void insertAllFields(CtType targetType, Template template) { - CtClass sourceClass = targetType.getFactory().Class().get(template.getClass()); + CtClass sourceClass = getTemplateCtClass(targetType, template); // insert all the fields for (CtTypeMember typeMember: sourceClass.getTypeMembers()) { if (!(typeMember instanceof CtField)) { @@ -251,7 +255,7 @@ public static void insertAllFields(CtType targetType, Template template) { */ public static void insertAllConstructors(CtType targetType, Template template) { - CtClass sourceClass = targetType.getFactory().Class().get(template.getClass()); + CtClass sourceClass = getTemplateCtClass(targetType, template); // insert all the constructors if (targetType instanceof CtClass) { for (CtConstructor c : sourceClass.getConstructors()) { @@ -368,7 +372,7 @@ public static CtConstructor insertConstructor(CtClass targetClass, Tem * the template parameters substituted */ public static CtBlock substituteMethodBody(CtClass targetClass, Template template, String executableName, CtTypeReference... parameterTypes) { - CtClass sourceClass = targetClass.getFactory().Class().get(template.getClass()); + CtClass sourceClass = getTemplateCtClass(targetClass, template); CtExecutable sourceExecutable = executableName.equals(template.getClass().getSimpleName()) ? sourceClass.getConstructor(parameterTypes) : sourceClass.getMethod(executableName, parameterTypes); @@ -393,7 +397,7 @@ public static CtBlock substituteMethodBody(CtClass targetClass, Template targetClass, Template template, int statementIndex, String executableName, CtTypeReference... parameterTypes) { - CtClass sourceClass = targetClass.getFactory().Class().get(template.getClass()); + CtClass sourceClass = getTemplateCtClass(targetClass, template); CtExecutable sourceExecutable = executableName.equals(template.getClass().getSimpleName()) ? sourceClass.getConstructor(parameterTypes) : sourceClass.getMethod(executableName, parameterTypes); @@ -415,7 +419,7 @@ public static CtStatement substituteStatement(CtClass targetClass, Template substituteFieldDefaultExpression(CtType targetType, Template template, String fieldName) { - CtClass sourceClass = targetType.getFactory().Class().get(template.getClass()); + CtClass sourceClass = getTemplateCtClass(targetType, template); CtField sourceField = sourceClass.getField(fieldName); return substitute(targetType, template, sourceField.getDefaultExpression()); } @@ -533,4 +537,55 @@ public static void redirectTypeReferences(CtElement element, CtTypeReference } } + /** + * @param targetType - the element which is going to receive the model produced by the template. + * It is needed here just to provide the spoon factory, which contains the model of the template + * + * @param template - java instance of the template + * + * @return - CtClass from the already built spoon model, which represents the template + */ + static CtClass getTemplateCtClass(CtType targetType, Template template) { + Factory factory; + // we first need a factory + if (targetType != null) { + // if it's template with reference replacement + factory = targetType.getFactory(); + } else { + // else we have at least one template parameter with a factory + factory = getFactory(template); + } + return getTemplateCtClass(factory, template); + } + + /** + * @param factory - the factory, which contains the model of the template + * + * @param template - java instance of the template + * + * @return - CtClass from the already built spoon model, which represents the template + */ + static CtClass getTemplateCtClass(Factory factory, Template template) { + CtClass c = factory.Class().get(template.getClass()); + if (c.isShadow()) { + throw new SpoonException("The template " + template.getClass().getName() + " is not part of model. Add template sources to spoon template path."); + } + return c; + } + + /** + * returns a Spoon factory object from the first template parameter that contains one + */ + static Factory getFactory(Template template) { + try { + for (Field f : Parameters.getAllTemplateParameterFields(template.getClass())) { + if (f.get(template) != null && f.get(template) instanceof FactoryAccessor) { + return ((FactoryAccessor) f.get(template)).getFactory(); + } + } + } catch (Exception e) { + throw new SpoonException(e); + } + throw new TemplateException("no factory found in template " + template.getClass().getName()); + } }