Second fix for bug 453287 

We'll need a cleaner solution in the future

Change-Id: Id0e197501ee91b51ed16f9833908df96945d5be4
diff --git a/plugins/org.eclipse.emf.henshin.interpreter/src/org/eclipse/emf/henshin/interpreter/info/VariableInfo.java b/plugins/org.eclipse.emf.henshin.interpreter/src/org/eclipse/emf/henshin/interpreter/info/VariableInfo.java
index 3486343..de54a70 100644
--- a/plugins/org.eclipse.emf.henshin.interpreter/src/org/eclipse/emf/henshin/interpreter/info/VariableInfo.java
+++ b/plugins/org.eclipse.emf.henshin.interpreter/src/org/eclipse/emf/henshin/interpreter/info/VariableInfo.java
@@ -41,109 +41,109 @@
 import org.eclipse.emf.henshin.model.staticanalysis.PathFinder;
 
 public class VariableInfo {
-	
+
 	// variables which represent nodes when they are first introduced, e.g. if a
 	// mapped node occurs in the LHS and in one condition, only the variable
 	// representing the LHS node will be in this collection
 	private Collection<Variable> mainVariables;
-	
+
 	// node-variable pair
 	private Map<Node, Variable> node2variable;
-	
+
 	// variable-node pair
 	private Map<Variable, Node> variable2node;
-	
+
 	// map between a graph and all variables corresponding to nodes of that
 	// graph
 	private Map<Graph, List<Variable>> graph2variables;
-	
+
 	// map between a key variable and its main variable, e.g. there is a mapping
 	// chain from the node belonging to the main variable to the key variable
 	private Map<Variable, Variable> variable2mainVariable;
-	
+
 	private Rule rule;
 	private EngineImpl engine;
-	
+
 	public VariableInfo(RuleInfo ruleInfo, EngineImpl engine) {
 		this.rule = ruleInfo.getRule();
 		this.engine = engine;
-		
+
 		this.node2variable = new HashMap<Node, Variable>();
 		this.variable2node = new HashMap<Variable, Node>();
-		
+
 		this.graph2variables = new HashMap<Graph, List<Variable>>();
 		this.variable2mainVariable = new HashMap<Variable, Variable>();
-		
+
 		createVariables(rule.getLhs(), null);
-		
+
 		for (Node node : rule.getLhs().getNodes()) {
-			if (rule.getMappings().getImage(node,rule.getRhs())==null)
+			if (rule.getMappings().getImage(node, rule.getRhs()) == null) {
 				createDanglingConstraints(node);
+			}
 		}
-		
+
 		mainVariables = variable2mainVariable.values();
 	}
-	
+
 	private void createVariables(Graph g, Collection<Mapping> mappings) {
 		List<Variable> variables = new ArrayList<Variable>();
-		
+
 		for (Node node : g.getNodes()) {
 			EClass type = node.getType();
 			Variable var = new Variable(type);
 			variables.add(var);
 			node2variable.put(node, var);
 			variable2node.put(var, node);
-			
+
 			Variable mainVariable = var;
 			if (mappings != null) {
 				for (Mapping mapping : mappings) {
 					if (node == mapping.getImage()) {
-						mainVariable = variable2mainVariable.get(node2variable.get(mapping
-								.getOrigin()));
+						mainVariable = variable2mainVariable.get(node2variable.get(mapping.getOrigin()));
 					}
 				}
 			}
-			
+
 			variable2mainVariable.put(var, mainVariable);
 		}
-		
+
 		for (Node node : g.getNodes()) {
 			createConstraints(node);
 		}
-		
+
 		graph2variables.put(g, variables);
-		
+
 		createVariables(g.getFormula());
 	}
-	
+
 	private void createVariables(Formula formula) {
 		if (formula instanceof BinaryFormula) {
 			createVariables(((BinaryFormula) formula).getLeft());
 			createVariables(((BinaryFormula) formula).getRight());
-		} else if (formula instanceof UnaryFormula)
+		} else if (formula instanceof UnaryFormula) {
 			createVariables(((UnaryFormula) formula).getChild());
-		else if (formula instanceof NestedCondition) {
+		} else if (formula instanceof NestedCondition) {
 			NestedCondition nc = (NestedCondition) formula;
 			createVariables(nc.getConclusion(), nc.getMappings());
 		}
 	}
-	
+
 	private void createConstraints(Node node) {
 		Variable var = node2variable.get(node);
-		
+
 		// User-defined node constraints:
 		UnaryConstraint userConstraint = engine.createUserConstraints(node);
-		if (userConstraint != null){
+		if (userConstraint != null) {
 			var.userConstraints.add(userConstraint);
 		}
-		
+
 		// Outgoing edges:
 		for (Edge edge : node.getOutgoing()) {
 			Variable target = node2variable.get(edge.getTarget());
 			ReferenceConstraint constraint;
 			String index = edge.getIndex();
-			if (index!=null && index.length()>0) {
-				if (rule.getParameter(index)!=null) {
+			if (index != null && index.length() > 0) {
+				if (rule.getParameter(index) != null) {
 					constraint = new ReferenceConstraint(target, edge.getType(), index, false);
 					var.requiresFinalCheck = true;
 				} else {
@@ -159,12 +159,12 @@
 			}
 			var.referenceConstraints.add(constraint);
 			BinaryConstraint binaryUserConstraint = engine.createUserConstraints(edge);
-			if (binaryUserConstraint != null){
+			if (binaryUserConstraint != null) {
 				var.binaryUserConstraints.put(constraint, binaryUserConstraint);
 			}
-			
+
 		}
-		
+
 		// Incoming edges:
 		for (Edge edge : node.getIncoming()) {
 			if (edge.getType().isContainment()) {
@@ -173,16 +173,17 @@
 				var.containmentConstraints.add(constraint);
 			} else if (edge.getType().getEOpposite() != null) {
 				Variable target = node2variable.get(edge.getSource());
-				ReferenceConstraint constraint = new ReferenceConstraint(target, edge.getType().getEOpposite(), null, true);
+				ReferenceConstraint constraint = new ReferenceConstraint(target, edge.getType().getEOpposite(), null,
+						true);
 				var.referenceConstraints.add(constraint);
 			}
 		}
-		
+
 		// Attributes:
 		for (Attribute attribute : node.getAttributes()) {
 			String value = attribute.getValue();
 			AttributeConstraint constraint;
-			if (rule.getParameter(value)!=null) {
+			if (rule.getParameter(value) != null) {
 				constraint = new AttributeConstraint(attribute.getType(), value, false);
 			} else {
 				Object constant = engine.evalAttributeExpression(attribute, rule);
@@ -190,41 +191,43 @@
 			}
 			var.attributeConstraints.add(constraint);
 			UnaryConstraint unaryUserConstraint = engine.createUserConstraints(attribute);
-			if (unaryUserConstraint != null){
+			if (unaryUserConstraint != null) {
 				var.attributeUserConstraints.put(constraint, unaryUserConstraint);
 			}
 		}
-		
+
 		// Path constraints:
-		if (!rule.getLhs().getPACs().isEmpty()) {
+		if (node.getGraph() == rule.getLhs() && !rule.getLhs().getPACs().isEmpty()) {
 			for (Node target : node.getGraph().getNodes()) {
-				if (node==target) continue;
-				for (Entry<List<EReference>,Integer> entry : PathFinder.findReferencePaths(node, target, true, true).entrySet()) {
-					if (entry.getKey().size() > 1) { // only paths of length > 1
-						Variable targetVar = node2variable.get(target);
-						PathConstraint constraint = new PathConstraint(targetVar, entry.getKey(), entry.getValue());
-						var.pathConstraints.add(constraint);
-					}
+				if (node == target) {
+					continue;
+				}
+				for (Entry<List<EReference>, Integer> entry : PathFinder.findReferencePaths(node, target, true, true)
+						.entrySet()) {
+					Variable targetVar = node2variable.get(target);
+					PathConstraint constraint = new PathConstraint(targetVar, entry.getKey(), entry.getValue());
+					var.pathConstraints.add(constraint);
 				}
 			}
 		}
-		
+
 	}
-	
+
 	private void createDanglingConstraints(Node node) {
 		Variable var = node2variable.get(node);
-		DanglingConstraint constraint = 
-				new DanglingConstraint(getEdgeCounts(node, false), getEdgeCounts(node, true));
+		DanglingConstraint constraint = new DanglingConstraint(getEdgeCounts(node, false), getEdgeCounts(node, true));
 		var.danglingConstraints.add(constraint);
 	}
-	
+
 	private Map<EReference, Integer> getEdgeCounts(Node node, boolean incoming) {
+
 		Collection<Edge> edges = incoming ? node.getIncoming() : node.getOutgoing();
 		Collection<Edge> oppositeEdges = incoming ? node.getOutgoing() : node.getIncoming();
-		
-		if (edges.size() == 0)
+
+		if (edges.size() == 0) {
 			return null;
-		
+		}
+
 		Map<EReference, Integer> edgeCount = new HashMap<EReference, Integer>();
 		for (Edge edge : edges) {
 			EReference type = edge.getType();
@@ -236,13 +239,13 @@
 			}
 			edgeCount.put(type, count);
 		}
-		
+
 		for (Edge edge : oppositeEdges) {
 			if (edge.getType().getEOpposite() == null)
 				continue;
-			
+
 			EReference oppType = edge.getType().getEOpposite();
-			
+
 			if (incoming) {
 				// opposite edges are outgoing from the PoV of the node
 				Node remoteNode = edge.getTarget();
@@ -269,35 +272,36 @@
 				}
 			}
 		}
-		
+
 		return edgeCount;
 	}
-	
+
 	public Node getVariableForNode(Variable variable) {
 		return variable2node.get(variable);
 	}
-	
+
 	public Collection<Variable> getDependendVariables(Variable mainVariable) {
 		Collection<Variable> dependendVariables = new HashSet<Variable>();
 		for (Variable var : variable2mainVariable.keySet()) {
-			if (variable2mainVariable.get(var) == mainVariable)
+			if (variable2mainVariable.get(var) == mainVariable) {
 				dependendVariables.add(var);
+			}
 		}
-		
+
 		return dependendVariables;
 	}
-	
+
 	public Collection<Variable> getMainVariables() {
 		return mainVariables;
 	}
-	
+
 	/**
 	 * @return the graph2variables
 	 */
 	public Map<Graph, List<Variable>> getGraph2variables() {
 		return graph2variables;
 	}
-	
+
 	/**
 	 * @return the node2variable
 	 */
@@ -305,7 +309,7 @@
 		// TODO: change Solution to get rid of this method
 		return node2variable;
 	}
-		
+
 	private static final Integer ONE = new Integer(1);
-	
+
 }
diff --git a/plugins/org.eclipse.emf.henshin.model/src/org/eclipse/emf/henshin/model/staticanalysis/PathFinder.java b/plugins/org.eclipse.emf.henshin.model/src/org/eclipse/emf/henshin/model/staticanalysis/PathFinder.java
index 48cea9e..4e7ddd8 100644
--- a/plugins/org.eclipse.emf.henshin.model/src/org/eclipse/emf/henshin/model/staticanalysis/PathFinder.java
+++ b/plugins/org.eclipse.emf.henshin.model/src/org/eclipse/emf/henshin/model/staticanalysis/PathFinder.java
@@ -107,7 +107,7 @@
 	public static List<Path> findAllPaths(Graph graph, boolean withPACs) {
 		List<Path> paths = new ArrayList<Path>();
 		for (int i = 0; i < graph.getNodes().size(); i++) {
-			for (int j = 0; i < graph.getNodes().size(); i++) {
+			for (int j = 0; j < graph.getNodes().size(); j++) {
 				paths.addAll(findEdgePaths(graph.getNodes().get(i), graph.getNodes().get(j), true, withPACs));
 			}
 		}
diff --git a/plugins/org.eclipse.emf.henshin.tests/src/org/eclipse/emf/henshin/tests/basic/MatchTest2.java b/plugins/org.eclipse.emf.henshin.tests/src/org/eclipse/emf/henshin/tests/basic/MatchTest2.java
index 5a92122..476b220 100644
--- a/plugins/org.eclipse.emf.henshin.tests/src/org/eclipse/emf/henshin/tests/basic/MatchTest2.java
+++ b/plugins/org.eclipse.emf.henshin.tests/src/org/eclipse/emf/henshin/tests/basic/MatchTest2.java
@@ -11,6 +11,7 @@
 import org.eclipse.emf.henshin.interpreter.impl.EngineImpl;
 import org.eclipse.emf.henshin.interpreter.util.InterpreterUtil;
 import org.eclipse.emf.henshin.model.Action;
+import org.eclipse.emf.henshin.model.Edge;
 import org.eclipse.emf.henshin.model.HenshinFactory;
 import org.eclipse.emf.henshin.model.Node;
 import org.eclipse.emf.henshin.model.Rule;
@@ -43,4 +44,26 @@
 
 	}
 
+	@Test
+	public void bug453287_2() {
+
+		Rule rule = HenshinFactory.eINSTANCE.createRule();
+		Node p = rule.createNode(EcorePackage.eINSTANCE.getEPackage());
+		Node c = rule.createNode(EcorePackage.eINSTANCE.getEClass());
+		Edge e = rule.createEdge(p, c, EcorePackage.eINSTANCE.getEPackage_EClassifiers());
+
+		e.setAction(new Action(Action.Type.REQUIRE));
+		Assert.assertEquals(2, rule.getLhs().getNodes().size());
+		Assert.assertEquals(0, rule.getLhs().getEdges().size());
+
+		EGraph graph = new EGraphImpl();
+		graph.add(EcoreFactory.eINSTANCE.createEPackage());
+		graph.add(EcoreFactory.eINSTANCE.createEClass());
+
+		Engine engine = new EngineImpl();
+		List<Match> matches = InterpreterUtil.findAllMatches(engine, rule, graph, null);
+		Assert.assertEquals(0, matches.size());
+
+	}
+
 }