JsonOutput.java
- package org.jbehave.core.reporters;
- import static org.jbehave.core.reporters.PrintStreamOutput.Format.JSON;
- import java.io.PrintStream;
- import java.util.Properties;
- import org.apache.commons.lang3.ArrayUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.jbehave.core.configuration.Keywords;
- /**
- * <p>
- * Story reporter that outputs to a PrintStream, as JSON. It extends
- * {@link PrintStreamOutput}, providing JSON-based default output
- * patterns, which can be overridden via the {@link
- * JsonOutput (PrintStream,Properties)} constructor.
- * </p>
- *
- * @author Valery Yatsynovich
- */
- public class JsonOutput extends PrintStreamOutput {
- private static final char JSON_DOCUMENT_START = 0;
- private static final char JSON_OBJECT_START = '{';
- private static final char JSON_ARRAY_START = '[';
- private static final char[] JSON_START_CHARS = { JSON_DOCUMENT_START, JSON_OBJECT_START, JSON_ARRAY_START };
- private static final String[] STEP_KEYS = { "successful", "ignorable", "comment", "pending", "notPerformed",
- "failed", "restarted" };
- private char lastChar = JSON_DOCUMENT_START;
- private int givenStoriesLevel = 0;
- private int storyPublishingLevel = 0;
- private boolean stepPublishing = false;
- public JsonOutput(PrintStream output, Keywords keywords) {
- this(output, new Properties(), keywords);
- }
- public JsonOutput(PrintStream output, Properties outputPatterns, Keywords keywords) {
- super(JSON, output, defaultXmlPatterns(), outputPatterns, keywords);
- }
- @Override
- protected void print(PrintStream output, String text) {
- if (!text.isEmpty()) {
- boolean doNotAddComma =
- ArrayUtils.contains(JSON_START_CHARS, lastChar) || StringUtils.startsWithAny(text, "}", "]", ",");
- super.print(output, doNotAddComma ? text : "," + text);
- lastChar = text.charAt(text.length() - 1);
- }
- }
- @Override
- protected String format(String key, String defaultPattern, Object... args) {
- if ("beforeGivenStories".equals(key)) {
- givenStoriesLevel++;
- } else if ("afterGivenStories".equals(key)) {
- if (storyPublishingLevel == givenStoriesLevel) {
- // Closing given "stories"
- print("]");
- storyPublishingLevel--;
- }
- givenStoriesLevel--;
- return super.format(key, defaultPattern, args);
- } else if ("beforeStory".equals(key) && storyPublishingLevel < givenStoriesLevel) {
- // Starting given "stories"
- print("\"stories\": [");
- storyPublishingLevel++;
- }
- //Closing "examples" if "steps" are empty
- if ("exampleScenariosEnd".equals(key) && !stepPublishing) {
- print("}");
- }
- if (key.startsWith("afterBefore")) {
- stepPublishing = false;
- }
- if (stepPublishing) {
- if ("exampleScenariosEnd".equals(key) || "example".equals(key)) {
- // Closing previous "example"
- print("}");
- }
- if ("afterScenario".equals(key) || "afterScenarioWithFailure".equals(key)) {
- stepPublishing = false;
- }
- } else if (ArrayUtils.contains(STEP_KEYS, key)) {
- stepPublishing = true;
- }
- return super.format(key, defaultPattern, args);
- }
- @Override
- protected String transformPrintingTable(String text, String tableStart, String tableEnd) {
- return text;
- }
- @SuppressWarnings("checkstyle:LineLength")
- private static Properties defaultXmlPatterns() {
- Properties patterns = new Properties();
- patterns.setProperty("dryRun", "\"dryRun\": \"{0}\"");
- patterns.setProperty("beforeStory", "'{'\"id\": \"{0}\", \"path\": \"{2}\", \"title\": \"{1}\"");
- patterns.setProperty("storyCancelled", "'{'\"cancelled\": '{'\"keyword\": \"{0}\", \"durationKeyword\": \"{1}\", \"durationInSecs\": \"{2}\"}}");
- patterns.setProperty("afterStory", "}");
- patterns.setProperty("beforeScenarios", "\"scenarios\": [");
- patterns.setProperty("afterScenarios", "]");
- patterns.setProperty("afterStory", "}");
- patterns.setProperty("metaStart", "\"meta\": '['");
- patterns.setProperty("metaProperty", "'{'\"keyword\": \"{0}\", \"name\": \"{1}\", \"value\": \"{2}\"}");
- patterns.setProperty("metaEnd", "']'");
- patterns.setProperty("filter", "\"filter\": \"{0}\"");
- patterns.setProperty("narrative", "\"narrative\": '{'\"keyword\": \"{0}\", \"inOrderTo\": '{'\"keyword\": \"{1}\", \"value\": \"{2}\"}, \"asA\": '{'\"keyword\": \"{3}\", \"value\": \"{4}\"}, \"iWantTo\": '{'\"keyword\": \"{5}\", \"value\": \"{6}\"}}");
- patterns.setProperty("lifecycleStart", "\"lifecycle\": '{'\"keyword\": \"{0}\"");
- patterns.setProperty("lifecycleEnd", "}");
- patterns.setProperty("lifecycleBeforeStart", "\"before\": '{'\"keyword\": \"{0}\", \"scopes\": [");
- patterns.setProperty("lifecycleBeforeEnd", "]}");
- patterns.setProperty("lifecycleAfterStart", "\"after\": '{'\"keyword\": \"{0}\", \"scopes\": [");
- patterns.setProperty("lifecycleAfterEnd", "]}");
- patterns.setProperty("lifecycleBeforeScopeStart", "'{'\"keyword\": \"{0}\", \"value\": \"{1}\", \"steps\": [");
- patterns.setProperty("lifecycleBeforeScopeEnd", "]}");
- patterns.setProperty("lifecycleAfterScopeStart", "'{'\"keyword\": \"{0}\", \"value\": \"{1}\", \"outcomes\": [");
- patterns.setProperty("lifecycleAfterScopeEnd", "]}");
- patterns.setProperty("lifecycleOutcomeStart", "'{'\"keyword\": \"{0}\", \"value\": \"{1}\", \"steps\": [");
- patterns.setProperty("lifecycleOutcomeEnd", "]}");
- patterns.setProperty("lifecycleMetaFilter", "\"metaFilter\": \"{0} {1}\"");
- patterns.setProperty("lifecycleStep", "\"{0}\"");
- patterns.setProperty("beforeBeforeStoriesSteps", "'{'\"beforeStoriesSteps\": [");
- patterns.setProperty("afterBeforeStoriesSteps", "]}");
- patterns.setProperty("beforeAfterStoriesSteps", "'{'\"afterStoriesSteps\": [");
- patterns.setProperty("afterAfterStoriesSteps", "]}");
- patterns.setProperty("beforeBeforeSystemStorySteps", "\"beforeSystemStorySteps\": [");
- patterns.setProperty("afterBeforeSystemStorySteps", "]");
- patterns.setProperty("beforeAfterSystemStorySteps", "\"afterSystemStorySteps\": [");
- patterns.setProperty("afterAfterSystemStorySteps", "]");
- patterns.setProperty("beforeBeforeUserStorySteps", "\"beforeUserStorySteps\": [");
- patterns.setProperty("afterBeforeUserStorySteps", "]");
- patterns.setProperty("beforeAfterUserStorySteps", "\"afterUserStorySteps\": [");
- patterns.setProperty("afterAfterUserStorySteps", "]");
- patterns.setProperty("beforeBeforeSystemScenarioSteps", "\"beforeSystemScenarioSteps\": [");
- patterns.setProperty("afterBeforeSystemScenarioSteps", "]");
- patterns.setProperty("beforeAfterSystemScenarioSteps", "\"afterSystemScenarioSteps\": [");
- patterns.setProperty("afterAfterSystemScenarioSteps", "]");
- patterns.setProperty("beforeBeforeUserScenarioSteps", "\"beforeUserScenarioSteps\": [");
- patterns.setProperty("afterBeforeUserScenarioSteps", "]");
- patterns.setProperty("beforeAfterUserScenarioSteps", "\"afterUserScenarioSteps\": [");
- patterns.setProperty("afterAfterUserScenarioSteps", "]");
- patterns.setProperty("beforeScenarioSteps", "\"steps\": [");
- patterns.setProperty("afterScenarioSteps", "]");
- patterns.setProperty("beforeScenario","'{'\"keyword\": \"{1}\", \"id\": \"{0}\", \"title\": \"{2}\"");
- patterns.setProperty("scenarioExcluded", "\"excluded\": '{'\"pattern\": \"{0}\"}");
- patterns.setProperty("afterScenario", "}");
- patterns.setProperty("afterScenarioWithFailure", "\"failure\": \"{0}\" }");
- patterns.setProperty("givenStories", "\"givenStories\": '{'\"keyword\": \"{0}\", \"paths\": \"{1}\"}");
- patterns.setProperty("beforeGivenStories", "\"givenStories\": '{'");
- patterns.setProperty("givenStoriesStart", "\"keyword\": \"{0}\", \"givenStories\":[");
- patterns.setProperty("givenStory", "'{'\"parameters\": \"{1}\", \"path\": \"{0}\"}");
- patterns.setProperty("givenStoriesEnd", "]");
- patterns.setProperty("afterGivenStories", "}");
- patterns.setProperty("beforeStep", "'{'");
- patterns.setProperty("successful", "\"outcome\": \"successful\", \"value\": \"{0}\"}");
- patterns.setProperty("ignorable", "\"outcome\": \"ignorable\", \"value\": \"{0}\"}");
- patterns.setProperty("comment", "\"outcome\": \"comment\", \"value\": \"{0}\"}");
- patterns.setProperty("pending", "\"outcome\": \"pending\", \"keyword\": \"{1}\", \"value\": \"{0}\", \"pendingMethod\": \"{2}\"}");
- patterns.setProperty("notPerformed", "\"outcome\": \"notPerformed\", \"keyword\": \"{1}\", \"value\": \"{0}\"}");
- patterns.setProperty("failed", "\"outcome\": \"failed\", \"keyword\": \"{1}\", \"value\": \"{0}\", \"failure\": \"{2}\"}");
- patterns.setProperty("restarted", "\"outcome\": \"restarted\", \"value\": \"{0}\", \"reason\": \"{1}\"}");
- patterns.setProperty("restartedStory", "'{'\"story\": '{'\"outcome\": \"restartedStory\", \"value\": \"{0}\", \"reason\": \"{1}\"}}");
- patterns.setProperty("outcomesTableStart", "'{'\"outcomes\": '{'");
- patterns.setProperty("outcomesTableHeadStart", "\"fields\": [");
- patterns.setProperty("outcomesTableHeadCell", "\"{0}\"");
- patterns.setProperty("outcomesTableHeadEnd", "]");
- patterns.setProperty("outcomesTableBodyStart", "\"values\": [");
- patterns.setProperty("outcomesTableRowStart", "[");
- patterns.setProperty("outcomesTableCell", "\"{0}\"");
- patterns.setProperty("outcomesTableRowEnd", "]");
- patterns.setProperty("outcomesTableBodyEnd", "]");
- patterns.setProperty("outcomesTableEnd", "}}");
- patterns.setProperty("beforeExampleParameters", " \"parameters\": '{'");
- patterns.setProperty("afterExampleParameters", "}");
- patterns.setProperty("exampleParameter", "\"{0}\":\"{1}\"");
- patterns.setProperty("numericParameter", "\"{0}\":{1}");
- patterns.setProperty("beforeExamples", "\"examples\": '{'\"keyword\": \"{0}\"");
- patterns.setProperty("examplesStepsStart", "\"steps\": [");
- patterns.setProperty("examplesStep", "\"{0}\"");
- patterns.setProperty("examplesStepsEnd", "]");
- patterns.setProperty("afterExamples", "}");
- patterns.setProperty("examplesTableStart", "\"parameters\": '{'");
- patterns.setProperty("examplesTableHeadStart", "\"names\": [");
- patterns.setProperty("examplesTableHeadCell", "\"{0}\"");
- patterns.setProperty("examplesTableHeadEnd", "]");
- patterns.setProperty("examplesTableBodyStart", "\"values\": [");
- patterns.setProperty("examplesTableRowStart", "[");
- patterns.setProperty("examplesTableCell", "\"{0}\"");
- patterns.setProperty("examplesTableRowEnd", "]");
- patterns.setProperty("examplesTableBodyEnd", "]");
- patterns.setProperty("examplesTableEnd", "}");
- patterns.setProperty("exampleScenariosStart", "\"examples\": [");
- patterns.setProperty("exampleScenariosEnd", "]");
- patterns.setProperty("example", "'{'\"keyword\": \"{0}\"");
- patterns.setProperty("parameterVerbatimStart", "[[");
- patterns.setProperty("parameterVerbatimEnd", "]]");
- patterns.setProperty("parameterValueStart", "((");
- patterns.setProperty("parameterValueEnd", "))");
- patterns.setProperty("parameterValueNewline", "\\n");
- patterns.setProperty("beforeComposedSteps", "\"steps\": [");
- patterns.setProperty("afterComposedSteps", "]");
- return patterns;
- }
- }