/*
* Copyright Technophobia Ltd 2012
*
* This file is part of Substeps.
*
* Substeps is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Substeps 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Substeps. If not, see <http://www.gnu.org/licenses/>.
*/
package com.technophobia.substeps.report;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.technophobia.substeps.execution.AbstractExecutionNodeVisitor;
import com.technophobia.substeps.execution.ExecutionResult;
import com.technophobia.substeps.execution.node.ExecutionNode;
import com.technophobia.substeps.execution.node.IExecutionNode;
import com.technophobia.substeps.execution.node.NodeWithChildren;
import com.technophobia.substeps.execution.node.RootNode;
import com.technophobia.substeps.execution.node.StepImplementationNode;
import com.technophobia.substeps.model.exception.SubstepsRuntimeException;
public final class TreeJsonBuilder extends AbstractExecutionNodeVisitor<JsonObject> {
private final ReportData reportData;
private static Map<ExecutionResult, String> resultToImageMap = new HashMap<ExecutionResult, String>();
private static final Predicate<ExecutionNode> NODE_HAS_ERROR = new Predicate<ExecutionNode>() {
public boolean apply(ExecutionNode node) {
return node.hasError();
}
};
static {
resultToImageMap.put(ExecutionResult.PASSED, "img/PASSED.png");
resultToImageMap.put(ExecutionResult.NOT_RUN, "img/NOT_RUN.png");
resultToImageMap.put(ExecutionResult.PARSE_FAILURE, "img/PARSE_FAILURE.png");
resultToImageMap.put(ExecutionResult.FAILED, "img/FAILED.png");
}
public static void writeTreeJson(ReportData reportData, File jsonFile) {
new TreeJsonBuilder(reportData).createFile(jsonFile);
}
private TreeJsonBuilder(ReportData reportData) {
this.reportData = reportData;
}
private void createFile(File jsonFile) {
JsonObject tree = buildTree();
writeFile(jsonFile, tree);
}
private void writeFile(File jsonFile, JsonObject tree) {
BufferedWriter writer = null;
try {
writer = Files.newWriter(jsonFile, Charset.defaultCharset());
writer.append("var treeData = " + tree.toString());
} catch (IOException e) {
throw new SubstepsRuntimeException("Failed writing to detail json file");
} finally {
if (writer != null) {
try {
writer.flush();
writer.close();
} catch (IOException e) {
throw new SubstepsRuntimeException("Failed writing to detail json file");
}
}
}
}
private JsonObject buildTree() {
List<RootNode> rootNodes = reportData.getRootNodes();
JsonObject tree = new JsonObject();
boolean rootNodeInError = Iterables.any(rootNodes, NODE_HAS_ERROR);
addChildren(tree, rootNodeInError, rootNodes);
JsonObject data = new JsonObject();
tree.add("data", data);
data.addProperty("title", "Substeps tests");
JsonObject attr = new JsonObject();
data.add("attr", attr);
attr.addProperty("id", "0");
String icon = rootNodeInError ? resultToImageMap.get(ExecutionResult.FAILED) : resultToImageMap
.get(ExecutionResult.PASSED);
data.addProperty("icon", icon);
if (rootNodeInError) {
data.addProperty("state", "open");
}
return tree;
}
private JsonObject createJsonWithBasicNodeDetails(IExecutionNode node) {
JsonObject json = new JsonObject();
JsonObject data = new JsonObject();
json.add("data", data);
data.addProperty("title", getDescriptionForNode(node));
JsonObject attr = new JsonObject();
data.add("attr", attr);
attr.addProperty("id", Long.toString(node.getId()));
data.addProperty("icon", getNodeImage(node));
return json;
}
@Override
public JsonObject visit(NodeWithChildren<?> node) {
return addChildren(createJsonWithBasicNodeDetails(node), node.hasError(), node.getChildren());
}
@Override
public JsonObject visit(StepImplementationNode node) {
return createJsonWithBasicNodeDetails(node);
}
private String getNodeImage(final IExecutionNode node) {
return resultToImageMap.get(node.getResult().getResult());
}
private String getDescriptionForNode(final IExecutionNode node) {
final StringBuilder buf = new StringBuilder();
ExecutionReportBuilder.buildDescriptionString(null, node, buf);
// need to replace "
String msg = buf.toString();
if (msg.contains("\"")) {
msg = msg.replace("\"", "\\\"");
}
return msg;
}
JsonObject addChildren(JsonObject json, boolean hasError, List<? extends IExecutionNode> childNodes) {
if (childNodes != null && !childNodes.isEmpty()) {
if (hasError) {
json.addProperty("state", "open");
}
JsonArray children = new JsonArray();
for (IExecutionNode node : childNodes) {
children.add(node.dispatch(this));
}
json.add("children", children);
}
return json;
}
}