/******************************************************************************* * Copyright (c) 2016, 2017 Obeo. * 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: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.eef.core.api.utils; import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; import org.eclipse.eef.common.api.utils.Util; import org.eclipse.eef.core.internal.EEFCorePlugin; import org.eclipse.eef.core.internal.Messages; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.sirius.common.interpreter.api.IEvaluationResult; import org.eclipse.sirius.common.interpreter.api.IInterpreter; import org.eclipse.sirius.common.interpreter.api.IVariableManager; /** * Utility class used to create the {@link Eval}. * * @author sbegaudeau */ public final class EvalFactory { /** * The constructor. */ private EvalFactory() { // Prevent the instantiation } /** * Creates a new {@link Eval} with the given interpreter and variables. * * @param interpreter * The interpreter * @param variables * The variables * @return The new {@link Eval} builder */ public static Eval<Object> of(IInterpreter interpreter, Map<String, Object> variables) { return new Eval<Object>(interpreter, variables, Object.class); } /** * Creates a new {@link Eval} with the given interpreter and variable manager. * * @param interpreter * The interpreter * @param variableManager * The variable manager * @return The new {@link Eval} */ public static Eval<Object> of(IInterpreter interpreter, IVariableManager variableManager) { return new Eval<Object>(interpreter, variableManager, Object.class); } /** * This class will be used to evaluate the expression. * * @author sbegaudeau * * @param <TYPE> * The type of the result returned by the execution of the expression */ public static final class Eval<TYPE> { /** * The interpreter. */ private IInterpreter interpreter; /** * The variables. */ private Map<String, Object> variables = new HashMap<String, Object>(); /** * The EAttribute containing the expression. It will be used, if not null, to log an error if the expression is * blank. */ private EAttribute eAttribute; /** * The value to use by default if the evaluation of the expression returns null. */ private TYPE defaultValue; /** * The expected type of the result. */ private Class<TYPE> type; /** * The constructor. * * @param interpreter * The interpreter * @param variables * The variables * @param type * The expected type of the result */ private Eval(IInterpreter interpreter, Map<String, Object> variables, Class<TYPE> type) { this.interpreter = interpreter; this.variables.putAll(variables); this.type = type; } /** * The constructor. * * @param interpreter * The interpreter * @param variableManager * The variable manager * @param type * The expected type of the result */ private Eval(IInterpreter interpreter, IVariableManager variableManager, Class<TYPE> type) { this(interpreter, variableManager.getVariables(), type); } /** * Indicates that an error should be logged using the given EAttribute if the expression to execute is blank. * * @param attribute * The EAttribute containing the expression to execute * @return The current {@link Eval} */ public Eval<TYPE> logIfBlank(EAttribute attribute) { this.eAttribute = attribute; return this; } /** * Indicates that the result should have the same type as the given class. It will log an error if the type of * the result does not match the given type. * * @param expectedType * The expected type * @param <E> * The expected type of the execution of the expression * @return The current {@link Eval} * */ public <E> Eval<E> logIfInvalidType(Class<E> expectedType) { E value = null; if (expectedType.isInstance(this.defaultValue)) { value = expectedType.cast(this.defaultValue); } return new Eval<E>(this.interpreter, this.variables, expectedType).logIfBlank(this.eAttribute).defaultValue(value); } /** * Indicates the value to use by default if the result of the evaluation of the expression is null. * * @param value * The default value * @return The current {@link Eval} */ public Eval<TYPE> defaultValue(TYPE value) { this.defaultValue = value; return this; } /** * Executes the given expression and process its result using the given consumer. * * @param expression * The expression */ public void call(String expression) { this.call(expression, null); } /** * Executes the given expression and process its result using the given consumer. * * @param expression * The expression * @param consumer * The consumer */ public void call(String expression, Consumer<TYPE> consumer) { if (Util.isBlank(expression)) { if (this.eAttribute != null && EEFCorePlugin.getPlugin() != null) { EEFCorePlugin.getPlugin().blank(this.eAttribute); } if (this.defaultValue != null && consumer != null) { consumer.accept(this.defaultValue); } return; } IEvaluationResult evaluationResult = this.interpreter.evaluateExpression(this.variables, expression); if (evaluationResult.success()) { if (consumer != null) { TYPE returnValue = this.defaultValue; Object value = evaluationResult.getValue(); if (value != null && this.type.isInstance(value)) { returnValue = this.type.cast(value); } else if (value != null && EEFCorePlugin.getPlugin() != null) { String message = MessageFormat.format(Messages.AbstractEEFWidgetController_InvalidValueForExpression, expression, this.type.getName(), value); EEFCorePlugin.getPlugin().error(message); } consumer.accept(returnValue); } } else if (EEFCorePlugin.getPlugin() != null) { EEFCorePlugin.getPlugin().diagnostic(expression, evaluationResult.getDiagnostic()); } } /** * Executes the given expression. * * @param expression * The expression * @return The result of the expression */ public TYPE evaluate(String expression) { if (Util.isBlank(expression)) { if (this.eAttribute != null && EEFCorePlugin.getPlugin() != null) { EEFCorePlugin.getPlugin().blank(this.eAttribute); } return this.defaultValue; } TYPE result = this.defaultValue; IEvaluationResult evaluationResult = this.interpreter.evaluateExpression(this.variables, expression); if (evaluationResult.success()) { Object value = evaluationResult.getValue(); if (value != null && this.type.isInstance(value)) { TYPE castValue = this.type.cast(value); result = castValue; } else if (value != null && EEFCorePlugin.getPlugin() != null) { String message = MessageFormat.format(Messages.AbstractEEFWidgetController_InvalidValueForExpression, expression, this.type.getName(), value); EEFCorePlugin.getPlugin().error(message); } } else if (EEFCorePlugin.getPlugin() != null) { EEFCorePlugin.getPlugin().diagnostic(expression, evaluationResult.getDiagnostic()); } return result; } } }