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.controller.impl;
17  
18  import java.lang.reflect.Array;
19  import java.util.Collection;
20  
21  import org.seasar.cubby.action.RequestParameter;
22  import org.seasar.cubby.converter.ConversionHelper;
23  import org.seasar.cubby.converter.Converter;
24  import org.seasar.cubby.converter.impl.ConversionHelperImpl;
25  import org.seasar.cubby.internal.controller.FormWrapper;
26  import org.seasar.cubby.internal.controller.FormWrapperFactory;
27  import org.seasar.cubby.spi.ConverterProvider;
28  import org.seasar.cubby.spi.ProviderFactory;
29  import org.seasar.cubby.spi.beans.BeanDesc;
30  import org.seasar.cubby.spi.beans.BeanDescFactory;
31  import org.seasar.cubby.spi.beans.PropertyDesc;
32  
33  /**
34   * フォームオブジェクトのラッパーファクトリの実装です。
35   * 
36   * @author baba
37   * @since 1.1.0
38   */
39  public class FormWrapperFactoryImpl implements FormWrapperFactory {
40  
41  	/** 変換のヘルパクラス。 */
42  	private final ConversionHelper conversionHelper = new ConversionHelperImpl();
43  
44  	/**
45  	 * {@inheritDoc}
46  	 */
47  	public FormWrapper create(final Object form) {
48  		final FormWrapper formObject = new FormWrapperImpl(form);
49  		return formObject;
50  	}
51  
52  	/**
53  	 * フォームオブジェクトのラッパーの実装です。
54  	 * 
55  	 * @author baba
56  	 * @since 1.1.0
57  	 */
58  	private class FormWrapperImpl implements FormWrapper {
59  
60  		/** フォームオブジェクト */
61  		private final Object form;
62  
63  		/**
64  		 * インスタンス化します。
65  		 * 
66  		 * @param form
67  		 *            フォームオブジェクト
68  		 * @param context
69  		 *            変換中のコンテキスト
70  		 */
71  		private FormWrapperImpl(final Object form) {
72  			this.form = form;
73  		}
74  
75  		/**
76  		 * {@inheritDoc}
77  		 */
78  		public boolean hasValues(final String name) {
79  			if (this.form == null) {
80  				return false;
81  			}
82  			final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(this.form
83  					.getClass());
84  			final PropertyDesc propertyDesc = findPropertyDesc(beanDesc, name);
85  			return propertyDesc != null;
86  		}
87  
88  		/**
89  		 * {@inheritDoc}
90  		 */
91  		public String[] getValues(final String name) {
92  			if (this.form == null) {
93  				return null;
94  			}
95  			final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(this.form
96  					.getClass());
97  			final PropertyDesc propertyDesc = findPropertyDesc(beanDesc, name);
98  			if (propertyDesc == null) {
99  				return null;
100 			}
101 			final Object value = propertyDesc.getValue(this.form);
102 			if (value == null) {
103 				return null;
104 			} else if (value instanceof String[]) {
105 				return (String[]) value;
106 			} else {
107 				final Class<? extends Converter> converterType;
108 				if (propertyDesc.isAnnotationPresent(RequestParameter.class)) {
109 					final RequestParameter requestParameter = propertyDesc
110 							.getAnnotation(RequestParameter.class);
111 					if (Converter.class.equals(requestParameter.converter())) {
112 						converterType = null;
113 					} else {
114 						converterType = requestParameter.converter();
115 					}
116 				} else {
117 					converterType = null;
118 				}
119 				if (value.getClass().isArray()) {
120 					final int length = Array.getLength(value);
121 					final String[] array = (String[]) Array.newInstance(
122 							String.class, length);
123 					for (int i = 0; i < length; i++) {
124 						final Object element = Array.get(value, i);
125 						final String converted = convert(element, converterType);
126 						Array.set(array, i, converted);
127 					}
128 					return array;
129 				} else if (value instanceof Collection) {
130 					final Collection<?> collection = (Collection<?>) value;
131 					final String[] array = (String[]) Array.newInstance(
132 							String.class, collection.size());
133 					int i = 0;
134 					for (final Object element : collection) {
135 						final String converted = convert(element, converterType);
136 						Array.set(array, i++, converted);
137 					}
138 					return array;
139 				} else {
140 					final String[] array = (String[]) Array.newInstance(
141 							String.class, 1);
142 					final String converted = convert(value, converterType);
143 					Array.set(array, 0, converted);
144 					return array;
145 				}
146 			}
147 		}
148 
149 		/**
150 		 * 指定された名前に対応するプロパティを検索します。
151 		 * 
152 		 * @param beanDesc
153 		 *            Java Beans の定義
154 		 * @param name
155 		 *            名前
156 		 * @return プロパティの定義
157 		 */
158 		private PropertyDesc findPropertyDesc(final BeanDesc beanDesc,
159 				final String name) {
160 			for (final PropertyDesc propertyDesc : beanDesc.getPropertyDescs()) {
161 				if (propertyDesc.isAnnotationPresent(RequestParameter.class)) {
162 					final RequestParameter requestParameter = propertyDesc
163 							.getAnnotation(RequestParameter.class);
164 					final String parameterName = requestParameter.name();
165 					if (parameterName == null || parameterName.length() == 0) {
166 						if (name.equals(propertyDesc.getPropertyName())) {
167 							return propertyDesc;
168 						}
169 					} else {
170 						if (name.equals(parameterName)) {
171 							return propertyDesc;
172 						}
173 					}
174 				} else {
175 					if (name.equals(propertyDesc.getPropertyName())) {
176 						return propertyDesc;
177 					}
178 				}
179 			}
180 			return null;
181 		}
182 
183 		/**
184 		 * 指定されたオブジェクトを文字列に変換します。
185 		 * 
186 		 * @param value
187 		 *            値
188 		 * @param converterType
189 		 *            コンバータの型
190 		 * @return <code>value</code>を変換した文字列
191 		 */
192 		private String convert(final Object value,
193 				final Class<? extends Converter> converterType) {
194 			if (value == null) {
195 				return null;
196 			}
197 			final ConverterProvider converterProvider = ProviderFactory
198 					.get(ConverterProvider.class);
199 			final Converter converter;
200 			if (converterType == null) {
201 				converter = converterProvider.getConverter(null, value
202 						.getClass());
203 			} else {
204 				converter = converterProvider.getConverter(converterType);
205 			}
206 			if (converter == null) {
207 				return value.toString();
208 			} else {
209 				return converter.convertToString(value, conversionHelper);
210 			}
211 		}
212 
213 	}
214 }