blob: b8ba916b4ace2a773f067419101e9f130bf22bb7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 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.examples.debug.evaluator;
import java.io.IOException;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.debug.OCLDebugPlugin;
import org.eclipse.ocl.examples.debug.vm.evaluator.IVMContext;
import org.eclipse.ocl.examples.debug.vm.evaluator.VMEvaluationStepper;
import org.eclipse.ocl.examples.debug.vm.evaluator.VMExecutor;
import org.eclipse.ocl.pivot.Constraint;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.LanguageExpression;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
import org.eclipse.ocl.pivot.evaluation.EvaluationVisitor;
import org.eclipse.ocl.pivot.internal.evaluation.BasicOCLExecutor;
import org.eclipse.ocl.pivot.internal.evaluation.OCLEvaluationVisitor;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal.EnvironmentFactoryInternalExtension;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
import org.eclipse.ocl.pivot.utilities.MetamodelManager;
import org.eclipse.ocl.pivot.utilities.ParserException;
public class OCLVMExecutor extends BasicOCLExecutor implements VMExecutor
{
private static @NonNull EObject loadContext(@NonNull EnvironmentFactory environmentFactory, @NonNull URI contextURI) throws IOException {
EObject eObject = environmentFactory.getResourceSet().getEObject(contextURI, true);
if (eObject == null) {
throw new IOException("Nothing loadable as '" + contextURI + "'");
}
return eObject;
}
private static @NonNull ExpressionInOCL loadExpression(@NonNull EnvironmentFactory environmentFactory, @NonNull URI constraintURI, boolean keepDebug) throws IOException, ParserException {
MetamodelManager metamodelManager = environmentFactory.getMetamodelManager();
EObject eObject = metamodelManager.getASResourceSet().getEObject(constraintURI, true);
return loadExpression(environmentFactory, eObject, constraintURI);
}
private static @NonNull ExpressionInOCL loadExpression(@NonNull EnvironmentFactory environmentFactory, EObject eObject, URI constraintURI) throws IOException, ParserException {
if (eObject == null) {
throw new IOException("Nothing loadable as '" + constraintURI + "'");
}
if (!(eObject instanceof Constraint)) {
throw new IOException("Constraint rather than " + eObject.eClass().getName() + " expected as '" + constraintURI + "'");
}
LanguageExpression specification = ((Constraint)eObject).getOwnedSpecification();
if (specification == null) {
throw new IOException("Missing OCL expression " + eObject.eClass().getName() + " expected as '" + constraintURI + "'");
}
return ((EnvironmentFactoryInternalExtension)environmentFactory).parseSpecification(specification);
}
protected final @NonNull IVMContext vmContext;
protected final @NonNull ExpressionInOCL expressionInOCL;
protected final @Nullable EObject context;
private boolean suspendOnStartup = false;
private long envId = 0;
public OCLVMExecutor(IVMContext vmContext, @NonNull URI oclURI, @Nullable URI contextURI) throws IOException, ParserException {
this(vmContext, loadExpression(vmContext.getEnvironmentFactory(), oclURI, vmContext.keepDebug()), contextURI != null ? loadContext(vmContext.getEnvironmentFactory(), contextURI) : null);
}
public OCLVMExecutor(@NonNull IVMContext vmContext, @NonNull ExpressionInOCL expressionInOCL, @Nullable EObject context) {
super(vmContext.getEnvironmentFactory(), new OCLVMModelManager(vmContext.getEnvironmentFactory().getMetamodelManager()));
this.vmContext = vmContext;
this.expressionInOCL = expressionInOCL;
this.context = context;
}
@Override
protected EvaluationVisitor.@NonNull EvaluationVisitorExtension createEvaluationVisitor() {
OCLEvaluationVisitor evaluationVisitor = new OCLEvaluationVisitor(this);
OCLVMEvaluationStepper vmEvaluationStepper = new OCLVMEvaluationStepper(evaluationVisitor, vmContext);
return new OCLVMEvaluationVisitor(vmEvaluationStepper, evaluationVisitor);
}
@Override
protected @NonNull OCLVMEvaluationEnvironment createNestedEvaluationEnvironment(EvaluationEnvironment.@NonNull EvaluationEnvironmentExtension evaluationEnvironment, @NonNull NamedElement executableObject, @Nullable Object caller) {
return new OCLVMNestedEvaluationEnvironment((OCLVMEvaluationEnvironment) evaluationEnvironment, executableObject, caller, ++envId);
}
@Override
protected @NonNull OCLVMEvaluationEnvironment createRootEvaluationEnvironment(@NonNull NamedElement executableObject) {
return new OCLVMRootEvaluationEnvironment(this, (ExpressionInOCL)executableObject, ++envId);
}
@Override
public Object execute() {
initializeEvaluationEnvironment(expressionInOCL);
getRootEvaluationEnvironment();
Variable contextVariable = expressionInOCL.getOwnedContext();
if (contextVariable != null) {
add(contextVariable, context);
}
OCLVMEvaluationVisitor visitor = (OCLVMEvaluationVisitor) getEvaluationVisitor();
VMEvaluationStepper vmStepper = visitor.getVMEvaluationStepper();
vmStepper.start(suspendOnStartup);
return expressionInOCL.accept(visitor);
}
@Override
public @NonNull ExpressionInOCL getDebuggable() {
return expressionInOCL;
}
@Override
public @NonNull String getPluginId() {
return OCLDebugPlugin.PLUGIN_ID;
}
@Override
public void saveModels() {}
@Override
public void setSuspendOnStartUp(boolean suspendOnStartup) {
this.suspendOnStartup = suspendOnStartup;
}
}