blob: 5728febc6e69073952ae20cf97a1a6e8408d8936 [file] [log] [blame]
package org.eclipse.qvtd.pivot.qvtimperative.evaluation;
import java.io.IOException;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CallExp;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.PivotFactory;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
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.complete.StandardLibraryInternal;
import org.eclipse.ocl.pivot.internal.evaluation.AbstractExecutor;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.qvtd.pivot.qvtbase.Domain;
import org.eclipse.qvtd.pivot.qvtbase.Predicate;
import org.eclipse.qvtd.pivot.qvtbase.Rule;
import org.eclipse.qvtd.pivot.qvtbase.Transformation;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
import org.eclipse.qvtd.pivot.qvtcorebase.Area;
import org.eclipse.qvtd.pivot.qvtcorebase.Assignment;
import org.eclipse.qvtd.pivot.qvtcorebase.BottomPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.CoreDomain;
import org.eclipse.qvtd.pivot.qvtcorebase.EnforcementOperation;
import org.eclipse.qvtd.pivot.qvtcorebase.GuardPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.PropertyAssignment;
import org.eclipse.qvtd.pivot.qvtcorebase.RealizedVariable;
import org.eclipse.qvtd.pivot.qvtcorebase.utilities.QVTcoreBaseUtil;
import org.eclipse.qvtd.pivot.qvtimperative.ImperativeModel;
import org.eclipse.qvtd.pivot.qvtimperative.Mapping;
import org.eclipse.qvtd.pivot.qvtimperative.MappingCall;
import org.eclipse.qvtd.pivot.qvtimperative.MappingStatement;
import org.eclipse.qvtd.pivot.qvtimperative.utilities.QVTimperativeUtil;
public class BasicQVTiExecutor extends AbstractExecutor implements QVTiExecutor
{
private static @NonNull QVTiTransformationAnalysis createTransformationAnalysis(@NonNull QVTiEnvironmentFactory environmentFactory, @NonNull Transformation transformation) {
QVTiTransformationAnalysis transformationAnalysis = environmentFactory.createTransformationAnalysis();
transformationAnalysis.analyzeTransformation(transformation);
return transformationAnalysis;
}
protected final @NonNull Transformation transformation;
public BasicQVTiExecutor(@NonNull QVTiEnvironmentFactory environmentFactory, @NonNull URI transformationURI) throws IOException {
this(environmentFactory, QVTbaseUtil.loadTransformation(ImperativeModel.class, environmentFactory, transformationURI, environmentFactory.keepDebug()));
}
public BasicQVTiExecutor(@NonNull QVTiEnvironmentFactory environmentFactory, @NonNull Transformation transformation) {
this(environmentFactory, transformation, createTransformationAnalysis(environmentFactory, transformation));
}
private BasicQVTiExecutor(@NonNull QVTiEnvironmentFactory environmentFactory, @NonNull Transformation transformation, @NonNull QVTiTransformationAnalysis transformationAnalysis) {
super(environmentFactory, new QVTiModelManager(transformationAnalysis));
this.transformation = transformation;
}
/**
* Adds the model.
*/
public void addModel(@NonNull TypedModel typedModel, @NonNull Resource resource) {
getModelManager().addModel(typedModel, resource);
}
@Override
protected @NonNull EvaluationVisitor createEvaluationVisitor() {
IQVTiEvaluationVisitor visitor = new QVTiEvaluationVisitor(this);
if (environmentFactory.isEvaluationTracingEnabled()) {
// decorate the evaluation visitor with tracing support
visitor = new QVTiTracingEvaluationVisitor(visitor);
// ((QVTiTracingEvaluationVisitor)visitor).setVerboseLevel(QVTiTracingEvaluationVisitor.VERBOSE_LEVEL_HIGH);
}
return visitor;
}
public void createModel(@NonNull String name, @NonNull URI modelURI, String contentType) {
TypedModel typedModel = NameUtil.getNameable(transformation.getModelParameter(), name);
if (typedModel == null) {
throw new IllegalStateException("Unknown TypedModel '" + name + "'");
}
Resource resource = environmentFactory.getResourceSet().createResource(modelURI, contentType);
if (resource != null) {
getModelManager().addModel(typedModel, resource);
}
}
@Override
protected @NonNull EvaluationEnvironment createNestedEvaluationEnvironment(@NonNull EvaluationEnvironment evaluationEnvironment, @NonNull NamedElement executableObject, @NonNull OCLExpression callingObject) {
if (evaluationEnvironment instanceof QVTiEvaluationEnvironment) {
return new QVTiNestedEvaluationEnvironment((QVTiEvaluationEnvironment) evaluationEnvironment, executableObject, callingObject);
}
else{
return super.createNestedEvaluationEnvironment(evaluationEnvironment, executableObject, callingObject);
}
}
@Override
protected @NonNull EvaluationEnvironment createRootEvaluationEnvironment(@NonNull NamedElement executableObject) {
if (executableObject instanceof Transformation) {
return new QVTiRootEvaluationEnvironment(this, (Transformation) executableObject);
}
else {
return super.createRootEvaluationEnvironment(executableObject);
}
}
protected void doCommits(@NonNull Mapping mapping, @NonNull EvaluationVisitor undecoratedVisitor) {
for (Domain domain : mapping.getDomain()) {
if (domain.isIsEnforceable()) {
CoreDomain enforceableDomain = (CoreDomain)domain;
BottomPattern enforceableBottomPattern = enforceableDomain.getBottomPattern();
for (RealizedVariable realizedVariable : enforceableBottomPattern.getRealizedVariable()) {
realizedVariable.accept(undecoratedVisitor);
}
}
}
BottomPattern middleBottomPattern = mapping.getBottomPattern();
for (Assignment assignment : middleBottomPattern.getAssignment()) {
if (assignment instanceof PropertyAssignment) {
assignment.accept(undecoratedVisitor);
}
}
for (Domain domain : mapping.getDomain()) {
if (domain.isIsEnforceable()) {
CoreDomain enforceableDomain = (CoreDomain)domain;
BottomPattern enforceableBottomPattern = enforceableDomain.getBottomPattern();
for (EnforcementOperation enforceOp : enforceableBottomPattern.getEnforcementOperation()) {
enforceOp.accept(undecoratedVisitor);
}
}
}
// for (EnforcementOperation enforceOp : middleBottomPattern.getEnforcementOperation()) {
// enforceOp.accept(undecoratedVisitor);
// }
}
protected void doEvaluations(@NonNull Mapping mapping, @NonNull EvaluationVisitor undecoratedVisitor) {
for (Domain domain : mapping.getDomain()) {
if (!domain.isIsEnforceable()) {
assert domain.isIsCheckable();
CoreDomain checkableDomain = (CoreDomain)domain;
GuardPattern checkableGuardPattern = checkableDomain.getGuardPattern();
assert checkableGuardPattern.getPredicate().isEmpty();
BottomPattern checkableBottomPattern = checkableDomain.getBottomPattern();
assert checkableBottomPattern.getAssignment().isEmpty();
assert checkableBottomPattern.getEnforcementOperation().isEmpty();
assert checkableBottomPattern.getPredicate().isEmpty();
assert checkableBottomPattern.getRealizedVariable().isEmpty();
assert checkableBottomPattern.getVariable().isEmpty();
}
else {
CoreDomain enforceableDomain = (CoreDomain)domain;
GuardPattern enforceableGuardPattern = enforceableDomain.getGuardPattern();
assert enforceableGuardPattern.getPredicate().isEmpty();
BottomPattern enforceableBottomPattern = enforceableDomain.getBottomPattern();
assert enforceableBottomPattern.getAssignment().isEmpty();
assert enforceableBottomPattern.getPredicate().isEmpty();
for (Variable rVar : enforceableBottomPattern.getVariable()) {
OCLExpression ownedInit = rVar.getOwnedInit();
if (ownedInit != null) {
Object initValue = ownedInit.accept(undecoratedVisitor);
replace(rVar, initValue);
}
}
}
}
BottomPattern middleBottomPattern = mapping.getBottomPattern();
assert middleBottomPattern.getEnforcementOperation().isEmpty();
assert middleBottomPattern.getPredicate().isEmpty();
assert middleBottomPattern.getRealizedVariable().isEmpty();
for (Variable rVar : middleBottomPattern.getVariable()) {
OCLExpression ownedInit = rVar.getOwnedInit();
if (ownedInit != null) {
Object initValue = ownedInit.accept(undecoratedVisitor);
replace(rVar, initValue);
}
}
for (Assignment assignment : middleBottomPattern.getAssignment()) {
if (!(assignment instanceof PropertyAssignment)) {
assignment.accept(undecoratedVisitor);
}
}
}
protected boolean doPredicates(@NonNull Mapping mapping, @NonNull EvaluationVisitor undecoratedVisitor) {
GuardPattern middleGuardPattern = mapping.getGuardPattern();
assert middleGuardPattern.getVariable().isEmpty();
for (Predicate predicate : middleGuardPattern.getPredicate()) {
// If the predicate is not true, the binding is not valid
Object result = predicate.accept(undecoratedVisitor);
if (result != Boolean.TRUE) {
return false;
}
}
return true;
}
public Boolean execute() {
initializeEvaluationEnvironment(transformation);
getRootEvaluationEnvironment();
StandardLibraryInternal standardLibrary = environmentFactory.getStandardLibrary();
Variable ownedContext = QVTbaseUtil.getContextVariable(standardLibrary, transformation);
QVTiModelManager modelManager = getModelManager();
add(ownedContext, modelManager.getTransformationInstance(transformation));
for (TypedModel typedModel : transformation.getModelParameter()) {
if (typedModel != null) {
ownedContext = QVTbaseUtil.getContextVariable(standardLibrary, typedModel);
add(ownedContext, modelManager.getTypedModelInstance(typedModel));
}
}
return executeInternal();
}
protected Boolean executeInternal() {
return (Boolean) getEvaluationVisitor().visit(transformation);
}
@Override
public @NonNull QVTiEnvironmentFactory getEnvironmentFactory() {
return (QVTiEnvironmentFactory) super.getEnvironmentFactory();
}
@Override
public @NonNull QVTiEvaluationEnvironment getEvaluationEnvironment() {
return (QVTiEvaluationEnvironment) super.getEvaluationEnvironment();
}
@Override
public @NonNull QVTiModelManager getModelManager() {
return (QVTiModelManager) modelManager;
}
public @NonNull Transformation getTransformation() {
return transformation;
}
@Override
public @Nullable Object internalExecuteMappingCall(@NonNull MappingCall mappingCall, @NonNull EvaluationVisitor undecoratedVisitor) {
Mapping calledMapping = mappingCall.getReferredMapping();
if (calledMapping != null) {
calledMapping.accept(undecoratedVisitor);
}
return true;
}
@Override
public @Nullable Object internalExecuteMapping(@NonNull Mapping mapping, @NonNull EvaluationVisitor undecoratedVisitor) {
//
// Check the predicates
//
if (!doPredicates(mapping, undecoratedVisitor)) {
return false;
}
//
// Evaluate the enforceable domain expressions.
//
doEvaluations(mapping, undecoratedVisitor);
//
// Perform the instance model addition and property assignment only after all expressions have been evaluated
// possibly throwing a not-ready exception that bypasses premature commits.
//
doCommits(mapping, undecoratedVisitor);
//
// Invoke any corrolaries
//
MappingStatement mappingStatement = mapping.getMappingStatement();
if (mappingStatement != null) {
mappingStatement.accept(undecoratedVisitor);
}
return true;
}
@Override
public @Nullable Object internalExecutePropertyAssignment(@NonNull PropertyAssignment propertyAssignment, @NonNull Object slotObject, @Nullable Object ecoreValue) {
Property targetProperty = propertyAssignment.getTargetProperty();
targetProperty.initValue(slotObject, ecoreValue);
QVTiModelManager modelManager = getModelManager();
Integer cacheIndex = modelManager.getTransformationAnalysis().getCacheIndex(propertyAssignment);
if (cacheIndex != null) {
modelManager.setUnnavigableOpposite(cacheIndex, slotObject, ecoreValue);
}
return ecoreValue;
}
@Override
public @Nullable Object internalExecuteRealizedVariable(@NonNull RealizedVariable realizedVariable, @NonNull EvaluationVisitor undecoratedVisitor) {
// Realized variables are in the mapping's target bottom pattern
// and create elements in the target model. The realized variables
// are being visited for each binding of variable in the mapping.
Type type = realizedVariable.getType();
if (!(type instanceof org.eclipse.ocl.pivot.Class)) {
return null;
}
Area area = ((BottomPattern)realizedVariable.eContainer()).getArea();
TypedModel typedModel = QVTcoreBaseUtil.getTypedModel(area);
assert typedModel != null;
Object element = ((org.eclipse.ocl.pivot.Class)type).createInstance();
// Add the realize variable binding to the environment
replace(realizedVariable, element);
getModelManager().addModelElement(typedModel, element);
return element;
}
@Override
public @Nullable Object internalExecuteTransformation(@NonNull Transformation transformation, @NonNull EvaluationVisitor undecoratedVisitor) {
Rule rule = NameUtil.getNameable(transformation.getRule(), QVTimperativeUtil.ROOT_MAPPING_NAME);
if (rule == null) {
throw new IllegalStateException("Transformation " + transformation.getName() + " has no root mapping");
}
@SuppressWarnings("null")@NonNull CallExp callExp = PivotFactory.eINSTANCE.createOperationCallExp(); // FIXME TransformationCallExp
pushEvaluationEnvironment(rule, callExp);
try {
rule.accept(undecoratedVisitor);
}
finally {
popEvaluationEnvironment();
}
return true;
}
/**
* Loads the modelURI and binds it to the named TypedModel.
*/
public void loadModel(@NonNull String name, @NonNull URI modelURI) {
TypedModel typedModel = NameUtil.getNameable(transformation.getModelParameter(), name);
if (typedModel == null) {
throw new IllegalStateException("Unknown TypedModel '" + name + "'");
}
Resource resource = environmentFactory.getResourceSet().getResource(modelURI, true);
if (resource != null) {
getModelManager().addModel(typedModel, resource);
}
}
public void loadModel(@NonNull String name, @NonNull URI modelURI, String contentType) {
TypedModel typedModel = NameUtil.getNameable(transformation.getModelParameter(), name);
if (typedModel == null) {
throw new IllegalStateException("Unknown TypedModel '" + name + "'");
}
Resource resource;
ResourceSet resourceSet = environmentFactory.getResourceSet();
if (contentType == null) {
resource = resourceSet.getResource(modelURI, true);
}
else {
resource = resourceSet.createResource(modelURI, contentType);
try {
resource.load(null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (resource != null) {
getModelManager().addModel(typedModel, resource);
}
}
public void saveModels() {
getModelManager().saveModels();
}
public void saveModels(@Nullable Map<?, ?> savingOptions) {
getModelManager().saveModels(savingOptions);
}
public void saveModels(@NonNull URI traceURI) {
this.saveModels(traceURI, null);
}
public void saveModels(@NonNull URI traceURI, @Nullable Map<?, ?> savingOptions) {
this.saveModels(savingOptions);
getModelManager().saveMiddleModel(traceURI, savingOptions);
}
public void saveTransformation(Map<?,?> options) throws IOException {
XMLResource resource = (XMLResource) transformation.eResource();
// new AS2ID().assignIds(resource.getResourceSet());
resource.save(options);
}
}