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);