##### Coverage Report - org.jbehave.core.reporters.StoryReporterBuilder

Classes in this File | Line Coverage | Branch Coverage | Complexity
StoryReporterBuilder |
88% | 69/78
77% | 14/18
| 1.2285714285714286;1.229
StoryReporterBuilder$Format |
100% | 10/10
N/A | N/A
| 1.2285714285714286;1.229
StoryReporterBuilder$ProvidedFormat |
100% | 4/4
N/A | N/A
| 1.2285714285714286;1.229

1 |  |
     package org.jbehave.core.reporters;
2 |  |
3 |  |
     import java.io.File;
4 |  |
     import java.net.URL;
5 |  |
     import java.util.ArrayList;
6 |  |
     import java.util.HashMap;
7 |  |
     import java.util.List;
8 |  |
     import java.util.Locale;
9 |  |
     import java.util.Map;
10 |  |
     import java.util.Properties;
11 |  |
12 |  |
     import org.jbehave.core.configuration.Keywords;
13 |  |
     import org.jbehave.core.i18n.LocalizedKeywords;
14 |  |
     import org.jbehave.core.io.CodeLocations;
15 |  |
     import org.jbehave.core.io.StoryLocation;
16 |  |
     import org.jbehave.core.reporters.FilePrintStreamFactory.FileConfiguration;
17 |  |
     import org.jbehave.core.reporters.FilePrintStreamFactory.FilePathResolver;
18 |  |
19 |  |
     import static java.util.Arrays.asList;
20 |  |
21 |  |
     /**
22 |  |
      * <p>
23 |  |
      * A <a href="http://en.wikipedia.org/wiki/Builder_pattern">Builder</a> for
24 |  |
      * {@link StoryReporter}s. It builds a {@link DelegatingStoryReporter} with
25 |  |
      * delegates for a number of formats - mostly file-based ones except
26 |  |
      * {@Format.CONSOLE}. It requires a
27 |  |
      * {@link FilePrintStreamFactory} and provides default delegate instances for
28 |  |
      * each format.
29 |  |
      * </p>
30 |  |
      * <p>
31 |  |
      * To build a reporter for a single story path with default and given formats:
32 |  |
      *
33 |  |
      * <pre>
34 |  |
      * Class&lt;MyStory&gt; storyClass = MyStory.class;
35 |  |
      * StoryPathResolver resolver = new UnderscoredCamelCaseResolver();
36 |  |
      * String storyPath = resolver.resolve(storyClass);
37 |  |
      * StoryReporter reporter = new StoryReporterBuilder().withCodeLocation(CodeLocations.codeLocationFromClass(storyClass))
38 |  |
      *         .withDefaultFormats().withFormats(TXT, HTML, XML).build(storyPath);
39 |  |
      * </pre>
40 |  |
      *
41 |  |
      * </p>
42 |  |
      * <p>
43 |  |
      * The builder is configured to build with the {@link Format#STATS} as default
44 |  |
      * format. To change the default formats the user can override the method:
45 |  |
      *
46 |  |
      * <pre>
47 |  |
      * new StoryReporterBuilder() {
48 |  |
      *     protected StoryReporterBuilder withDefaultFormats() {
49 |  |
      *         return withFormats(STATS);
50 |  |
      *     }
51 |  |
      * }
52 |  |
      * </pre>
53 |  |
      *
54 |  |
      * </p>
55 |  |
      * <p>
56 |  |
      * The builder configures the file-based reporters to output to the default file
57 |  |
      * directory {@link FileConfiguration#DIRECTORY} as relative to the code
58 |  |
      * location. In some case, e.g. with Ant class loader, the code source location
59 |  |
      * from class may not be properly set. In this case, we may specify it from a
60 |  |
      * file:
61 |  |
      *
62 |  |
      * <pre>
63 |  |
      * new StoryReporterBuilder().withCodeLocation(CodeLocations.codeLocationFromFile(new File(&quot;target/classes&quot;)))
64 |  |
      *         .withDefaultFormats().withFormats(TXT, HTML, XML).build(storyPath);
65 |  |
      * </pre>
66 |  |
      *
67 |  |
      * </p>
68 |  |
      * <p>
69 |  |
      * By default, the reporters will output minimal failure information, the single
70 |  |
      * line describing the failure cause and the outcomes if failures occur. To
71 |  |
      * configure the failure trace to be reported as well:
72 |  |
      *
73 |  |
      * <pre>
74 |  |
      * new StoryReporterBuilder().withFailureTrace(true)
75 |  |
      * </pre>
76 |  |
      *
77 |  |
      * </p>
78 |  |
      * <p>
79 |  |
      * If failure trace is reported, it is with the full stack trace. In some cases,
80 |  |
      * it's useful to have it compressed, eliminating unnecessary lines that are not
81 |  |
      * very informative:
82 |  |
      *
83 |  |
      * <pre>
84 |  |
      * new StoryReporterBuilder().withFailureTraceCompression(true)
85 |  |
      * </pre>
86 |  |
      *
87 |  |
      * </p>
88 |  |
      *
89 |  |
      * <p>
90 |  |
      * To specify the use of keywords for a given locale:
91 |  |
      *
92 |  |
      * <pre>
93 |  |
      * new StoryReporterBuilder().withKeywords(new LocalisedKeywords(Locale.IT)
94 |  |
      * </pre>
95 |  |
      *
96 |  |
      * </p>
97 |  |
      *
98 |  |
      * <p>
99 |  |
      * The builder provides default instances for all reporters, using the default
100 |  |
      * output patterns. To change the reporter for a specific instance, e.g. to
101 |  |
      * report format <b>TXT</b> to <b>.text</b> files and to inject other
102 |  |
      * non-default parameters, such as the custom output patterns:
103 |  |
      *
104 |  |
      * <pre>
105 |  |
      * new StoryReporterBuilder(){
106 |  |
      *   public StoryReporter reporterFor(String storyPath, Format format){
107 |  |
      *       FilePrintStreamFactory factory = new FilePrintStreamFactory(new StoryLocation(storyPath, codeLocation));
108 |  |
      *       switch (format) {
109 |  |
      *           case TXT:
110 |  |
      *               factory.useConfiguration(new FileConfiguration("text"));
111 |  |
      *               Properties customPatterns = new Properties();
112 |  |
      *               customPatterns.setProperty("successful", "{0}(YEAH!!!)\n");
113 |  |
      *               return new TxtOutput(factory.createPrintStream(), customPatterns, keywords);
114 |  |
      *            default:
115 |  |
      *               return super.reporterFor(format);
116 |  |
      *   }
117 |  |
      * }
118 |  |
      * </pre>
119 |  |
      *
120 |  |
      * </p>
121 |  |
      */
122 | 350 |
     public class StoryReporterBuilder {
123 |  |
124 | 8 |
         public enum Format {
125 | 1 |
             CONSOLE(org.jbehave.core.reporters.Format.CONSOLE),
126 | 1 |
             IDE_CONSOLE(org.jbehave.core.reporters.Format.IDE_CONSOLE),
127 | 1 |
             TXT(org.jbehave.core.reporters.Format.TXT),
128 | 1 |
             HTML(org.jbehave.core.reporters.Format.HTML),
129 | 1 |
             XML(org.jbehave.core.reporters.Format.XML),
130 | 1 |
             STATS(org.jbehave.core.reporters.Format.STATS);
131 |  |
132 |  |
             private org.jbehave.core.reporters.Format realFormat;
133 |  |
134 | 6 |
             Format(org.jbehave.core.reporters.Format realFormat) {
135 | 6 |
                 this.realFormat = realFormat;
136 | 6 |
             }
137 |  |
138 |  |
         }
139 |  |
140 | 350 |
         private List<org.jbehave.core.reporters.Format> formats = new ArrayList<org.jbehave.core.reporters.Format>();
141 | 350 |
         private String relativeDirectory = new FileConfiguration().getRelativeDirectory();
142 | 350 |
         private FilePathResolver pathResolver = new FileConfiguration().getPathResolver();
143 | 350 |
         private URL codeLocation = CodeLocations.codeLocationFromPath("target/classes");
144 | 350 |
         private Properties viewResources = new FreemarkerViewGenerator().defaultViewProperties();
145 | 350 |
         private boolean reportFailureTrace = false;
146 | 350 |
         private boolean compressFailureTrace = false;
147 | 350 |
         private Keywords keywords = new LocalizedKeywords();
148 |  |
         private CrossReference crossReference;
149 |  |
         private boolean multiThreading;
150 |  |
151 |  |
         public File outputDirectory() {
152 | 15 |
             return filePrintStreamFactory("").outputDirectory();
153 |  |
         }
154 |  |
155 |  |
         public String relativeDirectory() {
156 | 1 |
             return relativeDirectory;
157 |  |
         }
158 |  |
159 |  |
         public FilePathResolver pathResolver() {
160 | 2 |
             return pathResolver;
161 |  |
         }
162 |  |
163 |  |
         public URL codeLocation() {
164 | 1 |
             return codeLocation;
165 |  |
         }
166 |  |
167 |  |
         public List<org.jbehave.core.reporters.Format> formats() {
168 | 2 |
             return formats;
169 |  |
         }
170 |  |
171 |  |
         public List<String> formatNames(boolean toLowerCase) {
172 | 14 |
             Locale locale = Locale.getDefault();
173 | 14 |
             if (keywords instanceof LocalizedKeywords) {
174 | 14 |
                 locale = ((LocalizedKeywords) keywords).getLocale();
175 |  |
             }
176 | 14 |
             List<String> names = new ArrayList<String>();
177 | 14 |
             for (org.jbehave.core.reporters.Format format : formats) {
178 | 31 |
                 String name = format.name();
179 | 31 |
                 if (toLowerCase) {
180 | 17 |
                     name = name.toLowerCase(locale);
181 |  |
                 }
182 | 31 |
                 names.add(name);
183 | 31 |
             }
184 | 14 |
             return names;
185 |  |
         }
186 |  |
187 |  |
         public Keywords keywords() {
188 | 31 |
             return keywords;
189 |  |
         }
190 |  |
191 |  |
         public boolean multiThreading(){
192 | 0 |
             return multiThreading;
193 |  |
         }
194 |  |
195 |  |
         public boolean reportFailureTrace() {
196 | 31 |
             return reportFailureTrace;
197 |  |
         }
198 |  |
199 |  |
         public boolean compressFailureTrace() {
200 | 30 |
             return compressFailureTrace;
201 |  |
         }
202 |  |
203 |  |
         public Properties viewResources() {
204 | 12 |
             return viewResources;
205 |  |
         }
206 |  |
207 |  |
         public StoryReporterBuilder withRelativeDirectory(String relativeDirectory) {
208 | 3 |
             this.relativeDirectory = relativeDirectory;
209 | 3 |
             return this;
210 |  |
         }
211 |  |
212 |  |
         public StoryReporterBuilder withPathResolver(FilePathResolver pathResolver) {
213 | 1 |
             this.pathResolver = pathResolver;
214 | 1 |
             return this;
215 |  |
         }
216 |  |
217 |  |
         public StoryReporterBuilder withCodeLocation(URL codeLocation) {
218 | 1 |
             this.codeLocation = codeLocation;
219 | 1 |
             return this;
220 |  |
         }
221 |  |
222 |  |
         public CrossReference crossReference() {
223 | 1 |
             return crossReference;
224 |  |
         }
225 |  |
226 |  |
         public boolean hasCrossReference() {
227 | 13 |
             return crossReference != null;
228 |  |
         }
229 |  |
230 |  |
         public StoryReporterBuilder withCrossReference(CrossReference crossReference) {
231 | 1 |
             this.crossReference = crossReference;
232 | 1 |
             return this;
233 |  |
         }
234 |  |
235 |  |
         public StoryReporterBuilder withDefaultFormats() {
236 | 7 |
             return withFormats(Format.STATS);
237 |  |
         }
238 |  |
239 |  |
         /**
240 |  |
          * @deprecated Use {@link withFormats(org.jbehave.core.reporters.Format... formats)}
241 |  |
          */
242 |  |
         @Deprecated
243 |  |
         public StoryReporterBuilder withFormats(Format... formats) {
244 | 7 |
             List<org.jbehave.core.reporters.Format> formatz = new ArrayList<org.jbehave.core.reporters.Format>();
245 | 14 |
             for (Format format : formats) {
246 | 7 |
                 formatz.add(format.realFormat);
247 |  |
             }
248 | 7 |
             this.formats.addAll(formatz);
249 | 7 |
             return this;
250 |  |
         }
251 |  |
252 |  |
         public StoryReporterBuilder withFormats(org.jbehave.core.reporters.Format... formats) {
253 | 12 |
             this.formats.addAll(asList(formats));
254 | 12 |
             return this;
255 |  |
         }
256 |  |
257 |  |
         public StoryReporterBuilder withReporters(StoryReporter... reporters) {
258 | 3 |
             for (StoryReporter reporter : reporters) {
259 | 2 |
                 this.formats.add(new ProvidedFormat(reporter));
260 |  |
             }
261 | 1 |
             return this;
262 |  |
         }
263 |  |
264 |  |
         public StoryReporterBuilder withFailureTrace(boolean reportFailureTrace) {
265 | 1 |
             this.reportFailureTrace = reportFailureTrace;
266 | 1 |
             return this;
267 |  |
         }
268 |  |
269 |  |
         public StoryReporterBuilder withFailureTraceCompression(boolean compressFailureTrace) {
270 | 0 |
             this.compressFailureTrace = compressFailureTrace;
271 | 0 |
             return this;
272 |  |
         }
273 |  |
274 |  |
         public StoryReporterBuilder withKeywords(Keywords keywords) {
275 | 3 |
             this.keywords = keywords;
276 | 3 |
             return this;
277 |  |
         }
278 |  |
279 |  |
         public StoryReporterBuilder withMultiThreading(boolean multiThreading) {
280 | 104 |
             this.multiThreading = multiThreading;
281 | 104 |
             return this;
282 |  |
         }
283 |  |
284 |  |
         public StoryReporterBuilder withViewResources(Properties resources) {
285 | 1 |
             this.viewResources = resources;
286 | 1 |
             return this;
287 |  |
         }
288 |  |
289 |  |
         public StoryReporter build(String storyPath) {
290 | 19 |
             Map<org.jbehave.core.reporters.Format, StoryReporter> delegates = new HashMap<org.jbehave.core.reporters.Format, StoryReporter>();
291 | 19 |
             for (org.jbehave.core.reporters.Format format : formats) {
292 | 42 |
                 delegates.put(format, reporterFor(storyPath, format));
293 |  |
             }
294 |  |
295 | 19 |
             DelegatingStoryReporter delegate = new DelegatingStoryReporter(delegates.values());
296 | 19 |
             StoryReporter crossReferencing = (crossReference == null ? new NullStoryReporter() : reporterFor(storyPath,
297 |  |
                     crossReference));
298 | 19 |
             return new ConcurrentStoryReporter(crossReferencing, delegate, multiThreading);
299 |  |
         }
300 |  |
301 |  |
         public Map<String, StoryReporter> build(List<String> storyPaths) {
302 | 0 |
             Map<String, StoryReporter> reporters = new HashMap<String, StoryReporter>();
303 | 0 |
             for (String storyPath : storyPaths) {
304 | 0 |
                 reporters.put(storyPath, build(storyPath));
305 |  |
             }
306 | 0 |
             reporters.put("*", build("*"));
307 | 0 |
             return reporters;
308 |  |
         }
309 |  |
310 |  |
         public StoryReporter reporterFor(String storyPath, Format format) {
311 | 0 |
             return reporterFor(storyPath, format.realFormat);
312 |  |
         }
313 |  |
314 |  |
         public StoryReporter reporterFor(String storyPath, org.jbehave.core.reporters.Format format) {
315 | 40 |
             FilePrintStreamFactory factory = filePrintStreamFactory(storyPath);
316 | 40 |
             return format.createStoryReporter(factory, this);
317 |  |
         }
318 |  |
319 |  |
         protected FilePrintStreamFactory filePrintStreamFactory(String storyPath) {
320 | 54 |
             return new FilePrintStreamFactory(new StoryLocation(codeLocation, storyPath), fileConfiguration(""));
321 |  |
         }
322 |  |
323 |  |
         public FileConfiguration fileConfiguration(String extension) {
324 | 86 |
             return new FileConfiguration(relativeDirectory, extension, pathResolver);
325 |  |
         }
326 |  |
327 |  |
         /**
328 |  |
          * A Format that wraps a StoryReporter instance provided.
329 |  |
          */
330 | 350 |
         public static class ProvidedFormat extends org.jbehave.core.reporters.Format {
331 |  |
332 |  |
             private final StoryReporter reporter;
333 |  |
334 |  |
             public ProvidedFormat(StoryReporter reporter) {
335 | 2 |
                 super(reporter.getClass().getSimpleName());
336 | 2 |
                 this.reporter = reporter;
337 | 2 |
             }
338 |  |
339 |  |
             @Override
340 |  |
             public StoryReporter createStoryReporter(FilePrintStreamFactory factory,
341 |  |
                     StoryReporterBuilder storyReporterBuilder) {
342 | 2 |
                 return reporter;
343 |  |
             }
344 |  |
345 |  |
         }
346 |  |
     }