##### Coverage Report - org.seasar.cubby.routing.impl.PathTemplateParserImpl

Classes in this File | Line Coverage | Branch Coverage | Complexity
PathTemplateParserImpl |
96% | 51/53
93% | 29/31
| 23.0;23
PathTemplateParserImpl$1 |
100% | 1/1
N/A | N/A
| 23.0;23
PathTemplateParserImpl$State |
100% | 2/2
N/A | N/A
| 23.0;23

1 |  |
     /*
2 |  |
      * Copyright 2004-2009 the Seasar Foundation and the Others.
3 |  |
      *
4 |  |
      * Licensed under the Apache License, Version 2.0 (the "License");
5 |  |
      * you may not use this file except in compliance with the License.
6 |  |
      * You may obtain a copy of the License at
7 |  |
      *
8 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
9 |  |
      *
10 |  |
      * Unless required by applicable law or agreed to in writing, software
11 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
12 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 |  |
      * either express or implied. See the License for the specific language
14 |  |
      * governing permissions and limitations under the License.
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 |  |
      * @author baba
27 |  |
      */
28 | 64 |
     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 |  |
              * @author baba
46 |  |
              */
47 | 64 |
             private enum State {
48 | 1 |
                     NORMAL, PARAM_NAME, PARAM_REGEX, PARAM_REGEX_ESCAPE;
49 |  |
             }
50 |  |
51 |  |
             /**
52 |  |
              * {@inheritDoc}
53 |  |
              */
54 |  |
             public String parse(final String template, final Handler handler) {
55 | 607 |
                     final StringBuilder pathRegex = new StringBuilder(100);
56 | 607 |
                     final StringBuilder paramName = new StringBuilder(10);
57 | 607 |
                     final StringBuilder paramRegex = new StringBuilder(10);
58 |  |
59 | 607 |
                     State state = State.NORMAL;
60 | 607 |
                     int braceDepth = 0;
61 |  |
62 | 10273 |
                     for (int i = 0; i < template.length(); i++) {
63 | 9670 |
                             final char c = template.charAt(i);
64 | 9670 |
                             switch (state) {
65 |  |
                             case NORMAL: {
66 | 6651 |
                                     if (c == OPEN_PLACE_HOLDER) {
67 | 419 |
                                             state = State.PARAM_NAME;
68 |  |
                                     } else {
69 | 6232 |
                                             pathRegex.append(c);
70 |  |
                                     }
71 | 6232 |
                                     break;
72 |  |
                             }
73 |  |
                             case PARAM_NAME: {
74 | 2091 |
                                     if (c == CLOSE_PLACE_HOLDER) {
75 | 278 |
                                             if (paramName.length() == 0) {
76 | 1 |
                                                     throw new PathTemplateException(format("ECUB0108",
77 |  |
                                                                     template, i));
78 |  |
                                             }
79 | 277 |
                                             final String replacement = handler.handle(paramName
80 |  |
                                                             .toString(), DEFAULT_URI_PARAMETER_REGEX);
81 | 277 |
                                             pathRegex.append(replacement);
82 |  |
83 | 277 |
                                             paramName.setLength(0);
84 | 277 |
                                             state = State.NORMAL;
85 | 277 |
                                     } else if (c == PLACE_HOLDER_SEPARATOR) {
86 | 139 |
                                             state = State.PARAM_REGEX;
87 |  |
                                     } else {
88 | 1674 |
                                             paramName.append(c);
89 |  |
                                     }
90 | 1674 |
                                     break;
91 |  |
                             }
92 |  |
                             case PARAM_REGEX: {
93 | 924 |
                                     if (c == REGEXP_ESCAPE) {
94 | 4 |
                                             paramRegex.append(c);
95 | 4 |
                                             state = State.PARAM_REGEX_ESCAPE;
96 | 920 |
                                     } else if (c == CLOSE_PLACE_HOLDER && braceDepth == 0) {
97 | 137 |
                                             if (paramName.length() == 0) {
98 | 0 |
                                                     throw new PathTemplateException(format("ECUB0108",
99 |  |
                                                                     template, i));
100 |  |
                                             }
101 | 137 |
                                             if (paramRegex.length() == 0) {
102 | 1 |
                                                     throw new PathTemplateException(format("ECUB0109",
103 |  |
                                                                     template, i));
104 |  |
                                             }
105 | 136 |
                                             final String replacement = handler.handle(paramName
106 |  |
                                                             .toString(), paramRegex.toString());
107 | 134 |
                                             pathRegex.append(replacement);
108 |  |
109 | 134 |
                                             paramName.setLength(0);
110 | 134 |
                                             paramRegex.setLength(0);
111 | 134 |
                                             braceDepth = 0;
112 | 134 |
                                             state = State.NORMAL;
113 | 134 |
                                     } else {
114 | 783 |
                                             if (c == OPEN_PLACE_HOLDER) {
115 | 1 |
                                                     braceDepth++;
116 | 782 |
                                             } else if (c == CLOSE_PLACE_HOLDER) {
117 | 1 |
                                                     braceDepth--;
118 |  |
                                             }
119 | 783 |
                                             paramRegex.append(c);
120 |  |
                                     }
121 | 783 |
                                     break;
122 |  |
                             }
123 |  |
                             case PARAM_REGEX_ESCAPE: {
124 | 4 |
                                     paramRegex.append(c);
125 | 4 |
                                     state = State.PARAM_REGEX;
126 | 4 |
                                     break;
127 |  |
                             }
128 |  |
                             default:
129 | 0 |
                                     throw new IllegalStateException();
130 |  |
                             }
131 |  |
                     }
132 | 603 |
                     if (state != State.NORMAL) {
133 | 4 |
                             throw new PathTemplateException(format("ECUB0107", template));
134 |  |
                     }
135 | 599 |
                     return pathRegex.toString();
136 |  |
             }
137 |  |
138 |  |
     }