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
PathTemplateParserImpl$1
100%
1/1
N/A
23
PathTemplateParserImpl$State
100%
2/2
N/A
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  
 }