1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
31
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
61
62 public List<String> getAll() {
63 return all;
64 }
65
66
67
68
69
70
71 public Map<String, List<String>> getFields() {
72 return fields;
73 }
74
75
76
77
78
79
80 public Map<String, Map<Integer, List<String>>> getIndexedFields() {
81 return indexedFields;
82 }
83
84
85
86
87
88
89 public List<String> getOthers() {
90 return others;
91 }
92
93
94
95
96
97
98 public boolean isEmpty() {
99 return all.isEmpty();
100 }
101
102
103
104
105
106
107
108 public void add(final String message) {
109 this.add(message, new FieldInfo[0]);
110 }
111
112
113
114
115
116
117
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
132
133
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
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
199
200 T create();
201 }
202
203 private static class MessageListEmptyValueFactory implements
204 EmptyValueFactory<List<String>> {
205
206
207
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
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 }