package gherkin;
import gherkin.deps.com.google.gson.Gson;
import gherkin.deps.net.iharder.Base64;
import gherkin.formatter.Argument;
import gherkin.formatter.Formatter;
import gherkin.formatter.Reporter;
import gherkin.formatter.model.Background;
import gherkin.formatter.model.BasicStatement;
import gherkin.formatter.model.Comment;
import gherkin.formatter.model.DataTableRow;
import gherkin.formatter.model.DocString;
import gherkin.formatter.model.Examples;
import gherkin.formatter.model.ExamplesTableRow;
import gherkin.formatter.model.Feature;
import gherkin.formatter.model.Match;
import gherkin.formatter.model.Result;
import gherkin.formatter.model.Scenario;
import gherkin.formatter.model.ScenarioOutline;
import gherkin.formatter.model.Step;
import gherkin.formatter.model.Tag;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class JSONParser {
private final Gson gson = new Gson();
private final Reporter reporter;
private final Formatter formatter;
public JSONParser(Reporter reporter, Formatter formatter) {
this.reporter = reporter;
this.formatter = formatter;
}
public void parse(String src) {
List<Map> featureHashes = gson.fromJson(new StringReader(src), List.class);
for (Map o : featureHashes) {
formatter.uri(getString(o, "uri"));
new Feature(comments(o), tags(o), keyword(o), name(o), description(o), line(o), id(o)).replay(formatter);
for (Map featureElement : (List<Map>) getList(o, "elements")) {
featureElement(featureElement).replay(formatter);
for (Map hook : (List<Map>) getList(featureElement, "before")) {
before(hook);
}
for (Map step : (List<Map>) getList(featureElement, "steps")) {
step(step);
}
for (Map hook : (List<Map>) getList(featureElement, "after")) {
after(hook);
}
for (Map eo : (List<Map>) getList(featureElement, "examples")) {
new Examples(comments(eo), tags(eo), keyword(eo), name(eo), description(eo), line(eo), id(eo), examplesTableRows(getList(eo, "rows"))).replay(formatter);
}
}
formatter.eof();
}
}
private BasicStatement featureElement(Map o) {
String type = (String) o.get("type");
if (type.equals("background")) {
return new Background(comments(o), keyword(o), name(o), description(o), line(o));
} else if (type.equals("scenario")) {
return new Scenario(comments(o), tags(o), keyword(o), name(o), description(o), line(o), id(o));
} else if (type.equals("scenario_outline")) {
return new ScenarioOutline(comments(o), tags(o), keyword(o), name(o), description(o), line(o), id(o));
} else {
return null;
}
}
private void before(Map o) {
Map m = (Map) o.get("match");
Match match = new Match(arguments(m), location(m));
Map r = (Map) o.get("result");
Result result = new Result(status(r), duration(r), errorMessage(r));
reporter.before(match, result);
}
private void after(Map o) {
Map m = (Map) o.get("match");
Match match = new Match(arguments(m), location(m));
Map r = (Map) o.get("result");
Result result = new Result(status(r), duration(r), errorMessage(r));
reporter.after(match, result);
}
private void step(Map o) {
List<DataTableRow> rows = null;
if (o.containsKey("rows")) {
rows = dataTableRows(getList(o, "rows"));
}
DocString docString = null;
if (o.containsKey("doc_string")) {
Map ds = (Map) o.get("doc_string");
docString = new DocString(getString(ds, "content_type"), getString(ds, "value"), getInt(ds, "line"));
}
Step step = new Step(comments(o), keyword(o), name(o), line(o), rows, docString);
step.replay(formatter);
if (o.containsKey("match")) {
Map m = (Map) o.get("match");
new Match(arguments(m), location(m)).replay(reporter);
}
if (o.containsKey("result")) {
Map r = (Map) o.get("result");
new Result(status(r), duration(r), errorMessage(r)).replay(reporter);
}
if (o.containsKey("embeddings")) {
List<Map> embeddings = (List<Map>) o.get("embeddings");
for (Map embedding : embeddings) {
try {
reporter.embedding(getString(embedding, "mime_type"), Base64.decode(getString(embedding, "data")));
} catch (IOException ex) {
throw new RuntimeException("Couldn't decode data", ex);
}
}
}
if (o.containsKey("output")) {
List<String> output = (List<String>) o.get("output");
for (String text : output) {
reporter.write(text);
}
}
}
private List<DataTableRow> dataTableRows(List o) {
List<DataTableRow> rows = new ArrayList<DataTableRow>(o.size());
for (Object e : o) {
Map row = (Map) e;
rows.add(new DataTableRow(comments(row), getList(row, "cells"), getInt(row, "line")));
}
return rows;
}
private List<ExamplesTableRow> examplesTableRows(List o) {
List<ExamplesTableRow> rows = new ArrayList<ExamplesTableRow>(o.size());
for (Object e : o) {
Map row = (Map) e;
rows.add(new ExamplesTableRow(comments(row), getList(row, "cells"), getInt(row, "line"), id(row)));
}
return rows;
}
private List<Comment> comments(Map o) {
List<Comment> comments = new ArrayList<Comment>();
if (o.containsKey("comments")) {
for (Object e : ((List) o.get("comments"))) {
Map map = (Map) e;
comments.add(new Comment(getString(map, "value"), getInt(map, "line")));
}
}
return comments;
}
private List<Tag> tags(Map o) {
List<Tag> tags = new ArrayList<Tag>();
if (o.containsKey("tags")) {
for (Object e : ((List) o.get("tags"))) {
Map map = (Map) e;
tags.add(new Tag(getString(map, "name"), getInt(map, "line")));
}
}
return tags;
}
private String keyword(Map o) {
return getString(o, "keyword");
}
private String name(Map o) {
return getString(o, "name");
}
private String description(Map o) {
return getString(o, "description");
}
private Integer line(Map o) {
return getInt(o, "line");
}
private String id(Map o) {
return getString(o, "id");
}
private List<Argument> arguments(Map m) {
List arguments = getList(m, "arguments");
List<Argument> result = new ArrayList<Argument>();
for (Object argument : arguments) {
Map argMap = (Map) argument;
result.add(new Argument(getInt(argMap, "offset"), getString(argMap, "val")));
}
return result;
}
private String location(Map m) {
return getString(m, "location");
}
private String status(Map r) {
return getString(r, "status");
}
private Long duration(Map r) {
return getLong(r, "duration");
}
private String errorMessage(Map r) {
return getString(r, "error_message");
}
private String getString(Map map, String key) {
Object string = map.get(key);
return string == null ? null : (String) string;
}
private Integer getInt(Map map, String key) {
Object n = map.get(key);
return n == null ? null : ((Number) n).intValue();
}
private Long getLong(Map map, String key) {
Object n = map.get(key);
return n == null ? null : ((Number) n).longValue();
}
private List getList(Map map, String key) {
Object list = map.get(key);
return list == null ? Collections.emptyList() : (List) list;
}
}