View Javadoc

1   /*
2    * Copyright 2004-2008 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   * @since 1.0.0
32   */
33  public 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 = fieldInfo == null ? null : fieldInfo.getName();
149 		final Integer index = fieldInfo == null ? null : fieldInfo.getIndex();
150 
151 		final List<String> messages = this.fields.get(name);
152 		messages.add(message);
153 
154 		final List<String> indexedMessages = this.indexedFields.get(name).get(
155 				index);
156 		indexedMessages.add(message);
157 	}
158 
159 	private static class NotNullHashMap<K, V> extends HashMap<K, V> {
160 
161 		private static final long serialVersionUID = 1L;
162 
163 		private final EmptyValueFactory<V> emptyValueFactory;
164 
165 		private NotNullHashMap(EmptyValueFactory<V> emptyValueFactory) {
166 			this.emptyValueFactory = emptyValueFactory;
167 		}
168 
169 		/**
170 		 * {@inheritDoc}
171 		 */
172 		@SuppressWarnings("unchecked")
173 		@Override
174 		public V get(final Object key) {
175 			final V value = super.get(key);
176 			if (value != null) {
177 				return value;
178 			}
179 
180 			final V emptyValue = emptyValueFactory.create();
181 			this.put((K) key, emptyValue);
182 			return emptyValue;
183 		}
184 
185 	}
186 
187 	private interface EmptyValueFactory<T> {
188 		/**
189 		 * 空のオブジェクトを生成します。
190 		 * 
191 		 * @return 空のオブジェクト
192 		 */
193 		T create();
194 	}
195 
196 	private static class MessageListEmptyValueFactory implements
197 			EmptyValueFactory<List<String>> {
198 
199 		/**
200 		 * {@inheritDoc}
201 		 */
202 		public List<String> create() {
203 			return new ArrayList<String>();
204 		}
205 
206 	}
207 
208 	private static class IndexMapEmptyValueFactory implements
209 			EmptyValueFactory<Map<Integer, List<String>>> {
210 
211 		/**
212 		 * {@inheritDoc}
213 		 */
214 		public Map<Integer, List<String>> create() {
215 			return new NotNullHashMap<Integer, List<String>>(
216 					new MessageListEmptyValueFactory());
217 		}
218 
219 	}
220 
221 	/**
222 	 * エラーをクリアします。
223 	 */
224 	public void clear() {
225 		this.all.clear();
226 		this.fields.clear();
227 		this.indexedFields.clear();
228 		this.others.clear();
229 	}
230 
231 }