Coverage Report - org.jbehave.core.reporters.ConcurrentStoryReporter
 
Classes in this File Line Coverage Branch Coverage Complexity
ConcurrentStoryReporter
69%
111/160
38%
20/52
2.214
ConcurrentStoryReporter$DelayedMethod
0%
0/13
N/A
2.214
 
 1  
 package org.jbehave.core.reporters;
 2  
 
 3  
 import java.lang.reflect.InvocationTargetException;
 4  
 import java.lang.reflect.Method;
 5  
 import java.util.ArrayList;
 6  
 import java.util.List;
 7  
 import java.util.Map;
 8  
 
 9  
 import org.jbehave.core.model.ExamplesTable;
 10  
 import org.jbehave.core.model.GivenStories;
 11  
 import org.jbehave.core.model.Meta;
 12  
 import org.jbehave.core.model.Narrative;
 13  
 import org.jbehave.core.model.OutcomesTable;
 14  
 import org.jbehave.core.model.Scenario;
 15  
 import org.jbehave.core.model.Story;
 16  
 
 17  
 /**
 18  
  * When running a multithreading mode, reports cannot be written concurrently but should 
 19  
  * be delayed and invoked only at the end of a story, ensuring synchronization on the delegate
 20  
  * responsible for the reporting.
 21  
  */
 22  
 public class ConcurrentStoryReporter implements StoryReporter {
 23  
 
 24  
     private static Method storyNotAllowed;
 25  
     private static Method beforeStory;
 26  
     private static Method narrative;
 27  
     private static Method afterStory;
 28  
     private static Method scenarioNotAllowed;
 29  
     private static Method beforeScenario;
 30  
     private static Method scenarioMeta;
 31  
     private static Method afterScenario;
 32  
     private static Method givenStories;
 33  
     private static Method givenStoriesPaths;
 34  
     private static Method beforeExamples;
 35  
     private static Method example;
 36  
     private static Method afterExamples;
 37  
     private static Method successful;
 38  
     private static Method ignorable;
 39  
     private static Method pending;
 40  
     private static Method notPerformed;
 41  
     private static Method failed;
 42  
     private static Method failedOutcomes;
 43  
     private static Method dryRun;
 44  
     private static Method pendingMethods;
 45  
     private static Method restarted;
 46  
     private static Method cancelled;
 47  
 
 48  
     static {
 49  
         try {
 50  1
             storyNotAllowed = StoryReporter.class.getMethod("storyNotAllowed", Story.class, String.class);
 51  1
             beforeStory = StoryReporter.class.getMethod("beforeStory", Story.class, Boolean.TYPE);
 52  1
             narrative = StoryReporter.class.getMethod("narrative", Narrative.class);
 53  1
             afterStory = StoryReporter.class.getMethod("afterStory", Boolean.TYPE);
 54  1
             scenarioNotAllowed = StoryReporter.class.getMethod("scenarioNotAllowed", Scenario.class, String.class);
 55  1
             beforeScenario = StoryReporter.class.getMethod("beforeScenario", String.class);
 56  1
             scenarioMeta = StoryReporter.class.getMethod("scenarioMeta", Meta.class);
 57  1
             afterScenario = StoryReporter.class.getMethod("afterScenario");
 58  1
             givenStories = StoryReporter.class.getMethod("givenStories", GivenStories.class);
 59  1
             givenStoriesPaths = StoryReporter.class.getMethod("givenStories", List.class);
 60  1
             beforeExamples = StoryReporter.class.getMethod("beforeExamples", List.class, ExamplesTable.class);
 61  1
             example = StoryReporter.class.getMethod("example", Map.class);
 62  1
             afterExamples = StoryReporter.class.getMethod("afterExamples");
 63  1
             successful = StoryReporter.class.getMethod("successful", String.class);
 64  1
             ignorable = StoryReporter.class.getMethod("ignorable", String.class);
 65  1
             pending = StoryReporter.class.getMethod("pending", String.class);
 66  1
             notPerformed = StoryReporter.class.getMethod("notPerformed", String.class);
 67  1
             failed = StoryReporter.class.getMethod("failed", String.class, Throwable.class);
 68  1
             failedOutcomes = StoryReporter.class.getMethod("failedOutcomes", String.class, OutcomesTable.class);
 69  1
             dryRun = StoryReporter.class.getMethod("dryRun");
 70  1
             pendingMethods = StoryReporter.class.getMethod("pendingMethods", List.class);
 71  1
             restarted = StoryReporter.class.getMethod("restarted", String.class, Throwable.class);
 72  1
             cancelled = StoryReporter.class.getMethod("cancelled");
 73  0
         } catch (NoSuchMethodException e) {
 74  0
             throw new RuntimeException(e);
 75  1
         }
 76  1
     }
 77  
 
 78  14
     private List<DelayedMethod> delayedMethods = new ArrayList<DelayedMethod>();
 79  
     private final StoryReporter crossReferencing;
 80  
     private final StoryReporter delegate;
 81  
     private final boolean multiThreading;
 82  14
     private boolean invoked = false;
 83  
 
 84  14
     public ConcurrentStoryReporter(StoryReporter crossReferencing, StoryReporter delegate, boolean multiThreading) {
 85  14
         this.crossReferencing = crossReferencing;
 86  14
         this.multiThreading = multiThreading;
 87  14
         this.delegate = delegate;
 88  14
     }
 89  
 
 90  
     public void storyNotAllowed(Story story, String filter) {
 91  0
         crossReferencing.storyNotAllowed(story, filter);
 92  0
         if (multiThreading) {
 93  0
             delayedMethods.add(new DelayedMethod(storyNotAllowed, story, filter));
 94  
         } else {
 95  0
             delegate.storyNotAllowed(story, filter);
 96  
         }
 97  0
     }
 98  
 
 99  
     public void beforeStory(Story story, boolean givenStory) {
 100  3
         crossReferencing.beforeStory(story, givenStory);
 101  3
         if (multiThreading) {
 102  0
             delayedMethods.add(new DelayedMethod(beforeStory, story, givenStory));
 103  
         } else {
 104  3
             delegate.beforeStory(story, givenStory);
 105  
         }
 106  3
     }
 107  
 
 108  
     public void narrative(Narrative aNarrative) {
 109  3
         crossReferencing.narrative(aNarrative);
 110  3
         if (multiThreading) {
 111  0
             delayedMethods.add(new DelayedMethod(narrative, aNarrative));
 112  
         } else {
 113  3
             delegate.narrative(aNarrative);
 114  
         }
 115  3
     }
 116  
 
 117  
     public void afterStory(boolean givenStory) {
 118  3
         crossReferencing.afterStory(givenStory);
 119  3
         if (multiThreading) {
 120  0
             delayedMethods.add(new DelayedMethod(afterStory, givenStory));
 121  
         } else {
 122  3
             delegate.afterStory(givenStory);
 123  
         }
 124  3
     }
 125  
 
 126  
     public void scenarioNotAllowed(Scenario scenario, String filter) {
 127  0
         crossReferencing.scenarioNotAllowed(scenario, filter);
 128  0
         if (multiThreading) {
 129  0
             delayedMethods.add(new DelayedMethod(scenarioNotAllowed, scenario, filter));
 130  
         } else {
 131  0
             delegate.scenarioNotAllowed(scenario, filter);
 132  
         }
 133  0
     }
 134  
 
 135  
     public void beforeScenario(String scenarioTitle) {
 136  3
         crossReferencing.beforeScenario(scenarioTitle);
 137  3
         if (multiThreading) {
 138  0
             delayedMethods.add(new DelayedMethod(beforeScenario, scenarioTitle));
 139  
         } else {
 140  3
             delegate.beforeScenario(scenarioTitle);
 141  
         }
 142  3
     }
 143  
 
 144  
     public void scenarioMeta(Meta meta) {
 145  0
         crossReferencing.scenarioMeta(meta);
 146  0
         if (multiThreading) {
 147  0
             delayedMethods.add(new DelayedMethod(scenarioMeta, meta));
 148  
         } else {
 149  0
             delegate.scenarioMeta(meta);
 150  
         }
 151  0
     }
 152  
 
 153  
     public void afterScenario() {
 154  3
         crossReferencing.afterScenario();
 155  3
         if (multiThreading) {
 156  0
             delayedMethods.add(new DelayedMethod(afterScenario));
 157  
         } else {
 158  3
             delegate.afterScenario();
 159  
         }
 160  3
     }
 161  
 
 162  
     public void givenStories(GivenStories stories) {
 163  0
         crossReferencing.givenStories(stories);
 164  0
         if (multiThreading) {
 165  0
             delayedMethods.add(new DelayedMethod(givenStories, stories));
 166  
         } else {
 167  0
             delegate.givenStories(stories);
 168  
         }
 169  0
     }
 170  
 
 171  
     public void givenStories(List<String> storyPaths) {
 172  3
         crossReferencing.givenStories(storyPaths);
 173  3
         if (multiThreading) {
 174  0
             delayedMethods.add(new DelayedMethod(givenStoriesPaths, storyPaths));
 175  
         } else {
 176  3
             delegate.givenStories(storyPaths);
 177  
         }
 178  3
     }
 179  
 
 180  
     public void beforeExamples(List<String> steps, ExamplesTable table) {
 181  3
         crossReferencing.beforeExamples(steps, table);
 182  3
         if (multiThreading) {
 183  0
             delayedMethods.add(new DelayedMethod(beforeExamples, steps, table));
 184  
         } else {
 185  3
             delegate.beforeExamples(steps, table);
 186  
         }
 187  3
     }
 188  
 
 189  
     public void example(Map<String, String> tableRow) {
 190  6
         crossReferencing.example(tableRow);
 191  6
         if (multiThreading) {
 192  0
             delayedMethods.add(new DelayedMethod(example, tableRow));
 193  
         } else {
 194  6
             delegate.example(tableRow);
 195  
         }
 196  6
     }
 197  
 
 198  
     public void afterExamples() {
 199  3
         crossReferencing.afterExamples();
 200  3
         if (multiThreading) {
 201  0
             delayedMethods.add(new DelayedMethod(afterExamples));
 202  
         } else {
 203  3
             delegate.afterExamples();
 204  
         }
 205  3
     }
 206  
 
 207  
     public void successful(String step) {
 208  9
         crossReferencing.successful(step);
 209  9
         if (multiThreading) {
 210  0
             delayedMethods.add(new DelayedMethod(successful, step));
 211  
         } else {
 212  9
             delegate.successful(step);
 213  
         }
 214  9
     }
 215  
 
 216  
     public void ignorable(String step) {
 217  3
         crossReferencing.ignorable(step);
 218  3
         if (multiThreading) {
 219  0
             delayedMethods.add(new DelayedMethod(ignorable, step));
 220  
         } else {
 221  3
             delegate.ignorable(step);
 222  
         }
 223  3
     }
 224  
 
 225  
     public void pending(String step) {
 226  3
         crossReferencing.pending(step);
 227  3
         if (multiThreading) {
 228  0
             delayedMethods.add(new DelayedMethod(pending, step));
 229  
         } else {
 230  3
             delegate.pending(step);
 231  
         }
 232  3
     }
 233  
 
 234  
     public void notPerformed(String step) {
 235  3
         crossReferencing.notPerformed(step);
 236  3
         if (multiThreading) {
 237  0
             delayedMethods.add(new DelayedMethod(notPerformed, step));
 238  
         } else {
 239  3
             delegate.notPerformed(step);
 240  
         }
 241  3
     }
 242  
 
 243  
     public void failed(String step, Throwable cause) {
 244  1
         crossReferencing.failed(step, cause);
 245  1
         if (multiThreading) {
 246  0
             delayedMethods.add(new DelayedMethod(failed, step, cause));
 247  
         } else {
 248  1
             delegate.failed(step, cause);
 249  
         }
 250  1
     }
 251  
 
 252  
     public void failedOutcomes(String step, OutcomesTable table) {
 253  3
         crossReferencing.failedOutcomes(step, table);
 254  3
         if (multiThreading) {
 255  0
             delayedMethods.add(new DelayedMethod(failedOutcomes, step, table));
 256  
         } else {
 257  3
             delegate.failedOutcomes(step, table);
 258  
         }
 259  3
     }
 260  
 
 261  
     public void dryRun() {
 262  3
         crossReferencing.dryRun();
 263  3
         if (multiThreading) {
 264  0
             delayedMethods.add(new DelayedMethod(dryRun));
 265  
         } else {
 266  3
             delegate.dryRun();
 267  
         }
 268  3
     }
 269  
 
 270  
     public void pendingMethods(List<String> methods) {
 271  3
         crossReferencing.pendingMethods(methods);
 272  3
         if (multiThreading) {
 273  0
             delayedMethods.add(new DelayedMethod(pendingMethods, methods));
 274  
         } else {
 275  3
             delegate.pendingMethods(methods);
 276  
         }
 277  
         
 278  3
     }
 279  
 
 280  
     public void restarted(String step, Throwable cause) {
 281  3
         crossReferencing.restarted(step, cause);
 282  3
         if (multiThreading) {
 283  0
             delayedMethods.add(new DelayedMethod(restarted, step, cause));
 284  
         } else {
 285  3
             delegate.restarted(step, cause);
 286  
         }
 287  3
     }
 288  
 
 289  
     public void cancelled() {
 290  3
         crossReferencing.cancelled();
 291  3
         if (multiThreading) {
 292  0
             delayedMethods.add(new DelayedMethod(cancelled));
 293  
         } else {
 294  3
             delegate.cancelled();
 295  
         }
 296  3
     }
 297  
 
 298  
     public StoryReporter getDelegate() {
 299  5
         return delegate;
 300  
     }
 301  
 
 302  
     public void invokeDelayed() {
 303  3
         if ( !multiThreading ){
 304  3
             return;
 305  
         }
 306  0
         if (invoked) {
 307  0
             throw new RuntimeException("Delayed methods already invoked");
 308  
         }
 309  0
         synchronized (delegate) {
 310  0
             for (DelayedMethod delayed : delayedMethods) {
 311  0
                 delayed.invoke(delegate);
 312  
             }
 313  0
         }
 314  0
         invoked = true;
 315  0
     }
 316  
 
 317  
     public static class DelayedMethod {
 318  
         private Method method;
 319  
         private Object[] args;
 320  
 
 321  0
         public DelayedMethod(Method method, Object... args) {
 322  0
             this.method = method;
 323  0
             this.args = args;
 324  0
         }
 325  
 
 326  
         public void invoke(StoryReporter delegate) {
 327  
             try {
 328  0
                 method.invoke(delegate, args);
 329  0
             } catch (IllegalAccessException e) {
 330  0
                 throw new RuntimeException(e);
 331  0
             } catch (InvocationTargetException e) {
 332  0
                 throw new RuntimeException(e);
 333  0
             } catch (IllegalArgumentException e) {
 334  0
                 throw new RuntimeException("" + method, e);
 335  0
             }
 336  0
         }
 337  
     }
 338  
 
 339  
 
 340  
 }