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