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