blob: 027c24d9da79205d499cc0c326a2fa7a3668272a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2016 The University of York and Willink Transformations.
* 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:
* Horacio Hoyos - initial API and implementation
******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvtr2qvtc;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.CollectionLiteralPart;
import org.eclipse.ocl.pivot.CollectionType;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.IntegerLiteralExp;
import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.qvtd.compiler.CompilerChainException;
import org.eclipse.qvtd.compiler.internal.qvtr2qvtc.InvokedRelationToMappingForEnforcement.InvokedEnforceableRelationDomain2CoreMapping;
import org.eclipse.qvtd.pivot.qvtbase.Domain;
import org.eclipse.qvtd.pivot.qvtbase.Pattern;
import org.eclipse.qvtd.pivot.qvtbase.Predicate;
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.qvtcore.BottomPattern;
import org.eclipse.qvtd.pivot.qvtcore.CoreDomain;
import org.eclipse.qvtd.pivot.qvtcore.CorePattern;
import org.eclipse.qvtd.pivot.qvtcore.GuardPattern;
import org.eclipse.qvtd.pivot.qvtcore.Mapping;
import org.eclipse.qvtd.pivot.qvtcore.RealizedVariable;
import org.eclipse.qvtd.pivot.qvtcore.VariableAssignment;
import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreHelper;
import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreUtil;
import org.eclipse.qvtd.pivot.qvtrelation.DomainPattern;
import org.eclipse.qvtd.pivot.qvtrelation.Key;
import org.eclipse.qvtd.pivot.qvtrelation.Relation;
import org.eclipse.qvtd.pivot.qvtrelation.RelationCallExp;
import org.eclipse.qvtd.pivot.qvtrelation.RelationDomain;
import org.eclipse.qvtd.pivot.qvtrelation.RelationalTransformation;
import org.eclipse.qvtd.pivot.qvtrelation.utilities.QVTrelationUtil;
import org.eclipse.qvtd.pivot.qvttemplate.CollectionTemplateExp;
import org.eclipse.qvtd.pivot.qvttemplate.ObjectTemplateExp;
import org.eclipse.qvtd.pivot.qvttemplate.PropertyTemplateItem;
import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
/**
* AbstractQVTr2QVTcRelations defines the mapping from a Relation, with a nested AbstractEnforceableRelationDomain2CoreMapping
* for each distinct enforcement of that relation and a further nested AbstractOtherRelationDomain2CoreDomain for each
* other domain of the distinct enforcement.
*/
/*public*/ abstract class AbstractQVTr2QVTcRelations extends QVTcoreHelper
{
protected abstract class AbstractEnforceableRelationDomain2CoreMapping
{
protected abstract class AbstractOtherRelationDomain2CoreDomain
{
protected final @NonNull RelationDomain rOtherDomain; // A not-enforced domain wrt the enforced domain
protected final @NonNull String rOtherDomainName;
protected final @NonNull TypedModel rOtherTypedModel;
protected final @NonNull TypedModel cOtherTypedModel;
protected final @NonNull CoreDomain cOtherDomain;
protected final @NonNull GuardPattern cOtherGuardPattern;
protected final @NonNull BottomPattern cOtherBottomPattern;
protected final @NonNull Map<@NonNull Variable, @Nullable TemplateExp> rOtherBoundVariables; // All variables defined in this other domain
protected final @NonNull Set<@NonNull Variable> rOtherReferredVariables; // All variables defined or referenced in this other domain
protected final @NonNull List<@NonNull Variable> rOtherRootVariables; // The template expression variable (the root variable of this other domain pattern)
public AbstractOtherRelationDomain2CoreDomain(@NonNull RelationDomain rOtherDomain) {
this.rOtherDomain = rOtherDomain;
this.rOtherDomainName = ClassUtil.nonNullState(rOtherDomain.getName());
this.rOtherTypedModel = QVTrelationUtil.getTypedModel(rOtherDomain);
this.cOtherTypedModel = getCoreTypedModel(rOtherTypedModel);
this.cOtherDomain = createCoreDomain(cOtherTypedModel, false);
cOtherDomain.setIsCheckable(rOtherDomain.isIsCheckable());
this.cOtherGuardPattern = ClassUtil.nonNullState(cOtherDomain.getGuardPattern());
this.cOtherBottomPattern = ClassUtil.nonNullState(cOtherDomain.getBottomPattern());
this.rOtherBoundVariables = new HashMap<>();
VariablesAnalysis.gatherBoundVariables(rOtherBoundVariables, rOtherDomain);
this.rOtherReferredVariables = new HashSet<>();
VariablesAnalysis.gatherReferredVariables(rOtherReferredVariables, rOtherDomain);
this.rOtherRootVariables = QVTrelationUtil.getRootVariables(rOtherDomain);
for (@NonNull Variable rVariable : rOtherBoundVariables.keySet()) {
variablesAnalysis.getVariableAnalysis(rVariable).setOtherBound(cOtherDomain);
}
for (@NonNull Variable rVariable : rOtherReferredVariables) {
variablesAnalysis.getVariableAnalysis(rVariable).setOtherReferred(cOtherDomain);
}
for (@NonNull Variable rVariable : rOtherRootVariables) {
variablesAnalysis.getVariableAnalysis(rVariable).setIsRoot();
}
}
// new
private void mapOtherCollectionTemplateExpression(@NonNull CollectionTemplateExp cte) throws CompilerChainException {
Variable vcte = ClassUtil.nonNullState(cte.getBindsTo());
Variable mvcte = variablesAnalysis.getCoreVariable(vcte);
/**
* Each CollectionTemplateExp member that is not a variable
* converts to a VariableAssignment of a new variable the member expression.
*
* ve1:T1{tp = ve2:Collection{a++b}} => a := a;
*/
Map<@NonNull OCLExpression, @NonNull Variable> rMember2mVariable = new HashMap<>();
List<@NonNull OCLExpression> rMembers = ClassUtil.nullFree(cte.getMember());
for (@NonNull OCLExpression rMember : rMembers) {
Variable mVariable;
if (rMember instanceof TemplateExp) {
TemplateExp rTemplateExp = (TemplateExp)rMember;
mapOtherTemplateExpression(rTemplateExp);
Variable rVariable = ClassUtil.nonNullState(rTemplateExp.getBindsTo());
mVariable = variablesAnalysis.getCoreVariable(rVariable);
}
else if (rMember instanceof VariableExp) {
Variable rVariable = ClassUtil.nonNullState((Variable)((VariableExp)rMember).getReferredVariable());
mVariable = variablesAnalysis.getCoreVariable(rVariable);
}
else {
OCLExpression mMember = mapExpression(rMember);
mVariable = variablesAnalysis.addCoreVariable("member", mMember);
}
rMember2mVariable.put(rMember, mVariable);
}
// CollectionTemplateExp cte = (CollectionTemplateExp) ptv;
// Variable vcte = ClassUtil.nonNullState(cte.getBindsTo());
// Variable mvcte = doRVarToMVar(vcte);
// PropertyCallExp pce = createPropertyCallExp(ve1, tp);
// VariableAssignment a = createVariableAssignment(mvcte, pce);
// mb.getAssignment().add(a);
CollectionType collectionType = ClassUtil.nonNullState(cte.getReferredCollectionType());
int size = rMembers.size();
Variable rRest = cte.getRest();
if (rRest == null) {
/**
* The predicate for a CollectionTemplateExp without a rest variable is a total comparison.
*
* ve1:T1{tp = ve2:Collection{a++b}} => ve2 := ve1.tp; ve2 = Collection{a,b};
*/
List<@NonNull CollectionLiteralPart> mParts = new ArrayList<>();
for (@NonNull OCLExpression rMember : rMembers) {
Variable mVariable = ClassUtil.nonNullState(rMember2mVariable.get(rMember));
CollectionLiteralPart mItem = createCollectionItem(createVariableExp(mVariable));
mParts.add(mItem);
}
CollectionLiteralExp cle = createCollectionLiteralExp(collectionType, mParts);
variablesAnalysis.addConditionPredicate(cMiddleBottomPattern, createVariableExp(mvcte), cle);
}
else {
Variable mRest = variablesAnalysis.getCoreVariable(rRest);
if (collectionType.isOrdered()) {
/**
* The assignment for an ordered CollectionTemplateExp rest variable is a sub-collection assignment.
*
* ve1:T1{tp = ve2:Collection{a,b++c}} => c := ve2->subCollection(3,ve2->size());
*/
VariableExp vRest = createVariableExp(rRest);
String opName = collectionType.isUnique() ? "subOrderedSet" : "subSequence";
IntegerLiteralExp eStart = createIntegerLiteralExp(size);
OCLExpression eFinish = createOperationCallExp(createVariableExp(mvcte), "size");
OCLExpression eTail = createOperationCallExp(createVariableExp(mvcte), opName, vRest, eStart, eFinish);
VariableAssignment aRest = createVariableAssignment(mRest, eTail);
cMiddleBottomPattern.getAssignment().add(aRest);
/**
* The predicates for each ordered CollectionTemplateExp member variable is an element comparison.
*
* ve1:T1{tp = ve2:Collection{a,b++c}} => a = ve2->at(1);
*/
for (int i = 0; i < size; i++) {
IntegerLiteralExp eIndex = createIntegerLiteralExp(i+1);
OCLExpression vElement = createOperationCallExp(createVariableExp(mvcte), "at", eIndex);
OCLExpression rMember = rMembers.get(i);
Variable mVariable = ClassUtil.nonNullState(rMember2mVariable.get(rMember));
variablesAnalysis.addConditionPredicate(cMiddleBottomPattern, createVariableExp(mVariable), vElement);
}
}
else {
/**
* The assignment for an unordered CollectionTemplateExp rest variable is a cumulative exclusion.
*
* ve1:T1{tp = ve2:Collection{a,b++c}} => c := ve2->excluding(a)->excluding(b);
*/
OCLExpression exclusions = createVariableExp(mvcte);
for (@NonNull OCLExpression rMember : rMembers) {
Variable mVariable = ClassUtil.nonNullState(rMember2mVariable.get(rMember));
exclusions = createOperationCallExp(exclusions, "excluding", createVariableExp(mVariable));
}
VariableAssignment aRest = createVariableAssignment(mRest, exclusions);
cMiddleBottomPattern.getAssignment().add(aRest);
/**
* The predicates for each unordered CollectionTemplateExp member variable is an excluded inclusion test.
*
* ve1:T1{tp = ve2:Collection{a,b++c}} => ve2->excluding(a)->includes(b);
*/
for (int i = 0; i < size; i++) {
@NonNull OCLExpression eTerm = createVariableExp(mvcte);
for (int j = 0; j < i; j++) {
OCLExpression rMember = rMembers.get(j);
Variable mVariable = ClassUtil.nonNullState(rMember2mVariable.get(rMember));
eTerm = createOperationCallExp(eTerm, "excluding", createVariableExp(mVariable));
}
OCLExpression rMember = rMembers.get(i);
Variable mVariable = ClassUtil.nonNullState(rMember2mVariable.get(rMember));
eTerm = createOperationCallExp(eTerm, "includes", createVariableExp(mVariable));
variablesAnalysis.addPredicate(cMiddleBottomPattern, eTerm);
}
}
}
}
// loop body of RDomainPatternToMDBottomPatternComposite
private void mapOtherObjectTemplateExpression(@NonNull ObjectTemplateExp rTemplateExpression) throws CompilerChainException {
Variable rTemplateVariable = ClassUtil.nonNullState(rTemplateExpression.getBindsTo());
for (@NonNull PropertyTemplateItem propertyTemplateItem : ClassUtil.nullFree(rTemplateExpression.getPart())) {
Property partProperty = ClassUtil.nonNullState(propertyTemplateItem.getReferredProperty());
Variable cTemplateVariable = variablesAnalysis.getCoreVariable(rTemplateVariable);
OCLExpression propertyTemplateValue = ClassUtil.nonNullState(propertyTemplateItem.getValue());
if (propertyTemplateValue instanceof VariableExp) {
// body of RDomainPatternToMDBottomPatternSimpleSharedVarExpr and RDomainPatternToMDBottomPatternSimpleUnSharedVarExpr
/**
* Each PropertyTemplateItem whose value is a simple VariableExp
* converts to a domain(unshared) / middle(shared) PropertyAssignment.
*
* ve1:T{tp = ve2} => ve1.tp := ve2;
*/
Variable rVariable/*vpte*/ = ClassUtil.nonNullState((Variable) ((VariableExp)propertyTemplateValue).getReferredVariable());
Variable cVariable/*mvpte*/ = variablesAnalysis.getCoreVariable(rVariable);
// BottomPattern cBottomPattern = rSharedVariables.contains(rVariable) ? cMiddleBottomPattern : cEnforcedBottomPattern;
variablesAnalysis.addNavigationAssignment(rTemplateVariable, partProperty, createVariableExp(cVariable));
}
else if (propertyTemplateValue instanceof CollectionTemplateExp) {
/**
* Each PropertyTemplateItem whose value is a CollectionTemplateExp
* converts to a VariableAssignment and Predicates.
*
* ve1:T1{tp = ve2:Collection{a++b}} => ve2 := ve1.tp;
*/
CollectionTemplateExp cte = (CollectionTemplateExp)propertyTemplateValue;
Variable vcte = ClassUtil.nonNullState(cte.getBindsTo());
Variable mvcte = variablesAnalysis.getCoreVariable(vcte);
NavigationCallExp pce = createNavigationCallExp(createVariableExp(cTemplateVariable), partProperty);
VariableAssignment a = createVariableAssignment(mvcte, pce);
cMiddleBottomPattern.getAssignment().add(a);
mapOtherCollectionTemplateExpression(cte);
}
else if (propertyTemplateValue instanceof ObjectTemplateExp) {
/**
* Each PropertyTemplateItem whose value is an ObjectTemplateExp
* converts to a PropertyAssignment.
*
* ve1:T1{tp = ve2:T2{...}} => ve1.tp := ve2;
*/
ObjectTemplateExp pte = (ObjectTemplateExp)propertyTemplateValue;
Variable vpte = ClassUtil.nonNullState(pte.getBindsTo());
Variable mvpte = variablesAnalysis.getCoreVariable(vpte);
variablesAnalysis.addNavigationAssignment(rTemplateVariable, partProperty, createVariableExp(mvpte));
mapOtherObjectTemplateExpression(pte);
}
else {
// loop body of RDomainPatternToMDBottomPatternSimpleNonVarExpr
/**
* Each PropertyTemplateItem whose value is not a TemplateExp and not a VariableExp
* converts to a PropertyAssignment.
*
* ve1:T{tp = me} => ve1.tp := me;
*/
variablesAnalysis.addNavigationAssignment(rTemplateVariable, partProperty, mapExpression(propertyTemplateValue));
}
}
}
// RDomainPatternToMDBottomPattern
protected void mapOtherTemplateExpression(@NonNull TemplateExp rTemplateExpression) throws CompilerChainException {
if (rTemplateExpression instanceof ObjectTemplateExp) {
mapOtherObjectTemplateExpression((ObjectTemplateExp)rTemplateExpression);
}
else if (rTemplateExpression instanceof CollectionTemplateExp) {
mapOtherCollectionTemplateExpression((CollectionTemplateExp)rTemplateExpression);
}
OCLExpression rGuardPredicate = rTemplateExpression.getWhere();
if (rGuardPredicate != null) {
cMiddleBottomPattern.getPredicate().add(createPredicate(mapExpression(rGuardPredicate)));
}
}
public void synthesize() throws CompilerChainException {
List<@NonNull TemplateExp> rOtherTemplateExpressions = getTemplateExpressions(rOtherDomain);
for (@NonNull TemplateExp rOtherTemplateExpression : rOtherTemplateExpressions) {
mapOtherTemplateExpression(rOtherTemplateExpression);
}
}
}
/**
* An ExpressionCopier deep copies an OCLExpression tree, exploiting the forward traceability of context to
* update references and using sibling to distinguish multiple targets.
*/
@SuppressWarnings("serial")
protected class ExpressionCopier extends EcoreUtil.Copier
{ // FIXME enforce unique names on let-variables, iterators
@Override
public EObject get(Object oIn) {
if (oIn instanceof Element) {
List<@NonNull Element> oOuts = source2targets.get(oIn);
if (oOuts != null) {
assert oOuts.size() == 1;
return oOuts.get(0);
}
oOuts = qvtr2qvtc.getGlobalTargets((Element) oIn);
if (oOuts != null) {
assert oOuts.size() == 1;
return oOuts.get(0);
}
}
return super.get(oIn);
}
}
// Relations
protected final @NonNull RelationDomain rEnforcedDomain; // rd: This source enforced domain
protected final @NonNull TypedModel rEnforcedTypedModel; // rEnforcedDomain.getTypedModel()
protected final @NonNull String rEnforcedDomainName; // rEnforcedDomain.getName()
protected final @NonNull Map<@NonNull Variable, @Nullable TemplateExp> rEnforcedBoundVariables; // All variables defined in this domain
protected final @NonNull Set<@NonNull Variable> rEnforcedReferredVariables; // All variables defined or referenced in this domain
protected final @NonNull List<@NonNull/*Object*/TemplateExp> rEnforcedTemplateExpressions; // te: The template expression defining the enforced domain pattern
protected final @NonNull List<@NonNull Variable> rEnforcedRootVariables; // tev: The template expression variable (the root variable of the enforced domain pattern)
protected final @NonNull List<@NonNull AbstractOtherRelationDomain2CoreDomain> otherDomain2coreDomains; // All other domains sharing the parent of this domain
protected final @NonNull Set<@NonNull Variable> rAllOtherBoundVariables; // All variables defined in other domains
protected final @NonNull Set<@NonNull Variable> rAllOtherReferredVariables; // All variables defined or referenced in other domains
// Core
protected final @NonNull Mapping cMapping; // m: The resultant mapping
protected final @NonNull GuardPattern cMiddleGuardPattern; // mg: The resultant mapping guard pattern
protected final @NonNull BottomPattern cMiddleBottomPattern; // mb : The resultant mapping bottom pattern
protected final @NonNull TypedModel cEnforcedTypedModel; // mdir: The resultant enforced typed model
protected final @NonNull CoreDomain cEnforcedDomain; // md: The resultant enforced domain
protected final @NonNull GuardPattern cEnforcedGuardPattern; // dg: The resultant enforced domain guard pattern
protected final @NonNull BottomPattern cEnforcedBottomPattern; // db: The resultant enforced domain bottom pattern
protected final @NonNull VariablesAnalysis variablesAnalysis;
protected final @NonNull RealizedVariable cMiddleRealizedVariable; // tcv: The trace class variable (the middle variable identifying the middle object)
private final @NonNull Map<@NonNull Element, @NonNull List<@NonNull Element>> source2targets = new HashMap<>();
private final @NonNull Map<@NonNull Element, @NonNull Element> target2source = new HashMap<>();
public AbstractEnforceableRelationDomain2CoreMapping(@NonNull RelationDomain rEnforcedDomain, @NonNull String cMappingName) {
this.rEnforcedDomain = rEnforcedDomain;
//
this.rEnforcedBoundVariables = new HashMap<>();
VariablesAnalysis.gatherBoundVariables(rEnforcedBoundVariables, rEnforcedDomain);
this.rEnforcedReferredVariables = new HashSet<>();
VariablesAnalysis.gatherReferredVariables(rEnforcedReferredVariables, rEnforcedDomain);
this.rEnforcedTemplateExpressions = getTemplateExpressions(rEnforcedDomain);
this.rEnforcedRootVariables = QVTrelationUtil.getRootVariables(rEnforcedDomain);
this.rEnforcedTypedModel = QVTrelationUtil.getTypedModel(rEnforcedDomain);
this.rEnforcedDomainName = ClassUtil.nonNullState(rEnforcedDomain.getName());
@NonNull Type traceClass = qvtr2qvtc.getTraceClass(rRelation);
//
this.cEnforcedTypedModel = getCoreTypedModel(rEnforcedTypedModel);
this.cMapping = qvtr2qvtc.createMapping(rRelation, cMappingName);
this.cMiddleGuardPattern = ClassUtil.nonNullState(cMapping.getGuardPattern());
this.cMiddleBottomPattern = ClassUtil.nonNullState(cMapping.getBottomPattern());
this.cEnforcedDomain = createCoreDomain(cEnforcedTypedModel, true);
this.cEnforcedGuardPattern = ClassUtil.nonNullState(cEnforcedDomain.getGuardPattern());
this.cEnforcedBottomPattern = ClassUtil.nonNullState(cEnforcedDomain.getBottomPattern());
//
this.variablesAnalysis = new VariablesAnalysis(qvtr2qvtc, rEnforcedDomain, cEnforcedDomain, traceClass, this instanceof InvokedEnforceableRelationDomain2CoreMapping);
this.cMiddleRealizedVariable = variablesAnalysis.getMiddleRealizedVariable();
// putTrace(cMiddleRealizedVariable, cMiddleBottomPattern);
//
this.otherDomain2coreDomains = new ArrayList<>();
this.rAllOtherBoundVariables = new HashSet<>();
for (@NonNull Domain rDomain : ClassUtil.nullFree(rEnforcedDomain.getRule().getDomain())) {
if ((rDomain != rEnforcedDomain) && (rDomain instanceof RelationDomain)) {
RelationDomain rRelationDomain = (RelationDomain)rDomain;
otherDomain2coreDomains.add(createOtherDomain2CoreDomain(rRelationDomain));
}
}
Set<@NonNull Variable> rUnsharedEnforcedDomainVariables = new HashSet<>(rEnforcedReferredVariables);
rUnsharedEnforcedDomainVariables.removeAll(rSharedVariables);
this.rAllOtherReferredVariables = new HashSet<>(rAllDomainVariables);
rAllOtherReferredVariables.removeAll(rUnsharedEnforcedDomainVariables);
//
for (Map.Entry<@NonNull Variable, @Nullable RelationDomain> entry : rWhenVariable2rDomain.entrySet()) {
RelationDomain rWhenDomain = entry.getValue();
if (rWhenDomain != null) {
variablesAnalysis.getVariableAnalysis(entry.getKey()).setWhen(getCoreDomain(rWhenDomain));
}
}
for (Map.Entry<@NonNull Variable, @Nullable RelationDomain> entry : rWhereVariable2rDomain.entrySet()) {
RelationDomain rWhereDomain = entry.getValue();
if (rWhereDomain != null) {
variablesAnalysis.getVariableAnalysis(entry.getKey()).setWhere(getCoreDomain(rWhereDomain));
}
}
for (@NonNull Variable rVariable : rEnforcedBoundVariables.keySet()) {
Key rKey = qvtr2qvtc.getKeyForType(ClassUtil.nonNullState(rVariable.getType()));
variablesAnalysis.getVariableAnalysis(rVariable).setIsEnforcedBound(rEnforcedBoundVariables.get(rVariable), rKey);
}
for (@NonNull Variable rVariable : rEnforcedReferredVariables) {
variablesAnalysis.getVariableAnalysis(rVariable).setIsEnforcedReferred();
}
for (@NonNull Variable rVariable : rEnforcedRootVariables) {
variablesAnalysis.getVariableAnalysis(rVariable).setIsRoot();
}
//
for (Map.Entry<@NonNull Variable, @Nullable RelationDomain> entry : rWhenVariable2rDomain.entrySet()) {
Variable rWhenVariable = entry.getKey();
RelationDomain rWhenDomain = entry.getValue();
VariableAnalysis variableAnalysis = variablesAnalysis.getVariableAnalysis(rWhenVariable);
if (rWhenDomain == null) {
OCLExpression rWhenInit = rWhenVariable.getOwnedInit();
if (rWhenInit != null) {
Set<@NonNull Variable> rReferredVariables = new HashSet<>();
VariablesAnalysis.gatherReferredVariables(rReferredVariables, rWhenInit);
for (Variable rReferredVariable : rReferredVariables) {
VariableAnalysis referredVariableAnalysis = variablesAnalysis.basicGetVariableAnalysis(rReferredVariable);
if (referredVariableAnalysis != null) {
CorePattern corePattern = referredVariableAnalysis.getCorePattern();
if (corePattern != null) {
variableAnalysis.setPredicate(ClassUtil.nonNullState(corePattern.getArea())); // FIXME need QVTrDomainAnalayis
}
break;
}
}
}
}
}
//
QVTr2QVTc.VARIABLES.println(" In " + cMapping + "\n\t\t" + variablesAnalysis.toString().replace("\n", "\n\t\t"));
for (@NonNull VariableAnalysis analysis : variablesAnalysis.getAnalyses()) {
Variable rVariable = analysis.getRelationVariable();
if (rVariable != null) {
Variable cVariable = analysis.getCoreVariable();
putTrace(cVariable, rVariable);
}
}
for (@NonNull VariableAnalysis analysis : variablesAnalysis.getAnalyses()) {
Variable rVariable = analysis.getRelationVariable();
if (rVariable != null) {
OCLExpression rOwnedInit = rVariable.getOwnedInit();
if (rOwnedInit != null) {
Variable cVariable = analysis.getCoreVariable();
cVariable.setOwnedInit(mapExpression(rOwnedInit));
// variablesAnalysis.addConditionPredicate(analysis.getCorePattern(), createVariableExp(cVariable), mapExpression(rOwnedInit));
}
}
}
}
// Quad call of RDomainPatternExprToMappingXXXX
private void addPropertyAssignmentToMiddleBottomPattern(@NonNull Variable rTargetVariable, @NonNull Property targetProperty, @NonNull OCLExpression rExpression) throws CompilerChainException {
Variable cTargetVariable = null;
OCLExpression cExpression = null;
if (rExpression instanceof ObjectTemplateExp) {
// body of RDomainPatternExprToMappingDomainTemplateVarAssignment
Variable rBoundVariable = ClassUtil.nonNullState(((ObjectTemplateExp)rExpression).getBindsTo());
if (!rSharedVariables.contains(rBoundVariable)) {
Variable cBoundVariable = variablesAnalysis.getCoreVariable(rBoundVariable); // FIXME whenVariable(cMiddleBottomPattern, rBoundVariable);
cExpression = createVariableExp(cBoundVariable);
cTargetVariable = variablesAnalysis.addTraceNavigationAssignment(rBoundVariable, false);
}
}
else if (rExpression instanceof VariableExp) {
cTargetVariable = variablesAnalysis.getCoreVariable(rTargetVariable); // getCoreVariable should do and be uniform
Variable rReferredVariable = ClassUtil.nonNullState((Variable) ((VariableExp)rExpression).getReferredVariable());
Variable cReferredVariable = variablesAnalysis.getCoreVariable(rReferredVariable);
if (rSharedVariables.contains(rReferredVariable) ) {
// body of RDomainPatternExprToMappingBottomVarAssignment
}
else {
// body of RDomainPatternExprToMappingDomainVarAssignment
if (!cEnforcedBottomPattern.getRealizedVariable().contains(cTargetVariable)) {
// FIXME variables should have been plotted earlier
cEnforcedBottomPattern.getRealizedVariable().add((RealizedVariable)cTargetVariable);
}
}
cExpression = createVariableExp(cReferredVariable);
}
else {
// body of RDomainPatternExprToMappingDomainAssignment
cTargetVariable = variablesAnalysis.getCoreVariable(rTargetVariable);
cExpression = mapExpression(rExpression);
}
if ((cTargetVariable != null) && (cExpression != null)) {
variablesAnalysis.addNavigationAssignment(rTargetVariable, targetProperty, cExpression);
}
}
private @NonNull CoreDomain createCoreDomain(@NonNull TypedModel cTypedModel, boolean isEnforced) {
CoreDomain coreDomain = qvtr2qvtc.createCoreDomain(cTypedModel);
coreDomain.setIsEnforceable(isEnforced);
coreDomain.setRule(cMapping);
return coreDomain;
}
protected abstract @NonNull AbstractOtherRelationDomain2CoreDomain createOtherDomain2CoreDomain(@NonNull RelationDomain rRelationDomain);
protected @NonNull CoreDomain getCoreDomain(@NonNull RelationDomain rDomain) {
TypedModel rTypedModel = QVTrelationUtil.getTypedModel(rDomain);
TypedModel cTypedModel = getCoreTypedModel(rTypedModel);
for (@NonNull Domain cDomain : ClassUtil.nullFree(cMapping.getDomain())) { // FIXME provide a Map cache
if (QVTcoreUtil.getTypedModel(cDomain) == cTypedModel) {
return (CoreDomain) cDomain;
}
}
throw new IllegalStateException();
}
protected @NonNull TypedModel getCoreTypedModel(@NonNull TypedModel rTypedModel) {
String name = PivotUtil.getName(rTypedModel);
Iterable<org.eclipse.ocl.pivot.@NonNull Package> usedPackages = QVTrelationUtil.getUsedPackages(rTypedModel);
for (@NonNull TypedModel tm : QVTcoreUtil.getModelParameters(cTransformation)) {
if (name.equals(tm.getName())) {
assert tm.getUsedPackage().equals(usedPackages);
return tm;
}
}
return ClassUtil.nonNullState(null);
}
protected abstract @NonNull Set<@NonNull Variable> getEnforcedBottomDomainVariables();
// protected abstract @NonNull Set<@NonNull Variable> getEnforcedDomainGuardVariables(@NonNull Set<@NonNull Variable> rEnforcedBottomDomainVariables);
protected @NonNull Set<@NonNull RelationDomain> getOtherRelationDomains() {
Set<@NonNull RelationDomain> relationDomains = new HashSet<>();
for (@NonNull Domain relationDomain : QVTrelationUtil.getOwnedDomains(rRelation)) {
relationDomains.add((RelationDomain) relationDomain);
}
relationDomains.remove(rEnforcedDomain);
return relationDomains;
}
protected @NonNull List<@NonNull TemplateExp> getTemplateExpressions(@NonNull RelationDomain rRelationDomain) {
List<@NonNull TemplateExp> rTemplateExpressions = new ArrayList<>();
for (@NonNull DomainPattern rDomainPattern : QVTrelationUtil.getOwnedPatterns(rRelationDomain)) {
rTemplateExpressions.add(QVTrelationUtil.getOwnedTemplateExpression(rDomainPattern));
}
return rTemplateExpressions;
}
private boolean isVarBoundToSomeOtherTemplate(ObjectTemplateExp rootTe, /*Object*/TemplateExp skipTe, Variable v) {
if (rootTe == skipTe) {
return false;
}
if (rootTe.getBindsTo().equals(v)) {
return true;
} else {
boolean exists = false;
for (PropertyTemplateItem p : rootTe.getPart()) {
if (p.getValue() instanceof ObjectTemplateExp) {
exists |= isVarBoundToSomeOtherTemplate((ObjectTemplateExp) p.getValue(), skipTe, v);
}
}
return exists;
}
}
protected void mapEnforcedCollectionTemplateExpression(@NonNull CollectionTemplateExp rEnforcedCollectionTemplateExp, @Nullable Key key) throws CompilerChainException {
// throw new CompilerChainException("Missing doInvokedRelationToMappingForEnforcement support for CollectionTemplateExp");
System.err.println("Missing mapEnforcedCollectionTemplateExpression support");
}
// RDomainToMDBottomForEnforcement (second half)
protected void mapEnforcedDomainPatterns() throws CompilerChainException {
for (@NonNull TemplateExp rEnforcedTemplateExpression/*te*/ : rEnforcedTemplateExpressions) {
mapEnforcedTemplateExpression(rEnforcedTemplateExpression);
}
}
protected void mapEnforcedObjectTemplateExpression(@NonNull ObjectTemplateExp rEnforcedObjectTemplateExpression, @Nullable Key key) throws CompilerChainException {
Variable rTemplateVariable/*v*/ = ClassUtil.nonNullState(rEnforcedObjectTemplateExpression.getBindsTo());
for (@NonNull PropertyTemplateItem pt : ClassUtil.nullFree(rEnforcedObjectTemplateExpression.getPart())) {
Property partProperty = ClassUtil.nonNullState(pt.getReferredProperty());
OCLExpression rPartValue/*pte*/ = ClassUtil.nonNullState(pt.getValue());
if ((key != null) && key.getPart().contains(partProperty)) {
// body of RDomainToMDBottomForEnforcementOfIdentityProp
addPropertyAssignmentToMiddleBottomPattern(rTemplateVariable, partProperty, rPartValue);
}
else if (rPartValue instanceof TemplateExp) {
// body of RDomainToMDBottomForEnforcementOfNonIdentityPropObject
TemplateExp pte = (TemplateExp)rPartValue;
Variable pv = ClassUtil.nonNullState(pte.getBindsTo());
/*Realized*/Variable cTargetVariable/*mpv*/ = variablesAnalysis.getCoreVariable(pv); //rWhenVariables.contains(pv) ? getCoreVariable(pv) : whenRealizedVariable(cEnforcedBottomPattern, pv);
// Variable cTemplateVariable/*mv*/ = variablesAnalysis.getCoreVariable(rTemplateVariable);
variablesAnalysis.addNavigationAssignment(rTemplateVariable, partProperty, createVariableExp(cTargetVariable));
mapEnforcedTemplateExpression(pte);
// Property cTargetProperty2 = qvtr2qvtc.getProperty(cMiddleRealizedVariable.getType(), cTargetVariable);
// variablesAnalysis.addNavigationAssignment(rMiddleRealizedVariable, cTargetProperty2, createVariableExp(cTargetVariable));
}
else {
// body of RDomainToMDBottomForEnforcementOfNonIdentityPropPrimitive
// Variable cTemplateVariable = variablesAnalysis.getCoreVariable(rTemplateVariable);
//RDomainToMComposedMappingGuardrEnforcedDomain
for (@NonNull TemplateExp rTemplateExpression : rEnforcedTemplateExpressions) {
if ((rPartValue instanceof VariableExp) && (rTemplateExpression instanceof ObjectTemplateExp)) {
// check
Variable rReferredVariable = (Variable) ClassUtil.nonNullState(((VariableExp) rPartValue).getReferredVariable());
if (isVarBoundToSomeOtherTemplate((ObjectTemplateExp) rTemplateExpression, rEnforcedObjectTemplateExpression, rReferredVariable)) {
Variable cReferredVariable = variablesAnalysis.getCoreVariable(rReferredVariable);
Property cTargetProperty = qvtr2qvtc.getProperty(cReferredVariable.getType(), cReferredVariable);
NavigationCallExp cPropertyCallExp = createNavigationCallExp(createVariableExp(cMiddleRealizedVariable), cTargetProperty);
variablesAnalysis.addConditionPredicate(cMiddleGuardPattern, cPropertyCallExp, createVariableExp(cReferredVariable));
cEnforcedGuardPattern.getBindsTo().add(cReferredVariable);
}
}
variablesAnalysis.addNavigationAssignment(rTemplateVariable, partProperty, mapExpression(rPartValue));
}
}
}
}
// RDomainToMDBottomForEnforcement
private void mapEnforcedTemplateExpression(@NonNull TemplateExp rEnforcedTemplateExpression/*te*/) throws CompilerChainException {
Variable rTemplateVariable/*v*/ = ClassUtil.nonNullState(rEnforcedTemplateExpression.getBindsTo());
Type rTemplateVariableType/*c*/ = ClassUtil.nonNullState(rTemplateVariable.getType());
Key key = qvtr2qvtc.getKeyForType(rTemplateVariableType);
VariableAnalysis variableAnalysis = variablesAnalysis.getVariableAnalysis(rTemplateVariable);
if (variableAnalysis.hasWhenDomain()) {
key = null;
}
// if (key == null){
// // Nothing to do
// }
/*else*/ if (rEnforcedTemplateExpression instanceof ObjectTemplateExp) {
mapEnforcedObjectTemplateExpression((ObjectTemplateExp)rEnforcedTemplateExpression, key);
}
else if (rEnforcedTemplateExpression instanceof CollectionTemplateExp) {
mapEnforcedCollectionTemplateExpression((CollectionTemplateExp)rEnforcedTemplateExpression, key);
}
else {
throw new CompilerChainException("Missing mapEnforcedTemplateExpression support " + rEnforcedTemplateExpression.eClass().getName());
}
// This call is wrong as the trace variable is realized, it can't be guarded.
// This should only be done in a nested mapping or later mapping
//doRDomainToMBottomPredicateForEnforcement(r, rd, te, predicatesWithoutVarBindings, unboundDomainVars, mb);
/*
* Creates the assignment of the middle model to the L/R models
*/
// RDomainVarToMDBottomAssignmnetForEnforcement
variablesAnalysis.addTraceNavigationAssignment(rTemplateVariable, false);
}
// 15
/*
* Creates a Predicate, who's ConditionExpression is an
* OperationCallExp:
* trace.<v.name> = v;
* TODO Suggest better name: RDomainPatternVariableToTracePredicate?
*
private void doRDomainToMBottomPredicateForEnforcement(@NonNull Set<@NonNull Predicate> predicatesWithoutVarBindings, @NonNull Set<@NonNull Variable> unboundDomainVars) throws CompilerChainException
{
Set<@NonNull Variable> remainingUnBoundDomainVars = new HashSet<>(unboundDomainVars);
remainingUnBoundDomainVars.removeAll(rEnforcedRootVariables);
Set<@NonNull Predicate> predicatesWithVarBindings =
selectPredicatesThatReferToVariables(predicatesWithoutVarBindings, remainingUnBoundDomainVars);
mapPredicatesToPredicates(predicatesWithVarBindings);
// assign
for (@NonNull Variable v : rEnforcedRootVariables) {
@NonNull Variable mv = getCoreVariable(v);
Property pep = getProperty(cMiddleRealizedVariable.getType(), v);
NavigationCallExp pe = createNavigationCallExp(createVariableExp(cMiddleRealizedVariable), pep);
addConditionPredicate(cMiddleBottomPattern, pe, createVariableExp(mv));
}
} */
/*
* The issue with this method is that all variables should have been
* transformed so all variable references can be correctly pointed.
* However, if we call it after all variable modifying relations it
* should work.
*/
// 25
protected @NonNull OCLExpression mapExpression(@NonNull OCLExpression rExpression) {
EcoreUtil.Copier copier = new ExpressionCopier();
OCLExpression eOut = (OCLExpression) copier.copy(rExpression);
copier.copyReferences();
for (EObject eSource : copier.keySet()) {
EObject eTarget = copier.get(eSource);
if (eTarget != null) {
assert eSource != null;
putTrace((Element)eTarget, (Element)eSource);
}
}
assert eOut != null;
return eOut;
}
protected void mapInvocation() throws CompilerChainException {}
// IROppositeDomainsToMappingForEnforcement
protected void mapOtherDomainPatterns() throws CompilerChainException
{
for (@NonNull AbstractOtherRelationDomain2CoreDomain otherDomain2coreDomain : otherDomain2coreDomains) {
otherDomain2coreDomain.synthesize();
}
}
// ROppositeDomainVarsToTraceClassProps
protected void mapOtherDomainVariables(@NonNull Set<@NonNull Variable> rDomainVariables) throws CompilerChainException {
for (@NonNull Variable rDomainVariable : rDomainVariables) {
// VariableAnalysis analysis = getVariableAnalysis(rDomainVariable);
// TemplateExp rTemplateExp = analysis.getTemplateExp();
// if (dvte instanceof ObjectTemplateExp) {
// tp=dv:T{...} => tcv.tp := dv;
variablesAnalysis.addTraceNavigationAssignment(rDomainVariable, true);
// }
/* else if (dvte instanceof CollectionTemplateExp) {
// tp=dv:T{...} => tcv.tp := dv;
Variable mdv = doRVarToMVar(dv);
// VariableExp ve1 = createVariableExp(tcv);
VariableExp ve2 = createVariableExp(mdv);
VariableAssignment a = createVariableAssignment(mdv, ve2);
mb.getAssignment().add(a);
} */
/* else if (dvte instanceof CollectionTemplateExp) {
CollectionTemplateExp collectionTemplateExp = (CollectionTemplateExp)dvte;
} */
}
}
// protected @NonNull Variable mapRealizedVariable(@NonNull Variable rVariable) {
// return whenRealizedVariable(cEnforcedBottomPattern, rVariable);
// }
/**
* Transform a rule implemented by a black box into an enforcement operation
*
* @param rRelation the r
* @param rEnforcedDomain the rd
* @param cMiddleBottomPattern the mb
*/
// RRelImplToMBottomEnforcementOperation
protected void mapRelationImplementation() {
// TODO Code this when testing transformations with operational implementations.
}
// protected void mapVariables(@NonNull Iterable<@NonNull Variable> rVariables, @NonNull CorePattern cPattern) { // RVarSetToDGVarSet, RVarSetToMBVarSet
// for (@NonNull Variable rVariable : rVariables) {
// whenVariable(cPattern, rVariable);
// }
// }
// RWhenPatternToMGuardPattern
protected void mapWhenPattern() throws CompilerChainException {
Pattern rWhenPattern = rRelation.getWhen();
if (rWhenPattern != null) {
Set<@NonNull Variable> rMiddleGuardDomainVariables = new HashSet<>(rWhenVariable2rDomain.keySet());
rMiddleGuardDomainVariables.removeAll(rAllDomainVariables);
//
for (@NonNull Predicate rWhenPredicate : QVTrelationUtil.getPredicates(rWhenPattern)) {
OCLExpression rConditionExpression = QVTrelationUtil.getConditionExpression(rWhenPredicate);
if (rConditionExpression instanceof RelationCallExp) {
// body of RWhenRelCallToMGuard
RelationCallExp rInvocation = (RelationCallExp)rConditionExpression;
Relation rInvokedRelation = QVTrelationUtil.getReferredRelation(rInvocation);
Type invokedTraceClass/*tc*/ = qvtr2qvtc.getTraceClass(rInvokedRelation);
//
List<@NonNull OCLExpression> rArguments = QVTrelationUtil.getOwnedArguments(rInvocation);
/* StringBuilder s = new StringBuilder();
for (OCLExpression rArgument : rArguments) {
VariableExp a = (VariableExp) rArgument;
s.append("_");
s.append(a.getReferredVariable().getName());
}
String vdId = s.toString(); */
String invokedName = "when_" + invokedTraceClass.getName()/* + vdId*/;
Variable cCalledVariable/*vd*/ = variablesAnalysis.addCoreGuardVariable(invokedName, invokedTraceClass); // FIXME
List<@NonNull Variable> rParameters = qvtr2qvtc.getRootVariables(rInvokedRelation);
int iSize = rArguments.size();
assert iSize == rParameters.size();
for (int i = 0; i < iSize; i++) {
VariableExp rArgument/*ve*/ = (VariableExp) rArguments.get(i);
Variable rParameter/*dv*/ = rParameters.get(i);
//RWhenRelCallArgToMGuardPredicate
Variable rArgumentVariable/*v*/ = QVTbaseUtil.getReferredVariable(rArgument);
Variable cArgumentVariable/*mv*/ = variablesAnalysis.getCoreVariable(rArgumentVariable);
Property cCalledProperty/*pep*/ = qvtr2qvtc.getProperty(cCalledVariable.getType(), rParameter);
NavigationCallExp cCalledValue/*pe*/ = createNavigationCallExp(createVariableExp(cCalledVariable), cCalledProperty);
variablesAnalysis.addConditionPredicate(cMiddleGuardPattern, cCalledValue, createVariableExp(cArgumentVariable));
}
}
else {
// body of RSimplePatternToMPattern
OCLExpression cConditionExpression = mapExpression(rConditionExpression);
variablesAnalysis.addPredicate(cMiddleGuardPattern, cConditionExpression);
// Predicate mpd = createPredicate(mapExpression(rConditionExpression)); // FIXME orphan
// addPredicate(composedMappingGuardPattern, cConditionExpression);
}
}
//doUnsharedWhenVarsToMgVars(unsharedWhenVars, mg);
// mapVariables(rMiddleGuardDomainVariables, cMiddleGuardPattern);
}
}
// RPredicateSetToMBPredicateSet
protected void mapWhereBottomPredicates(@NonNull Iterable<@NonNull Predicate> rWherePredicates) {
for (@NonNull Predicate rWherePredicate : rWherePredicates) {
OCLExpression rExpression = QVTrelationUtil.getConditionExpression(rWherePredicate);
variablesAnalysis.addPredicate(cMiddleBottomPattern, mapExpression(rExpression));
}
/*
// check
if(predSeq.isEmpty()) {
return;
}
Predicate rp = predSeq.remove(0);
OCLExpression re = rp.getConditionExpression();
assert re != null;
// init
@NonNull Predicate mp = createPredicate();
// when
@NonNull OCLExpression me = doRExpToMExp(re);
doRPredicateSetToMBPredicateSet(predSeq, mb);
// assign
mp.setConditionExpression(me);
mb.getPredicate().add(mp); */
}
// RDomainToMDBottomForEnforcement (first half)
protected void mapWhereGuardPredicates(@NonNull Set<@NonNull Predicate> rWhereGuardPredicates, @NonNull Set<@NonNull Variable> rEnforcedBottomDomainVariables) throws CompilerChainException
{
Set<@NonNull Variable> nonRootEnforcedBottomDomainVariables = new HashSet<>(rEnforcedBottomDomainVariables);
nonRootEnforcedBottomDomainVariables.removeAll(rEnforcedRootVariables);
//
Set<@NonNull Predicate> wherePredicatesWithVarBindings = selectPredicatesThatReferToVariables(rWhereGuardPredicates, nonRootEnforcedBottomDomainVariables);
Set<@NonNull Predicate> remainingWherePredicatesWithoutVarBindings = new HashSet<>(rWhereGuardPredicates);
remainingWherePredicatesWithoutVarBindings.removeAll(wherePredicatesWithVarBindings);
// FIXME How does this do anything?
}
private void putTrace(@NonNull Element coreElement, @NonNull Element relationElement) {
Element oldRelationElement = target2source.put(coreElement, relationElement);
assert oldRelationElement == null;
List<@NonNull Element> targets = source2targets.get(relationElement);
if (targets == null) {
targets = new ArrayList<>();
source2targets.put(relationElement, targets);
}
targets.add(coreElement);
}
protected @NonNull Set<@NonNull Predicate> selectPredicatesThatReferToVariables(@NonNull Set<@NonNull Predicate> rPredicates, @NonNull Set<@NonNull Variable> rVariables) {
Set<@NonNull Predicate> rPredicatesThatReferToVariables = new HashSet<>();
for (@NonNull Predicate rPredicate : rPredicates) {
// OCLExpression conditionExpression = rPredicate.getConditionExpression();
// assert conditionExpression != null;
Set<@NonNull Variable> rPredicateVariables = new HashSet<>();
VariablesAnalysis.gatherReferredVariables(rPredicateVariables, rPredicate);
rPredicateVariables.retainAll(rVariables);
if (rPredicateVariables.isEmpty()) { // FIXME smelly polarity
rPredicatesThatReferToVariables.add(rPredicate);
}
}
return rPredicatesThatReferToVariables;
}
/**
* Exploit the constructed/analyzed context to synthesize the Core constructs.
* @throws CompilerChainException
*/
protected void synthesize() throws CompilerChainException {
Set<@NonNull Variable> rEnforcedBottomDomainVariables = getEnforcedBottomDomainVariables();
//
Set<@NonNull Predicate> rWhereBottomPredicates = selectPredicatesThatReferToVariables(rWherePredicates, rEnforcedBottomDomainVariables);
Set<@NonNull Predicate> rWhereGuardPredicates = new HashSet<>(rWherePredicates);
rWhereGuardPredicates.removeAll(rWhereBottomPredicates);
//
// Set<@NonNull Variable> rEnforcedDomainGuardVariables = getEnforcedDomainGuardVariables(rEnforcedBottomDomainVariables);
// Relation Calls
mapWhereBottomPredicates(rWhereBottomPredicates);
// mapVariables(rEnforcedDomainGuardVariables, cEnforcedGuardPattern);
// mapVariables(rMiddleBottomDomainVariables, cMiddleBottomPattern);
mapOtherDomainPatterns();
// Invoked here so the variables are instantiated
mapInvocation(); // Only for Invoked rather than Top relation
mapOtherDomainVariables(rAllOtherReferredVariables);
mapWhenPattern();
mapWhereGuardPredicates(rWhereGuardPredicates, rEnforcedBottomDomainVariables);
mapEnforcedDomainPatterns();
mapRelationImplementation();
}
@Override
public @NonNull String toString() {
return rRelationName + "::" + rEnforcedDomainName + " => " + cMapping.getName() + "::" + cEnforcedDomain.getName();
}
}
protected @NonNull final QVTr2QVTc qvtr2qvtc;
// Relations
protected final @NonNull Relation rRelation; // r: Parent relation of this domain
protected final @NonNull RelationalTransformation rTransformation; // Parent transformation of parent relation of enforced domain
protected final @NonNull String rRelationName; // rRelation.getName()
protected final @NonNull Set<@NonNull Variable> rAllDomainVariables; // ??All pattern variables declared in all domains (not CollectionTemplateExp member/rest, Let/Iterator variables)
// protected final @NonNull List<@NonNull Variable> rAllRootVariables; // The root variables of each domain in relation call order.
protected final @NonNull Map<@NonNull Variable, @Nullable RelationDomain> rWhenVariable2rDomain; // All pattern variables used in when calls and their associated domain
protected final @NonNull Map<@NonNull Variable, @Nullable RelationDomain> rWhereVariable2rDomain;// All pattern variables used in where calls and their associated domain
protected final @NonNull Set<@NonNull Predicate> rWhenPredicates; // All non-RelationCallExp when predicates
protected final @NonNull Set<@NonNull Predicate> rWherePredicates; // All non-RelationCallExp where predicates
protected final @NonNull Set<@NonNull Variable> rSharedVariables; // All pattern variables shared by more than one domain
protected final @NonNull Set<@NonNull Variable> rMiddleBottomDomainVariables;
// Core
protected final @NonNull Transformation cTransformation; // mt: The transformation containing the result mapping
protected AbstractQVTr2QVTcRelations(@NonNull QVTr2QVTc qvtr2qvtc, @NonNull Relation rRelation) {
super(qvtr2qvtc.getEnvironmentFactory());
this.qvtr2qvtc = qvtr2qvtc;
this.rRelation = rRelation;
this.rTransformation = QVTrelationUtil.getTransformation(rRelation);
this.rRelationName = PivotUtil.getName(rRelation);
//
this.rWhenVariable2rDomain = new HashMap<>();
this.rWhenPredicates = new HashSet<>();
Pattern rWhenPattern = rRelation.getWhen();
if (rWhenPattern != null) {
VariablesAnalysis.gatherReferredVariablesWithDomains(rWhenVariable2rDomain, rWhenPattern);
// FIXME assert rWhenPattern.getBindsTo().equals(rWhenVariables);
// rWhenPattern.getBindsTo().addAll(rWhenVariables);
for (@NonNull Predicate rWhenPredicate : QVTrelationUtil.getPredicates(rWhenPattern)) {
if (!(rWhenPredicate.getConditionExpression() instanceof RelationCallExp)) {
rWhenPredicates.add(rWhenPredicate);
}
}
}
//
this.rWhereVariable2rDomain = new HashMap<>();
this.rWherePredicates = new HashSet<>();
Pattern rWherePattern = rRelation.getWhere();
if (rWherePattern != null) {
VariablesAnalysis.gatherReferredVariablesWithDomains(rWhereVariable2rDomain, rWherePattern);
// FIXME assert rWherePattern.getBindsTo().equals(rWhereVariables);
// rWherePattern.getBindsTo().addAll(rWhereVariables);
for (@NonNull Predicate rWherePredicate : QVTrelationUtil.getPredicates(rWherePattern)) {
if (!(rWherePredicate.getConditionExpression() instanceof RelationCallExp)) {
rWherePredicates.add(rWherePredicate);
}
}
}
//
this.rAllDomainVariables = new HashSet<>();
/* for (@NonNull Domain rDomain : ClassUtil.nullFree(rRelation.getDomain())) {
for (@NonNull DomainPattern rDomainPattern : ClassUtil.nullFree(((RelationDomain)rDomain).getPattern())) {
Set<@NonNull Variable> rDomainVariables = new HashSet<>();
VariablesAnalysis.gatherReferredVariables(rDomainVariables, rDomainPattern);
// FIXME assert rDomainPattern.getBindsTo().equals(rDomainVariables);
// rDomainPattern.getBindsTo().addAll(rDomainVariables);
rAllDomainVariables.addAll(rDomainVariables);
}
} */
VariablesAnalysis.gatherReferredVariables(rAllDomainVariables, QVTrelationUtil.getOwnedDomains(rRelation));
if (rWhenPattern != null) {
VariablesAnalysis.gatherReferredVariables(rAllDomainVariables, rWhenPattern);
}
//
this.rSharedVariables = VariablesAnalysis.getMiddleDomainVariables(rRelation);
//
this.rMiddleBottomDomainVariables = new HashSet<>(rWhereVariable2rDomain.keySet());
rMiddleBottomDomainVariables.removeAll(rWhenVariable2rDomain.keySet());
rMiddleBottomDomainVariables.removeAll(rAllDomainVariables);
rMiddleBottomDomainVariables.addAll(rSharedVariables); // FIXME this stinks
//
this.cTransformation = qvtr2qvtc.getCoreTransformation(rTransformation);
}
/**
* Return an AbstractEnforceableRelationDomain2CoreMapping for each Core Mapping that is to be synthesized.
*/
protected abstract @NonNull List<@NonNull ? extends AbstractEnforceableRelationDomain2CoreMapping> analyze() throws CompilerChainException;
public void transform() throws CompilerChainException {
List<@NonNull ? extends AbstractEnforceableRelationDomain2CoreMapping> enforceableRelationDomain2coreMappings = analyze();
for (@NonNull AbstractEnforceableRelationDomain2CoreMapping enforceableRelationDomain2coreMapping : enforceableRelationDomain2coreMappings) {
enforceableRelationDomain2coreMapping.synthesize();
enforceableRelationDomain2coreMapping.variablesAnalysis.check();
}
}
}