/******************************************************************************* * Copyright (c) 2005, 2009 committers of openArchitectureWare and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * committers of openArchitectureWare - initial API and implementation *******************************************************************************/ package org.eclipse.internal.xpand2.ast; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.internal.xpand2.model.XpandDefinition; import org.eclipse.internal.xpand2.model.XpandResource; import org.eclipse.internal.xtend.expression.ast.DeclaredParameter; import org.eclipse.internal.xtend.expression.ast.Identifier; import org.eclipse.internal.xtend.expression.ast.SyntaxElement; import org.eclipse.xpand2.XpandExecutionContext; import org.eclipse.xtend.expression.AnalysationIssue; import org.eclipse.xtend.expression.ExecutionContext; import org.eclipse.xtend.expression.Variable; import org.eclipse.xtend.typesystem.Type; public abstract class AbstractDefinition extends SyntaxElement implements XpandDefinition { private Template owner = null; private DeclaredParameter[] params; private Identifier name; private Identifier type; private Statement[] body; protected String _stringRepresentation = null; protected boolean wildParams = false; public AbstractDefinition(final Identifier name, final Identifier type, final DeclaredParameter[] params, final Statement[] body) { this.name = name; this.type = type; this.params = params; this.body = body; } public XpandResource getOwner() { return owner; } public void setOwner(final Template owner) { this.owner = owner; } public DeclaredParameter[] getParams() { return params; } public List<DeclaredParameter> getParamsAsList() { return Arrays.asList(params); } public Identifier getType() { return type; } public String getTargetType() { return type.getValue(); } public Identifier getDefName() { return name; } public String getName() { return name.getValue(); } public String getQualifiedName() { if (getFileName() != null) { String prefix = getFileName().replaceAll("/", "::"); prefix = prefix.substring(0, prefix.length() - 4); return prefix + "::" + getName(); } return getName(); } public String getParamString(boolean typesOnly) { if (params == null || params.length == 0) return wildParams ? "(*)" : ""; final StringBuilder buff = new StringBuilder("("); for (int i = 0; i < params.length; i++) { final DeclaredParameter p = params[i]; buff.append(p.getType().getValue()); if (!typesOnly) { buff.append(" ").append(p.getName().getValue()); } if (i + 1 < params.length) { buff.append(","); } } if (wildParams) { buff.append(",*"); } return buff.append(")").toString(); } public Statement[] getBody() { return body; } public List<Statement> getBodyAsList() { return Arrays.asList(body); } public void analyze(XpandExecutionContext ctx, final Set<AnalysationIssue> issues) { try { if (ctx.getCallback() != null) { if(!ctx.getCallback().pre(this, ctx)) { return; } } final Type thisType = ctx.getTypeForName(getType().getValue()); if (thisType == null) { issues.add(new AnalysationIssue(AnalysationIssue.TYPE_NOT_FOUND, "Couldn't find " + getType().getValue(), getType())); } ctx = (XpandExecutionContext) ctx.cloneWithVariable(new Variable(ExecutionContext.IMPLICIT_VARIABLE, thisType)); for (int i = 0; i < params.length; i++) { final DeclaredParameter param = params[i]; Type paramType = ctx.getTypeForName(param.getType().getValue()); if (paramType == null) { issues.add(new AnalysationIssue(AnalysationIssue.TYPE_NOT_FOUND, "Couldn't find " + param.getType().getValue(), param.getType())); paramType = ctx.getObjectType(); } final String name = param.getName().getValue(); ctx = (XpandExecutionContext) ctx.cloneWithVariable(new Variable(name, paramType)); } for (int i = 0; i < getBody().length; i++) { Statement stmt = getBody()[i]; try { stmt.analyze(ctx, issues); } catch (RuntimeException ex) { Map<String, Object> info = new HashMap<String, Object>(); info.put("body", stmt); ctx.handleRuntimeException(ex, this, info); } } } finally { if (ctx.getCallback() != null) { ctx.getCallback().post(this, ctx, null); } } } public void evaluate(XpandExecutionContext ctx, Object _this, Object...params) { try { ctx = (XpandExecutionContext) ctx.cloneWithResource(getOwner()); ctx = prepareDeclaredParameters(_this, ctx, params); if (ctx.getCallback() != null) { if (!ctx.getCallback().pre(this, ctx)) { return; } } for (int i = 0; i < getBody().length; i++) { Statement stmt = getBody()[i]; try { stmt.evaluate(ctx); } catch (RuntimeException ex) { Map<String, Object> info = new HashMap<String, Object>(); info.put("body", stmt); ctx.handleRuntimeException(ex, this, info); } } } finally { if (ctx.getCallback() != null) { ctx.getCallback().post(this, ctx, null); } } } protected XpandExecutionContext prepareDeclaredParameters(Object _this, XpandExecutionContext context, Object... params) { if (_this != null) { context = (XpandExecutionContext) context.cloneWithVariable(new Variable( ExecutionContext.IMPLICIT_VARIABLE, _this)); } if (params != null) { DeclaredParameter[] params2 = getParams(); for (int i = 0, x = params2.length; i < x;i++) { final Object o = params[i]; final String name = params2[i].getName().getValue(); context = (XpandExecutionContext) context.cloneWithVariable(new Variable(name, o)); } } return context; } @Override public String toString() { if (_stringRepresentation == null) { _stringRepresentation = name.getValue() + getParamString(false) + " : " + getType().getValue(); } return _stringRepresentation; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((toString() == null) ? 0 : toString().hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || toString() == null) return false; if (getClass() != obj.getClass()) return false; AbstractDefinition other = (AbstractDefinition) obj; return toString().equals(other.toString()); } }