/* * Copyright 2008-2010 the T2 Project ant the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.t2framework.confeito.internal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.t2framework.confeito.util.PatternUtil; /** * <#if locale="en"> * <p> * Utility class of collecting value from url template path. * * This utility helps * {@link org.t2framework.confeito.parameter.ParameterResolver} to resolve * expressions in the annotation which T2 should handle, for example it might be * {@literal @Page} or {@literal @ActionPath}. * </p> * <p> * The usage of this utility is described below: * </p> * * <#else> * <p> * テンプレートURL文字列から、値を取得するためのユーティリティクラスです. * * このユーティリティは主に{@link org.t2framework.confeito.parameter.ParameterResolver} * でT2で扱うべき{@literal @Page}や{@literal @ActionPath}の式言語部分を解釈するのに使用します. * </p> * <p> * このユーティリティの主な使い方は下記のようになります. * </p> * * </#if> * * <pre> * Map<String, String> map = VariablesUtil.createVarMap("{foo}/{bar}?key={hoge}", * "testpath/value1/value2?key=ttt"); * assertEquals("testpath", map.get("{foo}")); * assertEquals("value1/value2", map.get("{bar}")); * assertEquals("ttt", map.get("{hoge}")); * </pre> * * @author c9katayama * @author shot * @since 0.6.0 */ public class VariablesUtil { /** * <#if locale="en"> * <p> * Escape character patterns. * </p> * <#else> * <p> * エスケープすべき文字列のパターンです. * </p> * </#if> */ protected static final String ESCAPED_CHARS = "\\[].^$?*+()|,:<>="; /** * <#if locale="en"> * <p> * T2 variables pattern. * </p> * <#else> * <p> * T2の評価式のパターンです. * </p> * </#if> */ protected static final Pattern VAR_PATTERN = Pattern .compile("(\\{([^}]*)\\})"); /** * <#if locale="en"> * <p> * Minimum pattern :at least one or more length we need. * </p> * <#else> * <p> * 式言語内でマッチすべき1文字以上の正規表現です. * </p> * </#if> */ private static final String VAR_REGEX_PATTERN = "(.+?)"; /** * <#if locale="en"> * <p> * Get {@link Pattern} from possible variable string. * </p> * <#else> * <p> * 式言語の文字列表現から、{@link Pattern}に変換します. * </p> * </#if> * * @param varPattern * @return pattern instance */ public static Pattern toPattern(String varPattern) { Matcher m = VAR_PATTERN.matcher(varPattern); String regex = escapeSpecialChar(varPattern); while (m.find()) { String var = m.group(1); String pat = escapeVarPrefixSuffix(var); regex = regex.replaceFirst(pat, VAR_REGEX_PATTERN); } return PatternUtil.getPattern(regex); } /** * <#if locale="en"> * <p> * Create variable map from pattern and actual value. * </p> * <p> * The key of the map is {key} format and value must not be null. This * method must not return null, and return empty map instead. * </p> * <#else> * <p> * 式言語のキーとURLの該当する文字列を値とするマップを返します. * </p> * <p> * このマップはキーの形式は{key}のようになり、キーがある場合、値がnullになることはありません. * また、このメソッドがnullを返しません.代わりに空のマップを返します. * </p> * </#if> * * @param pattern * @param value * @return pattern map(key:variable name, value:value) */ public static Map<String, String> createVarMap(String pattern, String value) { Matcher m = VAR_PATTERN.matcher(pattern); String regex = escapeSpecialChar(pattern); List<String> varNameList = new ArrayList<String>(); while (m.find()) { String var = m.group(1); String pat = escapeVarPrefixSuffix(var); regex = regex.replaceFirst(pat, VAR_REGEX_PATTERN); varNameList.add(var); } Map<String, String> resultMap = new HashMap<String, String>(); Pattern p = PatternUtil.getPattern(regex); m = p.matcher(value); if (m.matches()) { int groupCount = m.groupCount(); for (int i = 0; i < groupCount; i++) { resultMap.put(varNameList.get(i), m.group(i + 1)); } } return resultMap; } /** * * <#if locale="en"> * <p> * Escape variable key. * </p> * <#else> * <p> * キーをエスケープします. * </p> * </#if> * * @param s * @return */ private static String escapeVarPrefixSuffix(String s) { s = s.substring(1); s = s.substring(0, s.length() - 1); s = escapeSpecialChar(s); return "\\{" + s + "\\}"; } /** * <#if locale="en"> * <p> * Escapape special chatacter. * </p> * <#else> * <p> * 特殊なキャラクタ({@link VariablesUtil#ESCAPED_CHARS})をエスケープします. * </p> * </#if> * * @param s * @return escaped string */ public static String escapeSpecialChar(String s) { if (s == null) { return null; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ESCAPED_CHARS.indexOf(ch) >= 0) { sb.append('\\'); } sb.append(ch); } return sb.toString(); } }