blob: 2e4db5c4ebc8d6f31eab0b80c6b238de67987025 [file] [log] [blame]
package org.eclipse.emf.henshin.sam.invcheck.algorithm;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.emf.henshin.sam.invcheck.InvariantCheckerUtil;
import org.eclipse.emf.henshin.sam.invcheck.nac.PatternEdge;
import org.eclipse.emf.henshin.sam.invcheck.nac.PatternNode;
import org.eclipse.emf.henshin.sam.model.samannotation.AnnotatedElem;
import org.eclipse.emf.henshin.sam.model.samgraph.Edge;
import org.eclipse.emf.henshin.sam.model.samgraph.Graph;
import org.eclipse.emf.henshin.sam.model.samgraph.Node;
import org.eclipse.emf.henshin.sam.model.samrules.RuleGraph;
import org.eclipse.emf.henshin.sam.model.samrules.SamrulesFactory;
import org.eclipse.emf.henshin.sam.model.samtrace.Match;
/**
* Merges two graphs and a graph matching to a merged graph.
* The typical inputs are a forbidden subgraph, a part of the right side of a graph rule and their matching.
*
* The following diagram shows the behaviour of the merge method.
*
* <p><img src="../../../../../doc/diagrams/graphMerger.png" alt="Graph merger"></p>
*
*/
public class GraphMerger implements AlgorithmComponent
{
private Map<Graph, Map<AnnotatedElem, AnnotatedElem>> refItems = new HashMap<Graph, Map<AnnotatedElem, AnnotatedElem>>();
//private Map<Graph, Map<AnnotatedElem, AnnotatedElem>> inverseSameInRuleProp = new HashMap<Graph, Map<AnnotatedElem, AnnotatedElem>>();
/**
* No comment provided by developer, please add a comment to improve documentation.
*
* @param forbiddenSubGraph No description provided
* @param rule No description provided
* @param matching No description provided
* @return No description provided
*/
public RuleGraph merge (Graph forbiddenSubGraph, Graph rule, Match matching)
{
refItems.put(forbiddenSubGraph, new HashMap<AnnotatedElem, AnnotatedElem>());
refItems.put(rule, new HashMap<AnnotatedElem, AnnotatedElem>());
RuleGraph result = null;
if (forbiddenSubGraph != null && rule != null && matching != null)
{
result = SamrulesFactory.eINSTANCE.createRuleGraph();//new Graph();
result.setTypedOver(rule.getTypedOver());
copyItems (forbiddenSubGraph, result, true);
createAssocs (forbiddenSubGraph, result);
/*
* this for loop ensures that items mentioned by the given matching, won't be copied twice.
*/
for (Iterator<Map.Entry<Node, Node>> iter = matching.getNodeMatching().iterator(); iter.hasNext(); )
{
Map.Entry<Node, Node> tmpEntry = iter.next();
Node ruleNode = tmpEntry.getKey();
Node resultNode = (Node) refItems.get(forbiddenSubGraph).get(tmpEntry.getValue());
assert resultNode != null;
refItems.get(rule).put(ruleNode, resultNode);
((PatternNode) resultNode).setSameInRule(ruleNode);
}
for (Iterator<Map.Entry<Edge, Edge>> iter = matching.getEdgeMatching().iterator(); iter.hasNext(); ) {
Map.Entry<Edge, Edge> tmpEntry = iter.next();
Edge ruleEdge = tmpEntry.getKey();
Edge resultEdge = (Edge) refItems.get(forbiddenSubGraph).get(tmpEntry.getValue());
assert resultEdge != null;
refItems.get(rule).put(ruleEdge, resultEdge);
((PatternEdge) resultEdge).setSameInRule(ruleEdge);
}
copyItems (rule, result, false);
createAssocs (rule, result);
}
return result;
}
/**
* copies all graph items from srcGraph to resultGraph. thereby the qualified assocs for copies of
* elements are set.
*
* @param srcGraph
* @param resultGraph
*/
private void copyItems (Graph srcGraph, Graph resultGraph, boolean isForbidden)
{
for (Iterator<Node> iter = srcGraph.getNodes().iterator(); iter.hasNext(); )
{
final Node srcNode = iter.next();
if (!refItems.get(srcGraph).containsKey(srcNode))
{
PatternNode resultNode = InvariantCheckerUtil.copyAsPattern(srcNode);
resultGraph.getNodes().add(resultNode);
refItems.get(srcGraph).put(srcNode, resultNode);
if (isForbidden) {
resultNode.setSameInProp(srcNode);
} else {
resultNode.setSameInRule(srcNode);
}
}
}
for (Iterator<Edge> iter = srcGraph.getEdges().iterator(); iter.hasNext(); )
{
final Edge srcEdge = iter.next();
if (!refItems.get(srcGraph).containsKey(srcEdge))
{
PatternEdge resultEdge = InvariantCheckerUtil.copyAsPattern(srcEdge);
resultGraph.getEdges().add(resultEdge);
refItems.get(srcGraph).put(srcEdge, resultEdge);
if (isForbidden) {
resultEdge.setSameInProp(srcEdge);
} else {
resultEdge.setSameInRule(srcEdge);
}
}
}
}
/**
* creates the assocs between the nodes and edges of srcGraph between the elements of resultGraph.
* to make this work, all elements have be copied first before calling this method
*
* @param srcGraph the source Graph
* @param resultGraph the resulting graph containing then the assoc from srcGraph
*/
private void createAssocs (Graph srcGraph, Graph resultGraph)
{
for (Iterator<Edge> iter = srcGraph.getEdges().iterator(); iter.hasNext(); )
{
final Edge srcEdge = iter.next();
Node srcTargetNode = srcEdge.getTarget();
Node srcSourceNode = srcEdge.getSource();
assert srcTargetNode != null : srcEdge + ": sourceNode equals null!";
assert srcSourceNode != null : srcEdge + ": targetNode quals null!";
Edge resultEdge = (Edge) refItems.get(srcGraph).get(srcEdge);
Node resultTargetNode = (Node) refItems.get(srcGraph).get(srcTargetNode);
Node resultSourceNode = (Node) refItems.get(srcGraph).get(srcSourceNode);
resultEdge.setSource (resultSourceNode);
resultEdge.setTarget (resultTargetNode);
}
}
public void reset(){
refItems = new HashMap<Graph, Map<AnnotatedElem, AnnotatedElem>>();
}
}
/*
* $Log$
* Revision 1.4 2007/06/25 17:48:20 basilb
* fixed a lot of these bugs testing does not find but evaluating ;)
*
* Revision 1.3 2007/01/11 14:44:23 basilb
* even more usage of generics
*
* Revision 1.2 2007/01/03 09:27:48 basilb
* removed compile errors caused by wrong import declarations; introduced empty plugin class to ensure correct loading
*
*/