Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Willink2017-03-07 08:56:19 +0000
committerEd Willink2017-03-11 10:47:37 +0000
commit351b5903016b50dd7c9d41fb3530dab3ff379fab (patch)
treecaefe40634f2666e3d7feea06b1ae42284cecb00
parent19ff65d7a26f24828a0320c05182b3898cfd0c3e (diff)
downloadorg.eclipse.qvtd-351b5903016b50dd7c9d41fb3530dab3ff379fab.tar.gz
org.eclipse.qvtd-351b5903016b50dd7c9d41fb3530dab3ff379fab.tar.xz
org.eclipse.qvtd-351b5903016b50dd7c9d41fb3530dab3ff379fab.zip
wip success property
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/AbstractQVTr2QVTcRelations.java142
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTr2QVTc.java91
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTrNameGenerator.java1
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/RelationalTransformationToTracePackage.java482
4 files changed, 484 insertions, 232 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/AbstractQVTr2QVTcRelations.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/AbstractQVTr2QVTcRelations.java
index 1d6686117..7fa51be58 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/AbstractQVTr2QVTcRelations.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/AbstractQVTr2QVTcRelations.java
@@ -21,6 +21,7 @@ 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.Class;
import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.CollectionLiteralPart;
import org.eclipse.ocl.pivot.CollectionType;
@@ -37,7 +38,6 @@ 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;
@@ -414,7 +414,10 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
@Override
public EObject copy(EObject oIn) {
try {
- if (oIn instanceof IteratorVariable) {
+ if (oIn instanceof RelationCallExp) {
+ return mapRelationCallExpToAndExpression((RelationCallExp)oIn);
+ }
+ else if (oIn instanceof IteratorVariable) {
return variablesAnalysis.getCoreVariable((IteratorVariable)oIn);
}
else if (oIn instanceof LetVariable) {
@@ -525,7 +528,7 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
*/
private final @NonNull Map<@NonNull Element, @NonNull Element> target2source = new HashMap<>();
- public AbstractEnforceableRelationDomain2CoreMapping(@NonNull RelationDomain rEnforcedDomain, @NonNull String cMappingName) throws CompilerChainException {
+ public AbstractEnforceableRelationDomain2CoreMapping(@NonNull RelationDomain rEnforcedDomain, @NonNull String cMappingName, @NonNull Class traceClass) throws CompilerChainException {
this.rEnforcedDomain = rEnforcedDomain;
//
this.rEnforcedBoundVariables = VariablesAnalysis.gatherBoundVariables(rEnforcedDomain);
@@ -537,7 +540,6 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
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);
@@ -547,7 +549,7 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
this.cEnforcedGuardPattern = ClassUtil.nonNullState(cEnforcedDomain.getGuardPattern());
this.cEnforcedBottomPattern = ClassUtil.nonNullState(cEnforcedDomain.getBottomPattern());
//
- this.variablesAnalysis = new VariablesAnalysis(qvtr2qvtc, rEnforcedDomain, cEnforcedDomain, traceClass, this instanceof InvokedEnforceableRelationDomain2CoreMapping);
+ this.variablesAnalysis = new VariablesAnalysis(qvtr2qvtc, rEnforcedDomain, cEnforcedDomain, traceClass, getWhenInvocations(), getWhereInvocations());
this.cMiddleRealizedVariable = variablesAnalysis.getMiddleRealizedVariable();
// putTrace(cMiddleRealizedVariable, cMiddleBottomPattern);
//
@@ -727,6 +729,18 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
return rTemplateExpressions;
}
+ private boolean isEnforced(@NonNull Variable rParameter) {
+ Relation rRelation = QVTrelationUtil.getContainingRelation(rParameter);
+ for (@NonNull RelationDomain rDomain : QVTrelationUtil.getOwnedDomains(rRelation)) {
+ for (@NonNull Variable rootVariable : QVTrelationUtil.getRootVariables(rDomain)) {
+ if (rootVariable == rParameter) {
+ return rDomain.getTypedModel() == rEnforcedTypedModel;
+ }
+ }
+ }
+ return false;
+ }
+
private boolean isVarBoundToSomeOtherTemplate(ObjectTemplateExp rootTe, /*Object*/TemplateExp skipTe, Variable v) {
if (rootTe == skipTe) {
return false;
@@ -1057,6 +1071,36 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
}
}
+ protected void mapRelationCallExpToPattern(@NonNull RelationCallExp rInvocation) throws CompilerChainException {
+ // body of RWhenRelCallToMGuard
+ Relation rInvokedRelation = QVTrelationUtil.getReferredRelation(rInvocation);
+ Type invokedTraceClass/*tc*/ = qvtr2qvtc.getTraceClass(rInvokedRelation); // ?? invocation
+ //
+ List<@NonNull OCLExpression> rArguments = QVTrelationUtil.Internal.getOwnedArgumentsList(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));
+ }
+ }
+
// protected @NonNull Variable mapRealizedVariable(@NonNull Variable rVariable) {
// return whenRealizedVariable(cEnforcedBottomPattern, rVariable);
// }
@@ -1086,37 +1130,10 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
Set<@NonNull Variable> rMiddleGuardDomainVariables = new HashSet<>(rWhenVariable2rTypedModel.keySet());
rMiddleGuardDomainVariables.removeAll(rAllVariables);
//
- for (@NonNull Predicate rWhenPredicate : QVTrelationUtil.getPredicates(rWhenPattern)) {
+ for (@NonNull Predicate rWhenPredicate : QVTrelationUtil.getOwnedPredicates(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.Internal.getOwnedArgumentsList(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));
- }
+ mapRelationCallExpToPattern((RelationCallExp)rConditionExpression);
}
else {
// body of RSimplePatternToMPattern
@@ -1131,6 +1148,51 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
}
}
+ protected @NonNull OperationCallExp mapRelationCallExpToAndExpression(@NonNull RelationCallExp rInvocation) throws CompilerChainException {
+ // body of RWhenRelCallToMGuard
+ Relation rInvokedRelation = QVTrelationUtil.getReferredRelation(rInvocation);
+ Type invokedTraceClass/*tc*/ = qvtr2qvtc.getTraceClass(rInvokedRelation); // ?? invocation
+ //
+ List<@NonNull OCLExpression> rArguments = QVTrelationUtil.Internal.getOwnedArgumentsList(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();
+ OperationCallExp result = null;
+ for (int i = 0; i < iSize; i++) {
+ VariableExp rArgument/*ve*/ = (VariableExp) rArguments.get(i);
+ Variable rParameter/*dv*/ = rParameters.get(i);
+ Property cCalledProperty/*pep*/ = qvtr2qvtc.getProperty(cCalledVariable.getType(), rParameter);
+ Variable rArgumentVariable/*v*/ = QVTbaseUtil.getReferredVariable(rArgument);
+ Variable cArgumentVariable/*mv*/ = variablesAnalysis.getCoreVariable(rArgumentVariable);
+ if (isEnforced(rParameter)) {
+ //RWhenRelCallArgToMGuardPredicate
+ NavigationCallExp cCalledValue/*pe*/ = createNavigationCallExp(createVariableExp(cCalledVariable), cCalledProperty);
+ OperationCallExp eTerm = createOperationCallExp(cCalledValue, "=", createVariableExp(cArgumentVariable));
+ if (result == null) {
+ result = eTerm;
+ }
+ else {
+ result = createOperationCallExp(result, "and", eTerm);
+ }
+ }
+ else {
+ NavigationCallExp cCalledValue/*pe*/ = createNavigationCallExp(createVariableExp(cCalledVariable), cCalledProperty);
+ variablesAnalysis.addConditionPredicate(cMiddleGuardPattern, cCalledValue, createVariableExp(cArgumentVariable));
+ }
+ }
+ assert result != null;
+ return result;
+ }
+
// RPredicateSetToMBPredicateSet
protected void mapWhereBottomPredicates(@NonNull Iterable<@NonNull Predicate> rWherePredicates) throws CompilerChainException {
for (@NonNull Predicate rWherePredicate : rWherePredicates) {
@@ -1292,7 +1354,7 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
VariablesAnalysis.gatherReferredVariablesWithTypedModels(rWhenVariable2rTypedModel, rWhenPattern);
// FIXME assert rWhenPattern.getBindsTo().equals(rWhenVariables);
// rWhenPattern.getBindsTo().addAll(rWhenVariables);
- for (@NonNull Predicate rWhenPredicate : QVTrelationUtil.getPredicates(rWhenPattern)) {
+ for (@NonNull Predicate rWhenPredicate : QVTrelationUtil.getOwnedPredicates(rWhenPattern)) {
if (!(rWhenPredicate.getConditionExpression() instanceof RelationCallExp)) { // FIXME Eliminate this redundant distinction
rWhenPredicates.add(rWhenPredicate);
}
@@ -1306,7 +1368,7 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
VariablesAnalysis.gatherReferredVariablesWithTypedModels(rWhereVariable2rTypedModel, rWherePattern);
// FIXME assert rWherePattern.getBindsTo().equals(rWhereVariables);
// rWherePattern.getBindsTo().addAll(rWhereVariables);
- for (@NonNull Predicate rWherePredicate : QVTrelationUtil.getPredicates(rWherePattern)) {
+ for (@NonNull Predicate rWherePredicate : QVTrelationUtil.getOwnedPredicates(rWherePattern)) {
if (!(rWherePredicate.getConditionExpression() instanceof RelationCallExp)) {
rWherePredicates.add(rWherePredicate);
}
@@ -1332,6 +1394,14 @@ import org.eclipse.qvtd.pivot.qvttemplate.TemplateExp;
*/
protected abstract @NonNull List<@NonNull ? extends AbstractEnforceableRelationDomain2CoreMapping> analyze() throws CompilerChainException;
+ protected @Nullable Iterable<@NonNull RelationCallExp> getWhenInvocations() {
+ return null;
+ }
+
+ protected @Nullable Iterable<@NonNull RelationCallExp> getWhereInvocations() {
+ return null;
+ }
+
@Override
public @NonNull String toString() {
return PivotUtil.getName(rTransformation) + "::" + rRelationName;
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTr2QVTc.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTr2QVTc.java
index f37f5b65d..523655095 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTr2QVTc.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTr2QVTc.java
@@ -210,9 +210,19 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
private final @NonNull Map<@NonNull Relation, org.eclipse.ocl.pivot.@NonNull Class> relation2traceClass = new HashMap<>();
/**
- * Map from each relation to all the expressions that call the relation.
+ * Mapping from each relation to its corresponding trace class.
+ */
+ private final @NonNull Map<@NonNull RelationCallExp, org.eclipse.ocl.pivot.@NonNull Class> invocation2traceClass = new HashMap<>();
+
+ /**
+ * Map from each relation to all the expressions that call the relationfrom a where clause.
+ */
+ private final @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2whenInvocations = new HashMap<>();
+
+ /**
+ * Map from each relation to all the expressions that call the relationfrom a when clause.
*/
- private final @NonNull Map<@NonNull Relation, @NonNull List<@NonNull RelationCallExp>> relation2invocations = new HashMap<>();
+ private final @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2whereInvocations = new HashMap<>();
/**
* Map from each relation invocation the relation whose where predicate contains the invocation.
@@ -284,21 +294,30 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
}
protected void analyzeInvocations(@NonNull Relation callingRelation) {
+ Pattern whenPattern = callingRelation.getWhen();
+ if (whenPattern != null) {
+ analyzeInvocations(callingRelation, whenPattern, relation2whenInvocations);
+ }
Pattern wherePattern = callingRelation.getWhere();
if (wherePattern != null) {
- for (Predicate predicate : wherePattern.getPredicate()) {
- OCLExpression predicateExpression = predicate.getConditionExpression();
- if (predicateExpression instanceof RelationCallExp) {
- RelationCallExp relationInvocation = (RelationCallExp) predicateExpression;
- Relation calledRelation = ClassUtil.nonNullState(relationInvocation.getReferredRelation());
- List<@NonNull RelationCallExp> relationInvocations = relation2invocations.get(calledRelation);
- if (relationInvocations == null) {
- relationInvocations = new ArrayList<>();
- relation2invocations.put(calledRelation, relationInvocations);
- }
- relationInvocations.add(relationInvocation);
- invocation2invokingRelation.put(relationInvocation, callingRelation);
+ analyzeInvocations(callingRelation, wherePattern, relation2whereInvocations);
+ }
+ }
+
+ protected void analyzeInvocations(@NonNull Relation callingRelation, @NonNull Pattern pattern,
+ @NonNull Map<@NonNull Relation, @Nullable List<@NonNull RelationCallExp>> relation2invocations2) {
+ for (Predicate predicate : pattern.getPredicate()) {
+ OCLExpression predicateExpression = predicate.getConditionExpression();
+ if (predicateExpression instanceof RelationCallExp) {
+ RelationCallExp relationInvocation = (RelationCallExp) predicateExpression;
+ Relation calledRelation = ClassUtil.nonNullState(relationInvocation.getReferredRelation());
+ List<@NonNull RelationCallExp> relationInvocations = relation2invocations2.get(calledRelation);
+ if (relationInvocations == null) {
+ relationInvocations = new ArrayList<>();
+ relation2invocations2.put(calledRelation, relationInvocations);
}
+ relationInvocations.add(relationInvocation);
+ invocation2invokingRelation.put(relationInvocation, callingRelation);
}
}
}
@@ -369,9 +388,14 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
name2mapping = new HashMap<>();
transformation2name2mapping.put(cTransformation, name2mapping);
}
+ String distinctName = name;
Mapping coreMapping = name2mapping.get(name);
- assert (coreMapping == null);// {
- coreMapping = helper.createMapping(name);
+ int suffix = 0;
+ while (coreMapping != null) {
+ distinctName = name + ++suffix;
+ coreMapping = name2mapping.get(distinctName);
+ }
+ coreMapping = helper.createMapping(distinctName);
putGlobalTrace(coreMapping, relation);
coreMapping.setTransformation(cTransformation);
name2mapping.put(name, coreMapping);
@@ -611,11 +635,6 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
return qvtcResource;
}
- public @NonNull List<@NonNull RelationCallExp> getRelationCallExpsForRelation(@NonNull Relation relation) {
- List<@NonNull RelationCallExp> invocations = relation2invocations.get(relation);
- return invocations != null ? invocations : Collections.emptyList();
- }
-
public @NonNull List<@NonNull Variable> getRootVariables(@NonNull Relation relation) {
return ClassUtil.nonNullState(relation2rootVariables.get(relation));
}
@@ -632,10 +651,22 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
return ClassUtil.nonNullState(relation2traceClass.get(relation));
}
+ /*public*/ org.eclipse.ocl.pivot.@NonNull Class getTraceClass(@NonNull RelationCallExp invocation) {
+ return ClassUtil.nonNullState(invocation2traceClass.get(invocation));
+ }
+
/*public*/ org.eclipse.ocl.pivot.@NonNull Package getTracePackage(@NonNull RelationalTransformation rTransformation) {
return ClassUtil.nonNullState(rTransformation2tracePackage.get(rTransformation));
}
+ public @Nullable Iterable<@NonNull RelationCallExp> getWhenRelationCallExpsForRelation(@NonNull Relation relation) {
+ return relation2whenInvocations.get(relation);
+ }
+
+ public @Nullable Iterable<@NonNull RelationCallExp> getWhereRelationCallExpsForRelation(@NonNull Relation relation) {
+ return relation2whereInvocations.get(relation);
+ }
+
protected void mapQueries(@NonNull RelationalTransformation rTransformation, @NonNull Transformation cTransformation) {
List<@NonNull Operation> cOperations = new ArrayList<>();
for (@NonNull Operation rOperation : QVTbaseUtil.getOwnedOperations(rTransformation)) {
@@ -679,7 +710,9 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
}
for (@NonNull Relation rRelation : rRelations) {
if (!rRelation.isIsTopLevel()) {
- InvokedRelationToMappingForEnforcement invokedRelationToMappingForEnforcement = new InvokedRelationToMappingForEnforcement(this, rRelation);
+ Iterable<@NonNull RelationCallExp> whenInvocations = relation2whenInvocations.get(rRelation);
+ Iterable<@NonNull RelationCallExp> whereInvocations = relation2whereInvocations.get(rRelation);
+ InvokedRelationToMappingForEnforcement invokedRelationToMappingForEnforcement = new InvokedRelationToMappingForEnforcement(this, rRelation, whenInvocations, whereInvocations);
invokedRelationToMappingForEnforcement.transform();
}
}
@@ -725,6 +758,12 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
// }
}
+ /*public*/ void putInvocationTrace(@NonNull RelationCallExp rInvocation, org.eclipse.ocl.pivot.@NonNull Class traceClass) {
+ org.eclipse.ocl.pivot.Class oldTraceClass = invocation2traceClass.put(rInvocation, traceClass);
+ assert oldTraceClass == null;
+ // putTrace(traceClass, r);
+ }
+
/*public*/ void putRelationTrace(@NonNull Relation rRelation, org.eclipse.ocl.pivot.@NonNull Class traceClass) {
org.eclipse.ocl.pivot.Class oldTraceClass = relation2traceClass.put(rRelation, traceClass);
assert oldTraceClass == null;
@@ -993,7 +1032,7 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
}
}
- public void transformToTracePackages() {
+ public void transformToTracePackages() throws CompilerChainException {
List<org.eclipse.ocl.pivot.@NonNull Package> rootTracePackages = null;
for (@NonNull EObject eObject : qvtrResource.getContents()) {
if (eObject instanceof RelationModel) {
@@ -1011,14 +1050,14 @@ public class QVTr2QVTc extends AbstractQVTc2QVTc
}
}
- private @Nullable List<org.eclipse.ocl.pivot.@NonNull Package> transformToTracePackageHierarchy(@NonNull Iterable<org.eclipse.ocl.pivot.@NonNull Package> relationPackages) {
+ private @Nullable List<org.eclipse.ocl.pivot.@NonNull Package> transformToTracePackageHierarchy(@NonNull Iterable<org.eclipse.ocl.pivot.@NonNull Package> relationPackages) throws CompilerChainException {
List<org.eclipse.ocl.pivot.@NonNull Package> nestingTracePackages = null;
for (org.eclipse.ocl.pivot.@NonNull Package relationPackage : relationPackages) {
List<org.eclipse.ocl.pivot.@NonNull Package> nestedTracePackages = null;
for (org.eclipse.ocl.pivot.@NonNull Class relationClass : ClassUtil.nullFree(relationPackage.getOwnedClasses())) {
if (relationClass instanceof RelationalTransformation) {
- RelationalTransformationToTracePackage rTransformationToTracePackage = new RelationalTransformationToTracePackage(this);
- org.eclipse.ocl.pivot.Package nestedTracePackage = rTransformationToTracePackage.doRelationalTransformationToTracePackage((RelationalTransformation)relationClass);
+ RelationalTransformationToTracePackage rTransformationToTracePackage = new RelationalTransformationToTracePackage(this, (RelationalTransformation)relationClass);
+ org.eclipse.ocl.pivot.Package nestedTracePackage = rTransformationToTracePackage.transform();
txTracePackages.add(nestedTracePackage);
if (nestedTracePackages == null) {
nestedTracePackages = new ArrayList<>();
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTrNameGenerator.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTrNameGenerator.java
index bdf3dcae7..a0350628c 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTrNameGenerator.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/QVTrNameGenerator.java
@@ -25,6 +25,7 @@ public class QVTrNameGenerator
public static final @NonNull String IDENTIFIED_INSTANCE_VARIABLE_NAME = "identifiedInstance";
public static final @NonNull String KEYED_INSTANCE_PROPERTY_NAME = "instance";
public static final @NonNull String KEY2INSTANCE_VARIABLE_NAME = "key2instance";
+ public static final @NonNull String TRACECLASS_SUCCESS_PROPERTY_NAME = "_success";
protected final @NonNull QVTr2QVTc qvtr2qvtc;
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/RelationalTransformationToTracePackage.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/RelationalTransformationToTracePackage.java
index e16c8d1f8..19e606bc2 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/RelationalTransformationToTracePackage.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvtc/RelationalTransformationToTracePackage.java
@@ -10,8 +10,13 @@
******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvtr2qvtc;
+import java.util.ArrayList;
import java.util.Collections;
+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.jdt.annotation.NonNull;
@@ -29,11 +34,11 @@ import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.TreeIterable;
+import org.eclipse.qvtd.compiler.CompilerChainException;
import org.eclipse.qvtd.compiler.internal.utilities.CompilerUtil;
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.Rule;
import org.eclipse.qvtd.pivot.qvtrelation.DomainPattern;
import org.eclipse.qvtd.pivot.qvtrelation.Relation;
import org.eclipse.qvtd.pivot.qvtrelation.RelationCallExp;
@@ -49,141 +54,307 @@ import com.google.common.collect.Iterables;
/*public*/ class RelationalTransformationToTracePackage
{
- protected final @NonNull QVTr2QVTc qvtr2qvtc;
+ public class Relation2TraceClass
+ {
+ protected final @NonNull Relation relation;
+ protected final @Nullable RelationCallExp invocation;
+ protected final org.eclipse.ocl.pivot.@NonNull Class traceClass;
+ protected final @NonNull Map<@NonNull String, @NonNull Property> name2property = new HashMap<>();
- public RelationalTransformationToTracePackage(@NonNull QVTr2QVTc qvtr2qvtc) {
- this.qvtr2qvtc = qvtr2qvtc;
- }
+ protected Relation2TraceClass(@NonNull Relation relation) {
+ this.relation = relation;
+ this.invocation = null;
+ this.traceClass = ClassUtil.nonNullState(PivotFactory.eINSTANCE.createClass());
+ String name = "T" + relation.getName();
+ traceClass.setName(getUniqueTraceClassName(this, name));
+ qvtr2qvtc.putRelationTrace(relation, traceClass);
+ }
- private void createTraceProperty(@Nullable Domain rDomain, org.eclipse.ocl.pivot.@NonNull Class rc, @NonNull TypedElement tv, boolean manyTraces) {
- String vn = ClassUtil.nonNullState(tv.getName());
- Type c = ClassUtil.nonNullState(tv.getType());
- qvtr2qvtc.whenTraceProperty(rDomain, rc, vn, c, tv.isIsRequired(), manyTraces);
- }
+ protected Relation2TraceClass(@NonNull RelationCallExp invocation, @NonNull String separator) throws CompilerChainException {
+ this.relation = QVTrelationUtil.getReferredRelation(invocation);
+ this.invocation = invocation;
+ this.traceClass = ClassUtil.nonNullState(PivotFactory.eINSTANCE.createClass());
+ String invokedName = QVTrelationUtil.getContainingRelation(invocation).getName();
+ String name = "T" + invokedName + separator + relation.getName();
+ traceClass.setName(getUniqueTraceClassName(this, name));
+ qvtr2qvtc.putInvocationTrace(invocation, traceClass);
+ Relation2TraceClass superRelation2TraceClass = getRelation2TraceClass(relation);
+ traceClass.getSuperClasses().add(superRelation2TraceClass.getTraceClass());
+ name2property.putAll(superRelation2TraceClass.name2property);
+ }
- private void createTraceProperty(@Nullable Domain rDomain, org.eclipse.ocl.pivot.@NonNull Class rc, @NonNull String name, @NonNull Type type, boolean isRequired) {
- qvtr2qvtc.whenTraceProperty(rDomain, rc, name, type, isRequired, false);
- }
+ private void createTraceProperty(@Nullable Domain rDomain, org.eclipse.ocl.pivot.@NonNull Class rc, @NonNull TypedElement tv, boolean manyTraces) throws CompilerChainException {
+ String vn = QVTrelationUtil.getName(tv);
+ Type c = QVTrelationUtil.getType(tv);
+ createTraceProperty(rDomain, rc, vn, c, tv.isIsRequired(), manyTraces);
+ }
- public org.eclipse.ocl.pivot.@NonNull Package doRelationalTransformationToTracePackage(@NonNull RelationalTransformation rTransformation) {
- org.eclipse.ocl.pivot.Package rPackage = rTransformation.getOwningPackage();
- org.eclipse.ocl.pivot.Package tracePackage = PivotFactory.eINSTANCE.createPackage();
- tracePackage.setName("P" + rTransformation.getName());
- tracePackage.setNsPrefix("P" + rTransformation.getName());
- StringBuilder s = new StringBuilder();
- getURI(rPackage, s);
- tracePackage.setURI(s.toString() + "/" + rTransformation.getName());
- qvtr2qvtc.putTracePackage(rTransformation, tracePackage);
- List<org.eclipse.ocl.pivot.@NonNull Class> ownedClasses = ClassUtil.nullFree(tracePackage.getOwnedClasses());
- for (@NonNull Rule rRule : ClassUtil.nullFree(rTransformation.getRule())) {
- if (rRule instanceof Relation) {
- ownedClasses.add(doRelationToTraceClass((Relation)rRule));
+ private void createTraceProperty(@Nullable Domain rDomain, org.eclipse.ocl.pivot.@NonNull Class rc, @NonNull String name, @NonNull Type type, boolean isRequired, boolean manyTraces) throws CompilerChainException {
+ Property traceProperty = name2property.get(name);
+ if (traceProperty != null) {
+ if ((type != traceProperty.getType()) || isRequired != traceProperty.isIsRequired()) {
+ throw new CompilerChainException("Inconsistent redefined property '" + name + "' for " + relation);
+ }
+ }
+ else {
+ traceProperty = qvtr2qvtc.whenTraceProperty(rDomain, rc, name, type, isRequired, manyTraces);
+ name2property.put(name, traceProperty);
}
}
- CompilerUtil.normalizeNameables(ownedClasses);
- return tracePackage;
- }
- private org.eclipse.ocl.pivot.@NonNull Class doRelationToTraceClass(@NonNull Relation rRelation) {
- @SuppressWarnings("null")org.eclipse.ocl.pivot.@NonNull Class traceClass = PivotFactory.eINSTANCE.createClass();
- qvtr2qvtc.putRelationTrace(rRelation, traceClass);
- traceClass.setName("T" + rRelation.getName());
- for (@NonNull Variable rVariable : VariablesAnalysis.getMiddleDomainVariables(rRelation)) {
- createTraceProperty(null, traceClass, rVariable, false);
+ /**
+ * Returns true if there are many subtemplate matches. If manyTraces is set there may be many trace class instances referencing the same objects
+ * and so the implicit opposites must be Bags. Only very simple patterns with pedantically 1:1 relationships can avoid the Bags.
+ * @throws CompilerChainException
+ */
+ private boolean doSubTemplateToTraceClassProps(@NonNull Domain rDomain, @NonNull TemplateExp te, org.eclipse.ocl.pivot.@NonNull Class rc, boolean manyTraces) throws CompilerChainException {
+ Variable tv = QVTrelationUtil.getBindsTo(te);
+ if (te instanceof CollectionTemplateExp) {
+ CollectionTemplateExp cte = (CollectionTemplateExp) te;
+ Variable collectionVariable = QVTrelationUtil.getBindsTo(cte);
+ CollectionType collectionType = (CollectionType)QVTrelationUtil.getType(collectionVariable);
+ Type elementType = QVTrelationUtil.getElementType(collectionType);
+ int argIndex = 0;
+ for (@NonNull OCLExpression m : QVTrelationUtil.getOwnedMembers(cte)) {
+ if (m instanceof TemplateExp) {
+ if (doSubTemplateToTraceClassProps(rDomain, (TemplateExp)m, rc, manyTraces)) {
+ // manyTraces = true;
+ }
+ }
+ else if (!(m instanceof VariableExp)) {
+ createTraceProperty(rDomain, rc, collectionVariable.getName() + "_" + argIndex, elementType, collectionType.isIsNullFree(), false);
+ }
+ argIndex++;
+ }
+ // Variable rv = cte.getRest();
+ // if (rv != null) {
+ // createTraceProperty(rDomain, rc, rv, isMany);
+ // }
+ createTraceProperty(rDomain, rc, tv, manyTraces); // ?? not required for CollectionTemplateExp's
+ }
+ else if (te instanceof ObjectTemplateExp) {
+ ObjectTemplateExp ote = (ObjectTemplateExp) te;
+ for (@NonNull PropertyTemplateItem pt : QVTrelationUtil.getOwnedParts(ote)) {
+ Property referredProperty = QVTrelationUtil.getReferredProperty(pt);
+ if (referredProperty.isIsMany()) {
+ manyTraces = true;
+ }
+ OCLExpression value = QVTrelationUtil.getOwnedValue(pt);
+ if (value instanceof TemplateExp) {
+ Property oppositeProperty = referredProperty.getOpposite();
+ boolean nestedManyTraces = manyTraces;
+ if ((oppositeProperty != null) && oppositeProperty.isIsMany()) {
+ nestedManyTraces = true;
+ }
+ if (doSubTemplateToTraceClassProps(rDomain, (TemplateExp)value, rc, nestedManyTraces)) {
+ // manyTraces = true;
+ }
+ }
+ }
+ createTraceProperty(rDomain, rc, tv, manyTraces); // ?? not required for CollectionTemplateExp's
+ }
+ return manyTraces;
+ }
+
+ public org.eclipse.ocl.pivot.@NonNull Class getTraceClass() {
+ return traceClass;
}
- //
- // Determine whether a navigation from the trace to an unambiguous ledft/right object can ever be possible.
- //
- boolean manyTraces = hasManyRootMatches(rRelation) || hasCollectionMemberMatches(rRelation) || hasMultiObjectMatches(rRelation);
- if (!manyTraces) {
- for (@NonNull Variable rVariable : ClassUtil.nullFree(rRelation.getVariable())) {
- if (hasManyVariableMatches(rRelation, rVariable)) {
- manyTraces = true;
- break;
+
+ private boolean hasCollectionMemberMatches(@NonNull Relation rRelation) {
+ for (EObject eObject : new TreeIterable(rRelation, true)) {
+ if (eObject instanceof CollectionTemplateExp) {
+ List<OCLExpression> members = ((CollectionTemplateExp)eObject).getMember();
+ if (members.size() > 0) {
+ return true;
+ }
}
}
+ return false;
}
- for (@NonNull Domain rDomain : ClassUtil.nullFree(rRelation.getDomain())) {
- for (@NonNull DomainPattern rDomainPattern : ClassUtil.nullFree(((RelationDomain)rDomain).getPattern())) {
- TemplateExp rTemplateExp = ClassUtil.nonNullState(rDomainPattern.getTemplateExpression());
- doSubTemplateToTraceClassProps(rDomain, rTemplateExp, traceClass, manyTraces);
+
+ /**
+ * Return true if there may be more than one trace instance for a given root variable.
+ */
+ private boolean hasManyRootMatches(@NonNull Relation rRelation) {
+ //
+ // Only a single root variable in each of just two domains gurantees just one trace per root variable.
+ //
+ List<@NonNull Domain> rDomains = QVTrelationUtil.Internal.getOwnedDomainsList(rRelation);
+ if (rDomains.size() > 2) {
+ return true;
}
+ else {
+ for (@NonNull Domain rDomain : rDomains) {
+ List<Variable> rootVariables = ((RelationDomain)rDomain).getRootVariable();
+ if (rootVariables.size() > 1) {
+ return true;
+ }
+ }
+ }
+ return false;
}
- Pattern rWhenPattern = rRelation.getWhen();
- if (rWhenPattern != null) {
- for (Predicate rWhenPredicate : ClassUtil.nullFree(rWhenPattern.getPredicate())) {
- OCLExpression rConditionExpression = ClassUtil.nonNullState(rWhenPredicate.getConditionExpression());
- if (rConditionExpression instanceof RelationCallExp) {
- RelationCallExp rInvocation = (RelationCallExp)rConditionExpression;
- List<@NonNull OCLExpression> rArguments = ClassUtil.nullFree(rInvocation.getArgument());
- for (int i = 0; i < rArguments.size(); i++) {
- OCLExpression rArgument = rArguments.get(i);
- if (rArgument instanceof VariableExp) {
- VariableDeclaration rVariable = ((VariableExp)rArgument).getReferredVariable();
- assert rVariable != null;
- RelationDomain rDomain = QVTrelationUtil.getRelationCallExpArgumentDomain(rInvocation, i);
- createTraceProperty(rDomain, traceClass, rVariable, manyTraces);
- // createTraceProperty(rDomain, rVariable.getType(), rVariable, isMany); // ?? not required for CollectionTemplateExp's
+
+ private boolean hasManyVariableMatches(@NonNull Relation rRelation, @NonNull Variable rVariable) {
+ for (@NonNull Domain rDomain : QVTrelationUtil.getOwnedDomains(rRelation)) {
+ Iterable<@NonNull Variable> bindsTo = QVTr2QVTcUtil.getRelationDomainBindsTo((RelationDomain) rDomain);
+ if (Iterables.contains(bindsTo, rVariable)) {
+ return false;
+ }
+ }
+ for (EObject eObject : new TreeIterable(rRelation, true)) {
+ if (eObject instanceof VariableExp) {
+ VariableDeclaration referredVariable = ((VariableExp)eObject).getReferredVariable();
+ if (referredVariable == rVariable) {
+ EObject eContainer = eObject.eContainer();
+ if (eContainer instanceof OperationCallExp) {
+ OperationCallExp operationCallExp = (OperationCallExp)eContainer;
+ Operation referredOperation = operationCallExp.getReferredOperation();
+ assert referredOperation != null;
+ if (operationCallExp.getOwnedArguments().equals(Collections.singletonList(eObject)) && "includes".equals(referredOperation.getName())) { // FIXME stronger test
+ return true;
+ }
}
+ // FIXME more cases
}
}
}
+ return false;
}
- CompilerUtil.normalizeNameables(ClassUtil.nullFree(traceClass.getOwnedProperties()));
- return traceClass;
- }
- /**
- * Returns true if there are many subtemplate matches. If manyTraces is set there may be many trace class instances referencing the same objects
- * and so the implicit opposites must be Bags. Only very simple patterns with pedantically 1:1 relationships can avoid the Bags.
- */
- private boolean doSubTemplateToTraceClassProps(@NonNull Domain rDomain, @NonNull TemplateExp te, org.eclipse.ocl.pivot.@NonNull Class rc, boolean manyTraces) {
- Variable tv = ClassUtil.nonNullState(te.getBindsTo());
- if (te instanceof CollectionTemplateExp) {
- CollectionTemplateExp cte = (CollectionTemplateExp) te;
- Variable collectionVariable = cte.getBindsTo();
- CollectionType collectionType = (CollectionType)collectionVariable.getType();
- Type elementType = ClassUtil.nonNullState(collectionType.getElementType());
- int argIndex = 0;
- for (@NonNull OCLExpression m : ClassUtil.nullFree(cte.getMember())) {
- if (m instanceof TemplateExp) {
- if (doSubTemplateToTraceClassProps(rDomain, (TemplateExp)m, rc, manyTraces)) {
- // manyTraces = true;
+ private boolean hasMultiObjectMatches(@NonNull Relation rRelation) {
+ for (EObject eObject : new TreeIterable(rRelation, true)) {
+ if (eObject instanceof PropertyTemplateItem) {
+ Property referredProperty = ((PropertyTemplateItem)eObject).getReferredProperty();
+ if (referredProperty.isIsMany()) {
+ return true;
}
}
- else if (!(m instanceof VariableExp)) {
- createTraceProperty(rDomain, rc, collectionVariable.getName() + "_" + argIndex, elementType, collectionType.isIsNullFree());
- }
- argIndex++;
}
- // Variable rv = cte.getRest();
- // if (rv != null) {
- // createTraceProperty(rDomain, rc, rv, isMany);
- // }
- createTraceProperty(rDomain, rc, tv, manyTraces); // ?? not required for CollectionTemplateExp's
+ return false;
}
- else if (te instanceof ObjectTemplateExp) {
- ObjectTemplateExp ote = (ObjectTemplateExp) te;
- for (@NonNull PropertyTemplateItem pt : ClassUtil.nullFree(ote.getPart())) {
- Property referredProperty = pt.getReferredProperty();
- if (referredProperty.isIsMany()) {
- manyTraces = true;
- }
- OCLExpression value = ClassUtil.nonNullState(pt.getValue());
- if (value instanceof TemplateExp) {
- Property oppositeProperty = referredProperty.getOpposite();
- boolean nestedManyTraces = manyTraces;
- if ((oppositeProperty != null) && oppositeProperty.isIsMany()) {
- nestedManyTraces = true;
+
+ @Override
+ public String toString() {
+ return relation.toString();
+ }
+
+ public org.eclipse.ocl.pivot.@NonNull Class transform() throws CompilerChainException {
+ Relation overriddenRelation = QVTrelationUtil.basicGetOverrides(relation);
+ if (overriddenRelation != null) {
+ Relation2TraceClass overriddenRelation2TraceClass = getRelation2TraceClass(overriddenRelation);
+ name2property.putAll(overriddenRelation2TraceClass.name2property);
+ traceClass.getSuperClasses().add(overriddenRelation2TraceClass.traceClass);
+ }
+
+ for (@NonNull Variable rVariable : VariablesAnalysis.getMiddleDomainVariables(relation)) {
+ createTraceProperty(null, traceClass, rVariable, false);
+ }
+ if (testableRelations.contains(relation) ) {
+ Type booleanType = qvtr2qvtc.getStandardLibrary().getBooleanType();
+ createTraceProperty(null, traceClass, QVTrNameGenerator.TRACECLASS_SUCCESS_PROPERTY_NAME, booleanType, false, false);
+ }
+ //
+ // Determine whether a navigation from the trace to an unambiguous left/right object can ever be possible.
+ //
+ boolean manyTraces = hasManyRootMatches(relation) || hasCollectionMemberMatches(relation) || hasMultiObjectMatches(relation);
+ if (!manyTraces) {
+ for (@NonNull Variable rVariable : QVTrelationUtil.getOwnedVariables(relation)) {
+ if (hasManyVariableMatches(relation, rVariable)) {
+ manyTraces = true;
+ break;
}
- if (doSubTemplateToTraceClassProps(rDomain, (TemplateExp)value, rc, nestedManyTraces)) {
- // manyTraces = true;
+ }
+ }
+ for (@NonNull RelationDomain rDomain : QVTrelationUtil.getOwnedDomains(relation)) {
+ for (@NonNull DomainPattern rDomainPattern : QVTrelationUtil.getOwnedPatterns(rDomain)) {
+ TemplateExp rTemplateExp = QVTrelationUtil.getOwnedTemplateExpression(rDomainPattern);
+ doSubTemplateToTraceClassProps(rDomain, rTemplateExp, traceClass, manyTraces);
+ }
+ }
+ Pattern rWhenPattern = relation.getWhen();
+ if (rWhenPattern != null) {
+ for (Predicate rWhenPredicate : QVTrelationUtil.getOwnedPredicates(rWhenPattern)) {
+ OCLExpression rConditionExpression = QVTrelationUtil.getConditionExpression(rWhenPredicate);
+ if (rConditionExpression instanceof RelationCallExp) {
+ RelationCallExp rInvocation = (RelationCallExp)rConditionExpression;
+ List<@NonNull OCLExpression> rArguments = QVTrelationUtil.Internal.getOwnedArgumentsList(rInvocation);
+ for (int i = 0; i < rArguments.size(); i++) {
+ OCLExpression rArgument = rArguments.get(i);
+ if (rArgument instanceof VariableExp) {
+ VariableDeclaration rVariable = ((VariableExp)rArgument).getReferredVariable();
+ assert rVariable != null;
+ RelationDomain rDomain = QVTrelationUtil.getRelationCallExpArgumentDomain(rInvocation, i);
+ createTraceProperty(rDomain, traceClass, rVariable, manyTraces);
+ // createTraceProperty(rDomain, rVariable.getType(), rVariable, isMany); // ?? not required for CollectionTemplateExp's
+ }
+ }
}
}
}
- createTraceProperty(rDomain, rc, tv, manyTraces); // ?? not required for CollectionTemplateExp's
+ CompilerUtil.normalizeNameables(ClassUtil.nullFree(traceClass.getOwnedProperties()));
+ return traceClass;
+ }
+ }
+
+ protected final @NonNull QVTr2QVTc qvtr2qvtc;
+ protected final @NonNull RelationalTransformation rTransformation;
+ private @NonNull Set<@NonNull Relation> testableRelations = new HashSet<>();
+
+ /**
+ * Name to corresponding trace class
+ */
+ protected final @NonNull Map<@NonNull String, @NonNull Relation2TraceClass> name2relation2traceClass = new HashMap<>();
+
+ /**
+ * Map of relation to trace class. The trace class is set null at the start of conversion enabling cycles to be ddetected.
+ */
+ protected final @NonNull Map<@NonNull Relation, @Nullable Relation2TraceClass> relation2relation2traceClass = new HashMap<>();
+
+ /**
+ * Map of invocation to trace class. The trace class is set null at the start of conversion enabling cycles to be ddetected.
+ */
+ protected final @NonNull Map<@NonNull RelationCallExp, @Nullable Relation2TraceClass> invocation2relation2traceClass = new HashMap<>();
+
+ public RelationalTransformationToTracePackage(@NonNull QVTr2QVTc qvtr2qvtc, @NonNull RelationalTransformation rTransformation) {
+ this.qvtr2qvtc = qvtr2qvtc;
+ this.rTransformation = rTransformation;
+ for (@NonNull EObject eObject : new TreeIterable(rTransformation, false)) {
+ if ((eObject instanceof RelationCallExp) && !(eObject.eContainer() instanceof Predicate)) {
+ testableRelations.add(QVTrelationUtil.getReferredRelation((RelationCallExp)eObject));
+ }
+ }
+ }
+
+ protected @NonNull Relation2TraceClass getInvocation2TraceClass(@NonNull RelationCallExp rInvocation, @NonNull String separator) throws CompilerChainException {
+ Relation2TraceClass relation2traceClass = new Relation2TraceClass(rInvocation, separator);
+ Relation2TraceClass oldRelation2traceClass = invocation2relation2traceClass.put(rInvocation, relation2traceClass);
+ assert oldRelation2traceClass == null;
+ relation2traceClass.transform();
+ return relation2traceClass;
+ }
+
+ protected @NonNull Relation2TraceClass getRelation2TraceClass(@NonNull Relation rRelation) throws CompilerChainException {
+ Relation2TraceClass relation2traceClass = relation2relation2traceClass.get(rRelation);
+ if (relation2traceClass == null) {
+ if (relation2relation2traceClass.containsKey(rRelation)) {
+ throw new CompilerChainException("Overrides cycle detected for " + rRelation);
+ }
+ relation2traceClass = new Relation2TraceClass(rRelation);
+ relation2relation2traceClass.put(rRelation, null);
+ relation2traceClass.transform();
+ relation2relation2traceClass.put(rRelation, relation2traceClass);
+ }
+ return relation2traceClass;
+ }
+
+ private @NonNull String getUniqueTraceClassName(@NonNull Relation2TraceClass relation2traceClass, @NonNull String name) {
+ String uniqueName = name;
+ int suffix = 0;
+ while (name2relation2traceClass.get(uniqueName) != null) {
+ uniqueName = name + ++suffix;
}
- return manyTraces;
+ name2relation2traceClass.put(uniqueName, relation2traceClass);
+ return uniqueName;
}
private String getURI(org.eclipse.ocl.pivot.Package rPackage, @NonNull StringBuilder s) {
@@ -201,76 +372,47 @@ import com.google.common.collect.Iterables;
return null;
}
- private boolean hasCollectionMemberMatches(@NonNull Relation rRelation) {
- for (EObject eObject : new TreeIterable(rRelation, true)) {
- if (eObject instanceof CollectionTemplateExp) {
- List<OCLExpression> members = ((CollectionTemplateExp)eObject).getMember();
- if (members.size() > 0) {
- return true;
- }
- }
- }
- return false;
+ @Override
+ public String toString() {
+ return rTransformation.toString();
}
- /**
- * Return true if there may be more than one trace instance for a given root variable.
- */
- private boolean hasManyRootMatches(@NonNull Relation rRelation) {
- //
- // Only a single root variable in each of just two domains gurantees just one trace per root variable.
- //
- List<@NonNull Domain> rDomains = ClassUtil.nullFree(rRelation.getDomain());
- if (rDomains.size() > 2) {
- return true;
+ public org.eclipse.ocl.pivot.@NonNull Package transform() throws CompilerChainException {
+ org.eclipse.ocl.pivot.Package rPackage = rTransformation.getOwningPackage();
+ org.eclipse.ocl.pivot.Package tracePackage = PivotFactory.eINSTANCE.createPackage();
+ tracePackage.setName("P" + rTransformation.getName());
+ tracePackage.setNsPrefix("P" + rTransformation.getName());
+ StringBuilder s = new StringBuilder();
+ getURI(rPackage, s);
+ tracePackage.setURI(s.toString() + "/" + rTransformation.getName());
+ qvtr2qvtc.putTracePackage(rTransformation, tracePackage);
+ for (@NonNull Relation rRelation : QVTrelationUtil.getOwnedRelations(rTransformation)) {
+ // if (rRelation.isIsTopLevel()) {
+ getRelation2TraceClass(rRelation);
+ // }
}
- else {
- for (@NonNull Domain rDomain : rDomains) {
- List<Variable> rootVariables = ((RelationDomain)rDomain).getRootVariable();
- if (rootVariables.size() > 1) {
- return true;
+ for (@NonNull Relation rRelation : QVTrelationUtil.getOwnedRelations(rTransformation)) {
+ if (!rRelation.isIsTopLevel()) {
+ Iterable<@NonNull RelationCallExp> whenInvocations = qvtr2qvtc.getWhenRelationCallExpsForRelation(rRelation);
+ if (whenInvocations != null) {
+ for (@NonNull RelationCallExp rInvocation : whenInvocations) {
+ getInvocation2TraceClass(rInvocation, "_when_");
+ }
}
- }
- }
- return false;
- }
-
- private boolean hasManyVariableMatches(@NonNull Relation rRelation, @NonNull Variable rVariable) {
- for (@NonNull Domain rDomain : ClassUtil.nullFree(rRelation.getDomain())) {
- Iterable<@NonNull Variable> bindsTo = QVTr2QVTcUtil.getRelationDomainBindsTo((RelationDomain) rDomain);
- if (Iterables.contains(bindsTo, rVariable)) {
- return false;
- }
- }
- for (EObject eObject : new TreeIterable(rRelation, true)) {
- if (eObject instanceof VariableExp) {
- VariableDeclaration referredVariable = ((VariableExp)eObject).getReferredVariable();
- if (referredVariable == rVariable) {
- EObject eContainer = eObject.eContainer();
- if (eContainer instanceof OperationCallExp) {
- OperationCallExp operationCallExp = (OperationCallExp)eContainer;
- Operation referredOperation = operationCallExp.getReferredOperation();
- assert referredOperation != null;
- if (operationCallExp.getOwnedArguments().equals(Collections.singletonList(eObject)) && "includes".equals(referredOperation.getName())) { // FIXME stronger test
- return true;
- }
+ Iterable<@NonNull RelationCallExp> whereInvocations = qvtr2qvtc.getWhereRelationCallExpsForRelation(rRelation);
+ if (whereInvocations != null) {
+ for (@NonNull RelationCallExp rInvocation : whereInvocations) {
+ getInvocation2TraceClass(rInvocation, "_where_");
}
- // FIXME more cases
}
}
}
- return false;
- }
-
- private boolean hasMultiObjectMatches(@NonNull Relation rRelation) {
- for (EObject eObject : new TreeIterable(rRelation, true)) {
- if (eObject instanceof PropertyTemplateItem) {
- Property referredProperty = ((PropertyTemplateItem)eObject).getReferredProperty();
- if (referredProperty.isIsMany()) {
- return true;
- }
- }
+ List<org.eclipse.ocl.pivot.@NonNull Class> traceClasses = new ArrayList<>(name2relation2traceClass.size());
+ for (@NonNull Relation2TraceClass relation2TraceClass : name2relation2traceClass.values()) {
+ traceClasses.add(relation2TraceClass.getTraceClass());
}
- return false;
+ CompilerUtil.normalizeNameables(traceClasses);
+ tracePackage.getOwnedClasses().addAll(traceClasses);
+ return tracePackage;
}
}

Back to the top