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 | |
* | |
*/ |