blob: 94e0e7319d31bc80e383b017f951700338f939cd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 SAP AG 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:
* Axel Uhl - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.ecore;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.EvaluationEnvironment;
import org.eclipse.ocl.ecore.delegate.InvocationBehavior;
import org.eclipse.ocl.ecore.delegate.OCLInvocationDelegate;
import org.eclipse.ocl.ecore.delegate.SettingBehavior;
import org.eclipse.ocl.ecore.utilities.VisitorExtension;
import org.eclipse.ocl.expressions.CollectionKind;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.types.CollectionType;
import org.eclipse.ocl.util.CollectionUtil;
/**
* @since 3.1
*/
public class EvaluationVisitorImpl
extends
org.eclipse.ocl.EvaluationVisitorImpl<
EPackage, EClassifier, EOperation, EStructuralFeature,
EEnumLiteral, EParameter, EObject,
CallOperationAction, SendSignalAction, Constraint,
EClass, EObject> implements VisitorExtension<Object> {
public EvaluationVisitorImpl(
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env,
EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> evalEnv,
Map<? extends EClass, ? extends Set<? extends EObject>> extentMap) {
super(env, evalEnv, extentMap);
}
/**
* Callback for a PropertyCallExp visit. Evaluates the source of the
* expression and then reflectively gets the value of the property on the
* result. For example, in "self.foo", "self" is the source and would be
* evaluated first, then the value of the property "foo" would be accessed
* on that object.
*/
@SuppressWarnings("unchecked")
public Object visitOppositePropertyCallExp(OppositePropertyCallExp pc) {
EReference property = pc.getReferredOppositeProperty();
OCLExpression<EClassifier> source = pc.getSource();
// evaluate source
Object context = source.accept(getVisitor());
// if source is undefined, result is OclInvalid
if (isUndefined(context)) {
return getInvalid();
}
Object result = ((EvaluationEnvironmentWithHiddenOpposites) getEvaluationEnvironment())
.navigateOppositeProperty(property, context);
if ((pc.getType() instanceof CollectionType<?, ?>)
&& !(result instanceof Collection<?>)) {
// this was an XSD "unspecified multiplicity". Now that we know what
// the multiplicity is, we can coerce it to a collection value
CollectionKind kind = ((CollectionType<EClassifier, EOperation>) pc.getType()).getKind();
Collection<Object> collection = CollectionUtil.createNewCollection(kind);
if (result != null) {
collection.add(result);
}
result = collection;
}
return result;
}
/**
* Tries to fetch an operation body from where the
* {@link OCLInvocationDelegate OCL invocation delegate} stores it. If nothing
* is found, this method delegates to the base class implementation which then
* performs the usual search in the OCL_NAMESPACE_URI annotation and the
* environment's body condition cache.
*/
@Override
protected OCLExpression<EClassifier> getOperationBody(EOperation operation) {
OCLExpression<EClassifier> result = InvocationBehavior.INSTANCE
.getCachedOCLExpression(operation);
if (result == InvocationBehavior.NO_OCL_DEFINITION) {
result = null;
}
else if (result == null) {
if (InvocationBehavior.INSTANCE.hasCompileableOperationBody(operation)) {
OCL ocl = OCL.newInstance(getEnvironment().getFactory());
result = InvocationBehavior.INSTANCE.getOperationBody(ocl, operation);
ocl.dispose();
}
if (result == null) {
result = super.getOperationBody(operation);
}
}
return result;
}
@Override
protected OCLExpression<EClassifier> getPropertyBody(
EStructuralFeature property) {
OCLExpression<EClassifier> result = SettingBehavior.INSTANCE
.getCachedOCLExpression(property);
if (result == SettingBehavior.NO_OCL_DEFINITION) {
result = null;
}
else if (result == null) {
if (SettingBehavior.INSTANCE.hasCompileableFeatureBody(property)) {
OCL ocl = OCL.newInstance(getEnvironment().getFactory());
result = SettingBehavior.INSTANCE.getFeatureBody(ocl, property);
ocl.dispose();
}
if (result == null) {
result = super.getPropertyBody(property);
}
}
return result;
}
}