15
15
*/
16
16
package org .springframework .data .repository .util ;
17
17
18
- import lombok .AccessLevel ;
19
- import lombok .RequiredArgsConstructor ;
20
- import lombok .Value ;
21
18
import lombok .experimental .UtilityClass ;
22
19
import reactor .core .publisher .Flux ;
23
20
import reactor .core .publisher .Mono ;
24
21
import rx .Completable ;
25
22
import rx .Observable ;
26
23
import rx .Single ;
27
24
25
+ import java .util .ArrayList ;
28
26
import java .util .Arrays ;
29
27
import java .util .Collection ;
30
28
import java .util .Collections ;
31
- import java .util .LinkedHashMap ;
32
- import java .util .Map ;
33
- import java .util .Map .Entry ;
34
29
import java .util .Optional ;
35
30
import java .util .stream .Collectors ;
36
31
37
32
import org .reactivestreams .Publisher ;
38
- import org .springframework .core .ReactiveAdapter ;
33
+
34
+ import org .springframework .core .ReactiveTypeDescriptor ;
39
35
import org .springframework .data .util .ReflectionUtils ;
40
36
import org .springframework .util .Assert ;
41
37
import org .springframework .util .ClassUtils ;
@@ -75,7 +71,7 @@ public class ReactiveWrappers {
75
71
private static final boolean RXJAVA2_PRESENT = ClassUtils .isPresent ("io.reactivex.Flowable" ,
76
72
ReactiveWrappers .class .getClassLoader ());
77
73
78
- private static final Map < Class <?>, Descriptor > REACTIVE_WRAPPERS ;
74
+ private static final Collection < ReactiveTypeDescriptor > REACTIVE_WRAPPERS ;
79
75
80
76
/**
81
77
* Enumeration of supported reactive libraries.
@@ -88,32 +84,36 @@ static enum ReactiveLibrary {
88
84
89
85
static {
90
86
91
- Map < Class <?>, Descriptor > reactiveWrappers = new LinkedHashMap <>(5 );
87
+ Collection < ReactiveTypeDescriptor > reactiveWrappers = new ArrayList <>(5 );
92
88
93
89
if (RXJAVA1_PRESENT ) {
94
90
95
- reactiveWrappers .put ( Single . class , Descriptor . forSingleValue (). forValue ( ));
96
- reactiveWrappers .put ( Completable .class , Descriptor . forSingleValue (). forNoValue ( ));
97
- reactiveWrappers .put ( Observable .class , Descriptor . forMultiValue (). forValue ( ));
91
+ reactiveWrappers .add ( ReactiveTypeDescriptor . singleRequiredValue ( Single . class ));
92
+ reactiveWrappers .add ( ReactiveTypeDescriptor . noValue ( Completable .class , Completable :: complete ));
93
+ reactiveWrappers .add ( ReactiveTypeDescriptor . multiValue ( Observable .class , Observable :: empty ));
98
94
}
99
95
100
96
if (RXJAVA2_PRESENT ) {
101
97
102
- reactiveWrappers .put (io .reactivex .Single .class , Descriptor .forSingleValue ().forValue ());
103
- reactiveWrappers .put (io .reactivex .Maybe .class , Descriptor .forSingleValue ().forValue ());
104
- reactiveWrappers .put (io .reactivex .Completable .class , Descriptor .forSingleValue ().forNoValue ());
105
- reactiveWrappers .put (io .reactivex .Flowable .class , Descriptor .forMultiValue ().forValue ());
106
- reactiveWrappers .put (io .reactivex .Observable .class , Descriptor .forMultiValue ().forValue ());
98
+ reactiveWrappers .add (ReactiveTypeDescriptor .singleRequiredValue (io .reactivex .Single .class ));
99
+ reactiveWrappers
100
+ .add (ReactiveTypeDescriptor .singleOptionalValue (io .reactivex .Maybe .class , io .reactivex .Maybe ::empty ));
101
+ reactiveWrappers
102
+ .add (ReactiveTypeDescriptor .noValue (io .reactivex .Completable .class , io .reactivex .Completable ::complete ));
103
+ reactiveWrappers
104
+ .add (ReactiveTypeDescriptor .multiValue (io .reactivex .Flowable .class , io .reactivex .Flowable ::empty ));
105
+ reactiveWrappers
106
+ .add (ReactiveTypeDescriptor .multiValue (io .reactivex .Observable .class , io .reactivex .Observable ::empty ));
107
107
}
108
108
109
109
if (PROJECT_REACTOR_PRESENT ) {
110
110
111
- reactiveWrappers .put ( Mono .class , Descriptor . forSingleValue (). forValue ( ));
112
- reactiveWrappers .put ( Flux .class , Descriptor . forMultiValue (). forNoValue ( ));
113
- reactiveWrappers .put ( Publisher .class , Descriptor . forMultiValue (). forNoValue ( ));
111
+ reactiveWrappers .add ( ReactiveTypeDescriptor . singleOptionalValue ( Mono .class , Mono :: empty ));
112
+ reactiveWrappers .add ( ReactiveTypeDescriptor . multiValue ( Flux .class , Flux :: empty ));
113
+ reactiveWrappers .add ( ReactiveTypeDescriptor . multiValue ( Publisher .class , Flux :: empty ));
114
114
}
115
115
116
- REACTIVE_WRAPPERS = Collections .unmodifiableMap (reactiveWrappers );
116
+ REACTIVE_WRAPPERS = Collections .unmodifiableCollection (reactiveWrappers );
117
117
}
118
118
119
119
/**
@@ -183,7 +183,7 @@ public static boolean isNoValueType(Class<?> type) {
183
183
184
184
Assert .notNull (type , "Candidate type must not be null!" );
185
185
186
- return findDescriptor (type ).map (Descriptor ::isNoValue ).orElse (false );
186
+ return findDescriptor (type ).map (ReactiveTypeDescriptor ::isNoValue ).orElse (false );
187
187
}
188
188
189
189
/**
@@ -213,7 +213,8 @@ public static boolean isMultiValueType(Class<?> type) {
213
213
214
214
// Prevent single-types with a multi-hierarchy supertype to be reported as multi type
215
215
// See Mono implements Publisher
216
- return isSingleValueType (type ) ? false : findDescriptor (type ).map (Descriptor ::isMultiValue ).orElse (false );
216
+ return isSingleValueType (type ) ? false
217
+ : findDescriptor (type ).map (ReactiveTypeDescriptor ::isMultiValue ).orElse (false );
217
218
}
218
219
219
220
/**
@@ -223,9 +224,10 @@ public static boolean isMultiValueType(Class<?> type) {
223
224
*/
224
225
public static Collection <Class <?>> getNoValueTypes () {
225
226
226
- return REACTIVE_WRAPPERS .entrySet ().stream ()//
227
- .filter (entry -> entry .getValue ().isNoValue ())//
228
- .map (Entry ::getKey ).collect (Collectors .toList ());
227
+ return REACTIVE_WRAPPERS .stream ()//
228
+ .filter (ReactiveTypeDescriptor ::isNoValue )//
229
+ .map (ReactiveTypeDescriptor ::getReactiveType )//
230
+ .collect (Collectors .toList ());
229
231
}
230
232
231
233
/**
@@ -235,9 +237,9 @@ public static Collection<Class<?>> getNoValueTypes() {
235
237
*/
236
238
public static Collection <Class <?>> getSingleValueTypes () {
237
239
238
- return REACTIVE_WRAPPERS .entrySet (). stream ()//
239
- .filter (entry -> !entry .getValue (). isMultiValue ())//
240
- .map (Entry :: getKey ).collect (Collectors .toList ());
240
+ return REACTIVE_WRAPPERS .stream ()//
241
+ .filter (entry -> !entry .isMultiValue ())//
242
+ .map (ReactiveTypeDescriptor :: getReactiveType ).collect (Collectors .toList ());
241
243
}
242
244
243
245
/**
@@ -247,9 +249,9 @@ public static Collection<Class<?>> getSingleValueTypes() {
247
249
*/
248
250
public static Collection <Class <?>> getMultiValueTypes () {
249
251
250
- return REACTIVE_WRAPPERS .entrySet (). stream ()//
251
- .filter (entry -> entry . getValue (). isMultiValue () )//
252
- .map (Entry :: getKey )//
252
+ return REACTIVE_WRAPPERS .stream ()//
253
+ .filter (ReactiveTypeDescriptor :: isMultiValue )//
254
+ .map (ReactiveTypeDescriptor :: getReactiveType )//
253
255
.collect (Collectors .toList ());
254
256
}
255
257
@@ -267,64 +269,17 @@ private static boolean isWrapper(Class<?> type) {
267
269
}
268
270
269
271
/**
270
- * Looks up a {@link Descriptor } for the given wrapper type.
272
+ * Looks up a {@link ReactiveTypeDescriptor } for the given wrapper type.
271
273
*
272
274
* @param type must not be {@literal null}.
273
275
* @return
274
276
*/
275
- private static Optional <Descriptor > findDescriptor (Class <?> type ) {
277
+ private static Optional <ReactiveTypeDescriptor > findDescriptor (Class <?> type ) {
276
278
277
279
Assert .notNull (type , "Wrapper type must not be null!" );
278
280
279
- return REACTIVE_WRAPPERS .entrySet ().stream ()//
280
- .filter (it -> ClassUtils .isAssignable (it .getKey (), type ))//
281
- .findFirst ().map (it -> it .getValue ());
282
- }
283
-
284
- /**
285
- * Basically a copy of Spring's {@link ReactiveAdapter.Descriptor} but without introducing the strong dependency to
286
- * Reactor so that we can safely use the class in non-reactive environments.
287
- *
288
- * @author Oliver Gierke
289
- * @since 2.0
290
- */
291
- @ Value
292
- @ RequiredArgsConstructor (access = AccessLevel .PRIVATE )
293
- private static class Descriptor {
294
-
295
- /**
296
- * Return {@code true} if the adaptee implies 0..N values can be produced and is therefore a good fit to adapt to
297
- * {@link Flux}. A {@code false} return value implies the adaptee will produce 1 value at most and is therefore a
298
- * good fit for {@link Mono}.
299
- */
300
- private final boolean multiValue ;
301
-
302
- /**
303
- * Return {@code true} if the adaptee implies no values will be produced, i.e. providing only completion or error
304
- * signal.
305
- */
306
- private final boolean noValue ;
307
-
308
- public static DescriptorBuilder forSingleValue () {
309
- return new DescriptorBuilder (false );
310
- }
311
-
312
- public static DescriptorBuilder forMultiValue () {
313
- return new DescriptorBuilder (true );
314
- }
315
-
316
- @ RequiredArgsConstructor
317
- static class DescriptorBuilder {
318
-
319
- private final boolean multi ;
320
-
321
- public Descriptor forValue () {
322
- return new Descriptor (multi , false );
323
- }
324
-
325
- public Descriptor forNoValue () {
326
- return new Descriptor (multi , true );
327
- }
328
- }
281
+ return REACTIVE_WRAPPERS .stream ()//
282
+ .filter (it -> ClassUtils .isAssignable (it .getReactiveType (), type ))//
283
+ .findFirst ();
329
284
}
330
285
}
0 commit comments