1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.beanutils2;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Objects;
26 import java.util.Set;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public abstract class BaseDynaBeanMapDecorator<K> implements Map<K, Object> {
51
52
53
54
55 private static final class MapEntry<K> implements Map.Entry<K, Object> {
56
57 private final K key;
58 private final Object value;
59
60 MapEntry(final K key, final Object value) {
61 this.key = key;
62 this.value = value;
63 }
64
65 @Override
66 public boolean equals(final Object obj) {
67 if (this == obj) {
68 return true;
69 }
70 if (!(obj instanceof Map.Entry)) {
71 return false;
72 }
73 final Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
74 return Objects.equals(key, other.getKey()) && Objects.equals(value, other.getValue());
75 }
76
77 @Override
78 public K getKey() {
79 return key;
80 }
81
82 @Override
83 public Object getValue() {
84 return value;
85 }
86
87 @Override
88 public int hashCode() {
89 return Objects.hash(key, value);
90 }
91
92 @Override
93 public Object setValue(final Object value) {
94 throw new UnsupportedOperationException();
95 }
96 }
97
98 private final DynaBean dynaBean;
99 private final boolean readOnly;
100
101 private transient Set<K> keySet;
102
103
104
105
106
107
108
109 public BaseDynaBeanMapDecorator(final DynaBean dynaBean) {
110 this(dynaBean, true);
111 }
112
113
114
115
116
117
118
119
120 public BaseDynaBeanMapDecorator(final DynaBean dynaBean, final boolean readOnly) {
121 this.dynaBean = Objects.requireNonNull(dynaBean, "dynaBean");
122 this.readOnly = readOnly;
123 }
124
125
126
127
128
129
130 @Override
131 public void clear() {
132 throw new UnsupportedOperationException();
133 }
134
135
136
137
138
139
140
141 @Override
142 public boolean containsKey(final Object key) {
143 final DynaClass dynaClass = getDynaBean().getDynaClass();
144 final DynaProperty dynaProperty = dynaClass.getDynaProperty(toString(key));
145 return dynaProperty != null;
146 }
147
148
149
150
151
152
153
154 @Override
155 public boolean containsValue(final Object value) {
156 final DynaProperty[] properties = getDynaProperties();
157 for (final DynaProperty property : properties) {
158 final String key = property.getName();
159 final Object prop = getDynaBean().get(key);
160 if (value == null) {
161 if (prop == null) {
162 return true;
163 }
164 } else if (value.equals(prop)) {
165 return true;
166 }
167 }
168 return false;
169 }
170
171
172
173
174
175
176
177 protected abstract K convertKey(String propertyName);
178
179
180
181
182
183
184
185
186
187
188
189
190 @Override
191 public Set<Map.Entry<K, Object>> entrySet() {
192 final DynaProperty[] properties = getDynaProperties();
193 final Set<Map.Entry<K, Object>> set = new HashSet<>(properties.length);
194 for (final DynaProperty property : properties) {
195 final K key = convertKey(property.getName());
196 final Object value = getDynaBean().get(property.getName());
197 set.add(new MapEntry<>(key, value));
198 }
199 return Collections.unmodifiableSet(set);
200 }
201
202
203
204
205
206
207
208 @Override
209 public Object get(final Object key) {
210 return getDynaBean().get(toString(key));
211 }
212
213
214
215
216
217
218 public DynaBean getDynaBean() {
219 return dynaBean;
220 }
221
222
223
224
225
226
227 private DynaProperty[] getDynaProperties() {
228 return getDynaBean().getDynaClass().getDynaProperties();
229 }
230
231
232
233
234
235
236 @Override
237 public boolean isEmpty() {
238 return getDynaProperties().length == 0;
239 }
240
241
242
243
244
245
246 public boolean isReadOnly() {
247 return readOnly;
248 }
249
250
251
252
253
254
255
256
257
258
259
260
261
262 @Override
263 public Set<K> keySet() {
264 if (keySet != null) {
265 return keySet;
266 }
267
268
269 final DynaProperty[] properties = getDynaProperties();
270 Set<K> set = new HashSet<>(properties.length);
271 for (final DynaProperty property : properties) {
272 set.add(convertKey(property.getName()));
273 }
274 set = Collections.unmodifiableSet(set);
275
276
277 final DynaClass dynaClass = getDynaBean().getDynaClass();
278 if (!(dynaClass instanceof MutableDynaClass)) {
279 keySet = set;
280 }
281
282 return set;
283
284 }
285
286
287
288
289
290
291
292
293
294 @Override
295 public Object put(final K key, final Object value) {
296 if (isReadOnly()) {
297 throw new UnsupportedOperationException("Map is read only");
298 }
299 final String property = toString(key);
300 final Object previous = getDynaBean().get(property);
301 getDynaBean().set(property, value);
302 return previous;
303 }
304
305
306
307
308
309
310
311 @Override
312 public void putAll(final Map<? extends K, ? extends Object> map) {
313 if (isReadOnly()) {
314 throw new UnsupportedOperationException("Map is read only");
315 }
316 map.forEach(this::put);
317 }
318
319
320
321
322
323
324
325
326 @Override
327 public Object remove(final Object key) {
328 throw new UnsupportedOperationException();
329 }
330
331
332
333
334
335
336 @Override
337 public int size() {
338 return getDynaProperties().length;
339 }
340
341
342
343
344
345
346
347 private String toString(final Object obj) {
348 return Objects.toString(obj, null);
349 }
350
351
352
353
354
355
356 @Override
357 public Collection<Object> values() {
358 final DynaProperty[] properties = getDynaProperties();
359 final List<Object> values = new ArrayList<>(properties.length);
360 for (final DynaProperty property : properties) {
361 final String key = property.getName();
362 final Object value = getDynaBean().get(key);
363 values.add(value);
364 }
365 return Collections.unmodifiableList(values);
366 }
367
368 }