/*******************************************************************************
* 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.tggeditor.util;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
import org.eclipse.emf.henshin.interpreter.EGraph;
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.Node;
import org.eclipse.emf.henshin.model.Rule;
import de.tub.tfs.henshin.tgg.GraphLayout;
import de.tub.tfs.henshin.tgg.TEdge;
import de.tub.tfs.henshin.tgg.TGG;
import de.tub.tfs.henshin.tgg.TNode;
import de.tub.tfs.henshin.tgg.TggFactory;
import de.tub.tfs.henshin.tgg.TggPackage;
import de.tub.tfs.henshin.tgg.TripleComponent;
import de.tub.tfs.henshin.tgg.TripleGraph;
import de.tub.tfs.henshin.tgg.interpreter.impl.NodeTypes;
import de.tub.tfs.henshin.tgg.interpreter.util.ExceptionUtil;
import de.tub.tfs.henshin.tgg.interpreter.util.NodeUtil;
import de.tub.tfs.henshin.tggeditor.editparts.graphical.GraphEditPart;
public class GraphUtil {
static public int center = 350;
static public int correstpondenceWidth = 100;
/**
* calculates the triple component for specific x coordinate in graph
* @param x is the given x coordinate
* @param graphEditPart where to calculate the type
* @return type
*/
public static TripleComponent getTripleComponentForXCoordinate(GraphEditPart graphEditPart, int x) {
if(graphEditPart != null) {
int SCx = graphEditPart.getCastedModel().getDividerSC_X();
int CTx = graphEditPart.getCastedModel().getDividerCT_X();
correstpondenceWidth = CTx-SCx;
center = SCx + correstpondenceWidth/2;
}
if(x < center - correstpondenceWidth/2) return TripleComponent.SOURCE;
if(x < center + correstpondenceWidth/2) return TripleComponent.CORRESPONDENCE;
if(x >= center + correstpondenceWidth/2) return TripleComponent.TARGET;
return TripleComponent.SOURCE;
}
public static int getMinXCoordinateForNodeGraphType(TripleComponent type){
switch (type) {
case SOURCE : return 0;
case CORRESPONDENCE: return center-correstpondenceWidth/2;
case TARGET: return center+correstpondenceWidth /2;
}
return 0;
}
/**
* Searches the graph layout of divider. If dividerSC is true it searches for
* source-correspondence divider, if its false it searches for the correspondence-target divider.
* @param graph which is linked to its dividers
* @param dividerSC (search SC or CT divider?)
* @return graph layout of searched divider
*/
public static GraphLayout getGraphLayout(Graph graph, boolean dividerSC) {
TGG layoutSystem = GraphicalNodeUtil.getLayoutSystem(graph);
if (layoutSystem != null) {
for (GraphLayout graphLayout : layoutSystem.getGraphlayouts()) {
if (graphLayout.getGraph() == graph) {
if (dividerSC == graphLayout.isIsSC())
return graphLayout;
}
}
}
return null;
}
/**
* Searches the graph layout for the dividers and returns them.
* @param graph which is linked to its dividers
* @return graph layouts [dividerSC,dividerCT]
*/
public static GraphLayout[] getGraphLayouts(Graph graph) {
TGG layoutSystem = GraphicalNodeUtil.getLayoutSystem(graph);
GraphLayout[] layouts = new GraphLayout[2];
if (layoutSystem != null) {
for (GraphLayout graphLayout : layoutSystem.getGraphlayouts()) {
if (graphLayout.getGraph() == graph) {
if (graphLayout.isIsSC()) layouts[0]=graphLayout;
else layouts[1]=graphLayout;
}
}
}
return layouts;
}
/**
* Computes the sets of nodes in each triple component.
* @param graph the graph that contains the nodes
* @return the distinguished node sets for each triple component
*/
public static HashMap<TripleComponent, List<TNode>> getDistinguishedNodeSets(
Graph graph) {
if (graph == null) {ExceptionUtil.error("Graph is missing for computing distinguished node sets."); return null;}
HashMap<TripleComponent, List<TNode>> nodeSets= new HashMap<TripleComponent, List<TNode>>();
EList<Node> nodes = graph.getNodes();
List<TNode> sourceNodes = new Vector<TNode>();
List<TNode> corrNodes = new Vector<TNode>();
List<TNode> targetNodes = new Vector<TNode>();
Iterator<TNode> iter = (Iterator)nodes.iterator();
TNode node;
// iterate over all nodes and put them in the respective lists for each component
while(iter.hasNext()){
node= iter.next();
if(NodeUtil.isSourceNode(node))
sourceNodes.add((TNode) node);
else if(NodeUtil.isCorrespondenceNode(node))
corrNodes.add((TNode) node);
else
targetNodes.add((TNode) node);
}
// add the lists to the hash map
nodeSets.put(TripleComponent.SOURCE, sourceNodes);
nodeSets.put(TripleComponent.CORRESPONDENCE, corrNodes);
nodeSets.put(TripleComponent.TARGET, targetNodes);
return nodeSets;
}
/**
* Computes the sets of edges in each triple component.
* @param graph the graph that contains the edges
* @return the distinguished edge sets for each triple component
*/
public static HashMap<TripleComponent, List<Edge>> getDistinguishedEdgeSets(
Graph graph) {
if (graph == null) {ExceptionUtil.error("Graph is missing for computing distinguished edge sets."); return null;}
HashMap<TripleComponent, List<Edge>> edgeSets= new HashMap<TripleComponent, List<Edge>>();
EList<Edge> edges = graph.getEdges();
List<Edge> sourceEdges = new Vector<Edge>();
List<Edge> corrEdges = new Vector<Edge>();
List<Edge> targetEdges = new Vector<Edge>();
Iterator<Edge> iter = edges.iterator();
Edge edge;
// iterate over all nodes and put them in the respective lists for each component
while(iter.hasNext()){
edge= iter.next();
if(NodeUtil.isSourceNode((TNode) edge.getSource())
&& NodeUtil.isSourceNode((TNode) edge.getTarget()))
sourceEdges.add(edge);
else if(NodeUtil.isTargetNode((TNode) edge.getSource())
&& NodeUtil.isTargetNode((TNode) edge.getTarget()))
targetEdges.add(edge);
else
corrEdges.add(edge);
}
// add the lists to the hash map
edgeSets.put(TripleComponent.SOURCE, sourceEdges);
edgeSets.put(TripleComponent.CORRESPONDENCE, corrEdges);
edgeSets.put(TripleComponent.TARGET, targetEdges);
return edgeSets;
}
/**
* Creates a triple graph with contents of the given graph and clears the contents of the given graph
* @param graph
* @return
*/
public static TripleGraph graphToTripleGraph(Graph graph) {
// create empty triple graph
TripleGraph tripleGraph = TggFactory.eINSTANCE.createTripleGraph();
tripleGraph.setName(graph.getName());
// copy nodes and remove them from the given graph
tripleGraph.getNodes().addAll(graph.getNodes());
graph.getNodes().clear();
// copy edges and remove them from the given graph
tripleGraph.getEdges().addAll(graph.getEdges());
graph.getEdges().clear();
return tripleGraph;
}
//NEW
public static void removeDoubleEdges(Graph graph){
HashSet<Edge> removed = new HashSet<Edge>();
HashSet<Edge> stays = new HashSet<Edge>();
for (Edge edge : graph.getEdges()){
for (Edge edge2 : graph.getEdges()){
if (edge!=edge2 && edge.getSource()==edge2.getSource() && edge.getTarget()==edge2.getTarget() && (! (stays.contains(edge) || removed.contains(edge)) ) ){
removed.add(edge2);
//((TEdge)edge).setMarkerType(null);
stays.add(edge);
}
}
}
graph.getEdges().removeAll(removed);
for (Edge edge : removed){
edge.getSource().getOutgoing().remove(edge);
edge.getTarget().getIncoming().remove(edge);
}
}
//NEW
/*
public static Graph merge(Graph g1, Graph g2) {
Graph result = copyGraph(g1, null, null, false);
Iterator<Node> nodes1 = g1.getNodes().iterator();
while (nodes1.hasNext()){
Node n1 = nodes1.next();
if (g2.getNode(n1.getName())!=null){
Node n2 = g2.getNode(n1.getName());
for (Attribute a : n2.getAttributes()){
if (!n1.getAttributes().contains(a)){
result.getNode(n1.getName()).getAttributes().add(a);
}
}
for (Edge edg : n2.getIncoming()){
edg.getSource().getName();
}
}
}
return null;
}*/
}