16
16
package org .springframework .data .repository .util ;
17
17
18
18
import javaslang .collection .Traversable ;
19
+ import lombok .AccessLevel ;
20
+ import lombok .Getter ;
21
+ import lombok .RequiredArgsConstructor ;
22
+ import lombok .Value ;
19
23
import scala .Function0 ;
20
24
import scala .Option ;
21
25
import scala .runtime .AbstractFunction0 ;
28
32
import java .util .concurrent .CompletableFuture ;
29
33
import java .util .concurrent .Future ;
30
34
import java .util .function .Supplier ;
35
+ import java .util .stream .Collectors ;
31
36
32
37
import org .springframework .core .convert .ConversionService ;
33
38
import org .springframework .core .convert .TypeDescriptor ;
@@ -72,16 +77,16 @@ public abstract class QueryExecutionConverters {
72
77
private static final boolean JAVASLANG_PRESENT = ClassUtils .isPresent ("javaslang.control.Option" ,
73
78
QueryExecutionConverters .class .getClassLoader ());
74
79
75
- private static final Set <Class <?>> WRAPPER_TYPES = new HashSet <Class <?> >();
76
- private static final Set <Class <?>> UNWRAPPER_TYPES = new HashSet <Class <?> >();
80
+ private static final Set <WrapperType > WRAPPER_TYPES = new HashSet <WrapperType >();
81
+ private static final Set <WrapperType > UNWRAPPER_TYPES = new HashSet <WrapperType >();
77
82
private static final Set <Converter <Object , Object >> UNWRAPPERS = new HashSet <Converter <Object , Object >>();
78
83
79
84
static {
80
85
81
- WRAPPER_TYPES .add (Future .class );
82
- UNWRAPPER_TYPES .add (Future .class );
83
- WRAPPER_TYPES .add (ListenableFuture .class );
84
- UNWRAPPER_TYPES .add (ListenableFuture .class );
86
+ WRAPPER_TYPES .add (WrapperType . singleValue ( Future .class ) );
87
+ UNWRAPPER_TYPES .add (WrapperType . singleValue ( Future .class ) );
88
+ WRAPPER_TYPES .add (WrapperType . singleValue ( ListenableFuture .class ) );
89
+ UNWRAPPER_TYPES .add (WrapperType . singleValue ( ListenableFuture .class ) );
85
90
86
91
if (GUAVA_PRESENT ) {
87
92
WRAPPER_TYPES .add (NullableWrapperToGuavaOptionalConverter .getWrapperType ());
@@ -115,9 +120,12 @@ public abstract class QueryExecutionConverters {
115
120
}
116
121
117
122
if (ReactiveWrappers .isAvailable ()) {
118
- WRAPPER_TYPES .addAll (ReactiveWrappers .getNoValueTypes ());
119
- WRAPPER_TYPES .addAll (ReactiveWrappers .getSingleValueTypes ());
120
- WRAPPER_TYPES .addAll (ReactiveWrappers .getMultiValueTypes ());
123
+ WRAPPER_TYPES
124
+ .addAll (ReactiveWrappers .getNoValueTypes ().stream ().map (WrapperType ::noValue ).collect (Collectors .toList ()));
125
+ WRAPPER_TYPES .addAll (
126
+ ReactiveWrappers .getSingleValueTypes ().stream ().map (WrapperType ::singleValue ).collect (Collectors .toList ()));
127
+ WRAPPER_TYPES .addAll (
128
+ ReactiveWrappers .getMultiValueTypes ().stream ().map (WrapperType ::multiValue ).collect (Collectors .toList ()));
121
129
}
122
130
}
123
131
@@ -133,8 +141,8 @@ public static boolean supports(Class<?> type) {
133
141
134
142
Assert .notNull (type , "Type must not be null!" );
135
143
136
- for (Class <?> candidate : WRAPPER_TYPES ) {
137
- if (candidate .isAssignableFrom (type )) {
144
+ for (WrapperType candidate : WRAPPER_TYPES ) {
145
+ if (candidate .getType (). isAssignableFrom (type )) {
138
146
return true ;
139
147
}
140
148
}
@@ -152,15 +160,26 @@ public static boolean supportsUnwrapping(Class<?> type) {
152
160
153
161
Assert .notNull (type , "Type must not be null!" );
154
162
155
- for (Class <?> candidate : UNWRAPPER_TYPES ) {
156
- if (candidate .isAssignableFrom (type )) {
163
+ for (WrapperType candidate : UNWRAPPER_TYPES ) {
164
+ if (candidate .getType (). isAssignableFrom (type )) {
157
165
return true ;
158
166
}
159
167
}
160
168
161
169
return false ;
162
170
}
163
171
172
+ public static boolean isSingleValue (Class <?> type ) {
173
+
174
+ for (WrapperType candidate : WRAPPER_TYPES ) {
175
+ if (candidate .getType ().isAssignableFrom (type )) {
176
+ return candidate .isSingleValue ();
177
+ }
178
+ }
179
+
180
+ return false ;
181
+ }
182
+
164
183
/**
165
184
* Registers converters for wrapper types found on the classpath.
166
185
*
@@ -311,8 +330,8 @@ protected Object wrap(Object source) {
311
330
return Optional .of (source );
312
331
}
313
332
314
- public static Class <?> getWrapperType () {
315
- return Optional .class ;
333
+ public static WrapperType getWrapperType () {
334
+ return WrapperType . singleValue ( Optional .class ) ;
316
335
}
317
336
}
318
337
@@ -341,8 +360,8 @@ protected Object wrap(Object source) {
341
360
return java .util .Optional .of (source );
342
361
}
343
362
344
- public static Class <?> getWrapperType () {
345
- return java .util .Optional .class ;
363
+ public static WrapperType getWrapperType () {
364
+ return WrapperType . singleValue ( java .util .Optional .class ) ;
346
365
}
347
366
}
348
367
@@ -397,8 +416,8 @@ protected Object wrap(Object source) {
397
416
return source instanceof CompletableFuture ? source : CompletableFuture .completedFuture (source );
398
417
}
399
418
400
- public static Class <?> getWrapperType () {
401
- return CompletableFuture .class ;
419
+ public static WrapperType getWrapperType () {
420
+ return WrapperType . singleValue ( CompletableFuture .class ) ;
402
421
}
403
422
}
404
423
@@ -423,8 +442,8 @@ protected Object wrap(Object source) {
423
442
return Option .apply (source );
424
443
}
425
444
426
- public static Class <?> getWrapperType () {
427
- return Option .class ;
445
+ public static WrapperType getWrapperType () {
446
+ return WrapperType . singleValue ( Option .class ) ;
428
447
}
429
448
}
430
449
@@ -440,8 +459,8 @@ private static class NullableWrapperToJavaslangOptionConverter extends AbstractW
440
459
private static final Method NONE_METHOD ;
441
460
442
461
static {
443
- OF_METHOD = ReflectionUtils .findMethod (getWrapperType () , "of" , Object .class );
444
- NONE_METHOD = ReflectionUtils .findMethod (getWrapperType () , "none" );
462
+ OF_METHOD = ReflectionUtils .findMethod (javaslang . control . Option . class , "of" , Object .class );
463
+ NONE_METHOD = ReflectionUtils .findMethod (javaslang . control . Option . class , "none" );
445
464
}
446
465
447
466
/**
@@ -450,11 +469,11 @@ private static class NullableWrapperToJavaslangOptionConverter extends AbstractW
450
469
* @param conversionService must not be {@literal null}.
451
470
*/
452
471
public NullableWrapperToJavaslangOptionConverter (ConversionService conversionService ) {
453
- super (conversionService , createEmptyOption (), getWrapperType () );
472
+ super (conversionService , createEmptyOption (), javaslang . control . Option . class );
454
473
}
455
474
456
- public static Class <?> getWrapperType () {
457
- return javaslang .control .Option .class ;
475
+ public static WrapperType getWrapperType () {
476
+ return WrapperType . singleValue ( javaslang .control .Option .class ) ;
458
477
}
459
478
460
479
/*
@@ -586,4 +605,32 @@ public Object convert(Object source) {
586
605
return source ;
587
606
}
588
607
}
608
+
609
+ @ Value
610
+ @ RequiredArgsConstructor (access = AccessLevel .PRIVATE )
611
+ public static class WrapperType {
612
+
613
+ enum Cardinality {
614
+ NONE , SINGLE , MULTI ;
615
+ }
616
+
617
+ Class <?> type ;
618
+ @ Getter (AccessLevel .NONE ) Cardinality cardinality ;
619
+
620
+ public static WrapperType singleValue (Class <?> type ) {
621
+ return new WrapperType (type , Cardinality .SINGLE );
622
+ }
623
+
624
+ public static WrapperType multiValue (Class <?> type ) {
625
+ return new WrapperType (type , Cardinality .MULTI );
626
+ }
627
+
628
+ public static WrapperType noValue (Class <?> type ) {
629
+ return new WrapperType (type , Cardinality .NONE );
630
+ }
631
+
632
+ boolean isSingleValue () {
633
+ return cardinality .equals (Cardinality .SINGLE );
634
+ }
635
+ }
589
636
}
0 commit comments