View Javadoc

1   /*
2    * Copyright 2004-2010 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  
17  package org.seasar.cubby.internal.util;
18  
19  import java.lang.reflect.Method;
20  
21  import org.seasar.cubby.action.Accept;
22  import org.seasar.cubby.action.OnSubmit;
23  import org.seasar.cubby.action.Path;
24  import org.seasar.cubby.action.RequestMethod;
25  
26  /**
27   * アクションのメタ情報を扱うためのユーティリティクラスです。
28   * 
29   * @author baba
30   */
31  public class MetaUtils {
32  
33  	/** インデックスのメソッド名。 */
34  	private static final String INDEX_METHOD_NAME = "index";
35  
36  	/** デフォルトの{@link Accept}アノテーション。 */
37  	private static final Accept DEFAULT_ACCEPT_ANNOTATION;
38  	static {
39  		@Accept
40  		class AcceptDummy {
41  		}
42  		DEFAULT_ACCEPT_ANNOTATION = AcceptDummy.class
43  				.getAnnotation(Accept.class);
44  	}
45  
46  	/**
47  	 * 指定されたアクションクラスに対応するディレクトリを取得します。
48  	 * 
49  	 * @param actionClass
50  	 *            アクションクラス
51  	 * @return アクションクラスに対応するディレクトリ
52  	 */
53  	public static String getActionDirectory(final Class<?> actionClass) {
54  		final String actionName;
55  		final Path path = actionClass.getAnnotation(Path.class);
56  		if (path != null && !StringUtils.isEmpty(path.value())) {
57  			actionName = path.value();
58  		} else {
59  			final String name = left(actionClass.getSimpleName(), "$");
60  			actionName = toFirstLower(name.replaceAll(
61  					"(.*[.])*([^.]+)(Action$)", "$2"));
62  		}
63  		return actionName;
64  	}
65  
66  	/**
67  	 * 指定された文字列をセパレータで区切った左側の文字列を返します。
68  	 * 
69  	 * @param text
70  	 *            文字列
71  	 * @param sep
72  	 *            セパレータ
73  	 * @return セパレータで区切った左側の文字列
74  	 */
75  	private static String left(final String text, final String sep) {
76  		final int pos = text.indexOf(sep);
77  		if (pos != -1) {
78  			return text.substring(0, pos);
79  		}
80  		return text;
81  	}
82  
83  	/**
84  	 * 指定された文字列の先頭1文字を小文字に変換します。
85  	 * 
86  	 * @param text
87  	 *            変換する文字列
88  	 * @return 先頭1文字を小文字にした文字列
89  	 */
90  	private static String toFirstLower(final String text) {
91  		if (StringUtils.isEmpty(text)) {
92  			throw new IllegalArgumentException("text is empty.");
93  		}
94  		final StringBuilder sb = new StringBuilder();
95  		sb.append(text.substring(0, 1).toLowerCase());
96  		if (text.length() > 1) {
97  			sb.append(text.substring(1));
98  		}
99  		return sb.toString();
100 	}
101 
102 	/**
103 	 * 指定されたアクションメソッドのパスを取得します。
104 	 * 
105 	 * @param actionClass
106 	 *            アクションクラス
107 	 * @param method
108 	 *            アクションメソッド
109 	 * @return アクションメソッドのパス
110 	 */
111 	public static String getActionPath(final Class<?> actionClass,
112 			final Method method) {
113 		final String path;
114 		final String actionMethodName = getActionMethodName(method);
115 		if (actionMethodName.startsWith("/")) {
116 			path = actionMethodName;
117 		} else {
118 			final String actionDirectory = getActionDirectory(actionClass);
119 			if ("/".equals(actionDirectory)) {
120 				path = "/" + actionMethodName;
121 			} else {
122 				path = "/" + actionDirectory + "/" + actionMethodName;
123 			}
124 		}
125 		return path;
126 	}
127 
128 	/**
129 	 * 指定されたアクションメソッドのアクションメソッド名を取得します。
130 	 * 
131 	 * @param method
132 	 *            アクションメソッド
133 	 * @return アクションメソッド名
134 	 */
135 	private static String getActionMethodName(final Method method) {
136 		final String actionName;
137 		final Path path = method.getAnnotation(Path.class);
138 		if (path != null && !StringUtils.isEmpty(path.value())) {
139 			if ("/".equals(path.value())) {
140 				actionName = "";
141 			} else {
142 				actionName = path.value();
143 			}
144 		} else {
145 			final String methodName = method.getName();
146 			if (INDEX_METHOD_NAME.equals(methodName)) {
147 				actionName = "";
148 			} else {
149 				actionName = methodName;
150 			}
151 		}
152 		return actionName;
153 	}
154 
155 	/**
156 	 * 指定されたアクションメソッドが受付可能な要求メソッドを取得します。
157 	 * 
158 	 * @param actionClass
159 	 *            アクションクラス
160 	 * @param method
161 	 *            アクションメソッド
162 	 * @return 受付可能な要求メソッド
163 	 */
164 	public static RequestMethod[] getAcceptableRequestMethods(
165 			final Class<?> actionClass, final Method method) {
166 		final Accept accept;
167 		if (method.isAnnotationPresent(Accept.class)) {
168 			accept = method.getAnnotation(Accept.class);
169 		} else if (actionClass.isAnnotationPresent(Accept.class)) {
170 			accept = actionClass.getAnnotation(Accept.class);
171 		} else {
172 			accept = DEFAULT_ACCEPT_ANNOTATION;
173 		}
174 		return accept.value();
175 	}
176 
177 	/**
178 	 * アクションメソッドの{@link Path}アノテーションから優先度を取得します。
179 	 * 
180 	 * @param method
181 	 *            アクションメソッド
182 	 * @return 優先度。メソッドに{@link Path}アノテーションが設定されていない場合{@link Integer#MAX_VALUE}
183 	 */
184 	public static int getPriority(final Method method) {
185 		final Path path = method.getAnnotation(Path.class);
186 		return path != null ? path.priority() : Integer.MAX_VALUE;
187 	}
188 
189 	/**
190 	 * 指定されたアクションメソッドを使用することを判断するためのパラメータ名を取得します。
191 	 * <p>
192 	 * パラメータ名によらずに実行する場合は <code>null</code> を返します。
193 	 * </p>
194 	 * 
195 	 * @param method
196 	 *            アクションメソッド
197 	 * @return パラメータ名
198 	 */
199 	public static String getOnSubmit(final Method method) {
200 		final OnSubmit onSubmit = method.getAnnotation(OnSubmit.class);
201 		final String parameterName;
202 		if (onSubmit == null) {
203 			parameterName = null;
204 		} else {
205 			parameterName = onSubmit.value();
206 		}
207 		return parameterName;
208 	}
209 
210 }