Coverage Report - org.jbehave.core.reporters.StoryReporterBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
StoryReporterBuilder
88%
69/78
77%
14/18
1.229
StoryReporterBuilder$Format
100%
10/10
N/A
1.229
StoryReporterBuilder$ProvidedFormat
100%
4/4
N/A
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  327
 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  327
     private List<org.jbehave.core.reporters.Format> formats = new ArrayList<org.jbehave.core.reporters.Format>();
 141  327
     private String relativeDirectory = new FileConfiguration().getRelativeDirectory();
 142  327
     private FilePathResolver pathResolver = new FileConfiguration().getPathResolver();
 143  327
     private URL codeLocation = CodeLocations.codeLocationFromPath("target/classes");
 144  327
     private Properties viewResources = new FreemarkerViewGenerator().defaultViewProperties();
 145  327
     private boolean reportFailureTrace = false;
 146  327
     private boolean compressFailureTrace = false;
 147  327
     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  28
         return keywords;
 189  
     }
 190  
 
 191  
     public boolean multiThreading(){
 192  0
         return multiThreading;
 193  
     }
 194  
     
 195  
     public boolean reportFailureTrace() {
 196  28
         return reportFailureTrace;
 197  
     }
 198  
 
 199  
     public boolean compressFailureTrace() {
 200  27
         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  2
         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  114
         this.multiThreading = multiThreading;
 281  114
         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  18
         Map<org.jbehave.core.reporters.Format, StoryReporter> delegates = new HashMap<org.jbehave.core.reporters.Format, StoryReporter>();
 291  18
         for (org.jbehave.core.reporters.Format format : formats) {
 292  39
             delegates.put(format, reporterFor(storyPath, format));
 293  
         }
 294  
 
 295  18
         DelegatingStoryReporter delegate = new DelegatingStoryReporter(delegates.values());
 296  18
         StoryReporter crossReferencing = (crossReference == null ? new NullStoryReporter() : reporterFor(storyPath,
 297  
                 crossReference));
 298  18
         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  37
         FilePrintStreamFactory factory = filePrintStreamFactory(storyPath);
 316  37
         return format.createStoryReporter(factory, this);
 317  
     }
 318  
 
 319  
     protected FilePrintStreamFactory filePrintStreamFactory(String storyPath) {
 320  51
         return new FilePrintStreamFactory(new StoryLocation(codeLocation, storyPath), fileConfiguration(""));
 321  
     }
 322  
 
 323  
     public FileConfiguration fileConfiguration(String extension) {
 324  81
         return new FileConfiguration(relativeDirectory, extension, pathResolver);
 325  
     }
 326  
 
 327  
     /**
 328  
      * A Format that wraps a StoryReporter instance provided.
 329  
      */
 330  327
     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  
 }