Coverage Report - org.jbehave.core.steps.StepCandidate
 
Classes in this File Line Coverage Branch Coverage Complexity
StepCandidate
98%
60/61
81%
18/22
1.609
 
 1  
 package org.jbehave.core.steps;
 2  
 
 3  
 import java.lang.reflect.Method;
 4  
 import java.util.ArrayList;
 5  
 import java.util.List;
 6  
 import java.util.Map;
 7  
 
 8  
 import org.apache.commons.lang.StringUtils;
 9  
 import org.jbehave.core.annotations.Given;
 10  
 import org.jbehave.core.annotations.Pending;
 11  
 import org.jbehave.core.annotations.Then;
 12  
 import org.jbehave.core.annotations.When;
 13  
 import org.jbehave.core.configuration.Keywords;
 14  
 import org.jbehave.core.configuration.Keywords.StartingWordNotFound;
 15  
 import org.jbehave.core.parsers.StepMatcher;
 16  
 import org.jbehave.core.parsers.StepPatternParser;
 17  
 
 18  
 import com.thoughtworks.paranamer.Paranamer;
 19  
 
 20  
 /**
 21  
  * A StepCandidate is associated to a Java method annotated with {@link Given},
 22  
  * {@link When}, {@link Then} in a steps instance class. The StepCandidate is
 23  
  * responsible for matching the textual step against the pattern contained in
 24  
  * the method annotation via the {@link StepMatcher} and for the creation of the
 25  
  * matched executable step via the {@link StepCreator}.
 26  
  */
 27  
 public class StepCandidate {
 28  
 
 29  
     private final String patternAsString;
 30  
     private final Integer priority;
 31  
     private final StepType stepType;
 32  
     private final Method method;
 33  
     private final Object stepsInstance;
 34  
     private final Keywords keywords;
 35  
     private final StepMatcher stepMatcher;
 36  
     private final StepCreator stepCreator;
 37  84
     private StepMonitor stepMonitor = new SilentStepMonitor();
 38  
     private String[] composedSteps;
 39  
 
 40  
     public StepCandidate(String patternAsString, int priority, StepType stepType, Method method, Object stepsInstance,
 41  
             Keywords keywords, StepPatternParser stepPatternParser,
 42  84
             ParameterConverters parameterConverters) {
 43  84
         this.patternAsString = patternAsString;
 44  84
         this.priority = priority;
 45  84
         this.stepType = stepType;
 46  84
         this.method = method;
 47  84
         this.stepsInstance = stepsInstance;
 48  84
         this.keywords = keywords;
 49  84
         this.stepMatcher = stepPatternParser.parseStep(stepType, patternAsString);
 50  84
         this.stepCreator = new StepCreator(stepsInstance, parameterConverters, stepMatcher, stepMonitor);
 51  84
     }
 52  
 
 53  
     public Method getMethod() {
 54  7
         return method;
 55  
     }
 56  
 
 57  
     public Integer getPriority() {
 58  1
         return priority;
 59  
     }
 60  
 
 61  
     public String getPatternAsString() {
 62  32
         return patternAsString;
 63  
     }
 64  
 
 65  
     public Object getStepsInstance() {
 66  7
         return stepsInstance;
 67  
     }
 68  
 
 69  
     public StepType getStepType() {
 70  102
         return stepType;
 71  
     }
 72  
 
 73  
     public String getStartingWord() {
 74  17
         return keywords.startingWordFor(stepType);
 75  
     }
 76  
 
 77  
     public void useStepMonitor(StepMonitor stepMonitor) {
 78  55
         this.stepMonitor = stepMonitor;
 79  55
         this.stepCreator.useStepMonitor(stepMonitor);
 80  55
     }
 81  
 
 82  
     public void doDryRun(boolean dryRun) {
 83  55
         this.stepCreator.doDryRun(dryRun);
 84  55
     }
 85  
 
 86  
     public void useParanamer(Paranamer paranamer) {
 87  58
         this.stepCreator.useParanamer(paranamer);
 88  58
     }
 89  
 
 90  
     public void composedOf(String[] steps) {
 91  2
         this.composedSteps = steps;        
 92  2
     }
 93  
     
 94  
     public boolean isComposite() {
 95  2
         return composedSteps != null && composedSteps.length > 0;
 96  
     }
 97  
 
 98  
     public boolean ignore(String stepAsString) {
 99  
         try {
 100  2
             String ignoreWord = keywords.startingWordFor(StepType.IGNORABLE);
 101  1
             return keywords.stepStartsWithWord(stepAsString, ignoreWord);
 102  1
         } catch (StartingWordNotFound e) {
 103  1
             return false;
 104  
         }
 105  
     }
 106  
     
 107  
     public boolean isPending(){
 108  2
         return method.isAnnotationPresent(Pending.class);
 109  
     }
 110  
 
 111  
     public boolean matches(String stepAsString) {
 112  14
         return matches(stepAsString, null);
 113  
     }
 114  
 
 115  
     public boolean matches(String step, String previousNonAndStep) {
 116  
         try {
 117  15
             boolean matchesType = true;
 118  15
             if (isAndStep(step)) {
 119  2
                 if (previousNonAndStep == null) {
 120  
                     // cannot handle AND step with no previous step
 121  1
                     matchesType = false;
 122  
                 } else {
 123  
                     // previous step type should match candidate step type
 124  1
                     matchesType = keywords.startingWordFor(stepType).equals(findStartingWord(previousNonAndStep));
 125  
                 }
 126  
             }
 127  14
             stepMonitor.stepMatchesType(step, previousNonAndStep, matchesType, stepType, method, stepsInstance);
 128  14
             boolean matchesPattern = stepMatcher.matches(stripStartingWord(step));
 129  10
             stepMonitor.stepMatchesPattern(step, matchesPattern, stepMatcher.pattern(), method, stepsInstance);
 130  
             // must match both type and pattern 
 131  10
             return matchesType && matchesPattern;
 132  5
         } catch (StartingWordNotFound e) {
 133  5
             return false;
 134  
         }
 135  
     }
 136  
 
 137  
     public Step createMatchedStep(String stepAsString, Map<String, String> namedParameters) {
 138  62
         return stepCreator.createParametrisedStep(method, stepAsString, stripStartingWord(stepAsString), namedParameters);
 139  
     }
 140  
     
 141  
     public List<Step> createComposedSteps(String stepAsString, Map<String, String> namedParameters,
 142  
             List<StepCandidate> allCandidates) {
 143  2
         Map<String, String> matchedParameters = stepCreator.matchedParameters(method, stepAsString, stripStartingWord(stepAsString), namedParameters);
 144  2
         matchedParameters.putAll(namedParameters);
 145  2
         List<Step> steps = new ArrayList<Step>();
 146  6
         for (String composedStep : composedSteps) {
 147  4
             StepCandidate candidate = findComposedCandidate(composedStep, allCandidates);
 148  4
             if ( candidate != null ){
 149  4
                 steps.add(candidate.createMatchedStep(composedStep, matchedParameters));
 150  
             }
 151  
         }
 152  2
         return steps;
 153  
     }
 154  
 
 155  
     private StepCandidate findComposedCandidate(String composedStep, List<StepCandidate> allCandidates) {
 156  4
         for (StepCandidate candidate : allCandidates) {
 157  10
             if ( StringUtils.startsWith(composedStep, candidate.getStartingWord()) &&
 158  
                  StringUtils.endsWith(composedStep, candidate.getPatternAsString()) ){
 159  4
                 return candidate;
 160  
             }
 161  
         }
 162  0
         return null;
 163  
     }
 164  
 
 165  
     public boolean isAndStep(String stepAsString) {
 166  15
         return keywords.isAndStep(stepAsString);
 167  
     }
 168  
 
 169  
     private String findStartingWord(String stepAsString) {
 170  1
        return keywords.startingWord(stepAsString, stepType);
 171  
     }
 172  
 
 173  
     private String stripStartingWord(String stepAsString) {
 174  78
         return keywords.stepWithoutStartingWord(stepAsString, stepType);
 175  
     }
 176  
 
 177  
     @Override
 178  
     public String toString() {
 179  93
         return stepType + " " + patternAsString;
 180  
     }
 181  
 
 182  
 
 183  
 }