##### Coverage Report - org.jbehave.core.parsers.RegexPrefixCapturingPatternParser

Classes in this File | Line Coverage | Branch Coverage | Complexity
RegexPrefixCapturingPatternParser |
100% | 32/32
100% | 6/6
| 1.2307692307692308;1.231
RegexPrefixCapturingPatternParser$Parameter |
100% | 7/7
N/A | N/A
| 1.2307692307692308;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 | 142 |
     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 | 685 |
                     this("$");
29 | 685 |
             }
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 | 686 |
             public RegexPrefixCapturingPatternParser(String prefix) {
38 | 686 |
                     this.prefix = prefix;
39 | 686 |
             }
40 |  |
41 |  |
             public String getPrefix(){
42 | 1 |
                 return prefix;
43 |  |
             }
44 |  |
45 |  |
             public StepMatcher parseStep(StepType stepType, String stepPattern) {
46 | 123 |
                     return new RegexStepMatcher(stepType, stepPattern,
47 |  |
                                     buildPattern(stepPattern), extractParameterNames(stepPattern));
48 |  |
             }
49 |  |
50 |  |
             private Pattern buildPattern(String stepPattern) {
51 | 123 |
                     String matchThisButLeaveBrackets = escapeRegexPunctuation(stepPattern);
52 | 123 |
                     String patternToMatchAgainst = replaceParametersWithCapture(
53 |  |
                                     matchThisButLeaveBrackets, findParametersToReplace(matchThisButLeaveBrackets));
54 | 123 |
                     String matchThisButIgnoreWhitespace = anyWhitespaceWillDo(patternToMatchAgainst);
55 | 123 |
                     return Pattern.compile(matchThisButIgnoreWhitespace, Pattern.DOTALL);
56 |  |
             }
57 |  |
58 |  |
         private String escapeRegexPunctuation(String matchThis) {
59 | 123 |
             return matchThis.replaceAll("([\\[\\]\\{\\}\\?\\^\\.\\*\\(\\)\\+\\\\])", "\\\\$1");
60 |  |
         }
61 |  |
62 |  |
             private String anyWhitespaceWillDo(String matchThis) {
63 | 123 |
                     return matchThis.replaceAll("\\s+", "\\\\s+");
64 |  |
             }
65 |  |
66 |  |
             private String[] extractParameterNames(String stepPattern) {
67 | 123 |
                     List<String> names = new ArrayList<String>();
68 | 123 |
                     for (Parameter parameter : findParametersToReplace(stepPattern)) {
69 | 71 |
                             names.add(parameter.name);
70 |  |
                     }
71 | 123 |
                     return names.toArray(new String[names.size()]);
72 |  |
             }
73 |  |
74 |  |
         private List<Parameter> findParametersToReplace(String matchThisButLeaveBrackets) {
75 | 246 |
             List<Parameter> parameters = new ArrayList<Parameter>();
76 | 246 |
             Matcher findingAllPrefixedWords = findAllPrefixedWords().matcher(matchThisButLeaveBrackets);
77 | 388 |
             while (findingAllPrefixedWords.find()) {
78 | 142 |
                 parameters.add(new Parameter(matchThisButLeaveBrackets, findingAllPrefixedWords.start(),
79 |  |
                         findingAllPrefixedWords.end(), findingAllPrefixedWords.group(2)));
80 |  |
             }
81 | 246 |
             return parameters;
82 |  |
         }
83 |  |
84 |  |
         private Pattern findAllPrefixedWords() {
85 | 246 |
             return Pattern.compile("(\\" + prefix + "\\w*)(\\W|\\Z)", Pattern.DOTALL);
86 |  |
         }
87 |  |
88 |  |
             private String replaceParametersWithCapture(String escapedMatch,
89 |  |
                             List<Parameter> parameters) {
90 | 123 |
             String replaced = escapedMatch;
91 | 194 |
             for (int i = parameters.size(); i > 0; i--) {
92 | 71 |
                 String start = replaced.substring(0, parameters.get(i - 1).start);
93 | 71 |
                 String end = replaced.substring(parameters.get(i - 1).end);
94 | 71 |
                 String whitespaceIfAny = parameters.get(i - 1).whitespaceIfAny;
95 | 71 |
                 replaced = start + "(.*)" + whitespaceIfAny + end;
96 |  |
             }
97 | 123 |
             return replaced;
98 |  |
             }
99 |  |
100 | 284 |
             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 | 142 |
                                     String whitespaceIfAny) {
108 | 142 |
                             this.start = start;
109 | 142 |
                             this.end = end;
110 | 142 |
                             this.whitespaceIfAny = whitespaceIfAny;
111 | 142 |
                             this.name = pattern.substring(start + prefix.length(), end - whitespaceIfAny.length()).trim();
112 | 142 |
                     }
113 |  |
114 |  |
             }
115 |  |
116 |  |
         @Override
117 |  |
         public String toString() {
118 | 1 |
             return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
119 |  |
         }
120 |  |
     }