/*******************************************************************************
* Copyright (c) 2010-2015 Henshin developers. All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* TU Berlin, University of Luxembourg, SES S.A.
*******************************************************************************/
package de.tub.tfs.henshin.tgg.interpreter.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
import org.eclipse.emf.henshin.model.Attribute;
import org.eclipse.emf.henshin.model.Edge;
import org.eclipse.emf.henshin.model.Graph;
import org.eclipse.emf.henshin.model.Mapping;
import org.eclipse.emf.henshin.model.NestedCondition;
import org.eclipse.emf.henshin.model.Node;
import org.eclipse.emf.henshin.model.Rule;
import de.tub.tfs.henshin.tgg.TGGRule;
import de.tub.tfs.henshin.tgg.TNode;
import de.tub.tfs.henshin.tgg.TripleGraph;
public class RuleUtil {
/** description of an original triple rule of the TGG */
public final static String TGG_RULE = "tgg";
/** description of a derived forward translation rule of the TGG */
public final static String TGG_FT_RULE = "ft";
public final static String TGG_BT_RULE = "bt";
public final static String TGG_CC_RULE = "cc";
//NEW
public final static String TGG_CON_RULE = "con";
//NEW
/** description of a derived integration translation rule of the TGG */
public final static String TGG_IT_RULE = "it";
public final static String NEW = "<++>";
public final static String Translated = "<tr>";
public final static String Translated_Graph = "[tr]";
public final static String Not_Translated_Graph = "[!tr]";
public final static String TR_UNSPECIFIED = "[tr=?]";
public final static String CP_CRITICAL = "[X]";
//NEW GERARD
public final static String NEW_Graph = "New";
public static final String ErrorMarker = "[unknown]";
//NEW
//public final static String INTERSECTING = "Intersecting";
/**
* retrieves a list of possible markers for rule elements (in NAC, LHS, RHS)
* @return
*/
public static HashSet<String> getRuleMarkerTypes(){
HashSet<String> ruleMarkerTypes = new HashSet<String>();
ruleMarkerTypes.addAll(Arrays.asList(new String[]{null,NEW,Not_Translated_Graph,TR_UNSPECIFIED,Translated,Translated_Graph}));
return ruleMarkerTypes;
};
/**
* get the mapping in rule of given node of rhs
* @param rhsNode
* @return
*/
public static Mapping getRHSNodeMapping(Node rhsNode) {
if(rhsNode!=null && rhsNode.getGraph() != null && rhsNode.getGraph().getRule() != null){
EList<Mapping> mappingList = rhsNode.getGraph().getRule().getMappings();
for (Mapping m : mappingList) {
if (m.getImage() == rhsNode) {
return m;
}
}
}
return null;
}
/**
* get all mappings in rule of given node of rhs
* @param rhsNode
* @return
*/
public static ArrayList<Mapping> getAllRHSNodeMappings(Node rhsNode) {
if (rhsNode.getGraph().getRule() == null)
return new ArrayList<Mapping>();
EList<Mapping> mappingList = rhsNode.getGraph().getRule().getMappings();
ArrayList<Mapping> result = new ArrayList<Mapping>();
for (Mapping m : mappingList) {
if (m.getImage() == rhsNode) {
result.add(m);
}
}
return result;
}
/**
* get the mapping in rule of given node of rhs
* @param lhsNode
* @return
*/
public static Mapping getLHSNodeMapping(Node lhsNode) {
EList<Mapping> mappingList = lhsNode.getGraph().getRule().getMappings();
for (Mapping m : mappingList) {
if (m.getOrigin() == lhsNode) {
return m;
}
}
return null;
}
/**
* Gets the corresponding LHS node of a RHS node, if it exists
* @param node of the RHS
* @return corresponding node of the LHS
*/
public static Node getLHSNode(Node rhsNode) {
Node lhsNode = null;
Mapping nodeMapping = getRHSNodeMapping(rhsNode);
if (nodeMapping!=null)
lhsNode = nodeMapping.getOrigin();
return lhsNode;
}
public static ArrayList<Node> getAllLHSNodes(
Node rhsNode) {
ArrayList<Node> result = new ArrayList<Node>();
// scan all nodes in LHS node
ArrayList<Mapping> nodeMappings = getAllRHSNodeMappings(rhsNode);
for (Mapping m: nodeMappings){
result.add(m.getOrigin());
}
return result;
}
public static Node getRHSNode(Node lhsNode) {
Node rhsNode = null;
Mapping nodeMapping=null;
EList<Mapping> mappingList = lhsNode.getGraph().getRule().getMappings();
for (Mapping m : mappingList) {
if (m.getOrigin() == lhsNode) {
nodeMapping=m;
}
}
if (nodeMapping!=null)
rhsNode = nodeMapping.getImage();
return rhsNode;
}
public static Attribute getLHSAttribute(Attribute rhsAttribute) {
Node lhsNode = getLHSNode(rhsAttribute.getNode());
if(lhsNode!=null){
// scan all attributes in LHS node
for (Attribute att : lhsNode.getAttributes()){
if (att.getType() == rhsAttribute.getType())
// attribute was found - return it
return att;
}
}
// attribute was not found
return null;
}
public static ArrayList<Attribute> getAllLHSAttributes(
Attribute rhsAttribute) {
ArrayList<Attribute> result = new ArrayList<Attribute>();
Node lhsNode = getLHSNode(rhsAttribute.getNode());
// scan all attributes in LHS node
if (lhsNode != null) {
for (Attribute att : lhsNode.getAttributes()) {
if (att.getType() == rhsAttribute.getType())
// attribute was found - return it
result.add(att);
}
}
return result;
}
/**
* Gets the corresponding LHS node of a RHS node, if it exists
* @param node of the RHS
* @return corresponding node of the LHS
*/
public static Edge getRHSEdge(Edge lhsEdge) {
Node lhsSourceNode = lhsEdge.getSource();
Node lhsTargetNode = lhsEdge.getTarget();
Mapping sourceNodeMapping =getLHSNodeMapping(lhsSourceNode);
Mapping targetNodeMapping =getLHSNodeMapping(lhsTargetNode);
if(sourceNodeMapping !=null && targetNodeMapping !=null)
{
Node rhsSourceNode = sourceNodeMapping.getImage();
for(Edge e: rhsSourceNode.getOutgoing())
{
if(e.getType()==lhsEdge.getType())
return e;
}
}
return null;
}
/**
* Gets the corresponding LHS node of a RHS node, if it exists
* @param node of the RHS
* @return corresponding node of the LHS
*/
public static Edge getLHSEdge(Edge rhsEdge) {
Node rhsSourceNode = rhsEdge.getSource();
Node rhsTargetNode = rhsEdge.getTarget();
Mapping sourceNodeMapping =getRHSNodeMapping(rhsSourceNode);
Mapping targetNodeMapping =getRHSNodeMapping(rhsTargetNode);
if(sourceNodeMapping !=null && targetNodeMapping !=null)
{
Node lhsSourceNode = sourceNodeMapping.getOrigin();
for(Edge e: lhsSourceNode.getOutgoing())
{
if(e.getTarget().equals(targetNodeMapping.getOrigin())){
if (rhsEdge.getType().equals(e.getType()))
return e;
}
}
}
return null;
}
public static ArrayList<Edge> getAllLHSEdges(
Edge rhsEdge) {
ArrayList<Edge> result = new ArrayList<Edge>();
// scan all nodes in LHS node
Node rhsSourceNode = rhsEdge.getSource();
Node rhsTargetNode = rhsEdge.getTarget();
if (rhsSourceNode!=null && rhsTargetNode!=null){
Mapping sourceNodeMapping =getRHSNodeMapping(rhsSourceNode);
Mapping targetNodeMapping =getRHSNodeMapping(rhsTargetNode);
if(sourceNodeMapping !=null && targetNodeMapping !=null)
{
Node lhsSourceNode = sourceNodeMapping.getOrigin();
Node lhsTargetNode = sourceNodeMapping.getImage();
for(Edge e: lhsSourceNode.getOutgoing())
{
// check that the type and target node match
if(e.getType()==rhsEdge.getType()
&& e.getTarget()==lhsTargetNode)
result.add(e);
}
}
}
return result;
}
public static Rule copyRule(Rule oldRule) {
Copier copier = new Copier();
EObject result = copier.copy(oldRule);
copier.copyReferences();
Rule r = (Rule)result;
RuleUtil.setLhsCoordinatesAndLayout(r);
return r;
}
public static EList<Graph> getNACGraphs(Rule rule){
EList<Graph> nacGraphs = new BasicEList <Graph>();
for (NestedCondition ac : rule.getLhs().getNestedConditions()) {
if (ac.getConclusion() != null) {
nacGraphs.add(ac.getConclusion());
}
}
return nacGraphs;
}
public static boolean checkNodeMarker(String objectMarker,
HashMap<Node, Boolean> isTranslatedMap, EObject graphObject) {
if (
(RuleUtil.Translated_Graph.equals(objectMarker) && isTranslatedMap
.get(graphObject))
// case: object is context element, then graph node has to be
// translated already
|| (RuleUtil.Not_Translated_Graph.equals(objectMarker) && !isTranslatedMap
.get(graphObject))
// case: object is effective element, then graph node has to be
// translated already
|| (RuleUtil.TR_UNSPECIFIED.equals(objectMarker) && isTranslatedMap
.containsKey(graphObject))
// case: object marker is not specified (e.g. for NAC objects)
// (maybe only required for unmapped (from LHS to NAC graph) )
) {
return true;
}
return false;
}
public static boolean checkAttributeMarker(String objectMarker,
HashMap<Attribute, Boolean> isTranslatedMap, EObject graphObject) {
// case: graph does not explicitly contain this attribute. Therefore, it is set to the default value and the pattern matcher was successful.
// TODO: during init: extend the graph with all default values.
if(graphObject==null) return false;
if ( (RuleUtil.Translated_Graph.equals(objectMarker) && isTranslatedMap
.get(graphObject))
// case: object is context element, then graph node has to be
// translated already
|| (RuleUtil.Not_Translated_Graph.equals(objectMarker) && !isTranslatedMap
.get(graphObject))
// case: object is effective element, then graph node has to be
// translated already
|| (RuleUtil.TR_UNSPECIFIED.equals(objectMarker) && isTranslatedMap
.containsKey(graphObject))
// case: object marker is not specified (e.g. for NAC objects)
// (maybe only required for unmapped (from LHS to NAC graph) )
) {
return true;
}
return false;
}
public static boolean checkAttributeMarkerEMF(String objectMarker,
HashMap<EObject, HashMap<EAttribute,Boolean>> isTranslatedMap, EObject graphNodeObject, EAttribute graphObject) {
if ( (RuleUtil.Translated_Graph.equals(objectMarker) && isTranslatedMap
.get(graphNodeObject).get(graphObject))
// case: object is context element, then graph node has to be
// translated already
|| (RuleUtil.Not_Translated_Graph.equals(objectMarker) && !isTranslatedMap
.get(graphNodeObject).get(graphObject))
// case: object is effective element, then graph node has to be
// translated already
|| (RuleUtil.TR_UNSPECIFIED.equals(objectMarker) && isTranslatedMap
.get(graphNodeObject).containsKey(graphObject))
// case: object marker is not specified (e.g. for NAC objects)
// (maybe only required for unmapped (from LHS to NAC graph) )
) {
return true;
}
return false;
}
public static boolean checkEdgeMarker(String objectMarker,
HashMap<Edge, Boolean> isTranslatedMap, EObject graphObject) {
if (
(RuleUtil.Translated_Graph.equals(objectMarker) && isTranslatedMap
.get(graphObject))
// case: object is context element, then graph node has to be
// translated already
|| (RuleUtil.Not_Translated_Graph.equals(objectMarker) && !isTranslatedMap
.get(graphObject))
// case: object is effective element, then graph node has to be
// translated already
|| (RuleUtil.TR_UNSPECIFIED.equals(objectMarker) && isTranslatedMap
.containsKey(graphObject))
// case: object marker is not specified (e.g. for NAC objects)
// (maybe only required for unmapped (from LHS to NAC graph) )
) {
return true;
}
return false;
}
// compute whether the node is contained in an LHS of a rule
public static boolean isLHSNode(Node n) {
Rule r = n.getGraph().getRule();
if(r!=null && r.getLhs()==n.getGraph())
return true;
else
return false;
}
// check whether the graph is an LHS graph
public static boolean isLHSGraph(Graph graph) {
return (graph.getRule() != null && graph.getRule().getLhs() == graph);
}
public static boolean graphIsOpRuleRHS(Graph graph) {
TGGRule rule=null;
EObject container = graph.eContainer();
if (container instanceof TGGRule)
rule = (TGGRule) container;
if (rule==null || RuleUtil.TGG_RULE.equals(rule.getMarkerType()))
return false;
return true;
}
public static boolean setLhsCoordinatesAndLayout(Rule rule){
if (rule.getLhs().getNodes().size()==0) return false;
//if (((TNode)rule.getLhs().getNodes().get(0)).getX()!=0) return false;
for (Node n : rule.getLhs().getNodes()){
TNode tn = (TNode) n;
TNode tni = (TNode) rule.getAllMappings().getImage(n, rule.getRhs());
tn.setX(tni.getX());
tn.setY(tni.getY());
}
if (rule.getLhs() instanceof TripleGraph && rule.getRhs() instanceof TripleGraph){
TripleGraph tg = (TripleGraph) rule.getRhs();
((TripleGraph)rule.getLhs()).setDividerCT_X(tg.getDividerCT_X());
((TripleGraph)rule.getLhs()).setDividerSC_X(tg.getDividerSC_X());
((TripleGraph)rule.getLhs()).setDividerMaxY(tg.getDividerMaxY());
((TripleGraph)rule.getLhs()).setDividerYOffset(tg.getDividerYOffset());
}else{
throw new IllegalArgumentException("Lhs has to be of Type TripleGraph");
}
return true;
}
}