Bugfixes multi-cda (thanks to Gabi Taentzer)
Change-Id: I32012b74c03ba9b6077e4409397458eec99f8038
diff --git a/plugins/org.eclipse.emf.henshin.multicda.cda/src/org/eclipse/emf/henshin/multicda/cda/ConflictAnalysis.java b/plugins/org.eclipse.emf.henshin.multicda.cda/src/org/eclipse/emf/henshin/multicda/cda/ConflictAnalysis.java
index d001104..e6ad492 100644
--- a/plugins/org.eclipse.emf.henshin.multicda.cda/src/org/eclipse/emf/henshin/multicda/cda/ConflictAnalysis.java
+++ b/plugins/org.eclipse.emf.henshin.multicda.cda/src/org/eclipse/emf/henshin/multicda/cda/ConflictAnalysis.java
@@ -332,7 +332,15 @@
Set<Node> l1 = new HashSet<>(rule1.getLhs().getNodes());
Set<Node> l2 = new HashSet<>(originalR2.getLhs().getNodes());
Set<Node> f = new HashSet<>();
- for (NestedCondition nc : originalR2.getLhs().getNACs())
+ Set<Node> l1InNac = new HashSet<>();
+ Set<Node> l2InNac = new HashSet<>();
+ boolean allowed1 = true;
+ boolean allowed2 = true;
+ boolean nac2Allowed = false;
+ boolean nac1Allowed = false;
+
+ //collect all negative nodes of rule 2
+ for (NestedCondition nc : originalR2.getLhs().getNACs()) {
for (Node fn : nc.getConclusion().getNodes()) {
Node mappedNode = nc.getMappings().getOrigin(fn);
if (mappedNode == null)
@@ -341,20 +349,32 @@
l2.remove(mappedNode);
f.add(fn);
}
+ else {
+ l2InNac.add(fn);
+ }
}
+ //if there are negative elements, add l2
if (!f.isEmpty()) {
Map<Node, Node> result = new HashMap<>();
- f.addAll(l2);
+ //f.addAll(l2);
+ f.addAll(l2InNac);
Utils.mapNodes(l1, f, result, true);
- boolean allowed = result.size() < f.size();
- if (!allowed)
- return false;
+ boolean allNodesMapped = result.size() == f.size();
+ if (allNodesMapped) {
+ nac2Allowed = checkValidityOfMapping(result);
+ }
+ else nac2Allowed = true;
}
+ else nac2Allowed = true;
f.clear();
+ l2InNac.clear();
+ allowed1 = allowed1 && nac2Allowed;
+ }
+
l2 = new HashSet<>(originalR2.getLhs().getNodes());
l1 = new HashSet<>(rule1.getLhs().getNodes());
- for (NestedCondition nc : rule1.getLhs().getNACs())
+ for (NestedCondition nc : rule1.getLhs().getNACs()) {
for (Node fn : nc.getConclusion().getNodes()) {
Node mappedNode = nc.getMappings().getOrigin(fn);
if (mappedNode == null)
@@ -363,17 +383,53 @@
l1.remove(mappedNode);
f.add(fn);
}
+ else {
+ l1InNac.add(fn);
+ }
}
if (!f.isEmpty()) {
Map<Node, Node> result = new HashMap<>();
- f.addAll(l1);
+ //f.addAll(l1);
+ f.addAll(l1InNac);
Utils.mapNodes(l2, f, result, true);
- boolean allowed = result.size() < f.size();
- if (!allowed)
- return false;
+ boolean allNodesMapped = result.size() == f.size();
+ if (allNodesMapped) {
+ nac1Allowed = checkValidityOfMapping(result);
+ }
+ else nac1Allowed = true;
+ }
+ else nac1Allowed = true;
+ f.clear();
+ l1InNac.clear();
+ allowed2 = allowed2 && nac1Allowed;
}
- return true;
+ return allowed1 && allowed2;
+ }
+
+ private boolean checkValidityOfMapping(Map<Node, Node> result) {
+ Set<Node> mappedNodes = result.keySet();
+ for (Node n : mappedNodes) {
+ if(n.getOutgoing().size() != result.get(n).getOutgoing().size() ||
+ n.getIncoming().size() != result.get(n).getIncoming().size()){
+ return true;
+ }
+ else if (n.getOutgoing().size() == result.get(n).getOutgoing().size()) {
+ for(Edge e: n.getOutgoing()) {
+ if(!result.containsKey(e.getTarget())){
+ return true;
+ }
+ }
+ if (n.getIncoming().size() == result.get(n).getIncoming().size()) {
+ for(Edge e: n.getIncoming()) {
+ if(!result.containsKey(e.getSource())){
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
}
public <T extends Span> Set<T> setRequires(Set<T> spans) {
diff --git a/plugins/org.eclipse.emf.henshin.multicda.cda/src/org/eclipse/emf/henshin/multicda/cda/Utils.java b/plugins/org.eclipse.emf.henshin.multicda.cda/src/org/eclipse/emf/henshin/multicda/cda/Utils.java
index 69d052e..6858742 100644
--- a/plugins/org.eclipse.emf.henshin.multicda.cda/src/org/eclipse/emf/henshin/multicda/cda/Utils.java
+++ b/plugins/org.eclipse.emf.henshin.multicda.cda/src/org/eclipse/emf/henshin/multicda/cda/Utils.java
@@ -1046,6 +1046,9 @@
public static Map<Node, Node> mapNodes(Set<Node> nodesOriginal1, Set<Node> nodesOriginal2, Set<Node> nodes2,
Map<Node, Node> result, boolean allActionTypes) {
+
+ //Tries to compute a mapping from nodesOriginal1 to nodesOriginal2
+ //When there is a mapping, result is not empty
if (result == null)
result = new HashMap<>();
for (Node n2 : nodes2) {
@@ -1058,12 +1061,16 @@
EList<Edge> e1 = n1.getOutgoing(e2.getType());
boolean foundEdge = false;
for (Edge e : e1)
- if ((allActionTypes || e.getAction().getType() == Action.Type.PRESERVE)
- && nodesOriginal1.contains(e.getTarget())) {
- foundEdge = true;
- break;
- }
- found = foundEdge;
+ if (allActionTypes || e.getAction().getType() == Action.Type.PRESERVE) {
+ //&& nodesOriginal1.contains(e.getTarget())
+ if (result.get(e.getTarget()) == null || result.get(e.getTarget())== e2.getTarget()) {
+ foundEdge = true;
+ break;
+ }
+ }
+ if (e1.size() != 0) {
+ found = foundEdge;
+ }
}
if (found)
for (Edge e2 : n2.getIncoming())
@@ -1071,12 +1078,17 @@
EList<Edge> e1 = n1.getIncoming(e2.getType());
boolean foundEdge = false;
for (Edge e : e1)
- if ((allActionTypes || e.getAction().getType() == Action.Type.PRESERVE)
- && nodesOriginal1.contains(e.getTarget())) {
- foundEdge = true;
- break;
- }
- found = foundEdge;
+ if (allActionTypes || e.getAction().getType() == Action.Type.PRESERVE) {
+ //&& nodesOriginal1.contains(e.getTarget())
+ // in the follwoing: getTarget() should be getSource()
+ if (result.get(e.getSource()) == null || result.get(e.getSource())== e2.getSource()) {
+ foundEdge = true;
+ break;
+ }
+ }
+ if (e1.size() != 0) {
+ found = foundEdge;
+ }
}
if (found) {
result.put(n1, n2);
@@ -1086,7 +1098,9 @@
return result;
}
mapNodes(nodesOriginal1, nodesOriginal2, remained, result, allActionTypes);
- if (result.size() == nodesOriginal2.size()) {
+ //was nodesOriginal2
+ if (result.size() == Math.min(nodesOriginal1.size(),nodesOriginal2.size())) {
+ //if (result.size() == nodesOriginal2.size() - remained.size()) {
return result;
}
result.remove(n1);