/* * Copyright (c) 2005, 2009 Sven Efftinge 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: * Sven Efftinge - Initial API and implementation * Artem Tikhomirov (Borland) - Migration to OCL expressions */ package org.eclipse.gmf.internal.xpand; import java.util.HashSet; import java.util.Set; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.gmf.internal.xpand.model.AmbiguousDefinitionException; import org.eclipse.gmf.internal.xpand.model.AnalysationIssue; import org.eclipse.gmf.internal.xpand.model.EvaluationException; import org.eclipse.gmf.internal.xpand.model.ExecutionContext; import org.eclipse.gmf.internal.xpand.model.ExecutionContextImpl; import org.eclipse.gmf.internal.xpand.model.Scope; import org.eclipse.gmf.internal.xpand.model.Variable; import org.eclipse.gmf.internal.xpand.model.XpandDefinition; import org.eclipse.gmf.internal.xpand.model.XpandResource; import org.eclipse.gmf.internal.xpand.ocl.DeclaredParameter; /** * @author Sven Efftinge */ public class XpandFacade { private final Scope scope; private ExecutionContext ctx; public XpandFacade(Scope scope) { assert scope != null; this.scope = scope; } public XpandFacade(ExecutionContext ctx) { this(ctx.getScope()); this.ctx = ctx; } public void evaluate(final String definitionName, final Object targetObject, Object[] params) throws AmbiguousDefinitionException { params = params == null ? new Object[0] : params; final EClassifier targetType = BuiltinMetaModel.getType(getContext(), targetObject); final EClassifier[] paramTypes = new EClassifier[params.length]; for (int i = 0; i < paramTypes.length; i++) { paramTypes[i] = BuiltinMetaModel.getType(getContext(), params[i]); } final XpandDefinition def = getContext().findDefinition(definitionName, targetType, paramTypes); if (def == null) { // TODO: throw DefinitionNotFoundException from here (just like AmbiguousDefinitionException) throw new EvaluationException("No Definition " + definitionName + getParamString(paramTypes) + " for " + targetType.getName() + " could be found!"); } ExecutionContext ctx = new ExecutionContextImpl(scope); ctx = ctx.cloneWithResource(def.getOwner()); ctx = ctx.cloneWithVariable(new Variable(ExecutionContext.IMPLICIT_VARIABLE, def.getTargetType().getTypeForName(ctx), targetObject)); for (int i = 0; i < params.length; i++) { DeclaredParameter declaredParameter = def.getParams()[i]; ctx = ctx.cloneWithVariable(new Variable(declaredParameter.getVarName(), declaredParameter.getTypeForName(ctx), params[i])); } def.evaluate(ctx); } // FIXME Actually, we don't need the whole context, just currentResource(), // but that would be another story to fix. private ExecutionContext getContext() { if (ctx == null) { ctx = new ExecutionContextImpl(scope); } return ctx; } private String getParamString(final EClassifier[] paramTypes) { if (paramTypes.length == 0) { return ""; } final StringBuilder buff = new StringBuilder("("); for (int i = 0; i < paramTypes.length; i++) { final EClassifier t = paramTypes[i]; buff.append(t.getName()); if (i + 1 < paramTypes.length) { buff.append(","); } } buff.append(")"); return buff.toString(); } public AnalysationIssue[] analyze(final String templateName) { final Set<AnalysationIssue> issues = new HashSet<AnalysationIssue>(); final XpandResource tpl = scope.findTemplate(templateName); tpl.analyze(new ExecutionContextImpl(scope, tpl, null), issues); return issues.toArray(new AnalysationIssue[issues.size()]); } }