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-2008 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 org.seasar.cubby.exception.PathTemplateParseException;
 19  
 import org.seasar.cubby.routing.PathTemplateParser;
 20  
 
 21  
 /**
 22  
  * パステンプレートのパーサーの実装です。
 23  
  * 
 24  
  * @author baba
 25  
  * @since 1.1.1
 26  
  */
 27  98
 public class PathTemplateParserImpl implements PathTemplateParser {
 28  
 
 29  
         /** プレースホルダの開始文字。 */
 30  
         private static final char OPEN_PLACE_HOLDER = '{';
 31  
 
 32  
         /** プレースホルダの終了文字。 */
 33  
         private static final char CLOSE_PLACE_HOLDER = '}';
 34  
 
 35  
         /** プレースホルダ中のパラメータ名と正規表現の区切り文字。 */
 36  
         private static final char PLACE_HOLDER_SEPARATOR = ',';
 37  
 
 38  
         /** 正規表現のエスケープ文字。 */
 39  
         private static final char REGEXP_ESCAPE = '\\';
 40  
 
 41  
         /**
 42  
          * パース中の状態。
 43  
          * 
 44  
          * @author baba
 45  
          * @since 1.1.1
 46  
          */
 47  98
         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  565
                 final StringBuilder pathRegex = new StringBuilder(100);
 56  565
                 final StringBuilder paramName = new StringBuilder(10);
 57  565
                 final StringBuilder paramRegex = new StringBuilder(10);
 58  
 
 59  565
                 State state = State.NORMAL;
 60  565
                 int braceDepth = 0;
 61  
 
 62  9906
                 for (int i = 0; i < template.length(); i++) {
 63  9345
                         final char c = template.charAt(i);
 64  9345
                         switch (state) {
 65  
                         case NORMAL: {
 66  6824
                                 if (c == OPEN_PLACE_HOLDER) {
 67  374
                                         state = State.PARAM_NAME;
 68  
                                 } else {
 69  6450
                                         pathRegex.append(c);
 70  
                                 }
 71  6450
                                 break;
 72  
                         }
 73  
                         case PARAM_NAME: {
 74  1768
                                 if (c == CLOSE_PLACE_HOLDER) {
 75  258
                                         if (paramName.length() == 0) {
 76  1
                                                 throw new PathTemplateParseException("ECUB0108",
 77  
                                                                 new Object[] { template, i });
 78  
                                         }
 79  257
                                         final String replacement = handler.handle(paramName
 80  
                                                         .toString(), DEFAULT_URI_PARAMETER_REGEX);
 81  257
                                         pathRegex.append(replacement);
 82  
 
 83  257
                                         paramName.setLength(0);
 84  257
                                         state = State.NORMAL;
 85  257
                                 } else if (c == PLACE_HOLDER_SEPARATOR) {
 86  114
                                         state = State.PARAM_REGEX;
 87  
                                 } else {
 88  1396
                                         paramName.append(c);
 89  
                                 }
 90  1396
                                 break;
 91  
                         }
 92  
                         case PARAM_REGEX: {
 93  749
                                 if (c == REGEXP_ESCAPE) {
 94  4
                                         paramRegex.append(c);
 95  4
                                         state = State.PARAM_REGEX_ESCAPE;
 96  745
                                 } else if (c == CLOSE_PLACE_HOLDER && braceDepth == 0) {
 97  112
                                         if (paramName.length() == 0) {
 98  0
                                                 throw new PathTemplateParseException("ECUB0108",
 99  
                                                                 new Object[] { template, i });
 100  
                                         }
 101  112
                                         if (paramRegex.length() == 0) {
 102  1
                                                 throw new PathTemplateParseException("ECUB0109",
 103  
                                                                 new Object[] { template, i });
 104  
                                         }
 105  111
                                         final String replacement = handler.handle(paramName
 106  
                                                         .toString(), paramRegex.toString());
 107  109
                                         pathRegex.append(replacement);
 108  
 
 109  109
                                         paramName.setLength(0);
 110  109
                                         paramRegex.setLength(0);
 111  109
                                         braceDepth = 0;
 112  109
                                         state = State.NORMAL;
 113  109
                                 } else {
 114  633
                                         if (c == OPEN_PLACE_HOLDER) {
 115  1
                                                 braceDepth++;
 116  632
                                         } else if (c == CLOSE_PLACE_HOLDER) {
 117  1
                                                 braceDepth--;
 118  
                                         }
 119  633
                                         paramRegex.append(c);
 120  
                                 }
 121  633
                                 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  561
                 if (state != State.NORMAL) {
 133  4
                         throw new PathTemplateParseException("ECUB0107",
 134  
                                         new Object[] { template });
 135  
                 }
 136  557
                 return pathRegex.toString();
 137  
         }
 138  
 
 139  
 }