From 531475fd9fe2cbc5c43a265dd36fa6f2e95bdb7c Mon Sep 17 00:00:00 2001 From: Didier Vojtisek Date: Wed, 13 Nov 2019 09:20:03 +0100 Subject: [PATCH] add ALEDynamicExpressionEvaluator This class offers services similar to AQLSiriusInterpreter but without the registration to the workspace listener If offers the possibility to parse and evaluate string expressions and return various kinds of objects It relies on the queryEnvironment of an existing ALEInterpreter. (ie. this is the responsibility of this ALEInterpreter to clean/dispose the query environment when not use anymore) --- .../META-INF/MANIFEST.MF | 4 +- .../plugin.properties | 18 ++ .../ale/ALEDynamicExpressionEvaluator.java | 196 ++++++++++++++++++ .../eclipse/emf/ecoretools/ale/Messages.java | 34 +++ .../emf/ecoretools/ale/messages.properties | 17 ++ 5 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 plugins/org.eclipse.emf.ecoretools.ale/plugin.properties create mode 100644 plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/ALEDynamicExpressionEvaluator.java create mode 100644 plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/Messages.java create mode 100644 plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/messages.properties diff --git a/plugins/org.eclipse.emf.ecoretools.ale/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.ecoretools.ale/META-INF/MANIFEST.MF index 1493ab052..0b12afef3 100644 --- a/plugins/org.eclipse.emf.ecoretools.ale/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.ecoretools.ale/META-INF/MANIFEST.MF @@ -10,5 +10,7 @@ Require-Bundle: org.eclipse.acceleo.query, org.eclipse.emf.ecore.xmi, org.eclipse.emf.ecoretools.ale.core, org.eclipse.sirius.common, - org.eclipse.core.resources + org.eclipse.core.resources, + com.google.guava;bundle-version="21.0.0", + org.eclipse.osgi Bundle-Vendor: Inria/Obeo diff --git a/plugins/org.eclipse.emf.ecoretools.ale/plugin.properties b/plugins/org.eclipse.emf.ecoretools.ale/plugin.properties new file mode 100644 index 000000000..6565e57df --- /dev/null +++ b/plugins/org.eclipse.emf.ecoretools.ale/plugin.properties @@ -0,0 +1,18 @@ +# ==================================================================== +# Copyright (c) 2019 Inria, Obeo +# This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Obeo - initial API and implementation +# ==================================================================== + +ALEInterpreter_errorWithExpression= An error has appeared during the evaluation of an expression:\n\ +Expression: {0}\n\ +Diagnostic: {1}\n\ +Target URI Fragment: {2}\n\ +Target: {3}\n\ \ No newline at end of file diff --git a/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/ALEDynamicExpressionEvaluator.java b/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/ALEDynamicExpressionEvaluator.java new file mode 100644 index 000000000..78a9d8c02 --- /dev/null +++ b/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/ALEDynamicExpressionEvaluator.java @@ -0,0 +1,196 @@ +package org.eclipse.emf.ecoretools.ale; + +import java.text.MessageFormat; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.acceleo.query.runtime.EvaluationResult; +import org.eclipse.acceleo.query.runtime.IQueryBuilderEngine; +import org.eclipse.acceleo.query.runtime.IQueryEnvironment; +import org.eclipse.acceleo.query.runtime.IQueryEvaluationEngine; +import org.eclipse.acceleo.query.runtime.QueryEvaluation; +import org.eclipse.acceleo.query.runtime.QueryParsing; +import org.eclipse.acceleo.query.runtime.IQueryBuilderEngine.AstResult; +import org.eclipse.emf.common.util.BasicDiagnostic; +import org.eclipse.emf.common.util.Diagnostic; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.ecoretools.ale.ALEInterpreter; +import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException; +import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterWithDiagnostic.IEvaluationResult; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + + +/** + * This class offers services similar to AQLSiriusInterpreter but without the registration to the workspace listener + * If offers the possibility to parse and evaluate string expressions and return various kinds of objects + * It relies on the queryEnvironment of an existing ALEInterpreter. (ie. this is the responsibility of this ALEInterpreter + * to clean/dispose the query environment when not use anymore) + */ +public class ALEDynamicExpressionEvaluator { + + ALEInterpreter aleInterpreter; + + public ALEDynamicExpressionEvaluator(ALEInterpreter aleInterpreter) { + super(); + this.aleInterpreter = aleInterpreter; + } + + public IEvaluationResult evaluateExpression(final EObject target, final String fullExpression) + throws EvaluationException { + // this.javaExtensions.reloadIfNeeded(); + String expression = fullExpression.replaceFirst("ale:", ""); + Map variables = new HashMap<>(); + variables.put("self", target); //$NON-NLS-1$ + + IQueryEnvironment queryEnv = aleInterpreter.getQueryEnvironment(); + if (queryEnv != null) { + final IQueryBuilderEngine builder = QueryParsing.newBuilder(queryEnv); + AstResult build = builder.build(expression); + IQueryEvaluationEngine evaluationEngine = QueryEvaluation.newEngine(queryEnv); + final EvaluationResult evalResult = evaluationEngine.eval(build, variables); + + final BasicDiagnostic diagnostic = new BasicDiagnostic(); + if (Diagnostic.OK != build.getDiagnostic().getSeverity()) { + diagnostic.merge(build.getDiagnostic()); + } + if (Diagnostic.OK != evalResult.getDiagnostic().getSeverity()) { + diagnostic.merge(evalResult.getDiagnostic()); + } + + return new IEvaluationResult() { + + @Override + public Object getValue() { + return evalResult.getResult(); + } + + @Override + public Diagnostic getDiagnostic() { + List children = diagnostic.getChildren(); + if (children.size() == 1) { + return children.get(0); + } else { + return diagnostic; + } + } + }; + } + return new IEvaluationResult() { + @Override + public Object getValue() { + return null; + } + + @Override + public Diagnostic getDiagnostic() { + return new BasicDiagnostic(); + } + + }; + + + } + + + public Object evaluate(EObject target, String fullExpression) throws EvaluationException { + IEvaluationResult evaluationResult = this.evaluateExpression(target, fullExpression); + // We fire the exception to keep the old behavior + Diagnostic diagnostic = evaluationResult.getDiagnostic(); + if (diagnostic.getSeverity() == Diagnostic.ERROR) { + String uri = EcoreUtil.getURI(target).toString(); + String message = MessageFormat.format(Messages.ALEInterpreter_errorWithExpression, fullExpression, diagnostic.toString(), uri, target); + throw new EvaluationException(message, diagnostic.getException()); + } + return evaluationResult.getValue(); + } + + /** + * {@inheritDoc} + */ + public Collection evaluateCollection(EObject context, String expression) throws EvaluationException { + Object raw = evaluate(context, expression); + final Collection result; + if (raw instanceof Collection) { + result = Lists.newArrayList(Iterables.filter((Collection) raw, EObject.class)); + } else if (raw instanceof EObject) { + result = Collections.singleton((EObject) raw); + } else if (raw != null && raw.getClass().isArray()) { + result = Lists.newArrayList(Iterables.filter(Lists.newArrayList((Object[]) raw), EObject.class)); + } else { + result = Collections.emptySet(); + } + return result; + } + + /** + * {@inheritDoc} + */ + public boolean evaluateBoolean(EObject context, String expression) throws EvaluationException { + Object raw = evaluate(context, expression); + final boolean result; + if (raw == null) { + result = false; + } else if (raw instanceof Boolean) { + result = ((Boolean) raw).booleanValue(); + } else { + String toString = raw.toString(); + if ("true".equalsIgnoreCase(toString)) { //$NON-NLS-1$ + result = true; + } else if ("false".equalsIgnoreCase(toString)) { //$NON-NLS-1$ + result = false; + } else { + /* + * raw is != null and its toString is neither true or false, + * this happens when the user expect the condition to check that + * a value is existing, then we consider any non null value + * returns true and null returns false. + */ + result = true; + } + } + return result; + } + + /** + * {@inheritDoc} + */ + public EObject evaluateEObject(EObject context, String expression) throws EvaluationException { + Object raw = evaluate(context, expression); + if (raw instanceof EObject) { + return (EObject) raw; + } else { + return null; + } + } + + /** + * {@inheritDoc} + */ + public String evaluateString(EObject context, String expression) throws EvaluationException { + Object raw = evaluate(context, expression); + if (raw != null) { + return String.valueOf(raw); + } else { + return ""; //$NON-NLS-1$ + } + } + + /** + * {@inheritDoc} + */ + public Integer evaluateInteger(EObject context, String expression) throws EvaluationException { + Object raw = evaluate(context, expression); + try { + return Integer.parseInt(String.valueOf(raw)); + } catch (NumberFormatException e) { + return Integer.valueOf(0); + } + } + +} diff --git a/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/Messages.java b/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/Messages.java new file mode 100644 index 000000000..a31ce4f04 --- /dev/null +++ b/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/Messages.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.ecoretools.ale; + +import org.eclipse.osgi.util.NLS; + +/** + * Helper class to obtains translated strings. + * + */ + + +public final class Messages extends NLS { + private static final String BASE_NAME = "org.eclipse.emf.ecoretools.ale.messages"; //$NON-NLS-1$ + + static { + // load message values from bundle file + NLS.initializeMessages(BASE_NAME, Messages.class); + } + + public static String ALEInterpreter_errorWithExpression; + + +} diff --git a/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/messages.properties b/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/messages.properties new file mode 100644 index 000000000..1b6781218 --- /dev/null +++ b/plugins/org.eclipse.emf.ecoretools.ale/src/org/eclipse/emf/ecoretools/ale/messages.properties @@ -0,0 +1,17 @@ +############################################################################### +# Copyright (c) 2019 Inria 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: +# Inria - initial API and implementation +############################################################################### + +### Supplied messageses +ALEInterpreter_errorWithExpression= An error has appeared during the evaluation of an expression:\n\ +Expression: {0}\n\ +Diagnostic: {1}\n\ +Target URI Fragment: {2}\n\ +Target: {3}\n\