Coverage Report - org.jbehave.core.parsers.RegexPrefixCapturingPatternParser
 
Classes in this File Line Coverage Branch Coverage Complexity
RegexPrefixCapturingPatternParser
100%
32/32
100%
6/6
1.231
RegexPrefixCapturingPatternParser$Parameter
100%
7/7
N/A
1.231
 
 1  
 package org.jbehave.core.parsers;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.List;
 5  
 import java.util.regex.Matcher;
 6  
 import java.util.regex.Pattern;
 7  
 
 8  
 import org.apache.commons.lang.builder.ToStringBuilder;
 9  
 import org.apache.commons.lang.builder.ToStringStyle;
 10  
 import org.jbehave.core.steps.StepType;
 11  
 
 12  
 /**
 13  
  * A step pattern parser that provides a step matcher which will capture
 14  
  * parameters starting with the given prefix in any matching step. Default
 15  
  * prefix is $.
 16  
  * 
 17  
  * @author Elizabeth Keogh
 18  
  */
 19  128
 public class RegexPrefixCapturingPatternParser implements StepPatternParser {
 20  
 
 21  
     private final String prefix;
 22  
 
 23  
         /**
 24  
          * Creates a parser which captures parameters starting with $ in a matching
 25  
          * step.
 26  
          */
 27  
         public RegexPrefixCapturingPatternParser() {
 28  637
                 this("$");
 29  637
         }
 30  
 
 31  
         /**
 32  
          * Creates a parser which captures parameters starting with a given prefix
 33  
          * in a matching step.
 34  
          * 
 35  
          * @param prefix the prefix to use in capturing parameters
 36  
          */
 37  638
         public RegexPrefixCapturingPatternParser(String prefix) {
 38  638
                 this.prefix = prefix;
 39  638
         }
 40  
 
 41  
         public String getPrefix(){
 42  1
             return prefix;
 43  
         }
 44  
         
 45  
         public StepMatcher parseStep(StepType stepType, String stepPattern) {
 46  111
                 return new RegexStepMatcher(stepType, stepPattern,
 47  
                                 buildPattern(stepPattern), extractParameterNames(stepPattern));
 48  
         }
 49  
 
 50  
         private Pattern buildPattern(String stepPattern) {
 51  111
                 String matchThisButLeaveBrackets = escapeRegexPunctuation(stepPattern);
 52  111
                 String patternToMatchAgainst = replaceParametersWithCapture(
 53  
                                 matchThisButLeaveBrackets, findParametersToReplace(matchThisButLeaveBrackets));
 54  111
                 String matchThisButIgnoreWhitespace = anyWhitespaceWillDo(patternToMatchAgainst);
 55  111
                 return Pattern.compile(matchThisButIgnoreWhitespace, Pattern.DOTALL);
 56  
         }
 57  
 
 58  
     private String escapeRegexPunctuation(String matchThis) {
 59  111
         return matchThis.replaceAll("([\\[\\]\\{\\}\\?\\^\\.\\*\\(\\)\\+\\\\])", "\\\\$1");
 60  
     }
 61  
 
 62  
         private String anyWhitespaceWillDo(String matchThis) {
 63  111
                 return matchThis.replaceAll("\\s+", "\\\\s+");
 64  
         }
 65  
 
 66  
         private String[] extractParameterNames(String stepPattern) {
 67  111
                 List<String> names = new ArrayList<String>();
 68  111
                 for (Parameter parameter : findParametersToReplace(stepPattern)) {
 69  64
                         names.add(parameter.name);
 70  
                 }
 71  111
                 return names.toArray(new String[names.size()]);
 72  
         }
 73  
 
 74  
     private List<Parameter> findParametersToReplace(String matchThisButLeaveBrackets) {
 75  222
         List<Parameter> parameters = new ArrayList<Parameter>();
 76  222
         Matcher findingAllPrefixedWords = findAllPrefixedWords().matcher(matchThisButLeaveBrackets);
 77  350
         while (findingAllPrefixedWords.find()) {
 78  128
             parameters.add(new Parameter(matchThisButLeaveBrackets, findingAllPrefixedWords.start(),
 79  
                     findingAllPrefixedWords.end(), findingAllPrefixedWords.group(2)));
 80  
         }
 81  222
         return parameters;
 82  
     }
 83  
 
 84  
     private Pattern findAllPrefixedWords() {
 85  222
         return Pattern.compile("(\\" + prefix + "\\w*)(\\W|\\Z)", Pattern.DOTALL);
 86  
     }
 87  
 
 88  
         private String replaceParametersWithCapture(String escapedMatch,
 89  
                         List<Parameter> parameters) {
 90  111
         String replaced = escapedMatch;
 91  175
         for (int i = parameters.size(); i > 0; i--) {
 92  64
             String start = replaced.substring(0, parameters.get(i - 1).start);
 93  64
             String end = replaced.substring(parameters.get(i - 1).end);
 94  64
             String whitespaceIfAny = parameters.get(i - 1).whitespaceIfAny;
 95  64
             replaced = start + "(.*)" + whitespaceIfAny + end;
 96  
         }
 97  111
         return replaced;
 98  
         }
 99  
 
 100  256
         private class Parameter {
 101  
                 private final int start;
 102  
                 private final int end;
 103  
                 private final String whitespaceIfAny;
 104  
                 private final String name;
 105  
 
 106  
                 public Parameter(String pattern, int start, int end,
 107  128
                                 String whitespaceIfAny) {
 108  128
                         this.start = start;
 109  128
                         this.end = end;
 110  128
                         this.whitespaceIfAny = whitespaceIfAny;
 111  128
                         this.name = pattern.substring(start + prefix.length(), end).trim();
 112  128
                 }
 113  
 
 114  
         }
 115  
 
 116  
     @Override
 117  
     public String toString() {
 118  1
         return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
 119  
     }
 120  
 }