From 30033b22bc17c7832b24ef448a67301f4621b9a8 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 2 Feb 2018 15:57:28 +0100 Subject: [PATCH] DATACMNS-1252 - Improved Vavr collection handling to convert between collection types. If a query method now uses e.g. a Vavr Set as return type, we now also use a potential source List as input for the LinkedHashSet, even if that changes the characteristics (duplicate policy etc.) of the result. This is consistent with our general handling of collections as we're using a Spring ConversionService for collection mapping anyway. In general the new conversion algorithm is driven by the expected target type first: - i.v.c.Seq -> i.v.c.List - i.v.c.Set -> i.v.c.LinkedHashSet - i.v.c.Map -> i.v.c.LinkedHashMap If none of the declared types is assignable we fall back to the previous algorithm choosing an implementation as close as possible to the original source value: - j.u.List -> i.v.c.List - j.u.Set -> i.v.c.LinkedHashSet - j.u.Map -> i.v.c.LinkedHashMap Removed some obsolete full qualifications of types. --- .../data/repository/util/VavrCollections.java | 25 ++++++++++++++++--- .../QueryExecutionConvertersUnitTests.java | 9 +++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/springframework/data/repository/util/VavrCollections.java b/src/main/java/org/springframework/data/repository/util/VavrCollections.java index 5fa1fb929..3c5818d9e 100644 --- a/src/main/java/org/springframework/data/repository/util/VavrCollections.java +++ b/src/main/java/org/springframework/data/repository/util/VavrCollections.java @@ -116,18 +116,35 @@ class VavrCollections { */ @Nullable @Override - public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + public Object convert(@Nullable Object source, TypeDescriptor sourceDescriptor, TypeDescriptor targetDescriptor) { + + Class targetType = targetDescriptor.getType(); + + if (io.vavr.collection.Seq.class.isAssignableFrom(targetType)) { + return io.vavr.collection.List.ofAll((Iterable) source); + } + + if (io.vavr.collection.Set.class.isAssignableFrom(targetType)) { + return LinkedHashSet.ofAll((Iterable) source); + } + + if (io.vavr.collection.Map.class.isAssignableFrom(targetType)) { + return LinkedHashMap.ofAll((Map) source); + } + + // No dedicated type asked for, probably Traversable. + // Try to stay as close to the source value. if (source instanceof List) { return io.vavr.collection.List.ofAll((Iterable) source); } - if (source instanceof java.util.Set) { + if (source instanceof Set) { return LinkedHashSet.ofAll((Iterable) source); } - if (source instanceof java.util.Map) { - return LinkedHashMap.ofAll((java.util.Map) source); + if (source instanceof Map) { + return LinkedHashMap.ofAll((Map) source); } return source; diff --git a/src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java b/src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java index 2460e7271..b1f8510ad 100755 --- a/src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java +++ b/src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java @@ -338,4 +338,13 @@ public class QueryExecutionConvertersUnitTests { Set> allowedPageableTypes = QueryExecutionConverters.getAllowedPageableTypes(); assertThat(allowedPageableTypes).contains(io.vavr.collection.Seq.class); } + + @Test // DATAJPA-1258 + public void convertsJavaListsToVavrSet() { + + List source = Collections.singletonList("foo"); + + assertThat(conversionService.convert(source, io.vavr.collection.Set.class)) // + .isInstanceOf(io.vavr.collection.Set.class); + } }