From 8bcd8cb3dad13dbf0a7edfb676b6f6de257e8885 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 30 Jan 2017 15:27:14 +0100 Subject: [PATCH] DATACMNS-867 - Fixed glitch causing failure in PropertyDescriptor lookup for ProjectionInformation. Re added PropertyDescriptor collection. Looks like the method got dropped during one of the rebase operations. Additionally make use of .distinct() name collection in tests as descriptors might appear multiple times for the same property name. --- .../DefaultProjectionInformation.java | 34 +++++++++++++++---- .../springframework/data/util/Optionals.java | 24 ++++++------- ...DefaultProjectionInformationUnitTests.java | 1 + 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java b/src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java index 7ed61c8ab..17b432695 100644 --- a/src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java +++ b/src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java @@ -20,15 +20,17 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import org.springframework.beans.BeanUtils; +import org.springframework.data.util.ReflectionUtils; import org.springframework.util.Assert; /** * Default implementation of {@link ProjectionInformation}. Exposes all properties of the type as required input * properties. - * + * * @author Oliver Gierke * @since 1.12 */ @@ -39,7 +41,7 @@ class DefaultProjectionInformation implements ProjectionInformation { /** * Creates a new {@link DefaultProjectionInformation} for the given type. - * + * * @param type must not be {@literal null}. */ public DefaultProjectionInformation(Class type) { @@ -47,10 +49,10 @@ class DefaultProjectionInformation implements ProjectionInformation { Assert.notNull(type, "Projection type must not be null!"); this.projectionType = type; - this.properties = Arrays.asList(BeanUtils.getPropertyDescriptors(type)); + this.properties = collectDescriptors(type); } - /* + /* * (non-Javadoc) * @see org.springframework.data.projection.ProjectionInformation#getType() */ @@ -71,7 +73,7 @@ class DefaultProjectionInformation implements ProjectionInformation { .collect(Collectors.toList()); } - /* + /* * (non-Javadoc) * @see org.springframework.data.projection.ProjectionInformation#isDynamic() */ @@ -84,7 +86,7 @@ class DefaultProjectionInformation implements ProjectionInformation { * Returns whether the given {@link PropertyDescriptor} describes an input property for the projection, i.e. a * property that needs to be present on the source to be able to create reasonable projections for the type the * descriptor was looked up on. - * + * * @param descriptor will never be {@literal null}. * @return */ @@ -92,6 +94,26 @@ class DefaultProjectionInformation implements ProjectionInformation { return true; } + /** + * Collects {@link PropertyDescriptor}s for all properties exposed by the given type and all its super interfaces. + * + * @param type must not be {@literal null}. + * @return + */ + private static List collectDescriptors(Class type) { + + List result = new ArrayList(); + result.addAll(Arrays.stream(BeanUtils.getPropertyDescriptors(type))// + .filter(it -> !hasDefaultGetter(it))// + .collect(Collectors.toList())); + + for (Class interfaze : type.getInterfaces()) { + result.addAll(collectDescriptors(interfaze)); + } + + return result.stream().distinct().collect(Collectors.toList()); + } + /** * Returns whether the given {@link PropertyDescriptor} has a getter that is a Java 8 default method. * diff --git a/src/main/java/org/springframework/data/util/Optionals.java b/src/main/java/org/springframework/data/util/Optionals.java index fe57165d2..d40a51d33 100644 --- a/src/main/java/org/springframework/data/util/Optionals.java +++ b/src/main/java/org/springframework/data/util/Optionals.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import org.springframework.util.Assert; /** * Utility methods to work with {@link Optional}s. - * + * * @author Oliver Gierke */ @UtilityClass @@ -40,7 +40,7 @@ public class Optionals { /** * Returns whether any of the given {@link Optional}s is present. - * + * * @param optionals must not be {@literal null}. * @return */ @@ -53,7 +53,7 @@ public class Optionals { /** * Turns the given {@link Optional} into a one-element {@link Stream} or an empty one if not present. - * + * * @param optionals must not be {@literal null}. * @return */ @@ -67,7 +67,7 @@ public class Optionals { /** * Applies the given function to the elements of the source and returns the first non-empty result. - * + * * @param source must not be {@literal null}. * @param function must not be {@literal null}. * @return @@ -85,7 +85,7 @@ public class Optionals { /** * Applies the given function to the elements of the source and returns the first non-empty result. - * + * * @param source must not be {@literal null}. * @param function must not be {@literal null}. * @return @@ -103,7 +103,7 @@ public class Optionals { /** * Invokes the given {@link Supplier}s for {@link Optional} results one by one and returns the first non-empty one. - * + * * @param suppliers must not be {@literal null}. * @return */ @@ -117,7 +117,7 @@ public class Optionals { /** * Invokes the given {@link Supplier}s for {@link Optional} results one by one and returns the first non-empty one. - * + * * @param suppliers must not be {@literal null}. * @return */ @@ -134,7 +134,7 @@ public class Optionals { /** * Returns the next element of the given {@link Iterator} or {@link Optional#empty()} in case there is no next * element. - * + * * @param iterator must not be {@literal null}. * @return */ @@ -148,7 +148,7 @@ public class Optionals { /** * Returns a {@link Pair} if both {@link Optional} instances have values or {@link Optional#empty()} if one or both * are missing. - * + * * @param left * @param right * @return @@ -159,7 +159,7 @@ public class Optionals { /** * Invokes the given {@link BiConsumer} if all given {@link Optional} are present. - * + * * @param left must not be {@literal null}. * @param right must not be {@literal null}. * @param consumer must not be {@literal null}. @@ -178,7 +178,7 @@ public class Optionals { /** * Maps the values contained in the given {@link Optional} if both of them are present. - * + * * @param left must not be {@literal null}. * @param right must not be {@literal null}. * @param function must not be {@literal null}. diff --git a/src/test/java/org/springframework/data/projection/DefaultProjectionInformationUnitTests.java b/src/test/java/org/springframework/data/projection/DefaultProjectionInformationUnitTests.java index 4e51dca42..016ee2be2 100755 --- a/src/test/java/org/springframework/data/projection/DefaultProjectionInformationUnitTests.java +++ b/src/test/java/org/springframework/data/projection/DefaultProjectionInformationUnitTests.java @@ -60,6 +60,7 @@ public class DefaultProjectionInformationUnitTests { return descriptors.stream()// .map(FeatureDescriptor::getName)// + .distinct() .collect(Collectors.toList()); }