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 java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.seasar.cubby.action.ActionErrors;
25  import org.seasar.cubby.action.FieldInfo;
26  
27  /**
28   * アクションエラーの実装クラス
29   * 
30   * @author agata
31   * @author baba
32   */
33  class ActionErrorsImpl implements ActionErrors {
34  
35  	/**
36  	 * 全てのエラーの一覧。
37  	 */
38  	private final List<String> all = new ArrayList<String>();
39  
40  	/**
41  	 * フィールドで発生したエラーの一覧。
42  	 */
43  	private final Map<String, List<String>> fields = new NotNullHashMap<String, List<String>>(
44  			new MessageListEmptyValueFactory());
45  
46  	/**
47  	 * インデックス付きフィールドで発生したエラーの一覧。
48  	 */
49  	private final Map<String, Map<Integer, List<String>>> indexedFields = new NotNullHashMap<String, Map<Integer, List<String>>>(
50  			new IndexMapEmptyValueFactory());
51  
52  	/**
53  	 * フィールド以外で発生したエラーの一覧。
54  	 */
55  	private final List<String> others = new ArrayList<String>();
56  
57  	/**
58  	 * アクションで発生した全てのエラーの一覧を取得します。
59  	 * 
60  	 * @return アクションで発生した全てエラーの一覧
61  	 */
62  	public List<String> getAll() {
63  		return all;
64  	}
65  
66  	/**
67  	 * フィールドで発生したエラーの一覧を取得します。
68  	 * 
69  	 * @return フィールドで発生したエラーの一覧
70  	 */
71  	public Map<String, List<String>> getFields() {
72  		return fields;
73  	}
74  
75  	/**
76  	 * インデックス付きフィールドで発生したエラーの一覧を取得します。
77  	 * 
78  	 * @return インデックス付きフィールドで発生したエラーの一覧
79  	 */
80  	public Map<String, Map<Integer, List<String>>> getIndexedFields() {
81  		return indexedFields;
82  	}
83  
84  	/**
85  	 * フィールド以外で発生したエラーの一覧を取得します。
86  	 * 
87  	 * @return フィールド以外で発生したエラーの一覧
88  	 */
89  	public List<String> getOthers() {
90  		return others;
91  	}
92  
93  	/**
94  	 * エラーが存在しないかどうかを判定します。
95  	 * 
96  	 * @return エラーが存在しなければtrue
97  	 */
98  	public boolean isEmpty() {
99  		return all.isEmpty();
100 	}
101 
102 	/**
103 	 * エラーメッセージを追加します。
104 	 * 
105 	 * @param message
106 	 *            メッセージ
107 	 */
108 	public void add(final String message) {
109 		this.add(message, new FieldInfo[0]);
110 	}
111 
112 	/**
113 	 * エラーメッセージを追加します。
114 	 * 
115 	 * @param message
116 	 *            メッセージ
117 	 * @param fieldNames
118 	 *            フィールド名
119 	 */
120 	public void add(final String message, final String... fieldNames) {
121 		final FieldInfo[] fieldInfos = new FieldInfo[fieldNames.length];
122 		for (int i = 0; i < fieldNames.length; i++) {
123 			fieldInfos[i] = new FieldInfo(fieldNames[i]);
124 		}
125 		this.add(message, fieldInfos);
126 	}
127 
128 	/**
129 	 * エラーメッセージを追加します。
130 	 * 
131 	 * @param message
132 	 *            メッセージ
133 	 * @param fieldInfos
134 	 *            フィールド情報
135 	 */
136 	public void add(final String message, final FieldInfo... fieldInfos) {
137 		if (fieldInfos == null || fieldInfos.length == 0) {
138 			others.add(message);
139 		} else {
140 			for (final FieldInfo fieldInfo : fieldInfos) {
141 				addFields(message, fieldInfo);
142 			}
143 		}
144 		this.all.add(message);
145 	}
146 
147 	private void addFields(final String message, final FieldInfo fieldInfo) {
148 		final String name;
149 		final Integer index;
150 		if (fieldInfo == null) {
151 			name = null;
152 			index = null;
153 		} else {
154 			name = fieldInfo.getName();
155 			index = fieldInfo.getIndex();
156 		}
157 
158 		final List<String> messages = this.fields.get(name);
159 		messages.add(message);
160 
161 		final List<String> indexedMessages = this.indexedFields.get(name).get(
162 				index);
163 		indexedMessages.add(message);
164 	}
165 
166 	private static class NotNullHashMap<K, V> extends HashMap<K, V> {
167 
168 		private static final long serialVersionUID = 1L;
169 
170 		private transient final EmptyValueFactory<V> emptyValueFactory;
171 
172 		private NotNullHashMap(final EmptyValueFactory<V> emptyValueFactory) {
173 			this.emptyValueFactory = emptyValueFactory;
174 		}
175 
176 		/**
177 		 * {@inheritDoc}
178 		 */
179 		@SuppressWarnings("unchecked")
180 		@Override
181 		public V get(final Object key) {
182 			final V value = super.get(key);
183 			if (value != null) {
184 				return value;
185 			}
186 
187 			final V emptyValue = emptyValueFactory.create();
188 			this.put((K) key, emptyValue);
189 			return emptyValue;
190 		}
191 
192 	}
193 
194 	private interface EmptyValueFactory<T> {
195 		/**
196 		 * 空のオブジェクトを生成します。
197 		 * 
198 		 * @return 空のオブジェクト
199 		 */
200 		T create();
201 	}
202 
203 	private static class MessageListEmptyValueFactory implements
204 			EmptyValueFactory<List<String>> {
205 
206 		/**
207 		 * {@inheritDoc}
208 		 */
209 		public List<String> create() {
210 			return new ArrayList<String>();
211 		}
212 
213 	}
214 
215 	private static class IndexMapEmptyValueFactory implements
216 			EmptyValueFactory<Map<Integer, List<String>>> {
217 
218 		/**
219 		 * {@inheritDoc}
220 		 */
221 		public Map<Integer, List<String>> create() {
222 			return new NotNullHashMap<Integer, List<String>>(
223 					new MessageListEmptyValueFactory());
224 		}
225 
226 	}
227 
228 	/**
229 	 * エラーをクリアします。
230 	 */
231 	public void clear() {
232 		this.all.clear();
233 		this.fields.clear();
234 		this.indexedFields.clear();
235 		this.others.clear();
236 	}
237 
238 }