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