1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.springframework.extensions.webscripts;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27
28
29
30
31
32
33
34 public class UriTemplate
35 {
36 private static final Pattern VALID_URI = Pattern.compile("^/(([\\w\\-]+|\\{([a-zA-Z][\\w]*)\\})(;*)/?)+(\\.\\w+$)?|^/$");
37 private static final Pattern VARIABLE = Pattern.compile("\\{([a-zA-Z]\\w*)\\}");
38 private static final String VARIABLE_REGEX = "(.*?)";
39
40 private String template;
41 private Pattern regex;
42 private String[] vars;
43 private int charCnt;
44
45
46
47
48
49
50 public UriTemplate(String template)
51 {
52
53 if (template == null || template.length() == 0)
54 {
55 throw new WebScriptException("URI Template not provided");
56 }
57
58
59 Matcher validMatcher = VALID_URI.matcher(template);
60 if (!validMatcher.matches())
61 {
62 throw new WebScriptException("URI Template malformed: " + template);
63 }
64
65
66
67 StringBuilder templateRegex = new StringBuilder();
68 List<String> names = new ArrayList<String>();
69 int charCnt = 0;
70 int start = 0;
71 int end = 0;
72 Matcher matcher = VARIABLE.matcher(template);
73 while(matcher.find())
74 {
75 end = matcher.start();
76 charCnt += appendTemplate(template, start, end, templateRegex);
77 templateRegex.append(VARIABLE_REGEX);
78 String name = matcher.group(1);
79 names.add(name);
80 start = matcher.end();
81 }
82 charCnt += appendTemplate(template, start, template.length(), templateRegex);
83
84
85 this.template = template;
86 this.charCnt = charCnt;
87 this.regex = Pattern.compile(templateRegex.toString());
88 this.vars = new String[names.size()];
89 names.toArray(this.vars);
90 }
91
92
93
94
95
96
97
98
99
100
101 private int appendTemplate(String template, int start, int end, StringBuilder regex)
102 {
103 for (int i = start; i < end; i++)
104 {
105 char c = template.charAt(i);
106 if ("(.?)".indexOf(c) != -1)
107 {
108 regex.append("\\");
109 }
110 regex.append(c);
111 }
112 return end - start;
113 }
114
115
116
117
118
119
120
121
122 public Map<String, String> match(String uri)
123 {
124 Map<String, String> values = null;
125
126 if (uri != null && uri.length() != 0)
127 {
128 Matcher m = regex.matcher(uri);
129 if (m.matches())
130 {
131 values = new HashMap<String, String>(m.groupCount(), 1.0f);
132 for (int i = 0; i < m.groupCount(); i++)
133 {
134 String name = vars[i];
135 String value = m.group(i + 1);
136
137
138
139
140
141
142 String existingValue = values.get(name);
143 if (existingValue != null && !existingValue.equals(value))
144 {
145 return null;
146 }
147
148 values.put(vars[i], value);
149 }
150 }
151 }
152
153 return values;
154 }
155
156
157
158
159 public String getTemplate()
160 {
161 return template;
162 }
163
164
165
166
167 public Pattern getRegex()
168 {
169 return regex;
170 }
171
172
173
174
175 public String[] getVariableNames()
176 {
177 return vars;
178 }
179
180
181
182
183 public int getStaticCharCount()
184 {
185 return charCnt;
186 }
187
188 @Override
189 public final String toString()
190 {
191 String strVars = "";
192 for (int i = 0; i < vars.length; i++)
193 {
194 strVars += vars[i];
195 if (i < vars.length -1)
196 {
197 strVars += ",";
198 }
199 }
200 return regex.toString() + " (vars=[" + strVars + "])";
201 }
202
203 @Override
204 public final int hashCode()
205 {
206 return regex.hashCode();
207 }
208
209 @Override
210 public final boolean equals(Object obj)
211 {
212 if (!(obj instanceof UriTemplate))
213 {
214 return false;
215 }
216 return regex.equals(((UriTemplate)obj).regex);
217 }
218 }