blob: 4ca696691716bfc4fdbd77a8215600d77ce20579 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2018 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.internal.evaluation;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
import org.eclipse.ocl.pivot.evaluation.ModelManager;
import org.eclipse.ocl.pivot.internal.messages.PivotMessagesInternal;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
import org.eclipse.ocl.pivot.utilities.Option;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.osgi.util.NLS;
/**
* Basic implementation of the {@link EvaluationEnvironment} interface,
* providing some useful common behaviors. Implementors of metamodel-specific
* environments are encourage to extend this class rather than implement
* an evaluation environment "from scratch."
*
* @author Christian W. Damus (cdamus)
*/
public class BasicEvaluationEnvironment extends AbstractCustomizable implements EvaluationEnvironment.EvaluationEnvironmentExtension
{
/**
* @since 1.1
*/
protected final @NonNull ExecutorInternal executor;
protected final @NonNull EnvironmentFactory environmentFactory;
protected final @Nullable EvaluationEnvironment parent; // parent in environment hierarchy, null at root
protected final @NonNull NamedElement executableObject;
/**
* @since 1.3
*/
protected final @Nullable Object caller;
/**
* @since 1.1
* @deprecated use caller
*/
@Deprecated
protected final @Nullable OCLExpression callingObject;
private final @NonNull Map<TypedElement, Object> variableValues = new HashMap<TypedElement, Object>();
/** @deprecated use an executor */
@Deprecated
protected final @NonNull ModelManager modelManager;
/** @deprecated use an executor */
@Deprecated
public BasicEvaluationEnvironment(@NonNull EnvironmentFactory environmentFactory, @NonNull NamedElement executableObject, @NonNull ModelManager modelManager) {
this(((EnvironmentFactoryInternal.EnvironmentFactoryInternalExtension)environmentFactory).createExecutor(modelManager), executableObject);
}
/**
* @since 1.1
*/
public BasicEvaluationEnvironment(@NonNull ExecutorInternal executor, @NonNull NamedElement executableObject) {
this.executor = executor;
this.environmentFactory = executor.getEnvironmentFactory();
this.parent = null;
this.executableObject = executableObject;
this.caller = null;
this.callingObject = null;
this.modelManager = executor.getModelManager();
}
/** @deprecated supply a callingObject */
@Deprecated
public BasicEvaluationEnvironment(@NonNull EvaluationEnvironment parent, @NonNull NamedElement executableObject) {
this((EvaluationEnvironment.EvaluationEnvironmentExtension)parent, executableObject, null);
}
/**
* @since 1.3
*/
public BasicEvaluationEnvironment(EvaluationEnvironment.@NonNull EvaluationEnvironmentExtension parent, @NonNull NamedElement executableObject, @Nullable Object caller) {
this.executor = parent.getExecutor();
this.environmentFactory = parent.getEnvironmentFactory();
this.parent = parent;
this.executableObject = executableObject;
this.caller = caller;
this.callingObject = caller instanceof OCLExpression ? (OCLExpression)caller : null;
this.modelManager = executor.getModelManager();
}
/**
* @since 1.1
* @deprecated use TypedElement argument.
*/
@Deprecated
public BasicEvaluationEnvironment(EvaluationEnvironment.@NonNull EvaluationEnvironmentExtension parent, @NonNull NamedElement executableObject, @Nullable OCLExpression caller) {
this(parent, executableObject, (TypedElement)caller);
}
/**
* Adds the supplied referredVariable and value binding to the environment
*
* @param referredVariable
* the referredVariable to add
* @param value
* the associated binding
*/
@Override
public void add(@NonNull TypedElement referredVariable, @Nullable Object value) {
if (variableValues.containsKey(referredVariable)) {
Object oldValue = variableValues.get(referredVariable);
if ((oldValue != value) && ((oldValue == null) || !oldValue.equals(value))) {
String message = NLS.bind(
PivotMessagesInternal.BindingExist_ERROR_,
referredVariable,
oldValue);
throw new IllegalArgumentException(message);
}
}
Object oldValue = variableValues.put(referredVariable, value);
}
/**
* Clears the environment of variables.
*/
@Override
public void clear() {
variableValues.clear();
}
/**
* Dispose of any owned objects.
*/
@Override
public void dispose() {}
/**
* Implements the interface method by testing whether I am an instance of
* the requested adapter type.
*/
@Override
@SuppressWarnings("unchecked")
public <T> @Nullable T getAdapter(java.lang.Class<T> adapterType) {
if (adapterType.isInstance(this)) {
return (T) this;
}
return null;
}
@Override
public @NonNull EnvironmentFactory getEnvironmentFactory() {
return environmentFactory;
}
@Override
public @NonNull NamedElement getExecutableObject() {
return executableObject;
}
/**
* @since 1.1
*/
@Override
public @NonNull ExecutorInternal getExecutor() {
return executor;
}
/** @deprecated moved to Evaluator */
@Deprecated
@Override
public @NonNull ModelManager getModelManager() {
return executor.getModelManager();
}
@Override
public @Nullable EvaluationEnvironment getParent() {
return parent;
}
/**
* @since 1.1
*/
@Override
public EvaluationEnvironment.@Nullable EvaluationEnvironmentExtension getParentEvaluationEnvironment() {
return (EvaluationEnvironment.EvaluationEnvironmentExtension)parent;
}
@Override
public <@Nullable T> T getValue(@NonNull Option<T> option) {
@SuppressWarnings("unchecked")
T result = (T) getOptions().get(option);
if (result == null) {
EvaluationEnvironment parent2 = parent;
result = (parent2 != null) ? parent2.getValue(option) : option.getDefaultValue();
}
return result;
}
/**
* Returns the value associated with the supplied referredVariable
*
* @param referredVariable
* the referredVariable whose value is to be returned
* @return the value associated with the referredVariable
*/
@Override
public @Nullable Object getValueOf(@NonNull TypedElement referredVariable) {
Object object = variableValues.get(referredVariable);
if (object == null) {
if (!variableValues.containsKey(referredVariable)) {
EvaluationEnvironment parent2 = parent;
if (parent2 != null) {
object = parent2.getValueOf(referredVariable);
}
else {
throw new InvalidValueException("Undefined Variable " + referredVariable);
}
}
}
return object;
}
@Override
public @NonNull Set<TypedElement> getVariables() {
return variableValues.keySet();
}
/**
* Removes the supplied referredVariable and binding from the environment (if it exists)
* and returns it.
*
* @param referredVariable
* the referredVariable to remove
* @return the value associated with the removed referredVariable
*/
@Override
public @Nullable Object remove(@NonNull TypedElement referredVariable) {
return variableValues.remove(referredVariable);
}
/**
* Replaces the current value of the supplied referredVariable with the supplied value.
*
* @param referredVariable
* the referredVariable
* @param value
* the new value
*/
@Override
public void replace(@NonNull TypedElement referredVariable, @Nullable Object value) {
variableValues.put(referredVariable, value);
}
@Override
public @Nullable Object replaceInternal(@NonNull VariableDeclaration referredVariable, @Nullable Object value) {
return variableValues.put(referredVariable, value);
}
/**
* Returns a string representation of the bindings
*/
@Override
public String toString() {
return variableValues.toString();
}
}