/*******************************************************************************
* 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.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import org.eclipse.emf.henshin.model.Edge;
import org.eclipse.emf.henshin.model.Graph;
import org.eclipse.emf.henshin.model.Node;
import de.tub.tfs.henshin.tgg.TGGRule;
import de.tub.tfs.henshin.tgg.TNode;
import de.tub.tfs.henshin.tgg.TripleComponent;
import de.tub.tfs.henshin.tgg.interpreter.util.NodeUtil;
import de.tub.tfs.henshin.tgg.interpreter.util.RuleUtil;
public class GraphOptimizer implements Comparator<Node>{
public static void optimize(Graph graph){
if (((TGGRule)graph.getRule()).isManualMatchingOrder()){
ArrayList<Node> nodes = new ArrayList<Node>();
for (Node n : graph.getRule().getRhs().getNodes()) {
Node lhs = RuleUtil.getLHSNode(n);
if (lhs != null)
nodes.add(lhs);
}
graph.getNodes().clear();
graph.getNodes().addAll(nodes);
} else {
ArrayList<Node> nodes = new ArrayList<Node>(graph.getNodes());
Collections.sort(nodes,new GraphOptimizer((TGGRule) graph.getRule()));
optimizeConnectivity(nodes,new LinkedHashSet<Node>());
graph.getNodes().clear();
graph.getNodes().addAll(nodes);
}
}
private static void optimizeConnectivity(ArrayList<Node> nodes,LinkedHashSet<Node> visited){
Node current = nodes.remove(0);
visited.add(current);
boolean added = false;
do {
added = false;
outer: for (Node node : nodes) {
if (node.getIncoming().isEmpty()){
if (!visited.contains(node)){
visited.add(node);
added = true;
}
} else {
for (Edge e : node.getIncoming()) {
if (visited.contains(e.getSource())){
if (!visited.contains(node)){
visited.add(node);
added = true;
continue outer;
}
}
if (e.getType().isContainment() && visited.contains(e.getSource())){
if (!visited.contains(node)){
visited.add(node);
added = true;
continue outer;
}
}
}
}
}
} while (added);
if (nodes.size() == 0){
nodes.addAll(visited);
return;
}
optimizeConnectivity(nodes, visited);
}
private TGGRule rule;
public GraphOptimizer(TGGRule rule) {
this.rule = rule;
}
@Override
public int compare(Node arg0, Node arg1) {
TripleComponent node0 = NodeUtil.guessTripleComponent((TNode) arg0);
TripleComponent node1 = NodeUtil.guessTripleComponent((TNode) arg1);
TripleComponent target = null;
String ruleMarkerType=rule.getMarkerType();
if(ruleMarkerType.equals(RuleUtil.TGG_FT_RULE))
target=TripleComponent.SOURCE;
if (ruleMarkerType.equals(RuleUtil.TGG_CC_RULE)){
target=TripleComponent.SOURCE;
}
if (ruleMarkerType.equals(RuleUtil.TGG_IT_RULE)){
target=TripleComponent.SOURCE;
}
if (ruleMarkerType.equals(RuleUtil.TGG_BT_RULE))
target=TripleComponent.TARGET;
int cmp = 0;
if (target==null){
System.out.println("Target id NULL!");
return cmp;
}
if (!node0.equals(node1)){
if (target.equals(node0))
cmp = -1;
if (target.equals(node1))
cmp = 1;
if (node0.equals(TripleComponent.CORRESPONDENCE)){
if (node1.equals(TripleComponent.CORRESPONDENCE)){
cmp = 0;
} else
if (!target.equals(node1)){
cmp = 1;
}
}
if (node1.equals(TripleComponent.CORRESPONDENCE)){
if (node0.equals(TripleComponent.CORRESPONDENCE)){
cmp = 0;
} else
if (!target.equals(node0)){
cmp = -1;
}
}
}
if (cmp == 0)
cmp = getMajorConstraintCount(arg1) - getMajorConstraintCount(arg0);
if (cmp == 0)
cmp = getHasContainerConstraint(arg1) - getHasContainerConstraint(arg0);
if (cmp == 0)
cmp = getAttributeConstraintCount(arg1) - getAttributeConstraintCount(arg0);
return cmp;
}
private int getMajorConstraintCount(Node node){
TripleComponent target = null;
if (rule.getMarkerType().equals(RuleUtil.TGG_FT_RULE))
target = TripleComponent.SOURCE;
if (rule.getMarkerType().equals(RuleUtil.TGG_BT_RULE))
target = TripleComponent.TARGET;
if (rule.getMarkerType().equals(RuleUtil.TGG_CC_RULE))
target = TripleComponent.SOURCE;
//NEW
if (rule.getMarkerType().equals(RuleUtil.TGG_IT_RULE))
target = TripleComponent.SOURCE;
if (TripleComponent.CORRESPONDENCE.equals(NodeUtil.guessTripleComponent((TNode) node))){
int amt = 0;
for (Edge e : node.getAllEdges()) {
if (target.equals(NodeUtil.guessTripleComponent((TNode) e.getSource()))){
amt += 1;
}
if (target.equals(NodeUtil.guessTripleComponent((TNode) e.getTarget()))){
amt += 1;
}
}
return amt;
}
return node.getOutgoing().size();
}
private int getHasContainerConstraint(Node node){
for (Edge e : node.getIncoming()) {
if (e.getType().isContainment()){
return 1;
}
}
return 0;
}
private int getAttributeConstraintCount(Node node){
return node.getAttributes().size();
}
}