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