16
16
package org .springframework .data .repository .util ;
17
17
18
18
import javaslang .collection .Seq ;
19
- import javaslang .collection .Traversable ;
20
19
import lombok .AccessLevel ;
21
20
import lombok .RequiredArgsConstructor ;
22
21
import lombok .Value ;
62
61
* <li>{@code javaslang.control.Option} - as of 1.13</li>
63
62
* <li>{@code javaslang.collection.Seq}, {@code javaslang.collection.Map}, {@code javaslang.collection.Set} - as of
64
63
* 1.13</li>
64
+ * <li>{@code io.vavr.collection.Seq}, {@code io.vavr.collection.Map}, {@code io.vavr.collection.Set} - as of 2.0</li>
65
65
* </ul>
66
66
*
67
67
* @author Oliver Gierke
@@ -79,6 +79,8 @@ public abstract class QueryExecutionConverters {
79
79
QueryExecutionConverters .class .getClassLoader ());
80
80
private static final boolean JAVASLANG_PRESENT = ClassUtils .isPresent ("javaslang.control.Option" ,
81
81
QueryExecutionConverters .class .getClassLoader ());
82
+ private static final boolean VAVR_PRESENT = ClassUtils .isPresent ("io.vavr.control.Option" ,
83
+ QueryExecutionConverters .class .getClassLoader ());
82
84
83
85
private static final Set <WrapperType > WRAPPER_TYPES = new HashSet <WrapperType >();
84
86
private static final Set <Converter <Object , Object >> UNWRAPPERS = new HashSet <Converter <Object , Object >>();
@@ -121,6 +123,16 @@ public abstract class QueryExecutionConverters {
121
123
122
124
ALLOWED_PAGEABLE_TYPES .add (Seq .class );
123
125
}
126
+
127
+ if (VAVR_PRESENT ) {
128
+
129
+ WRAPPER_TYPES .add (NullableWrapperToVavrOptionConverter .getWrapperType ());
130
+ WRAPPER_TYPES .add (VavrCollections .ToJavaConverter .INSTANCE .getWrapperType ());
131
+
132
+ UNWRAPPERS .add (VavrOptionUnwrapper .INSTANCE );
133
+
134
+ ALLOWED_PAGEABLE_TYPES .add (io .vavr .collection .Seq .class );
135
+ }
124
136
}
125
137
126
138
private QueryExecutionConverters () {}
@@ -194,6 +206,11 @@ public static void registerConvertersIn(ConfigurableConversionService conversion
194
206
conversionService .addConverter (JavaslangCollections .FromJavaConverter .INSTANCE );
195
207
}
196
208
209
+ if (VAVR_PRESENT ) {
210
+ conversionService .addConverter (new NullableWrapperToVavrOptionConverter (conversionService ));
211
+ conversionService .addConverter (VavrCollections .FromJavaConverter .INSTANCE );
212
+ }
213
+
197
214
conversionService .addConverter (new NullableWrapperToFutureConverter (conversionService ));
198
215
}
199
216
@@ -468,7 +485,7 @@ public static WrapperType getWrapperType() {
468
485
@ Override
469
486
@ SuppressWarnings ("unchecked" )
470
487
protected Object wrap (Object source ) {
471
- return ( javaslang . control . Option < Object >) ReflectionUtils .invokeMethod (OF_METHOD , null , source );
488
+ return ReflectionUtils .invokeMethod (OF_METHOD , null , source );
472
489
}
473
490
474
491
@ SuppressWarnings ("unchecked" )
@@ -477,6 +494,50 @@ private static javaslang.control.Option<Object> createEmptyOption() {
477
494
}
478
495
}
479
496
497
+ /**
498
+ * Converter to convert from {@link NullableWrapper} into JavaSlang's {@link io.vavr.control.Option}.
499
+ *
500
+ * @author Oliver Gierke
501
+ * @since 2.0
502
+ */
503
+ private static class NullableWrapperToVavrOptionConverter extends AbstractWrapperTypeConverter {
504
+
505
+ private static final Method OF_METHOD ;
506
+ private static final Method NONE_METHOD ;
507
+
508
+ static {
509
+ OF_METHOD = ReflectionUtils .findMethod (io .vavr .control .Option .class , "of" , Object .class );
510
+ NONE_METHOD = ReflectionUtils .findMethod (io .vavr .control .Option .class , "none" );
511
+ }
512
+
513
+ /**
514
+ * Creates a new {@link NullableWrapperToJavaslangOptionConverter} using the given {@link ConversionService}.
515
+ *
516
+ * @param conversionService must not be {@literal null}.
517
+ */
518
+ public NullableWrapperToVavrOptionConverter (ConversionService conversionService ) {
519
+ super (conversionService , createEmptyOption (), io .vavr .control .Option .class );
520
+ }
521
+
522
+ /*
523
+ * (non-Javadoc)
524
+ * @see org.springframework.data.repository.util.QueryExecutionConverters.AbstractWrapperTypeConverter#wrap(java.lang.Object)
525
+ */
526
+ @ Override
527
+ protected Object wrap (Object source ) {
528
+ return ReflectionUtils .invokeMethod (OF_METHOD , source );
529
+ }
530
+
531
+ public static WrapperType getWrapperType () {
532
+ return WrapperType .singleValue (io .vavr .control .Option .class );
533
+ }
534
+
535
+ @ SuppressWarnings ("unchecked" )
536
+ private static io .vavr .control .Option <Object > createEmptyOption () {
537
+ return (io .vavr .control .Option <Object >) ReflectionUtils .invokeMethod (NONE_METHOD , null );
538
+ }
539
+ }
540
+
480
541
/**
481
542
* A {@link Converter} to unwrap Guava {@link Optional} instances.
482
543
*
@@ -583,14 +644,55 @@ public Object convert(Object source) {
583
644
return ((javaslang .control .Option <Object >) source ).getOrElse (NULL_SUPPLIER );
584
645
}
585
646
586
- if (source instanceof Traversable ) {
647
+ if (source instanceof javaslang . collection . Traversable ) {
587
648
return JavaslangCollections .ToJavaConverter .INSTANCE .convert (source );
588
649
}
589
650
590
651
return source ;
591
652
}
592
653
}
593
654
655
+ /**
656
+ * Converter to unwrap Vavr {@link io.vavr.control.Option} instances.
657
+ *
658
+ * @author Oliver Gierke
659
+ * @since 2.0
660
+ */
661
+ private static enum VavrOptionUnwrapper implements Converter <Object , Object > {
662
+
663
+ INSTANCE ;
664
+
665
+ private static final Supplier <Object > NULL_SUPPLIER = new Supplier <Object >() {
666
+
667
+ /*
668
+ * (non-Javadoc)
669
+ * @see java.util.function.Supplier#get()
670
+ */
671
+ public Object get () {
672
+ return null ;
673
+ }
674
+ };
675
+
676
+ /*
677
+ * (non-Javadoc)
678
+ * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
679
+ */
680
+ @ Override
681
+ @ SuppressWarnings ("unchecked" )
682
+ public Object convert (Object source ) {
683
+
684
+ if (source instanceof io .vavr .control .Option ) {
685
+ return ((io .vavr .control .Option <Object >) source ).getOrElse (NULL_SUPPLIER );
686
+ }
687
+
688
+ if (source instanceof io .vavr .collection .Traversable ) {
689
+ return VavrCollections .ToJavaConverter .INSTANCE .convert (source );
690
+ }
691
+
692
+ return source ;
693
+ }
694
+ }
695
+
594
696
@ Value
595
697
@ RequiredArgsConstructor (access = AccessLevel .PRIVATE )
596
698
public static class WrapperType {
0 commit comments