[513375] Clarify connection containment
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/AbstractScheduleManager.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/AbstractScheduleManager.java
index 44dbae3..ff26722 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/AbstractScheduleManager.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/AbstractScheduleManager.java
@@ -865,28 +865,6 @@
}
@Override
- public boolean isElementallyConformantSource(@NonNull NavigableEdge thatEdge, @NonNull NavigableEdge thisEdge) {
- Node thatSource = thatEdge.getEdgeSource();
- Node thisSource = thisEdge.getEdgeSource();
- ClassDatum thatClassDatum = QVTscheduleUtil.getClassDatum(thatSource);
- ClassDatum thisClassDatum = QVTscheduleUtil.getClassDatum(thisSource);
- ClassDatum thatElementalClassDatum = getElementalClassDatum(thatClassDatum);
- ClassDatum thisElementalClassDatum = getElementalClassDatum(thisClassDatum);
- // CompleteClass thatType = ClassUtil.nonNullState(thatElementalClassDatum.getCompleteClass());
- // CompleteClass thisType = ClassUtil.nonNullState(thisElementalClassDatum.getCompleteClass());
- if (QVTscheduleUtil.conformsTo(thatElementalClassDatum, thisElementalClassDatum)) {
- return true;
- }
- if (thatSource.isRealized()) {
- return false;
- }
- if (QVTscheduleUtil.conformsTo(thisElementalClassDatum, thatElementalClassDatum)) {
- return true;
- }
- return false;
- }
-
- @Override
public boolean isInput(@NonNull DomainUsage domainUsage) {
return getDirectedDomainUsageAnalysis().isInput(domainUsage);
}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/ScheduleManager.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/ScheduleManager.java
index 8771aaf..48a1e16 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/ScheduleManager.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/ScheduleManager.java
@@ -39,7 +39,6 @@
import org.eclipse.qvtd.pivot.qvtbase.utilities.TraceHelper;
import org.eclipse.qvtd.pivot.qvtschedule.ClassDatum;
import org.eclipse.qvtd.pivot.qvtschedule.MappingRegion;
-import org.eclipse.qvtd.pivot.qvtschedule.NavigableEdge;
import org.eclipse.qvtd.pivot.qvtschedule.NavigationEdge;
import org.eclipse.qvtd.pivot.qvtschedule.Node;
import org.eclipse.qvtd.pivot.qvtschedule.OperationRegion;
@@ -158,11 +157,6 @@
boolean isDirty(@NonNull Property property);
/**
- * Return true if the elemental source type of thatEdge is compatible with the source type of thisEdge.
- */
- boolean isElementallyConformantSource(@NonNull NavigableEdge thatEdge, @NonNull NavigableEdge thisEdge);
-
- /**
* Return true if domainUsage's typed model is configured as an input (and possibly an input+output).
*/
boolean isInput(@NonNull DomainUsage domainUsage);
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/ConnectionManager.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/ConnectionManager.java
index a69286f..08b5241 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/ConnectionManager.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvts/ConnectionManager.java
@@ -33,6 +33,7 @@
import org.eclipse.qvtd.compiler.internal.utilities.CompilerUtil;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
+import org.eclipse.qvtd.pivot.qvtbase.utilities.StandardLibraryHelper;
import org.eclipse.qvtd.pivot.qvtschedule.ClassDatum;
import org.eclipse.qvtd.pivot.qvtschedule.CollectionClassDatum;
import org.eclipse.qvtd.pivot.qvtschedule.Connection;
@@ -99,11 +100,17 @@
*/
private final @NonNull Map<@NonNull Partition, @NonNull List<@NonNull Partition>> partition2children = new HashMap<>();
+ private final @NonNull Property oclContainerProperty;
+ private final @NonNull Property oclContentsProperty;
+
public ConnectionManager(@NonNull ProblemHandler problemHandler, @NonNull ScheduleManager scheduleManager, @NonNull LoadingRegionAnalysis loadingRegionAnalysis) {
// super(qvtm2qvts.getEnvironmentFactory());
this.scheduleManager = scheduleManager;
this.loadingRegionAnalysis = loadingRegionAnalysis;
this.originalContentsAnalysis = scheduleManager.getOriginalContentsAnalysis();
+ StandardLibraryHelper standardLibraryHelper = scheduleManager.getStandardLibraryHelper();
+ this.oclContainerProperty = standardLibraryHelper.getOclContainerProperty();
+ this.oclContentsProperty = standardLibraryHelper.getOclContentsProperty();
}
public void addCallToChild(@NonNull Partition parentPartition, @NonNull Partition childPartition) {
@@ -265,58 +272,75 @@
/**
* Create an EdgeConnection for the predicatedEdges and/or their target Class node.
*/
- private void createClassEdgeConnection(@Nullable StringBuilder s, @NonNull RootRegion rootRegion, @NonNull Region region, @NonNull Node castTargetNode, @NonNull Iterable<@NonNull NavigableEdge> predicatedEdges) {
+ private void createClassEdgeConnection(@Nullable StringBuilder s, @NonNull RootRegion rootRegion, @NonNull Region region, @NonNull Node castTargetNode, @NonNull Iterable<@NonNull NavigableEdge> consumedEdges) {
RootRegion invokingRegion2 = rootRegion;
assert invokingRegion2 != null;
Node castTarget = castTargetNode;
ClassDatum classDatum = QVTscheduleUtil.getClassDatum(castTarget);
- for (@NonNull NavigableEdge predicatedEdge : predicatedEdges) {
- assert predicatedEdge.isNavigation();
- assert predicatedEdge.getIncomingConnection() == null;
- assert !predicatedEdge.isCast();
- Property predicatedProperty = QVTscheduleUtil.getReferredProperty((NavigationEdge)predicatedEdge);
- assert !predicatedProperty.isIsImplicit();
+ for (@NonNull NavigableEdge consumedEdge : consumedEdges) {
+ assert consumedEdge.isNavigation();
+ assert consumedEdge.getIncomingConnection() == null;
+ assert !consumedEdge.isCast();
+ Property consumedProperty = QVTscheduleUtil.getReferredProperty((NavigationEdge)consumedEdge);
+ assert !consumedProperty.isIsImplicit();
boolean isDataType = classDatum.isDataType();
assert !isDataType;
Iterable<@NonNull Node> sourceNodes = getNewNodes(classDatum);
- Iterable<@NonNull NavigableEdge> realizedEdges = getNewEdges(predicatedEdge);
- if (realizedEdges != null) {
- Set<@NonNull Region> edgeSourceRegions = new HashSet<>();
- Set<@NonNull Region> nodeSourceRegions = new HashSet<>();
- for (@NonNull NavigableEdge realizedEdge : realizedEdges) {
- edgeSourceRegions.add(QVTscheduleUtil.getOwningRegion(realizedEdge));
+ Iterable<@NonNull NavigableEdge> producedEdges = getNewEdges(consumedEdge);
+ if (producedEdges != null) {
+ UniqueList<@NonNull Region> edgeSourceRegions = new UniqueList<>();
+ for (@NonNull NavigableEdge producedEdge : producedEdges) {
+ edgeSourceRegions.add(QVTscheduleUtil.getOwningRegion(producedEdge));
}
- if (sourceNodes != null) {
- for (@NonNull Node sourceNode : sourceNodes) {
- nodeSourceRegions.add(QVTscheduleUtil.getOwningRegion(sourceNode));
+ //
+ // Create an EdgeConnection for the edge realizations.
+ //
+ UniqueList<@NonNull NavigableEdge> thoseEdges = null;
+ for (@NonNull NavigableEdge producedEdge : producedEdges) {
+ Node producedSource = QVTscheduleUtil.getSourceNode(producedEdge);
+ Node producedTarget = QVTscheduleUtil.getTargetNode(producedEdge);
+ Property producedProperty = QVTscheduleUtil.getReferredProperty((NavigationEdge)producedEdge);
+ Node consumedSource;
+ Node consumedTarget;
+ // FIXME Workingaround Bug 560541 - should be able to exploit oclContainer/oclContents isComposite
+ boolean producedContainer = (producedProperty == oclContainerProperty) || ((producedProperty.getOpposite() != null) && producedProperty.getOpposite().isIsComposite());
+ boolean producedContainment = (producedProperty == oclContentsProperty) || producedProperty.isIsComposite();
+ boolean consumedContainer = (consumedProperty == oclContainerProperty) || ((consumedProperty.getOpposite() != null) && consumedProperty.getOpposite().isIsComposite());
+ boolean consumedContainment = (consumedProperty == oclContentsProperty) || consumedProperty.isIsComposite();
+ if ((producedProperty == consumedProperty) || ((producedContainer == consumedContainer) && (producedContainment == consumedContainment))) { // Normalize consumed direction to produced direction
+ consumedSource = QVTscheduleUtil.getSourceNode(consumedEdge);
+ consumedTarget = QVTscheduleUtil.getTargetNode(consumedEdge);
}
- }
- //
- // Create an EdgeConnection for the edge realizations unless all edges are sources by node sources.
- //
- // if (!nodeSourceRegions.containsAll(edgeSourceRegions)) { // If edges are assigned independently of their targets.
- Set<@NonNull Region> conformantEdgeSourceRegions = null;
- List<@NonNull NavigableEdge> thoseEdges = null;
- for (@NonNull NavigableEdge realizedEdge : realizedEdges) {
- if (scheduleManager.isElementallyConformantSource(realizedEdge, predicatedEdge) && QVTscheduleUtil.isConformantTarget(realizedEdge, predicatedEdge)) {
- if (thoseEdges == null) {
- thoseEdges = new ArrayList<>();
- conformantEdgeSourceRegions = new HashSet<>();
- }
- if (!thoseEdges.contains(realizedEdge)) {
- thoseEdges.add(realizedEdge);
- assert conformantEdgeSourceRegions != null;
- conformantEdgeSourceRegions.add(QVTscheduleUtil.getOwningRegion(realizedEdge));
+ else {
+ assert (producedProperty == consumedProperty.getOpposite()) || ((producedContainer == consumedContainment) && (producedContainment == consumedContainer));
+ consumedSource = QVTscheduleUtil.getTargetNode(consumedEdge);
+ consumedTarget = QVTscheduleUtil.getSourceNode(consumedEdge);
+ }
+ ClassDatum producedSourceClassDatum = QVTscheduleUtil.getClassDatum(producedSource);
+ ClassDatum consumedSourceClassDatum = QVTscheduleUtil.getClassDatum(consumedSource);
+ ClassDatum producedElementalClassDatum = scheduleManager.getElementalClassDatum(producedSourceClassDatum);
+ ClassDatum consumedElementalClassDatum = scheduleManager.getElementalClassDatum(consumedSourceClassDatum);
+ // FIXME why is this so complicated irregular ? testOCL2QVTi_Source2Target_CG is a demanding test
+ if (QVTscheduleUtil.conformsTo(producedElementalClassDatum, consumedElementalClassDatum)
+ || (!producedSource.isRealized() && QVTscheduleUtil.conformsTo(consumedElementalClassDatum, producedElementalClassDatum))) {
+ ClassDatum producedTargetClassDatum = QVTscheduleUtil.getClassDatum(producedTarget);
+ ClassDatum consumedTargetClassDatum = QVTscheduleUtil.getClassDatum(consumedTarget);
+ if (QVTscheduleUtil.conformsToClassOrBehavioralClass(producedTargetClassDatum, consumedTargetClassDatum)
+ || (!producedTarget.isRealized() && QVTscheduleUtil.conformsToClassOrBehavioralClass(consumedTargetClassDatum, producedTargetClassDatum))) {
+ if (thoseEdges == null) {
+ thoseEdges = new UniqueList<>();
+ }
+ thoseEdges.add(producedEdge);
}
}
}
- if (thoseEdges != null) { //&& !nodeSourceRegions.containsAll(conformantEdgeSourceRegions)) {
- EdgeConnection edgeConnection = getEdgeConnection(invokingRegion2, thoseEdges, predicatedProperty);
+ if (thoseEdges != null) {
+ EdgeConnection edgeConnection = getEdgeConnection(invokingRegion2, thoseEdges, consumedProperty);
if (s != null) {
- s.append("\n EdgeConnection \"" + edgeConnection + "\" to " + predicatedEdge);
+ s.append("\n EdgeConnection \"" + edgeConnection + "\" to " + consumedEdge);
}
- if (!Iterables.contains(edgeConnection.getTargetEdges(), predicatedEdge)) {
- edgeConnection.addUsedTargetEdge(predicatedEdge, false);
+ if (!Iterables.contains(edgeConnection.getTargetEdges(), consumedEdge)) {
+ edgeConnection.addUsedTargetEdge(consumedEdge, false);
if (s != null) {
for (@NonNull NavigableEdge thatEdge : thoseEdges) {
s.append("\n from " + thatEdge.getOwningRegion() + " : " + thatEdge);
@@ -324,7 +348,6 @@
}
}
}
- // }
//
// Create a NodeConnection for the node realizations.
//
@@ -335,13 +358,13 @@
&& !castTarget.isOperation()
&& (castTarget.getIncomingConnection() == null)
// && !castTarget.isAttributeNode()
- // && !rootRootRegion.isOnlyCastOrRecursed(predicatedNode)
- // && !hasEdgeConnection(predicatedNode)
+ // && !rootRootRegion.isOnlyCastOrRecursed(consumedNode)
+ // && !hasEdgeConnection(consumedNode)
) {
- NodeConnection predicatedConnection = getNodeConnection(invokingRegion2, sourceNodes, classDatum, scheduleManager.getDomainUsage(classDatum));
- predicatedConnection.addUsedTargetNode(castTarget, false);
+ NodeConnection nodeConnection = getNodeConnection(invokingRegion2, sourceNodes, classDatum, scheduleManager.getDomainUsage(classDatum));
+ nodeConnection.addUsedTargetNode(castTarget, false);
if (s != null) {
- s.append("\n NodeConnection \"" + predicatedConnection + "\" to " + castTarget);
+ s.append("\n NodeConnection \"" + nodeConnection + "\" to " + castTarget);
for (@NonNull Node sourceNode : sourceNodes) {
s.append("\n from " + sourceNode.getOwningRegion() + " : " + sourceNode);
}
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtbase/src/org/eclipse/qvtd/pivot/qvtbase/utilities/StandardLibraryHelper.java b/plugins/org.eclipse.qvtd.pivot.qvtbase/src/org/eclipse/qvtd/pivot/qvtbase/utilities/StandardLibraryHelper.java
index 8560eb9..1975960 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtbase/src/org/eclipse/qvtd/pivot/qvtbase/utilities/StandardLibraryHelper.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtbase/src/org/eclipse/qvtd/pivot/qvtbase/utilities/StandardLibraryHelper.java
@@ -35,6 +35,7 @@
private final @NonNull OperationId oclAnyOclAsTypeId;
private final @NonNull OperationId oclAnyOclIsKindOfId;
private final @NonNull Property oclContainerProperty;
+ private final @NonNull Property oclContentsProperty;
private final @NonNull OperationId oclElementOclContainerId;
@@ -71,6 +72,9 @@
Property candidateOclContainerProperty = NameUtil.getNameable(oclElementType.getOwnedProperties(), "oclContainer");
assert candidateOclContainerProperty != null : "OCL Standard Librarty has no OclElement::oclContainer property";
oclContainerProperty = candidateOclContainerProperty;
+ Property candidateOclContentsProperty = NameUtil.getNameable(oclElementType.getOwnedProperties(), "oclContents");
+ assert candidateOclContentsProperty != null : "OCL Standard Librarty has no OclElement::oclContents property";
+ oclContentsProperty = candidateOclContentsProperty;
}
public @NonNull Operation getCollectionExcludingOperation() {
@@ -109,6 +113,10 @@
return oclContainerProperty;
}
+ public @NonNull Property getOclContentsProperty() {
+ return oclContentsProperty;
+ }
+
public @NonNull OperationId getOclElementOclContainerId() {
return oclElementOclContainerId;
}
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/QVTscheduleUtil.java b/plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/QVTscheduleUtil.java
index 0a64d92..fd22aaa 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/QVTscheduleUtil.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/QVTscheduleUtil.java
@@ -710,26 +710,6 @@
return false;
}
- /**
- * Return true if the target of thatEdge is compatible with the target of thisEdge.
- */
- public static boolean isConformantTarget(@NonNull NavigableEdge thatEdge, @NonNull NavigableEdge thisEdge) {
- Node thatTarget = thatEdge.getEdgeTarget();
- Node thisTarget = thisEdge.getEdgeTarget();
- ClassDatum thatType = getClassDatum(thatTarget);
- ClassDatum thisType = getClassDatum(thisTarget);
- if (conformsToClassOrBehavioralClass(thatType, thisType)) {
- return true;
- }
- if (thatTarget.isRealized()) {
- return false;
- }
- if (conformsToClassOrBehavioralClass(thisType, thatType)) {
- return true;
- }
- return false;
- }
-
/* public static boolean isRealizedIncludes(@NonNull Edge edge) { // FIXME includes should be a pseudo-navigation edge
if (!edge.isRealized()) {
return false;