1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.batch.support;
17
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Comparator;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.springframework.util.Assert;
26
27
28
29
30
31 public class PatternMatcher<S> {
32
33 private Map<String, S> map = new HashMap<String, S>();
34 private List<String> sorted = new ArrayList<String>();
35
36
37
38
39
40 public PatternMatcher(Map<String, S> map) {
41 super();
42 this.map = map;
43
44 sorted = new ArrayList<String>(map.keySet());
45 Collections.sort(sorted, new Comparator<String>() {
46 @Override
47 public int compare(String o1, String o2) {
48 String s1 = o1;
49 String s2 = o2;
50 return s2.compareTo(s1);
51 }
52 });
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public static boolean match(String pattern, String str) {
69 char[] patArr = pattern.toCharArray();
70 char[] strArr = str.toCharArray();
71 int patIdxStart = 0;
72 int patIdxEnd = patArr.length - 1;
73 int strIdxStart = 0;
74 int strIdxEnd = strArr.length - 1;
75 char ch;
76
77 boolean containsStar = pattern.contains("*");
78
79 if (!containsStar) {
80
81 if (patIdxEnd != strIdxEnd) {
82 return false;
83 }
84 for (int i = 0; i <= patIdxEnd; i++) {
85 ch = patArr[i];
86 if (ch != '?') {
87 if (ch != strArr[i]) {
88 return false;
89 }
90 }
91 }
92 return true;
93 }
94
95 if (patIdxEnd == 0) {
96 return true;
97 }
98
99
100 while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
101 if (ch != '?') {
102 if (ch != strArr[strIdxStart]) {
103 return false;
104 }
105 }
106 patIdxStart++;
107 strIdxStart++;
108 }
109 if (strIdxStart > strIdxEnd) {
110
111
112 for (int i = patIdxStart; i <= patIdxEnd; i++) {
113 if (patArr[i] != '*') {
114 return false;
115 }
116 }
117 return true;
118 }
119
120
121 while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
122 if (ch != '?') {
123 if (ch != strArr[strIdxEnd]) {
124 return false;
125 }
126 }
127 patIdxEnd--;
128 strIdxEnd--;
129 }
130 if (strIdxStart > strIdxEnd) {
131
132
133 for (int i = patIdxStart; i <= patIdxEnd; i++) {
134 if (patArr[i] != '*') {
135 return false;
136 }
137 }
138 return true;
139 }
140
141
142
143 while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
144 int patIdxTmp = -1;
145 for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
146 if (patArr[i] == '*') {
147 patIdxTmp = i;
148 break;
149 }
150 }
151 if (patIdxTmp == patIdxStart + 1) {
152
153 patIdxStart++;
154 continue;
155 }
156
157
158 int patLength = (patIdxTmp - patIdxStart - 1);
159 int strLength = (strIdxEnd - strIdxStart + 1);
160 int foundIdx = -1;
161 strLoop: for (int i = 0; i <= strLength - patLength; i++) {
162 for (int j = 0; j < patLength; j++) {
163 ch = patArr[patIdxStart + j + 1];
164 if (ch != '?') {
165 if (ch != strArr[strIdxStart + i + j]) {
166 continue strLoop;
167 }
168 }
169 }
170
171 foundIdx = strIdxStart + i;
172 break;
173 }
174
175 if (foundIdx == -1) {
176 return false;
177 }
178
179 patIdxStart = patIdxTmp;
180 strIdxStart = foundIdx + patLength;
181 }
182
183
184
185 for (int i = patIdxStart; i <= patIdxEnd; i++) {
186 if (patArr[i] != '*') {
187 return false;
188 }
189 }
190
191 return true;
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 public S match(String line) {
214
215 S value = null;
216 Assert.notNull(line, "A non-null key must be provided to match against.");
217
218 for (String key : sorted) {
219 if (PatternMatcher.match(key, line)) {
220 value = map.get(key);
221 break;
222 }
223 }
224
225 if (value == null) {
226 throw new IllegalStateException("Could not find a matching pattern for key=[" + line + "]");
227 }
228 return value;
229
230 }
231
232 }