| /******************************************************************************* |
| * Copyright (c) 2004-2008 Peter Pasztor, Akos Horvath, Gergely Varro, Istvan Rath and Daniel Varro |
| * 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: |
| * Peter Pasztor, Akos Horvath, Gergely Varro, Istvan Rath - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.viatra2.gtasm.interpreter.term.rules; |
| |
| import java.util.Vector; |
| |
| import org.eclipse.emf.common.util.BasicEList; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.viatra2.core.IModelSpace; |
| import org.eclipse.viatra2.errors.VPMRuntimeException; |
| import org.eclipse.viatra2.gtasm.interpreter.exception.ViatraTransformationException; |
| import org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment; |
| import org.eclipse.viatra2.gtasm.interpreter.term.internal.TermInterpreterErrorString; |
| import org.eclipse.viatra2.gtasm.interpreter.term.internal.TermInterpreterException; |
| import org.eclipse.viatra2.gtasm.patternmatcher.patterns.IPatternMatcher; |
| import org.eclipse.viatra2.gtasm.patternmatcher.patterns.PatternMatcherProvider; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.MultiplicityKind; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ValueKind; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.ASMFunctionInvocation; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Constant; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.GTPatternCall; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.NativeFunctionInvocation; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Term; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.VariableReference; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Multiplicity; |
| import org.eclipse.viatra2.natives.ASMNativeFunction; |
| |
| |
| public class BasicTermEvaluator extends TermEvaluator { |
| private static BasicTermEvaluator _instance = new BasicTermEvaluator(); |
| |
| private BasicTermEvaluator() { |
| ; |
| } |
| |
| public static BasicTermEvaluator getInstance() { |
| return _instance; |
| } |
| |
| /** |
| * This function evaluates the basic Terms. Constants, |
| * ASMFunctionInvocations, NativeFunctionInvocations, VeriableReferences. |
| * |
| * The Native function invocation works for some functions, like |
| * java.util.Random.nextInt(), but fails to work for example with |
| * java.lang.Double.parseDouble(String) |
| * |
| */ |
| @Override |
| public Object evaluate(IExecutionEnvironment executionEnvironment, |
| Term termToBeEvaluated) throws ViatraTransformationException { |
| |
| |
| if (termToBeEvaluated instanceof Constant) { |
| int kind = ((Constant) termToBeEvaluated).getKind().getValue(); |
| switch (kind) { |
| case ValueKind.BOOLEAN: |
| return Boolean.valueOf(((Constant) termToBeEvaluated) |
| .getValue()); |
| case ValueKind.DOUBLE: |
| return Double |
| .valueOf(((Constant) termToBeEvaluated).getValue()); |
| case ValueKind.INTEGER: |
| return Integer.valueOf(((Constant) termToBeEvaluated) |
| .getValue()); |
| case ValueKind.STRING: |
| return ((Constant) termToBeEvaluated).getValue(); |
| case ValueKind.MULTIPLICITY: |
| if ("one_to_one".equals(((Constant) termToBeEvaluated) |
| .getValue())) { |
| return MultiplicityKind.ONE_TO_ONE_LITERAL; |
| } else if ("one_to_many".equals(((Constant) termToBeEvaluated) |
| .getValue())) { |
| return MultiplicityKind.ONE_TO_MANY_LITERAL; |
| } else if ("many_to_many".equals(((Constant) termToBeEvaluated) |
| .getValue())) { |
| return MultiplicityKind.MANY_TO_MANY_LITERAL; |
| } else if ("many_to_one".equals(((Constant) termToBeEvaluated) |
| .getValue())) { |
| return MultiplicityKind.MANY_TO_ONE_LITERAL; |
| } |
| case ValueKind.UNDEF: |
| return ValueKind.UNDEF_LITERAL; |
| case ValueKind.MODELELEMENT: |
| String fqn = ((Constant) termToBeEvaluated).getValue(); |
| // result is definitely not null |
| if (fqn == null) |
| {String[] context = {"Fully Qualified Name"}; |
| throw new TermInterpreterException( |
| TermInterpreterErrorString.REF_NOT_STRING_MODELELEMENTQUERY, |
| context, |
| termToBeEvaluated); |
| } |
| |
| // get the IModelElement from the manager |
| IModelSpace _topmodel = executionEnvironment.getFramework() |
| .getTopmodel(); |
| Object result = _topmodel.getModelManager().getElementByName(fqn); |
| |
| if (result != null) |
| return result; |
| else |
| { |
| String[] context = {fqn}; |
| throw new TermInterpreterException( |
| TermInterpreterErrorString.CONSTANT_MODELELEMENT_DOESNOTEXISTS |
| ,context |
| ,termToBeEvaluated); |
| } |
| |
| default: |
| {String[] context = {termToBeEvaluated.getName()}; |
| throw new TermInterpreterException( |
| TermInterpreterErrorString.UNIMP_TERM |
| ,context |
| ,termToBeEvaluated); |
| } |
| } |
| } else if (termToBeEvaluated instanceof ASMFunctionInvocation) { |
| EList<Object> evalParamList = new BasicEList<Object>(); |
| |
| for (Object term : ((ASMFunctionInvocation) termToBeEvaluated) |
| .getActualParameters()) { |
| evalParamList.add(TermEvaluator.getInstance() |
| .evaluate(executionEnvironment, (Term) term)); |
| } |
| |
| Object value = executionEnvironment.getValueOfASMFunction( |
| ((ASMFunctionInvocation) termToBeEvaluated) |
| .getCalledFunction(), evalParamList); |
| |
| return (value == null) ? ValueKind.UNDEF_LITERAL : value; |
| } else if (termToBeEvaluated instanceof NativeFunctionInvocation) { |
| // Name of the native function |
| String functionName = ((NativeFunctionInvocation) termToBeEvaluated) |
| .getFunctionName(); |
| // array for the evaluated parameters |
| Object[] parameters = new Object[((NativeFunctionInvocation) termToBeEvaluated) |
| .getActualParameters().size()]; |
| |
| // Evaluating each parameter |
| int i = 0; |
| for (Object parameterToBeEvaluated : ((NativeFunctionInvocation) termToBeEvaluated) |
| .getActualParameters()) { |
| Object currparameter = TermEvaluator.getInstance() |
| .evaluate(executionEnvironment, |
| (Term) parameterToBeEvaluated); |
| // unbox java native values for native functions calls |
| if (currparameter instanceof JavaNativeValue) |
| parameters[i++] = ((JavaNativeValue) currparameter) |
| .getValue(); |
| else |
| parameters[i++] = currparameter; |
| } |
| |
| //try { |
| ASMNativeFunction _nativeFunction = executionEnvironment.getFramework() |
| .getNativeFunctionManager().getNativeFunctionForName( |
| functionName); |
| IModelSpace _topmodel = executionEnvironment.getFramework().getTopmodel(); |
| Object o = null; |
| //Protects the Viatra runtime from any exception thrown from the native function invocation |
| try{ |
| o = _nativeFunction.evaluate( |
| _topmodel, parameters); |
| } |
| catch (VPMRuntimeException e) { |
| String[] context = {e.getMessage()}; |
| throw new TermInterpreterException( |
| TermInterpreterErrorString.VPM_CORE |
| ,context |
| ,termToBeEvaluated); |
| }// Any other exception that is not expected from the native ASM function |
| catch(Throwable t) { |
| String[] context = {functionName,t.getLocalizedMessage()}; |
| throw new TermInterpreterException( |
| TermInterpreterErrorString.NATIVE_FUNCTION_EXCEPTION |
| ,context |
| ,termToBeEvaluated); |
| } |
| |
| if (isASMNativeType(o)) |
| return o; |
| else |
| return new JavaNativeValue(o); |
| |
| |
| } else if (termToBeEvaluated instanceof VariableReference) { |
| try { |
| return executionEnvironment |
| .getVariableValue(((VariableReference) termToBeEvaluated) |
| .getVariable()); |
| } catch (ViatraTransformationException e) { |
| String[] context = {((VariableReference) termToBeEvaluated).getName()}; |
| throw new TermInterpreterException( |
| TermInterpreterErrorString.EXECUTION_ENVIRONMENT_EXCEPTION |
| + e.getMessage(), context, termToBeEvaluated); |
| } |
| } else if (termToBeEvaluated instanceof GTPatternCall) { |
| // Evaluates GTPatternCall for match. Boolean return value only. |
| // ((GTPatternBody)((GTPatternCall)termToBeEvaluated).getCalledPattern().getPatternBodies().get(0)).get |
| |
| GTPattern gtPattern = ((GTPatternCall) termToBeEvaluated) |
| .getCalledPattern(); |
| |
| try { |
| |
| IPatternMatcher patternMatcher = PatternMatcherProvider |
| .getInstance().getPatternMatcher(executionEnvironment, |
| gtPattern); |
| |
| Vector<Object> patternParams = new Vector<Object>(); |
| for (Object term : ((GTPatternCall) termToBeEvaluated) |
| .getActualParameters()) { |
| patternParams.add(TermEvaluator.getInstance() |
| .evaluate(executionEnvironment, (Term) term)); |
| } |
| |
| return patternMatcher.match(patternParams.toArray()); |
| } catch (ViatraTransformationException e) { |
| throw e.addNewStackElement(termToBeEvaluated); |
| } |
| |
| } else if (termToBeEvaluated instanceof Multiplicity) { |
| return termToBeEvaluated; |
| } |
| // the control gets here, if a non-implemented Term was evaluated. |
| String[] context = {termToBeEvaluated.getName()}; |
| throw new TermInterpreterException(TermInterpreterErrorString.UNIMP_TERM, context, termToBeEvaluated); |
| |
| } |
| |
| } |