Coverage Report - org.seasar.cubby.routing.impl.PathTemplateParserImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
PathTemplateParserImpl
96%
51/53
94%
29/31
0
PathTemplateParserImpl$1
100%
1/1
N/A
0
PathTemplateParserImpl$State
100%
2/2
N/A
0
 
 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  
  * @since 1.1.1
 28  
  */
 29  192
 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  
          * @author baba
 47  
          * @since 1.1.1
 48  
          */
 49  192
         private enum State {
 50  3
                 NORMAL, PARAM_NAME, PARAM_REGEX, PARAM_REGEX_ESCAPE;
 51  
         }
 52  
 
 53  
         /**
 54  
          * {@inheritDoc}
 55  
          */
 56  
         public String parse(final String template, final Handler handler) {
 57  1815
                 final StringBuilder pathRegex = new StringBuilder(100);
 58  1815
                 final StringBuilder paramName = new StringBuilder(10);
 59  1815
                 final StringBuilder paramRegex = new StringBuilder(10);
 60  
 
 61  1815
                 State state = State.NORMAL;
 62  1815
                 int braceDepth = 0;
 63  
 
 64  30684
                 for (int i = 0; i < template.length(); i++) {
 65  28881
                         final char c = template.charAt(i);
 66  28881
                         switch (state) {
 67  
                         case NORMAL: {
 68  19887
                                 if (c == OPEN_PLACE_HOLDER) {
 69  1251
                                         state = State.PARAM_NAME;
 70  
                                 } else {
 71  18636
                                         pathRegex.append(c);
 72  
                                 }
 73  18636
                                 break;
 74  
                         }
 75  
                         case PARAM_NAME: {
 76  6231
                                 if (c == CLOSE_PLACE_HOLDER) {
 77  831
                                         if (paramName.length() == 0) {
 78  3
                                                 throw new PathTemplateException(format("ECUB0108",
 79  
                                                                 template, i));
 80  
                                         }
 81  828
                                         final String replacement = handler.handle(paramName
 82  
                                                         .toString(), DEFAULT_URI_PARAMETER_REGEX);
 83  828
                                         pathRegex.append(replacement);
 84  
 
 85  828
                                         paramName.setLength(0);
 86  828
                                         state = State.NORMAL;
 87  828
                                 } else if (c == PLACE_HOLDER_SEPARATOR) {
 88  414
                                         state = State.PARAM_REGEX;
 89  
                                 } else {
 90  4986
                                         paramName.append(c);
 91  
                                 }
 92  4986
                                 break;
 93  
                         }
 94  
                         case PARAM_REGEX: {
 95  2751
                                 if (c == REGEXP_ESCAPE) {
 96  12
                                         paramRegex.append(c);
 97  12
                                         state = State.PARAM_REGEX_ESCAPE;
 98  2739
                                 } else if (c == CLOSE_PLACE_HOLDER && braceDepth == 0) {
 99  408
                                         if (paramName.length() == 0) {
 100  0
                                                 throw new PathTemplateException(format("ECUB0108",
 101  
                                                                 template, i));
 102  
                                         }
 103  408
                                         if (paramRegex.length() == 0) {
 104  3
                                                 throw new PathTemplateException(format("ECUB0109",
 105  
                                                                 template, i));
 106  
                                         }
 107  405
                                         final String replacement = handler.handle(paramName
 108  
                                                         .toString(), paramRegex.toString());
 109  399
                                         pathRegex.append(replacement);
 110  
 
 111  399
                                         paramName.setLength(0);
 112  399
                                         paramRegex.setLength(0);
 113  399
                                         braceDepth = 0;
 114  399
                                         state = State.NORMAL;
 115  399
                                 } else {
 116  2331
                                         if (c == OPEN_PLACE_HOLDER) {
 117  3
                                                 braceDepth++;
 118  2328
                                         } else if (c == CLOSE_PLACE_HOLDER) {
 119  3
                                                 braceDepth--;
 120  
                                         }
 121  2331
                                         paramRegex.append(c);
 122  
                                 }
 123  2331
                                 break;
 124  
                         }
 125  
                         case PARAM_REGEX_ESCAPE: {
 126  12
                                 paramRegex.append(c);
 127  12
                                 state = State.PARAM_REGEX;
 128  12
                                 break;
 129  
                         }
 130  
                         default:
 131  0
                                 throw new IllegalStateException();
 132  
                         }
 133  
                 }
 134  1803
                 if (state != State.NORMAL) {
 135  12
                         throw new PathTemplateException(format("ECUB0107", template));
 136  
                 }
 137  1791
                 return pathRegex.toString();
 138  
         }
 139  
 
 140  
 }