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