-
Notifications
You must be signed in to change notification settings - Fork 0
/
JsonDeserializerCollector.java
114 lines (101 loc) · 4.5 KB
/
JsonDeserializerCollector.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import java.lang.reflect.Type;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
public interface JsonDeserializerCollector
{
static <T> Collector<JsonToken, ?, T> deserializing(JsonDeserializer deserializer, TypeToken<T> type)
{
return internalDeserializing(deserializer, type.type());
}
static <T> Collector<JsonToken, ?, T> deserializing(JsonDeserializer deserializer, Class<T> type)
{
return internalDeserializing(deserializer, type);
}
static Collector<JsonToken, ?, Object> deserializing(JsonDeserializer deserializer, Type type)
{
return internalDeserializing(deserializer, type);
}
private static <T> Collector<JsonToken, ?, T> internalDeserializing(JsonDeserializer deserializer, Type type)
{
class Accumulator
{
JsonDeserializer.TypedDeserializer first;
JsonDeserializer.TypedDeserializer current;
}
JsonDeserializer.TypedDeserializer rootTypedDeserializer = new JsonDeserializer.TypedDeserializer()
{
@Override
public Object value()
{
throw new UnsupportedOperationException();
}
@Override
public JsonDeserializer.TypedDeserializer accept(JsonToken jsonToken)
{
return this;
}
};
return new Collector<JsonToken, Accumulator, T>() {
@Override
public Supplier<Accumulator> supplier()
{
return Accumulator::new;
}
@Override
public BiConsumer<Accumulator, JsonToken> accumulator()
{
return (accumulator, jsonToken) -> {
if (accumulator.first == null) {
accumulator.current = accumulator.first = deserializer.deserializerFor(rootTypedDeserializer, type);
}
accumulator.current = accumulator.current.accept(jsonToken);
};
}
@Override
public BinaryOperator<Accumulator> combiner()
{
return (accumulator, context2) -> {
/*
Caution to future library writers. Decisions you make early on that seem good at
the time will have far-reaching consequences for your users and your ability
to enhance your library in the future.
When the Java streams library was being developed it was determined that it would
be useful to have parallel streams as well as serial streams. This decision, by
itself, was not bad. However, the decision to burden the entire API with having
to support both parallel and serial streams was bad. In Java streams users have the
option to make _any_ stream run in parallel. Further, the operations on parallel
streams are exactly the same as serial streams. This decision has hampered the
utility of the Java streams library. Common functional idioms such as "fold"
are impossible to do with the current APIs unless you cheat as we have below.
This combiner() method has no utility when doing a fold reduction. There's no
way to make sense of combining two contexts mid-fold. It turns out, however,
that every version of the JDK streams has only called the combiner for
parallel streams. So, we take the decision to disallow parallel streams by
disallowing the combiner to run.
*/
throw new UnsupportedOperationException();
};
}
@SuppressWarnings("unchecked")
@Override
public Function<Accumulator, T> finisher()
{
return accumulator -> {
if (accumulator.first == null) {
throw new RuntimeException();
}
return (T) accumulator.first.value();
};
}
@Override
public Set<Characteristics> characteristics()
{
return Set.of();
}
};
}
}