Skip to content

Commit fd932e6

Browse files
committed
- Added tests for basic API functionality.
- Simplified/streamlined confusing AbstractContext API based on user feedback. - Added some minor tweaks.
1 parent c8424cd commit fd932e6

File tree

58 files changed

+1583
-1022
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1583
-1022
lines changed

src/main/java/javax/money/AbstractContext.java

Lines changed: 61 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
import java.time.Instant;
1515
import java.time.temporal.ChronoField;
1616
import java.time.temporal.TemporalAccessor;
17-
import java.util.*;
17+
import java.util.HashMap;
18+
import java.util.HashSet;
19+
import java.util.Map;
20+
import java.util.Objects;
21+
import java.util.Optional;
22+
import java.util.Set;
1823

1924
/**
2025
* Represents a general context of data targeting an item of type {@code Q}. Contexts are used to add arbitrary
@@ -40,7 +45,7 @@ public abstract class AbstractContext implements Serializable {
4045
/**
4146
* The data map containing all values.
4247
*/
43-
private final Map<Class<?>, Map<Object, Object>> data = new HashMap<>();
48+
final Map<Object, Object> data = new HashMap<>();
4449

4550
/**
4651
* Private constructor, used by {@link AbstractContextBuilder}.
@@ -49,59 +54,45 @@ public abstract class AbstractContext implements Serializable {
4954
*/
5055
@SuppressWarnings("rawtypes")
5156
protected AbstractContext(AbstractContextBuilder<?, ?> builder) {
52-
for (Map.Entry<Class, Map<Object, Object>> en : builder.data.entrySet()) {
53-
Map<Object, Object> presentMap = this.data.get(en.getKey());
54-
if (presentMap == null) {
55-
presentMap = new HashMap<>(en.getValue());
56-
this.data.put(en.getKey(), presentMap);
57-
} else {
58-
presentMap.putAll(en.getValue());
59-
}
60-
}
61-
}
57+
data.putAll(builder.data);
58+
}
6259

6360
/**
64-
* Get the present keys for a given attribute type.
61+
* Get the present keys of all entries with a given type, checking hereby if assignable.
6562
*
6663
* @param type The attribute type, not null.
67-
* @return all present keys of attributes of the (exact) given type, never null.
64+
* @return all present keys of attributes being assignable to the type, never null.
6865
*/
6966
public Set<Object> getKeys(Class<?> type) {
70-
Map<Object, Object> values = this.data.get(type);
71-
if (values != null) {
72-
return values.keySet();
67+
Set<Object> keys = new HashSet<>();
68+
for (Map.Entry<Object, Object> val : data.entrySet()) {
69+
if (type.isAssignableFrom(val.getValue().getClass())) {
70+
keys.add(val.getKey());
71+
}
7372
}
74-
return Collections.emptySet();
73+
return keys;
7574
}
7675

7776
/**
78-
* Get all currently present attribute types.
77+
* Get the current attribute type.
7978
*
80-
* @return all currently present attribute types, never null.
79+
* @return the current attribute type, or null, if no such attribute exists.
8180
*/
82-
public Set<Class<?>> getTypes() {
83-
return this.data.keySet();
81+
public Class<?> getType(Object key) {
82+
Object val = this.data.get(key);
83+
return val == null ? null : val.getClass();
8484
}
8585

8686
/**
8787
* Access an attribute.
8888
*
8989
* @param type the attribute's type, not {@code null}
9090
* @param key the attribute's key, not {@code null}
91+
* @param defaultValue the default value, or {@code null}.
9192
* @return the attribute value, or {@code null}.
9293
*/
93-
// Type safe cast
94-
@SuppressWarnings("unchecked")
95-
public <T> T getAny(Object key, Class<T> type, T defaultValue) {
96-
Map<Object, Object> values = this.data.get(type);
97-
Object value = null;
98-
if (values != null) {
99-
value = values.get(key);
100-
}
101-
if (value != null) {
102-
return (T) value;
103-
}
104-
return defaultValue;
94+
public <T> T get(Object key, Class<T> type, T defaultValue) {
95+
return (T) data.getOrDefault(key, defaultValue);
10596
}
10697

10798
/**
@@ -111,18 +102,18 @@ public <T> T getAny(Object key, Class<T> type, T defaultValue) {
111102
* @param key the attribute's key, not {@code null}
112103
* @return the attribute value, or {@code null}.
113104
*/
114-
public <T> T getAny(Object key, Class<T> type) {
115-
return getAny(key, type, null);
105+
public <T> T get(Object key, Class<T> type) {
106+
return get(key, type, null);
116107
}
117108

118109
/**
119110
* Access an attribute, hereby using the class name as key.
120111
*
121-
* @param type the attribute's type, not {@code null}
122-
* @return the attribute value, or {@code null}.
112+
* @param type the type, not {@code null}
113+
* @return the type attribute value, or {@code null}.
123114
*/
124-
public <T> T get(Class<T> type) {
125-
return getAny(type, type);
115+
public <T> T getTyped(Class<T> type) {
116+
return get(type, type);
126117
}
127118

128119
/**
@@ -133,8 +124,8 @@ public <T> T get(Class<T> type) {
133124
* @return the attribute's value, or the {@code defaultValue} passed, if no
134125
* such attribute is present.
135126
*/
136-
public <T> T get(Class<T> type, T defaultValue) {
137-
return Optional.ofNullable(get(type)).orElse(defaultValue);
127+
public <T> T getTyped(Class<T> type, T defaultValue) {
128+
return Optional.ofNullable(getTyped(type)).orElse(defaultValue);
138129
}
139130

140131

@@ -156,7 +147,7 @@ public Long getLong(Object key) {
156147
* @return the value, or default value.
157148
*/
158149
public Long getLong(Object key, Long defaultValue) {
159-
return getAny(key, Long.class, defaultValue);
150+
return get(key, Long.class, defaultValue);
160151
}
161152

162153

@@ -178,7 +169,7 @@ public Float getFloat(Object key) {
178169
* @return the value, or default value.
179170
*/
180171
public Float getFloat(Object key, Float defaultValue) {
181-
return getAny(key, Float.class, defaultValue);
172+
return get(key, Float.class, defaultValue);
182173
}
183174

184175
/**
@@ -199,7 +190,7 @@ public Integer getInt(Object key) {
199190
* @return the value, or default value.
200191
*/
201192
public Integer getInt(Object key, Integer defaultValue) {
202-
return getAny(key, Integer.class, defaultValue);
193+
return get(key, Integer.class, defaultValue);
203194
}
204195

205196
/**
@@ -220,7 +211,7 @@ public Boolean getBoolean(Object key) {
220211
* @return the value, or default value.
221212
*/
222213
public Boolean getBoolean(Object key, Boolean defaultValue) {
223-
return getAny(key, Boolean.class, defaultValue);
214+
return get(key, Boolean.class, defaultValue);
224215
}
225216

226217
/**
@@ -241,7 +232,7 @@ public Double getDouble(Object key) {
241232
* @return the value, or default value.
242233
*/
243234
public Double getDouble(Object key, Double defaultValue) {
244-
return getAny(key, Double.class, defaultValue);
235+
return get(key, Double.class, defaultValue);
245236
}
246237

247238
/**
@@ -262,7 +253,7 @@ public String getText(Object key) {
262253
* @return the value, or default value.
263254
*/
264255
public String getText(Object key, String defaultValue) {
265-
return getAny(key, String.class, defaultValue);
256+
return get(key, String.class, defaultValue);
266257
}
267258

268259

@@ -284,91 +275,7 @@ public Character getChar(Object key) {
284275
* @return the value, or default value.
285276
*/
286277
public Character getChar(Object key, Character defaultValue) {
287-
return getAny(key, Character.class, defaultValue);
288-
}
289-
290-
/**
291-
* Access a Collection attribute.
292-
*
293-
* @param key the attribute's key, not null.
294-
* @return the value, or null.
295-
*/
296-
public Collection<?> getCollection(Object key) {
297-
return getCollection(key, null);
298-
}
299-
300-
/**
301-
* Access a Collection attribute.
302-
*
303-
* @param key the attribute's key, not null.
304-
* @param defaultValue the default value returned, if the attribute is not present.
305-
* @return the value, or default value.
306-
*/
307-
public <T> Collection<T> getCollection(Object key, Collection<T> defaultValue) {
308-
return getAny(key, Collection.class, defaultValue);
309-
}
310-
311-
/**
312-
* Access a List attribute.
313-
*
314-
* @param key the attribute's key, not null.
315-
* @return the value, or null.
316-
*/
317-
public List<?> getList(Object key) {
318-
return getList(key, null);
319-
}
320-
321-
/**
322-
* Access a Collection attribute.
323-
*
324-
* @param key the attribute's key, not null.
325-
* @param defaultValue the default value returned, if the attribute is not present.
326-
* @return the value, or default value.
327-
*/
328-
public <T> List<T> getList(Object key, List<T> defaultValue) {
329-
return getAny(key, List.class, defaultValue);
330-
}
331-
332-
/**
333-
* Access a Set attribute.
334-
*
335-
* @param key the attribute's key, not null.
336-
* @return the value, or null.
337-
*/
338-
public Set<?> getSet(Object key) {
339-
return getSet(key, null);
340-
}
341-
342-
/**
343-
* Access a Set attribute.
344-
*
345-
* @param key the attribute's key, not null.
346-
* @param defaultValue the default value returned, if the attribute is not present.
347-
* @return the value, or default value.
348-
*/
349-
public <T> Set<T> getSet(Object key, Set<T> defaultValue) {
350-
return getAny(key, Set.class, defaultValue);
351-
}
352-
353-
/**
354-
* Access a Map attribute.
355-
*
356-
* @param key the attribute's key, not null.
357-
* @return the value, or null.
358-
*/
359-
public Map<?, ?> getMap(Object key) {
360-
return getMap(key, null);
361-
}
362-
363-
/**
364-
* Access a Map attribute.
365-
*
366-
* @param key the attribute's key, not null.
367-
* @param defaultValue the default value returned, if the attribute is not present.
368-
* @return the value, or default value.
369-
*/
370-
public <K, V> Map<K, V> getMap(Object key, Map<K, V> defaultValue) {
371-
return getAny(key, Map.class, defaultValue);
278+
return get(key, Character.class, defaultValue);
372279
}
373280

374281
/**
@@ -381,15 +288,15 @@ public String getProvider() {
381288
}
382289

383290
/**
384-
* Get the current target timestamp of the query in UTC milliseconds. If not set it tries to of an
291+
* Get the current target timestamp of the query in UTC milliseconds. If not setTyped it tries to of an
385292
* UTC timestamp from #getTimestamp(). This allows to select historical roundings that were valid in the
386293
* past. Its implementation specific, to what extend historical roundings are available. By default if this
387-
* property is not set always current {@link javax.money.MonetaryRounding} instances are provided.
294+
* property is not setTyped always current {@link javax.money.MonetaryRounding} instances are provided.
388295
*
389296
* @return the timestamp in millis, or null.
390297
*/
391298
public Long getTimestampMillis() {
392-
Long value = getAny(KEY_TIMESTAMP, Long.class, null);
299+
Long value = get(KEY_TIMESTAMP, Long.class, null);
393300
if (Objects.isNull(value)) {
394301
TemporalAccessor acc = getTimestamp();
395302
if (Objects.nonNull(acc)) {
@@ -400,17 +307,17 @@ public Long getTimestampMillis() {
400307
}
401308

402309
/**
403-
* Get the current target timestamp of the query. If not set it tries to of an Instant from
310+
* Get the current target timestamp of the query. If not setTyped it tries to of an Instant from
404311
* #getTimestampMillis(). This allows to select historical roundings that were valid in the
405312
* past. Its implementation specific, to what extend historical roundings are available. By default if this
406-
* property is not set always current {@link javax.money.MonetaryRounding} instances are provided.
313+
* property is not setTyped always current {@link javax.money.MonetaryRounding} instances are provided.
407314
*
408315
* @return the current timestamp, or null.
409316
*/
410317
public TemporalAccessor getTimestamp() {
411-
TemporalAccessor acc = getAny(KEY_TIMESTAMP, TemporalAccessor.class, null);
318+
TemporalAccessor acc = get(KEY_TIMESTAMP, TemporalAccessor.class, null);
412319
if (Objects.isNull(acc)) {
413-
Long value = getAny(KEY_TIMESTAMP, Long.class, null);
320+
Long value = get(KEY_TIMESTAMP, Long.class, null);
414321
if (Objects.nonNull(value)) {
415322
acc = Instant.ofEpochMilli(value);
416323
}
@@ -419,9 +326,9 @@ public TemporalAccessor getTimestamp() {
419326
}
420327

421328
/**
422-
* Checks if the current instance has no attributes set. This is often the cases, when used in default cases.
329+
* Checks if the current instance has no attributes setTyped. This is often the cases, when used in default cases.
423330
*
424-
* @return true, if no attributes are set.
331+
* @return true, if no attributes are setTyped.
425332
*/
426333
public boolean isEmpty() {
427334
return this.data.isEmpty();
@@ -438,13 +345,19 @@ public int hashCode() {
438345
}
439346

440347
/**
441-
* Access all the values present.
348+
* Access all the key/values present, filtered by the values that are assignable to the given type.
442349
*
443-
* @param type the type used.
444-
* @return
350+
* @param type the value type, not null.
351+
* @return return all key/values with values assignable to a given value type.
445352
*/
446-
public Map<Object, Object> getValues(Class<?> type) {
447-
return this.data.get(type);
353+
public <T> Map<Object, T> getValues(Class<T> type) {
354+
Map<Object, T> result = new HashMap<>();
355+
for (Map.Entry<Object, Object> en : data.entrySet()) {
356+
if (type.isAssignableFrom(en.getValue().getClass())) {
357+
result.put(en.getKey(), type.cast(en.getValue()));
358+
}
359+
}
360+
return result;
448361
}
449362

450363
/*
@@ -471,28 +384,6 @@ public boolean equals(Object obj) {
471384
*/
472385
@Override
473386
public String toString() {
474-
StringBuilder attrsBuilder = new StringBuilder();
475-
for (Map.Entry<Class<?>, Map<Object, Object>> en : this.data.entrySet()) {
476-
Map<Object, Object> sortedMap = new TreeMap<>((o1, o2) -> o1.toString().compareTo(o2.toString()));
477-
sortedMap.putAll(en.getValue());
478-
for (Map.Entry<Object, Object> entry : sortedMap.entrySet()) {
479-
Object key = entry.getKey();
480-
attrsBuilder.append(" ");
481-
if (key.getClass() == Class.class) {
482-
attrsBuilder.append(((Class<?>) key).getName());
483-
} else {
484-
attrsBuilder.append(key);
485-
}
486-
attrsBuilder.append('[');
487-
if (en.getKey().getName().startsWith("java.lang.")) {
488-
attrsBuilder.append(en.getKey().getName().substring("java.lang.".length()));
489-
} else {
490-
attrsBuilder.append(en.getKey().getName());
491-
}
492-
attrsBuilder.append("]=");
493-
attrsBuilder.append(entry.getValue()).append('\n');
494-
}
495-
}
496-
return getClass().getSimpleName() + " (\n" + attrsBuilder.toString() + ')';
387+
return getClass().getSimpleName() + " (\n" + data + ')';
497388
}
498389
}

0 commit comments

Comments
 (0)