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.controller.impl;
18  
19  import static org.seasar.cubby.action.RequestParameterBindingType.NONE;
20  import static org.seasar.cubby.internal.util.LogMessages.format;
21  
22  import java.lang.reflect.InvocationTargetException;
23  import java.lang.reflect.Method;
24  import java.util.Map;
25  
26  import javax.servlet.http.HttpServletRequest;
27  
28  import org.seasar.cubby.action.Action;
29  import org.seasar.cubby.action.ActionContext;
30  import org.seasar.cubby.action.ActionErrors;
31  import org.seasar.cubby.action.ActionException;
32  import org.seasar.cubby.action.Form;
33  import org.seasar.cubby.action.InitializeMethod;
34  import org.seasar.cubby.action.PostRenderMethod;
35  import org.seasar.cubby.action.PreRenderMethod;
36  import org.seasar.cubby.action.RequestParameterBindingType;
37  import org.seasar.cubby.spi.beans.Attribute;
38  import org.seasar.cubby.spi.beans.BeanDesc;
39  import org.seasar.cubby.spi.beans.BeanDescFactory;
40  
41  /**
42   * アクションのコンテキストの実装です。
43   * 
44   * @author baba
45   */
46  class ActionContextImpl implements ActionContext {
47  
48  	/** アクション。 */
49  	private final Object action;
50  
51  	/** アクションクラス。 */
52  	private final Class<?> actionClass;
53  
54  	/** アクションメソッド。 */
55  	private final Method actionMethod;
56  
57  	/** アクションエラー。 */
58  	private final ActionErrors actionErrors;
59  
60  	/** 揮発性メッセージ。 */
61  	private final Map<String, Object> flashMap;
62  
63  	/**
64  	 * インスタンス化します。
65  	 * 
66  	 * @param request
67  	 *            要求
68  	 * @param action
69  	 *            アクション
70  	 * @param actionClass
71  	 *            アクションクラス
72  	 * @param actionMethod
73  	 *            アクションメソッド
74  	 * @param actionErrors
75  	 *            アクションエラー
76  	 * @param flashMap
77  	 *            揮発性メッセージ
78  	 */
79  	public ActionContextImpl(final HttpServletRequest request,
80  			final Object action, final Class<?> actionClass,
81  			final Method actionMethod, final ActionErrors actionErrors,
82  			final Map<String, Object> flashMap) {
83  		this.action = action;
84  		this.actionClass = actionClass;
85  		this.actionMethod = actionMethod;
86  
87  		this.actionErrors = actionErrors;
88  		this.flashMap = flashMap;
89  
90  		if (action instanceof Action) {
91  			initializeAction((Action) action, actionErrors, flashMap);
92  		}
93  	}
94  
95  	/**
96  	 * アクションを初期化します。
97  	 * 
98  	 * @param action
99  	 *            アクション
100 	 * @param actionErrors
101 	 *            アクションエラー
102 	 * @param flashMap
103 	 *            揮発性マップ
104 	 */
105 	private void initializeAction(final Action action,
106 			final ActionErrors actionErrors, final Map<String, Object> flashMap) {
107 		action.setErrors(actionErrors);
108 		action.setFlash(flashMap);
109 	}
110 
111 	/**
112 	 * {@inheritDoc}
113 	 */
114 	public Object getAction() {
115 		return action;
116 	}
117 
118 	/**
119 	 * {@inheritDoc}
120 	 */
121 	public Class<?> getActionClass() {
122 		return actionClass;
123 	}
124 
125 	/**
126 	 * {@inheritDoc}
127 	 */
128 	public Method getActionMethod() {
129 		return actionMethod;
130 	}
131 
132 	/**
133 	 * {@inheritDoc}
134 	 */
135 	public Object getFormBean() {
136 		final Form form = getForm();
137 		if (form == null) {
138 			return action;
139 		}
140 		if (form.bindingType() == NONE) {
141 			return null;
142 		}
143 		if (Form.THIS.equals(form.value())) {
144 			return action;
145 		}
146 
147 		final String attributeName = form.value();
148 		final Object formBean;
149 		final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(actionClass);
150 		if (beanDesc.hasPropertyAttribute(attributeName)) {
151 			final Attribute attribute = beanDesc
152 					.getPropertyAttribute(attributeName);
153 			formBean = attribute.getValue(action);
154 			if (formBean == null) {
155 				throw new ActionException(format("ECUB0102", actionClass,
156 						attributeName));
157 			}
158 		} else if (beanDesc.hasFieldAttribute(attributeName)) {
159 			final Attribute attribute = beanDesc
160 					.getFieldAttribute(attributeName);
161 			formBean = attribute.getValue(action);
162 			if (formBean == null) {
163 				throw new ActionException(format("ECUB0111", actionClass,
164 						attributeName));
165 			}
166 		} else {
167 			throw new ActionException(format("ECUB0112", actionClass,
168 					attributeName));
169 		}
170 		return formBean;
171 	}
172 
173 	/**
174 	 * 指定されたアクションメソッドを修飾する {@link Form} を取得します。
175 	 * 
176 	 * @return {@link Form}、修飾されていない場合はメソッドが定義されたクラスを修飾する {@link Form}
177 	 *         、クラスも修飾されていない場合は <code>null</code>
178 	 */
179 	private Form getForm() {
180 		final Form form;
181 		if (actionMethod.isAnnotationPresent(Form.class)) {
182 			form = actionMethod.getAnnotation(Form.class);
183 		} else {
184 			form = actionClass.getAnnotation(Form.class);
185 		}
186 		return form;
187 	}
188 
189 	/**
190 	 * {@inheritDoc}
191 	 */
192 	public boolean isBindRequestParameterToAllProperties() {
193 		final Form form = this.getForm();
194 		if (form == null) {
195 			return false;
196 		}
197 
198 		final RequestParameterBindingType type = form.bindingType();
199 		switch (type) {
200 		case ALL_PROPERTIES:
201 			return true;
202 		case ONLY_SPECIFIED_PROPERTIES:
203 			return false;
204 		default:
205 			throw new IllegalStateException(type.toString());
206 		}
207 	}
208 
209 	/**
210 	 * {@inheritDoc}
211 	 */
212 	public void invokeInitializeMethod() {
213 		if (action instanceof Action) {
214 			((Action) action).invokeInitializeMethod(actionMethod);
215 		} else if (actionMethod.isAnnotationPresent(InitializeMethod.class)) {
216 			final InitializeMethod initializeMethod = actionMethod
217 					.getAnnotation(InitializeMethod.class);
218 			final String methodName = initializeMethod.value();
219 			this.invoke(action, methodName);
220 		}
221 	}
222 
223 	/**
224 	 * {@inheritDoc}
225 	 */
226 	public void invokePreRenderMethod() {
227 		if (action instanceof Action) {
228 			((Action) action).invokePreRenderMethod(actionMethod);
229 		} else if (actionMethod.isAnnotationPresent(PreRenderMethod.class)) {
230 			final PreRenderMethod preRenderMethod = actionMethod
231 					.getAnnotation(PreRenderMethod.class);
232 			final String methodName = preRenderMethod.value();
233 			this.invoke(action, methodName);
234 		}
235 	}
236 
237 	/**
238 	 * {@inheritDoc}
239 	 */
240 	public void invokePostRenderMethod() {
241 		if (action instanceof Action) {
242 			((Action) action).invokePostRenderMethod(actionMethod);
243 		} else if (actionMethod.isAnnotationPresent(PostRenderMethod.class)) {
244 			final PostRenderMethod postRenderMethod = actionMethod
245 					.getAnnotation(PostRenderMethod.class);
246 			final String methodName = postRenderMethod.value();
247 			this.invoke(action, methodName);
248 		}
249 	}
250 
251 	/**
252 	 * {@inheritDoc}
253 	 */
254 	public ActionErrors getActionErrors() {
255 		return actionErrors;
256 	}
257 
258 	/**
259 	 * {@inheritDoc}
260 	 */
261 	public Map<String, Object> getFlashMap() {
262 		return flashMap;
263 	}
264 
265 	/**
266 	 * {@inheritDoc}
267 	 */
268 	public void clearFlash() {
269 		if (flashMap != null) {
270 			flashMap.clear();
271 		}
272 	}
273 
274 	/**
275 	 * アクションの指定されたメソッド名のメソッドを実行します。
276 	 * 
277 	 * @param methodName
278 	 *            メソッド名
279 	 */
280 	private void invoke(final Object action, final String methodName) {
281 		try {
282 			final Method method = action.getClass().getMethod(methodName);
283 			method.invoke(action);
284 		} catch (final NoSuchMethodException e) {
285 			throw new ActionException(e);
286 		} catch (final IllegalAccessException e) {
287 			throw new ActionException(e);
288 		} catch (final InvocationTargetException e) {
289 			throw new ActionException(e);
290 		}
291 	}
292 
293 	/**
294 	 * {@inheritDoc}
295 	 */
296 	@Override
297 	public String toString() {
298 		final StringBuilder builder = new StringBuilder();
299 		builder.append("ActionContext[");
300 		builder.append("action=").append(action);
301 		builder.append(",actionClass=").append(actionClass);
302 		builder.append(",actionMethod=").append(actionMethod);
303 		builder.append("]");
304 		return builder.toString();
305 	}
306 
307 }