View Javadoc

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