Coverage Report - org.jbehave.core.steps.StepCreator
 
Classes in this File Line Coverage Branch Coverage Complexity
StepCreator
98%
130/132
90%
65/72
2.117
StepCreator$1
100%
1/1
N/A
2.117
StepCreator$AbstractStep
50%
1/2
N/A
2.117
StepCreator$AnyOrDefaultStep
100%
5/5
N/A
2.117
StepCreator$BeforeOrAfter
75%
9/12
75%
3/4
2.117
StepCreator$BeforeOrAfterStep
100%
5/5
N/A
2.117
StepCreator$FailureStep
100%
6/6
75%
3/4
2.117
StepCreator$IgnorableStep
100%
5/5
N/A
2.117
StepCreator$Jsr330Helper
100%
2/2
N/A
2.117
StepCreator$ParameterNotFound
100%
4/4
N/A
2.117
StepCreator$ParameterizedStep
93%
29/31
75%
3/4
2.117
StepCreator$PendingStep
72%
8/11
0%
0/2
2.117
StepCreator$Skip
100%
2/2
N/A
2.117
StepCreator$StepRunner
N/A
N/A
2.117
StepCreator$SuccessStep
100%
6/6
75%
3/4
2.117
 
 1  
 package org.jbehave.core.steps;
 2  
 
 3  
 import com.thoughtworks.paranamer.NullParanamer;
 4  
 import com.thoughtworks.paranamer.Paranamer;
 5  
 
 6  
 import org.apache.commons.lang.builder.ToStringBuilder;
 7  
 import org.apache.commons.lang.builder.ToStringStyle;
 8  
 import org.jbehave.core.annotations.AfterScenario.Outcome;
 9  
 import org.jbehave.core.annotations.Named;
 10  
 import org.jbehave.core.failures.BeforeOrAfterFailed;
 11  
 import org.jbehave.core.failures.UUIDExceptionWrapper;
 12  
 import org.jbehave.core.model.ExamplesTable;
 13  
 import org.jbehave.core.parsers.StepMatcher;
 14  
 
 15  
 import java.lang.annotation.Annotation;
 16  
 import java.lang.reflect.InvocationTargetException;
 17  
 import java.lang.reflect.Method;
 18  
 import java.lang.reflect.Type;
 19  
 import java.util.HashMap;
 20  
 import java.util.Map;
 21  
 
 22  
 import static java.util.Arrays.asList;
 23  
 import static org.jbehave.core.steps.AbstractStepResult.*;
 24  
 
 25  636
 public class StepCreator {
 26  
 
 27  
     public static final String PARAMETER_NAME_START = "<";
 28  
     public static final String PARAMETER_NAME_END = ">";
 29  
     public static final String PARAMETER_TABLE_START = "\uff3b";
 30  
     public static final String PARAMETER_TABLE_END = "\uff3d";
 31  
     public static final String PARAMETER_VALUE_START = "\uFF5F";
 32  
     public static final String PARAMETER_VALUE_END = "\uFF60";
 33  
     public static final String PARAMETER_VALUE_NEWLINE = "\u2424";
 34  1
     public static final UUIDExceptionWrapper NO_FAILURE = new UUIDExceptionWrapper("no failure");
 35  
     private final Object stepsInstance;
 36  
     private final ParameterConverters parameterConverters;
 37  
     private final StepMatcher stepMatcher;
 38  
     private final StepRunner beforeOrAfter;
 39  
     private final StepRunner skip;
 40  
     private StepMonitor stepMonitor;
 41  119
     private Paranamer paranamer = new NullParanamer();
 42  119
     private boolean dryRun = false;
 43  
 
 44  
     public StepCreator(Object stepsInstance, StepMonitor stepMonitor) {
 45  34
         this(stepsInstance, null, null, stepMonitor);
 46  34
     }
 47  
 
 48  
     public StepCreator(Object stepsInstance, ParameterConverters parameterConverters, StepMatcher stepMatcher,
 49  119
             StepMonitor stepMonitor) {
 50  119
         this.stepsInstance = stepsInstance;
 51  119
         this.parameterConverters = parameterConverters;
 52  119
         this.stepMatcher = stepMatcher;
 53  119
         this.stepMonitor = stepMonitor;
 54  119
         this.beforeOrAfter = new BeforeOrAfter();
 55  119
         this.skip = new Skip();
 56  119
     }
 57  
 
 58  
     public void useStepMonitor(StepMonitor stepMonitor) {
 59  56
         this.stepMonitor = stepMonitor;
 60  56
     }
 61  
 
 62  
     public void useParanamer(Paranamer paranamer) {
 63  58
         this.paranamer = paranamer;
 64  58
     }
 65  
 
 66  
     public void doDryRun(boolean dryRun) {
 67  55
         this.dryRun = dryRun;
 68  55
     }
 69  
 
 70  
     public Step createBeforeOrAfterStep(final Method method) {
 71  15
         return new BeforeOrAfterStep(method);
 72  
     }
 73  
 
 74  
     public Step createAfterStepUponOutcome(final Method method, final Outcome outcome, final boolean failureOccured) {
 75  11
         switch (outcome) {
 76  
         case ANY:
 77  
         default:
 78  5
             return new AnyOrDefaultStep(method);
 79  
         case SUCCESS:
 80  3
             return new SuccessStep(failureOccured, method);
 81  
         case FAILURE:
 82  3
             return new FailureStep(failureOccured, method);
 83  
         }
 84  
     }
 85  
 
 86  
     public Map<String, String> matchedParameters(final Method method, final String stepAsString,
 87  
             final String stepWithoutStartingWord, final Map<String, String> namedParameters) {
 88  2
         stepMatcher.find(stepWithoutStartingWord);
 89  2
         String[] annotationNames = annotatedParameterNames(method);
 90  2
         String[] parameterNames = paranamer.lookupParameterNames(method, false);
 91  2
         Type[] types = method.getGenericParameterTypes();
 92  2
         String[] names = (annotationNames.length > 0 ? annotationNames : parameterNames);
 93  2
         String[] parameters = parametersForStep(namedParameters, types, annotationNames, parameterNames);
 94  2
         Map<String, String> matchedParameters = new HashMap<String, String>();
 95  6
         for (int i = 0; i < names.length; i++) {
 96  4
             matchedParameters.put(names[i], parameters[i]);
 97  
         }
 98  2
         return matchedParameters;
 99  
     }
 100  
 
 101  
     public Step createParametrisedStep(final Method method, final String stepAsString,
 102  
             final String stepWithoutStartingWord, final Map<String, String> namedParameters) {
 103  62
         return new ParameterizedStep(stepAsString, method, stepWithoutStartingWord, namedParameters);
 104  
     }
 105  
 
 106  
     /**
 107  
      * Extract annotated parameter names from the @Named parameter annotations
 108  
      * of the method
 109  
      * 
 110  
      * @param method the Method containing the annotations
 111  
      * @return An array of annotated parameter names, which <b>may</b> include
 112  
      *         <code>null</code> values for parameters that are not annotated
 113  
      */
 114  
     private String[] annotatedParameterNames(Method method) {
 115  63
         Annotation[][] parameterAnnotations = method.getParameterAnnotations();
 116  63
         String[] names = new String[parameterAnnotations.length];
 117  115
         for (int x = 0; x < parameterAnnotations.length; x++) {
 118  52
             Annotation[] annotations = parameterAnnotations[x];
 119  76
             for (Annotation annotation : annotations) {
 120  24
                 names[x] = annotationName(annotation);
 121  
             }
 122  
         }
 123  63
         return names;
 124  
     }
 125  
 
 126  
     private String annotationName(Annotation annotation) {
 127  24
         if (annotation.annotationType().isAssignableFrom(Named.class)) {
 128  18
             return ((Named) annotation).value();
 129  6
         } else if ("javax.inject.Named".equals(annotation.annotationType().getName())) {
 130  6
             return Jsr330Helper.getNamedValue(annotation);
 131  
         } else {
 132  0
             return null;
 133  
         }
 134  
     }
 135  
 
 136  
     private String parametrisedStep(String stepAsString, Map<String, String> namedParameters, Type[] types,
 137  
             String[] annotationNames, String[] parameterNames, String[] parameters) {
 138  59
         String parametrisedStep = stepAsString;
 139  103
         for (int position = 0; position < types.length; position++) {
 140  44
             parametrisedStep = replaceParameterValuesInStep(parametrisedStep, position, types, annotationNames,
 141  
                     parameterNames, parameters, namedParameters);
 142  
         }
 143  59
         return parametrisedStep;
 144  
     }
 145  
 
 146  
     private String replaceParameterValuesInStep(String stepText, int position, Type[] types, String[] annotationNames,
 147  
             String[] parameterNames, String[] parameters, Map<String, String> namedParameters) {
 148  44
         int annotatedNamePosition = parameterPosition(annotationNames, position);
 149  44
         int parameterNamePosition = parameterPosition(parameterNames, position);
 150  44
         if (annotatedNamePosition != -1) {
 151  16
             stepText = replaceParameterValue(stepText, namedParameters, annotationNames[position]);
 152  28
         } else if (parameterNamePosition != -1) {
 153  6
             stepText = replaceParameterValue(stepText, namedParameters, parameterNames[position]);
 154  
         }
 155  44
         stepText = replaceParameterValue(stepText, position, types, parameters);
 156  44
         return stepText;
 157  
     }
 158  
 
 159  
     private String replaceParameterValue(String stepText, int position, Type[] types, String[] parameters) {
 160  44
         Type type = types[position];
 161  44
         String value = parameters[position];
 162  44
         if (value != null) {
 163  44
             if ( isTable(type)){
 164  0
                 stepText = stepText.replace(value, PARAMETER_TABLE_START + value + PARAMETER_TABLE_END);                
 165  
             } else {
 166  44
                 stepText = stepText.replace(value, PARAMETER_VALUE_START + value + PARAMETER_VALUE_END)
 167  
                                    .replace("\n", PARAMETER_VALUE_NEWLINE);
 168  
             }
 169  
         }
 170  44
         return stepText;
 171  
     }
 172  
 
 173  
     private boolean isTable(Type type) {
 174  44
         return type instanceof Class && ((Class<?>)type).isAssignableFrom(ExamplesTable.class);
 175  
     }
 176  
 
 177  
     private String replaceParameterValue(String stepText, Map<String, String> namedParameters, String name) {
 178  22
         String value = tableParameter(namedParameters, name);
 179  22
         if (value != null) {
 180  10
             stepText = stepText.replace(PARAMETER_NAME_START + name + PARAMETER_NAME_END, PARAMETER_VALUE_START + value
 181  
                     + PARAMETER_VALUE_END);
 182  
         }
 183  22
         return stepText;
 184  
     }
 185  
 
 186  
     private String[] parametersForStep(Map<String, String> namedParameters, Type[] types, String[] annotationNames,
 187  
             String[] parameterNames) {
 188  63
         final String[] parameters = new String[types.length];
 189  111
         for (int position = 0; position < types.length; position++) {
 190  50
             parameters[position] = parameterForPosition(position, annotationNames, parameterNames, namedParameters);
 191  
         }
 192  61
         return parameters;
 193  
     }
 194  
 
 195  
     private Object[] convertParameters(String[] parametersAsString, Type[] types) {
 196  59
         final Object[] parameters = new Object[parametersAsString.length];
 197  103
         for (int position = 0; position < parametersAsString.length; position++) {
 198  44
             parameters[position] = parameterConverters.convert(parametersAsString[position], types[position]);
 199  
         }
 200  59
         return parameters;
 201  
     }
 202  
 
 203  
     private String parameterForPosition(int position, String[] annotationNames, String[] parameterNames,
 204  
             Map<String, String> namedParameters) {
 205  50
         int annotatedNamePosition = parameterPosition(annotationNames, position);
 206  50
         int parameterNamePosition = parameterPosition(parameterNames, position);
 207  50
         String parameter = null;
 208  50
         if (annotatedNamePosition != -1 && isGroupName(annotationNames[position])) {
 209  10
             String name = annotationNames[position];
 210  10
             stepMonitor.usingAnnotatedNameForParameter(name, position);
 211  10
             parameter = matchedParameter(name);
 212  10
         } else if (parameterNamePosition != -1 && isGroupName(parameterNames[position])) {
 213  4
             String name = parameterNames[position];
 214  4
             stepMonitor.usingParameterNameForParameter(name, position);
 215  4
             parameter = matchedParameter(name);
 216  4
         } else if (annotatedNamePosition != -1 && isTableName(namedParameters, annotationNames[position])) {
 217  10
             String name = annotationNames[position];
 218  10
             stepMonitor.usingTableAnnotatedNameForParameter(name, position);
 219  10
             parameter = tableParameter(namedParameters, name);
 220  10
         } else if (parameterNamePosition != -1 && isTableName(namedParameters, parameterNames[position])) {
 221  2
             String name = parameterNames[position];
 222  2
             stepMonitor.usingTableParameterNameForParameter(name, position);
 223  2
             parameter = tableParameter(namedParameters, name);
 224  2
         } else {
 225  24
             stepMonitor.usingNaturalOrderForParameter(position);
 226  24
             parameter = matchedParameter(position);
 227  
         }
 228  48
         stepMonitor.foundParameter(parameter, position);
 229  48
         return parameter;
 230  
     }
 231  
 
 232  
     String matchedParameter(String name) {
 233  15
         String[] parameterNames = stepMatcher.parameterNames();
 234  22
         for (int i = 0; i < parameterNames.length; i++) {
 235  21
             String parameterName = parameterNames[i];
 236  21
             if (name.equals(parameterName)) {
 237  14
                 return matchedParameter(i);
 238  
             }
 239  
         }
 240  1
         throw new ParameterNotFound(name, parameterNames);
 241  
     }
 242  
 
 243  
     private String matchedParameter(int position) {
 244  38
         String[] parameterNames = stepMatcher.parameterNames();
 245  38
         int matchedPosition = position + 1;
 246  38
         if (matchedPosition <= parameterNames.length) {
 247  36
             return stepMatcher.parameter(matchedPosition);
 248  
         }
 249  2
         throw new ParameterNotFound(position, parameterNames);
 250  
     }
 251  
 
 252  
     private int parameterPosition(String[] names, int position) {
 253  188
         if (names.length == 0) {
 254  82
             return -1;
 255  
         }
 256  106
         String positionName = names[position];
 257  194
         for (int i = 0; i < names.length; i++) {
 258  138
             String name = names[i];
 259  138
             if (name != null && positionName.equals(name)) {
 260  50
                 return i;
 261  
             }
 262  
         }
 263  56
         return -1;
 264  
     }
 265  
 
 266  
     private boolean isGroupName(String name) {
 267  28
         String[] groupNames = stepMatcher.parameterNames();
 268  35
         for (String groupName : groupNames) {
 269  21
             if (name.equals(groupName)) {
 270  14
                 return true;
 271  
             }
 272  
         }
 273  14
         return false;
 274  
     }
 275  
 
 276  
     private String tableParameter(Map<String, String> namedParameters, String name) {
 277  48
         return namedParameters.get(name);
 278  
     }
 279  
 
 280  
     private boolean isTableName(Map<String, String> namedParameters, String name) {
 281  14
         return tableParameter(namedParameters, name) != null;
 282  
     }
 283  
 
 284  
     public interface StepRunner {
 285  
 
 286  
         StepResult run(Method method, UUIDExceptionWrapper failureIfItHappened);
 287  
 
 288  
     }
 289  
 
 290  238
     private class BeforeOrAfter implements StepRunner {
 291  
 
 292  
         public StepResult run(Method method, UUIDExceptionWrapper failureIfItHappened) {
 293  19
             if (method == null) {
 294  1
                 return failed(method, new UUIDExceptionWrapper(new BeforeOrAfterFailed(new NullPointerException(
 295  
                         "method"))));
 296  
             }
 297  
             try {
 298  18
                 if (method.getParameterTypes().length == 0) {
 299  18
                     method.invoke(stepsInstance);
 300  
                 } else {
 301  0
                     method.invoke(stepsInstance, failureIfItHappened);
 302  
                 }
 303  2
             } catch (InvocationTargetException e) {
 304  2
                 return failed(method, new UUIDExceptionWrapper(new BeforeOrAfterFailed(method, e.getCause())));
 305  0
             } catch (Throwable t) {
 306  0
                 return failed(method, new UUIDExceptionWrapper(new BeforeOrAfterFailed(method, t)));
 307  16
             }
 308  16
             return skipped();
 309  
         }
 310  
     }
 311  
 
 312  238
     private class Skip implements StepRunner {
 313  
 
 314  
         public StepResult run(Method method, UUIDExceptionWrapper failureIfItHappened) {
 315  3
             return skipped();
 316  
         }
 317  
     }
 318  
 
 319  
     public static Step createPendingStep(final String stepAsString, String previousNonAndStep) {
 320  19
         return new PendingStep(stepAsString, previousNonAndStep);
 321  
     }
 322  
 
 323  
     public static Step createIgnorableStep(final String stepAsString) {
 324  2
         return new IgnorableStep(stepAsString);
 325  
     }
 326  
 
 327  
     /**
 328  
      * This is a different class, because the @Inject jar may not be in the
 329  
      * classpath.
 330  
      */
 331  6
     public static class Jsr330Helper {
 332  
 
 333  
         private static String getNamedValue(Annotation annotation) {
 334  6
             return ((javax.inject.Named) annotation).value();
 335  
         }
 336  
 
 337  
     }
 338  
 
 339  
     @SuppressWarnings("serial")
 340  
     public static class ParameterNotFound extends RuntimeException {
 341  
 
 342  
         public ParameterNotFound(String name, String[] parameters) {
 343  1
             super("Parameter not found for name '" + name + "' amongst '" + asList(parameters) + "'");
 344  1
         }
 345  
 
 346  
         public ParameterNotFound(int position, String[] parameters) {
 347  2
             super("Parameter not found for position '" + position + "' amongst '" + asList(parameters) + "'");
 348  2
         }
 349  
     }
 350  
 
 351  109
     public static abstract class AbstractStep implements Step {
 352  
 
 353  
         @Override
 354  
         public String toString() {
 355  0
             return ToStringBuilder.reflectionToString(this, ToStringStyle.SIMPLE_STYLE);
 356  
         }
 357  
 
 358  
     }
 359  
 
 360  
     public class BeforeOrAfterStep extends AbstractStep {
 361  
         private final Method method;
 362  
 
 363  15
         public BeforeOrAfterStep(Method method) {
 364  15
             this.method = method;
 365  15
         }
 366  
 
 367  
         public StepResult doNotPerform(UUIDExceptionWrapper storyFailureIfItHappened) {
 368  1
             return beforeOrAfter.run(method, NO_FAILURE);
 369  
         }
 370  
 
 371  
         public StepResult perform(UUIDExceptionWrapper storyFailureIfItHappened) {
 372  12
             return beforeOrAfter.run(method, NO_FAILURE);
 373  
         }
 374  
 
 375  
     }
 376  
 
 377  
     public class AnyOrDefaultStep extends AbstractStep {
 378  
 
 379  
         private final Method method;
 380  
 
 381  5
         public AnyOrDefaultStep(Method method) {
 382  5
             this.method = method;
 383  5
         }
 384  
 
 385  
         public StepResult doNotPerform(UUIDExceptionWrapper storyFailureIfItHappened) {
 386  1
             return beforeOrAfter.run(method, NO_FAILURE);
 387  
         }
 388  
 
 389  
         public StepResult perform(UUIDExceptionWrapper storyFailureIfItHappened) {
 390  2
             return beforeOrAfter.run(method, NO_FAILURE);
 391  
         }
 392  
 
 393  
     }
 394  
 
 395  
     public class SuccessStep extends AbstractStep {
 396  
 
 397  
         private final boolean failureOccured;
 398  
         private final Method method;
 399  
 
 400  3
         public SuccessStep(boolean failureOccured, Method method) {
 401  3
             this.failureOccured = failureOccured;
 402  3
             this.method = method;
 403  3
         }
 404  
 
 405  
         public StepResult doNotPerform(UUIDExceptionWrapper storyFailureIfItHappened) {
 406  1
             return (failureOccured ? skip.run(method, NO_FAILURE) : beforeOrAfter.run(method, NO_FAILURE));
 407  
         }
 408  
 
 409  
         public StepResult perform(UUIDExceptionWrapper storyFailureIfItHappened) {
 410  2
             return (failureOccured ? skip.run(method, NO_FAILURE) : beforeOrAfter.run(method, NO_FAILURE));
 411  
         }
 412  
 
 413  
     }
 414  
 
 415  
     public class FailureStep extends AbstractStep {
 416  
 
 417  
         private final boolean failureOccured;
 418  
         private final Method method;
 419  
 
 420  3
         public FailureStep(boolean failureOccured, Method method) {
 421  3
             this.failureOccured = failureOccured;
 422  3
             this.method = method;
 423  3
         }
 424  
 
 425  
         public StepResult doNotPerform(UUIDExceptionWrapper storyFailureIfItHappened) {
 426  1
             return (failureOccured ? beforeOrAfter.run(method, storyFailureIfItHappened) : skip.run(method, NO_FAILURE));
 427  
         }
 428  
 
 429  
         public StepResult perform(UUIDExceptionWrapper storyFailureIfItHappened) {
 430  2
             return (failureOccured ? beforeOrAfter.run(method, storyFailureIfItHappened) : skip.run(method, NO_FAILURE));
 431  
         }
 432  
 
 433  
     }
 434  
 
 435  
     public class ParameterizedStep extends AbstractStep {
 436  
         private Object[] convertedParameters;
 437  
         private String parametrisedStep;
 438  
         private final String stepAsString;
 439  
         private final Method method;
 440  
         private final String stepWithoutStartingWord;
 441  
         private final Map<String, String> namedParameters;
 442  
 
 443  
         public ParameterizedStep(String stepAsString, Method method, String stepWithoutStartingWord,
 444  62
                 Map<String, String> namedParameters) {
 445  62
             this.stepAsString = stepAsString;
 446  62
             this.method = method;
 447  62
             this.stepWithoutStartingWord = stepWithoutStartingWord;
 448  62
             this.namedParameters = namedParameters;
 449  62
         }
 450  
 
 451  
         public StepResult perform(UUIDExceptionWrapper storyFailureIfItHappened) {
 452  
             try {
 453  62
                 parametriseStep();
 454  59
                 stepMonitor.performing(stepAsString, dryRun);
 455  59
                 if (!dryRun) {
 456  55
                     method.invoke(stepsInstance, convertedParameters);
 457  
                 }
 458  58
                 return successful(stepAsString).withParameterValues(parametrisedStep);
 459  1
             } catch (ParameterNotFound e) {
 460  
                 // step parametrisation failed, return pending StepResult
 461  1
                 return pending(stepAsString).withParameterValues(parametrisedStep);
 462  1
             } catch (InvocationTargetException e) {
 463  1
                 if (e.getCause() instanceof UUIDExceptionWrapper) {
 464  1
                     return failed(stepAsString, ((UUIDExceptionWrapper) e.getCause())).withParameterValues(
 465  
                             parametrisedStep);
 466  
                 }
 467  0
                 return failed(stepAsString, new UUIDExceptionWrapper(e.getCause())).withParameterValues(
 468  
                         parametrisedStep);
 469  2
             } catch (Throwable t) {
 470  2
                 return failed(stepAsString, new UUIDExceptionWrapper(t)).withParameterValues(parametrisedStep);
 471  
             }
 472  
         }
 473  
 
 474  
         public StepResult doNotPerform(UUIDExceptionWrapper storyFailureIfItHappened) {
 475  
             try {
 476  1
                 parametriseStep();
 477  
                 // } catch (ParameterNotFound e) {
 478  1
             } catch (Throwable t) {
 479  
                 // step parametrisation failed, but still return
 480  
                 // notPerformed StepResult
 481  0
             }
 482  1
             return notPerformed(stepAsString).withParameterValues(parametrisedStep);
 483  
         }
 484  
 
 485  
         private void parametriseStep() {
 486  63
             stepMatcher.find(stepWithoutStartingWord);
 487  61
             String[] annotationNames = annotatedParameterNames(method);
 488  61
             String[] parameterNames = paranamer.lookupParameterNames(method, false);
 489  61
             Type[] types = method.getGenericParameterTypes();
 490  61
             String[] parameters = parametersForStep(namedParameters, types, annotationNames, parameterNames);
 491  59
             convertedParameters = convertParameters(parameters, types);
 492  59
             parametrisedStep = parametrisedStep(stepAsString, namedParameters, types, annotationNames, parameterNames,
 493  
                     parameters);
 494  59
         }
 495  
 
 496  
     }
 497  
 
 498  
     public static class PendingStep extends AbstractStep {
 499  
         private final String stepAsString;
 500  
         private final String previousNonAndStep;
 501  
         private Method method;
 502  
 
 503  19
         public PendingStep(String stepAsString, String previousNonAndStep) {
 504  19
             this.stepAsString = stepAsString;
 505  19
             this.previousNonAndStep = previousNonAndStep;
 506  19
         }
 507  
 
 508  
         public StepResult perform(UUIDExceptionWrapper storyFailureIfItHappened) {
 509  9
             return pending(stepAsString);
 510  
         }
 511  
 
 512  
         public StepResult doNotPerform(UUIDExceptionWrapper storyFailureIfItHappened) {
 513  1
             return pending(stepAsString);
 514  
         }
 515  
 
 516  
         public String stepAsString() {
 517  11
             return stepAsString;
 518  
         }
 519  
 
 520  
         public String previousNonAndStepAsString() {
 521  11
             return previousNonAndStep;
 522  
         }
 523  
 
 524  
         public void annotatedOn(Method method) {
 525  0
             this.method = method;
 526  0
         }
 527  
 
 528  
         public boolean annotated() {
 529  0
             return method != null;
 530  
         }
 531  
 
 532  
     }
 533  
 
 534  
     public static class IgnorableStep extends AbstractStep {
 535  
         private final String stepAsString;
 536  
 
 537  2
         public IgnorableStep(String stepAsString) {
 538  2
             this.stepAsString = stepAsString;
 539  2
         }
 540  
 
 541  
         public StepResult perform(UUIDExceptionWrapper storyFailureIfItHappened) {
 542  2
             return ignorable(stepAsString);
 543  
         }
 544  
 
 545  
         public StepResult doNotPerform(UUIDExceptionWrapper storyFailureIfItHappened) {
 546  1
             return ignorable(stepAsString);
 547  
         }
 548  
     }
 549  
 
 550  
 }