1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.cubby.routing.impl;
17
18 import static org.seasar.cubby.internal.util.LogMessages.format;
19
20 import org.seasar.cubby.routing.PathTemplateException;
21 import org.seasar.cubby.routing.PathTemplateParser;
22
23
24
25
26
27
28
29 public class PathTemplateParserImpl implements PathTemplateParser {
30
31
32 private static final char OPEN_PLACE_HOLDER = '{';
33
34
35 private static final char CLOSE_PLACE_HOLDER = '}';
36
37
38 private static final char PLACE_HOLDER_SEPARATOR = ',';
39
40
41 private static final char REGEXP_ESCAPE = '\\';
42
43
44
45
46
47
48
49 private enum State {
50 NORMAL, PARAM_NAME, PARAM_REGEX, PARAM_REGEX_ESCAPE;
51 }
52
53
54
55
56 public String parse(final String template, final Handler handler) {
57 final StringBuilder pathRegex = new StringBuilder(100);
58 final StringBuilder paramName = new StringBuilder(10);
59 final StringBuilder paramRegex = new StringBuilder(10);
60
61 State state = State.NORMAL;
62 int braceDepth = 0;
63
64 for (int i = 0; i < template.length(); i++) {
65 final char c = template.charAt(i);
66 switch (state) {
67 case NORMAL: {
68 if (c == OPEN_PLACE_HOLDER) {
69 state = State.PARAM_NAME;
70 } else {
71 pathRegex.append(c);
72 }
73 break;
74 }
75 case PARAM_NAME: {
76 if (c == CLOSE_PLACE_HOLDER) {
77 if (paramName.length() == 0) {
78 throw new PathTemplateException(format("ECUB0108",
79 template, i));
80 }
81 final String replacement = handler.handle(paramName
82 .toString(), DEFAULT_URI_PARAMETER_REGEX);
83 pathRegex.append(replacement);
84
85 paramName.setLength(0);
86 state = State.NORMAL;
87 } else if (c == PLACE_HOLDER_SEPARATOR) {
88 state = State.PARAM_REGEX;
89 } else {
90 paramName.append(c);
91 }
92 break;
93 }
94 case PARAM_REGEX: {
95 if (c == REGEXP_ESCAPE) {
96 paramRegex.append(c);
97 state = State.PARAM_REGEX_ESCAPE;
98 } else if (c == CLOSE_PLACE_HOLDER && braceDepth == 0) {
99 if (paramName.length() == 0) {
100 throw new PathTemplateException(format("ECUB0108",
101 template, i));
102 }
103 if (paramRegex.length() == 0) {
104 throw new PathTemplateException(format("ECUB0109",
105 template, i));
106 }
107 final String replacement = handler.handle(paramName
108 .toString(), paramRegex.toString());
109 pathRegex.append(replacement);
110
111 paramName.setLength(0);
112 paramRegex.setLength(0);
113 braceDepth = 0;
114 state = State.NORMAL;
115 } else {
116 if (c == OPEN_PLACE_HOLDER) {
117 braceDepth++;
118 } else if (c == CLOSE_PLACE_HOLDER) {
119 braceDepth--;
120 }
121 paramRegex.append(c);
122 }
123 break;
124 }
125 case PARAM_REGEX_ESCAPE: {
126 paramRegex.append(c);
127 state = State.PARAM_REGEX;
128 break;
129 }
130 default:
131 throw new IllegalStateException();
132 }
133 }
134 if (state != State.NORMAL) {
135 throw new PathTemplateException(format("ECUB0107", template));
136 }
137 return pathRegex.toString();
138 }
139
140 }