/* This file is part of SlumDroid <https://code.google.com/p/slumdroid/>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License <http://www.gnu.org/licenses/gpl-3.0.txt>
* for more details.
*
* Copyright (C) 2013-2015 Gennaro Imparato
*/
package it.slumdroid.utilities.module.androidtest.graphviz;
import static it.slumdroid.droidmodels.model.ActivityState.CRASH;
import static it.slumdroid.droidmodels.model.ActivityState.EXIT;
import static it.slumdroid.droidmodels.model.ActivityState.FAILURE;
import static it.slumdroid.utilities.Resources.BREAK;
import static it.slumdroid.utilities.Resources.NEW_LINE;
import static it.slumdroid.utilities.Resources.TAB;
import static it.slumdroid.utilities.module.androidtest.graphviz.DotUtilities.getCaption;
import it.slumdroid.droidmodels.guitree.GuiTree;
import it.slumdroid.droidmodels.model.ActivityState;
import it.slumdroid.droidmodels.model.Task;
import it.slumdroid.droidmodels.model.Transition;
import it.slumdroid.droidmodels.model.UserEvent;
import it.slumdroid.droidmodels.model.UserInput;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// TODO: Auto-generated Javadoc
/**
* The Class GuiTreeToDot.
*/
public class GuiTreeToDot {
/** The crash count. */
private int crashCount = 0;
/** The edges. */
private List<Edge> edges;
/** The fail count. */
private int failCount = 0;
/** The nodes. */
private List<Node> nodes;
/** The session. */
private GuiTree session;
/**
* Instantiates a new gui tree to dot.
*
* @param session the session
*/
public GuiTreeToDot(GuiTree session) {
this.session = session;
this.nodes = new ArrayList<Node>();
this.edges = new ArrayList<Edge>();
}
/**
* Gets the dot.
*
* @return the dot
*/
public String getDot() {
boolean first = true;
for (Task theTask: this.session) {
Transition theTransition = theTask.getFinalTransition();
addTransition(theTransition, first);
first = false;
}
StringBuilder dot = new StringBuilder ();
dot.append("digraph GuiTree {" + BREAK);
for (Edge edge: this.edges) {
dot.append(TAB + edge + " [label=\"" + edge.getLabel() + "\"];" + NEW_LINE);
}
dot.append(NEW_LINE);
for (Node node: this.nodes) {
if (node.hasImage()) {
dot.append(TAB + "subgraph cluster_" + node + "{label=\"" + node.getLabel() + "\"; " + node + "};" + NEW_LINE);
dot.append(TAB + node + " [label=\"" + node + "\", shapefile=\"" + node.getImage() + "\"];" + BREAK);
} else {
dot.append(TAB + node + " [label=\"" + node.getLabel() + "\"];" + NEW_LINE);
}
}
dot.append(NEW_LINE + "}");
return dot.toString();
}
/**
* Adds the transition.
*
* @param action the action
* @param first the first
*/
private void addTransition(Transition action, boolean first) {
Node start = getNode(action.getStartActivity());
Node finish = getNode(action.getFinalActivity());
UserEvent event = action.getEvent();
Iterator<UserInput> inputs = action.iterator();
String userInputs = new String();
while(inputs.hasNext()) {
UserInput input = inputs.next();
userInputs = userInputs.concat(" Input: " + input.getType() + " " + input.getWidget().getSimpleType());
if (!input.getValue().equals("")) {
userInputs = userInputs.concat(" Value: "+ input.getValue());
}
}
// Add main activity to nodes
if (first) {
this.nodes.add(start);
}
// Add new activity to nodes
finish.setLabel(createLabel (finish));
this.nodes.add(finish);
// Add event to edges
Edge e = new Edge(start,finish);
e.setLabel(getCaption(event) + userInputs);
e.setId(event.getId());
this.edges.add(e);
}
/**
* Creates the label.
*
* @param state the state
* @return the string
*/
private String createLabel(Node state) {
String label = state.getLabel();
String id = state.getId();
if (label.equals(state.getId())) {
return label;
}
if (abnormalState(label)) {
return label;
}
if (id.equals("")) {
return label;
}
if (label.equals("")) {
return id;
}
return id + " = " + label;
}
/**
* Abnormal state.
*
* @param id the id
* @return true, if successful
*/
protected boolean abnormalState(String id) {
return id.equals(EXIT) || id.equals(CRASH) || id.equals(FAILURE);
}
/**
* Gets the node.
*
* @param state the state
* @return the node
*/
private Node getNode(ActivityState state) {
Node ret = new Node (state);
if (state.isCrash()) {
ret.setId(getCrashId());
}
if (state.isFailure()) {
ret.setId(getFailId());
}
return ret;
}
/**
* Gets the crash id.
*
* @return the crash id
*/
private String getCrashId() {
String ret = CRASH + this.crashCount;
this.crashCount++;
return ret;
}
/**
* Gets the fail id.
*
* @return the fail id
*/
private String getFailId() {
String ret = FAILURE + this.failCount;
this.failCount++;
return ret;
}
}