All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spoon.examples.distcalc.processing.NodeProcessor Maven / Gradle / Ivy

The newest version!
package spoon.examples.distcalc.processing;

import java.util.ArrayList;

import spoon.examples.distcalc.annotation.Node;
import spoon.examples.distcalc.template.ServicesImplTemplate;
import spoon.examples.distcalc.template._NodeImpl_;
import spoon.examples.distcalc.template._ReturnType_;
import spoon.processing.AbstractAnnotationProcessor;
import spoon.processing.Environment;
import spoon.processing.Severity;
import spoon.reflect.Factory;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtIf;
import spoon.reflect.code.CtInvocation;
import spoon.reflect.code.CtStatement;
import spoon.reflect.declaration.CtAnonymousExecutable;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtInterface;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtPackage;
import spoon.reflect.declaration.CtParameter;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.reference.CtTypeReference;
import spoon.template.Substitution;
import spoon.template.TemplateParameter;

public class NodeProcessor extends
		AbstractAnnotationProcessor> {

	public CtTypeReference getNodeInterfaceReference(CtPackage p,
			String funName) {
		return getFactory().Type().createReference(
				p.getQualifiedName() + ".Node_" + funName);
	}

	public static CtInterface getNodeInterface(Factory f, _NodeImpl_ t,
			CtPackage p, String funName) {
		CtInterface i = null;
		i = f.Interface().get(p.getQualifiedName() + ".Node_" + funName);
		if (i == null) {
			i = f.Interface().create(p, "Node_" + funName);
			i.getModifiers().add(ModifierKind.PUBLIC);
			Substitution.insertAll(i, t);
		}
		return i;
	}

	public void process(Node node, CtMethod method) {
		Factory f = method.getFactory();
		Environment env = f.getEnvironment();
		CtPackage p = method.getParent(CtPackage.class);
		CtClass c = f.Class().create(p,
				"Node_" + method.getSimpleName());
		TemplateParameter pre = null;
		CtBlock<_ReturnType_> b = f.Core().createBlock();
		CtMethod fun = null;
		for (CtStatement s : method.getBody().getStatements()) {
			if (s.getLabel() != null) {
				if (s.getLabel().equals("pre")) {
					pre = ((CtIf) s).getCondition();
				} else if (s.getLabel().equals("fun")) {
					fun = (CtMethod) ((CtInvocation) s).getExecutable()
							.getDeclaration();
				}
			} else {
				b.getStatements().add(s);
			}
		}
		if (pre == null) {
			env.report(this, Severity.ERROR, method,
					"undefined 'pre' clause in node");
			env.setProcessingStopped(true);
		} else {
			_NodeImpl_ t = new _NodeImpl_(null, getNodeInterfaceReference(p,
					fun.getSimpleName()), method.getType().getActualClass(),
					pre, b, new ArrayList>(method.getParameters()));
			Substitution.insertAll(c, t);
			CtInterface i = getNodeInterface(f, t, p, fun.getSimpleName());
			c.getSuperInterfaces().add(f.Interface().createReference(i));
			CtClass funsImpl = ServiceProcessor.getFunsImpl(f,
					(CtInterface) fun.getParent());
			c.setSuperclass(f.Type().createReference(funsImpl));

			// insert initializer
			ServicesImplTemplate ft = new ServicesImplTemplate(f.Type()
					.createReference(i), f.Type().createReference(c), null,
					Object.class, fun.getSimpleName(), null);
			CtBlock block = Substitution.substituteMethodBody(funsImpl, ft,
					"initializer");
			CtAnonymousExecutable a = f.Executable().createAnonymous(funsImpl,
					block);
			a.getModifiers().add(ModifierKind.STATIC);
		}
	}

}