/*******************************************************************************
* 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.editor.actions.graph;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.henshin.model.Edge;
import org.eclipse.emf.henshin.model.Graph;
import org.eclipse.emf.henshin.model.Node;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.ui.actions.SelectionAction;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IWorkbenchPart;
import de.tub.tfs.henshin.editor.ui.dialog.ValidTestDialog;
import de.tub.tfs.henshin.editor.util.NodeTypes;
import de.tub.tfs.henshin.editor.util.ResourceUtil;
/**
* The Class GraphValidAction.
*
* @author Johann
*/
public class ValidateGraphAction extends SelectionAction {
/** The Constant ID. */
public static final String ID = "henshineditor.actions.ValidateGraphAction"; //$NON-NLS-1$
/** The Constant DESC. */
static private final String DESC = "Validate the selected Graph.";
/** The Constant TOOLTIP. */
static private final String TOOLTIP = "Validate this Graph.";
static private final String LABEL = "Validate";
/** The graph. */
protected Graph graph;
/**
*
* @param part
* the part
*/
public ValidateGraphAction(IWorkbenchPart part) {
super(part);
setId(ID);
setText(LABEL);
setDescription(DESC);
setToolTipText(TOOLTIP);
setImageDescriptor(ResourceUtil.ICONS.CHECK.descr(18));
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.ui.actions.WorkbenchPartAction#calculateEnabled()
*/
@Override
protected boolean calculateEnabled() {
List<?> selectedObjects = getSelectedObjects();
graph = null;
if (selectedObjects.size() == 1) {
Object selectedObject = selectedObjects.get(0);
if (selectedObject instanceof EditPart) {
Object model = ((EditPart) selectedObject).getModel();
if (model instanceof Graph) {
graph = (Graph) model;
}
}
}
return graph != null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
List<String> fehlerMeldungen = new ArrayList<String>();
Map<EPackage, LinkedList<Node>> ePackage2NodeList = getRoots();
Set<EPackage> ePackages = ePackage2NodeList.keySet();
for (EPackage ePackage : ePackages) {
LinkedList<Node> wurzeln = ePackage2NodeList.get(ePackage);
if (wurzeln.size() != 1) {
if (wurzeln.size() == 0) {
fehlerMeldungen
.add("Der Graph hat keinen Wurzelknoten von EMF_Model "
+ ePackage.getName() + "!");
ePackage2NodeList.remove(ePackage);
}
if (wurzeln.size() > 1) {
fehlerMeldungen
.add("Der Graph enth�lt mehrere Wurzelknoten eines EMF-Modells ("
+ ePackage.getName() + ")!");
}
}
}
for (Node node : graph.getNodes()) {
if (NodeTypes.isContainment(node)) {
int count = 0;
for (Edge edge : node.getIncoming()) {
if (edge.getType().isContainment()) {
count++;
}
}
if (count > 1) {
fehlerMeldungen.add("Der Knoten " + node.getName() + ": "
+ node.getType().getName()
+ " hat mehrere containment Kanten. ");
}
}
}
LinkedList<Node> allNodes = new LinkedList<Node>(graph.getNodes());
while (allNodes.size() > 0) {
Map<Node, List<List<Node>>> nodeWithPaths = new HashMap<Node, List<List<Node>>>();
List<Node> pfad = new ArrayList<Node>();
Node startNode = getNextStartNode(ePackage2NodeList, allNodes);
addSuccessorNodes(nodeWithPaths, allNodes, startNode, pfad, true);
while (nodeWithPaths.size() > 0) {
Node node = nodeWithPaths.keySet().iterator().next();
List<List<Node>> actualPaths = nodeWithPaths.get(node);
nodeWithPaths.remove(node);
for (List<Node> visitedNodes : actualPaths) {
if (visitedNodes.contains(node)) {
String s = "Der Graph enth�lt Zyklen. (";
int index = visitedNodes.indexOf(node);
for (int i = index; i < visitedNodes.size(); i++) {
Node nn = visitedNodes.get(i);
String name = " ";
if (nn.getName() != null) {
name += nn.getName();
}
name += ":" + nn.getType().getName();
s += name + " ->";
}
String name = " ";
if (node.getName() != null) {
name += node.getName();
}
name += ":" + node.getType().getName();
s += name + ")";
fehlerMeldungen.add(s);
continue;
}
List<Node> newVisitedNode = new ArrayList<Node>(
visitedNodes);
addSuccessorNodes(nodeWithPaths, allNodes, node,
newVisitedNode, false);
}
}
}
if (fehlerMeldungen.size() == 0) {
fehlerMeldungen.add("Alles Ok!");
}
ValidTestDialog vD = new ValidTestDialog(getWorkbenchPart().getSite()
.getShell(), SWT.NULL, fehlerMeldungen);
vD.open();
}
/**
* Gets the next start node.
*
* @param ePackage2NodeList
* the e package2 node list
* @param allNodes
* the all nodes
* @return the next start node
*/
private Node getNextStartNode(
Map<EPackage, LinkedList<Node>> ePackage2NodeList,
LinkedList<Node> allNodes) {
Node startNode;
if (ePackage2NodeList.size() > 0) {
EPackage eP = ePackage2NodeList.keySet().iterator().next();
LinkedList<Node> wurzelnNodes = ePackage2NodeList.get(eP);
startNode = wurzelnNodes.poll();
if (wurzelnNodes.isEmpty()) {
ePackage2NodeList.remove(eP);
}
allNodes.remove(startNode);
} else {
startNode = allNodes.poll();
}
return startNode;
}
/**
* Adds the successor nodes.
*
* @param nodeWithPaths
* the node with paths
* @param allNodes
* the all nodes
* @param actualNode
* the actual node
* @param pfad
* the pfad
* @param nurNichtBesuchte
* the nur nicht besuchte
*/
private void addSuccessorNodes(Map<Node, List<List<Node>>> nodeWithPaths,
LinkedList<Node> allNodes, Node actualNode, List<Node> pfad,
boolean nurNichtBesuchte) {
pfad.add(actualNode);
for (Edge edge : actualNode.getOutgoing()) {
if (edge.getType().isContainment()) {
Node target = edge.getTarget();
if (!nurNichtBesuchte || allNodes.contains(target)
|| target == actualNode) {
allNodes.remove(target);
if (nodeWithPaths.containsKey(target)) {
nodeWithPaths.get(target).add(pfad);
} else {
List<List<Node>> newPaths = new ArrayList<List<Node>>();
newPaths.add(pfad);
nodeWithPaths.put(target, newPaths);
}
}
}
}
}
/**
* Gets the roots.
*
* @return the roots
*/
private Map<EPackage, LinkedList<Node>> getRoots() {
Map<EPackage, LinkedList<Node>> ePackage2NodeList = new HashMap<EPackage, LinkedList<Node>>();
for (Node node : graph.getNodes()) {
EPackage ePackge = node.getType().getEPackage();
if (!ePackage2NodeList.containsKey(ePackge)) {
ePackage2NodeList.put(ePackge, new LinkedList<Node>());
}
if (!NodeTypes.isContainment(node)) {
ePackage2NodeList.get(node.getType().getEPackage()).add(node);
}
}
return ePackage2NodeList;
}
}