1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.javagen.agile.core.util;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 /***
24 * Itererates through a list of regular expressions and applies a replacement string when a match is found.
25 * <p>
26 * Currently only applies the first match found, ingnoring any remaining regex's in the list.
27 * <p>
28 * Regex and replacePatterns can be set as a single property string or added individually by calling
29 * <code>addReplacementPattern</code>.
30 * <p>For example to add a regex to remove 'Fk' & 'Pk' suffixes from a name such as <code>'PersonPk'</code>,
31 * you can call either:
32 * <pre>addReplacementPattern("^([a-zA-Z]+)(Fk|Pk)$", "$1")</pre>
33 * or
34 * <pre>setRegexReplacePairs("^([a-zA-Z]+)(Fk|Pk)$>$1")</pre>
35 * <p>As a single string property the general form of the list is: regex1>replace1,regex2>replace2,...
36 * <p>The replacePattern can be any text interspersed with regex group
37 * replacement holders of the form $n, for example: text$1text$3text
38 *
39 * @author Richard Easterling
40 */
41 public class RegexRenamer {
42
43 /***
44 * Defines the (property file friendly) key-value structure of regex-replacement pairs.
45 * example: regex1>replace1,regex2>replace2
46 */
47 private static Pattern keyValuePattern = Pattern.compile("([^>]+)>([^,]+),?");
48
49 /***
50 * Used internally for parsing replacement pattern containing regex group indexes
51 * example: text${2}text${4}text
52 */
53 private static Pattern replacePattern = Pattern.compile("//$([0-9])");
54
55 private List<PatternHolder> patternHolders = new ArrayList<PatternHolder>();
56
57
58
59
60
61 public String rename(String name) {
62 if (patternHolders.size()>0) {
63 for(PatternHolder patternHolder : patternHolders) {
64 String newName = patternHolder.match(name);
65 if (newName!=null)
66 return newName;
67 }
68 }
69 return null;
70 }
71
72
73
74
75
76 /***
77 * Property file friendly means of adding regex-replacePattern pairs as comma-delineated list.
78 * <p>general form of the list: regex1>replace1,regex2>replace2,...
79 * <p>regex can be any regular expression excluding the > symbol.
80 * <p>The replacePattern can be any text interspersed with regex group
81 * replacement holders of the form $n, for example: text$1text$3text
82 * <p>For example to remove 'Fk' & 'Pk' suffixes use: ^([a-zA-Z]+)(Fk|Pk)$>$1
83 */
84 public void setRegexReplacePairs(String replacePatterns) {
85 Matcher matcher = keyValuePattern.matcher(replacePatterns);
86 while (matcher.find()) {
87 String regex = matcher.group(1).trim();
88 String replace = matcher.group(2).trim();
89 addReplacementPattern(regex, replace);
90 }
91 }
92
93 public void addReplacementPattern(String regex, String replacementPattern) {
94 patternHolders.add( new PatternHolder(regex, replacementPattern) );
95 }
96
97 public List<PatternHolder> getPatternHolders() {
98 return patternHolders;
99 }
100
101 public boolean isEmpty() {
102 return patternHolders==null ? true : patternHolders.isEmpty();
103 }
104
105
106
107
108
109 private static class PatternHolder {
110 public Pattern pattern;
111 public String replace;
112
113 public PatternHolder(String regex, String replace) {
114 pattern = Pattern.compile(regex);
115 this.replace = replace;
116 }
117
118 public String match(String name) {
119 Matcher matcher = pattern.matcher(name);
120 if (matcher.matches()) {
121 return replace(matcher, replace);
122 } else {
123 return null;
124 }
125 }
126
127 public String replace(Matcher matcher, String resultPattern) {
128 if ("${1}".equals(resultPattern) && matcher.groupCount()>0)
129 return matcher.group(1);
130 Matcher resultMatcher = replacePattern.matcher(resultPattern);
131 StringBuilder str = new StringBuilder();
132 int pos = 0;
133 while (resultMatcher.find()) {
134 if (resultMatcher.start()>pos) {
135 String prefix = resultPattern.substring(pos, resultMatcher.start());
136 str.append(prefix);
137 }
138 pos = resultMatcher.end();
139 String indexStr = resultMatcher.group(1);
140 int index = Integer.parseInt( indexStr );
141 if (index>matcher.groupCount())
142 throw new IndexOutOfBoundsException("group index "+index+" exceeds groups in regex "+pattern.toString());
143 String group = matcher.group(index);
144 str.append(group);
145 }
146 if (resultPattern.length()>pos) {
147 String suffix = resultPattern.substring(pos);
148 str.append(suffix);
149 }
150 if (str.length()==0) {
151 return null;
152 } else {
153 return str.toString();
154 }
155 }
156 }
157
158 }