diff --git a/src/main/java/org/springframework/data/mapping/PropertyPath.java b/src/main/java/org/springframework/data/mapping/PropertyPath.java index 9a5a82fbe..8b6f333d2 100644 --- a/src/main/java/org/springframework/data/mapping/PropertyPath.java +++ b/src/main/java/org/springframework/data/mapping/PropertyPath.java @@ -34,9 +34,10 @@ import org.springframework.util.StringUtils; /** * Abstraction of a {@link PropertyPath} of a domain class. - * + * * @author Oliver Gierke * @author Christoph Strobl + * @author Mark Paluch */ @EqualsAndHashCode public class PropertyPath implements Streamable { @@ -56,7 +57,7 @@ public class PropertyPath implements Streamable { /** * Creates a leaf {@link PropertyPath} (no nested ones) with the given name inside the given owning type. - * + * * @param name must not be {@literal null} or empty. * @param owningType must not be {@literal null}. */ @@ -66,7 +67,7 @@ public class PropertyPath implements Streamable { /** * Creates a leaf {@link PropertyPath} (no nested ones with the given name and owning type. - * + * * @param name must not be {@literal null} or empty. * @param owningType must not be {@literal null}. * @param base the {@link PropertyPath} previously found. @@ -78,8 +79,11 @@ public class PropertyPath implements Streamable { Assert.notNull(base, "Perviously found properties must not be null!"); String propertyName = name.matches(ALL_UPPERCASE) ? name : StringUtils.uncapitalize(name); - TypeInformation propertyType = owningType.getProperty(propertyName) - .orElseThrow(() -> new PropertyReferenceException(propertyName, owningType, base)); + TypeInformation propertyType = owningType.getProperty(propertyName); + + if (propertyType == null) { + throw new PropertyReferenceException(propertyName, owningType, base); + } this.owningType = owningType; this.typeInformation = propertyType; @@ -90,7 +94,7 @@ public class PropertyPath implements Streamable { /** * Returns the owning type of the {@link PropertyPath}. - * + * * @return the owningType will never be {@literal null}. */ public TypeInformation getOwningType() { @@ -99,7 +103,7 @@ public class PropertyPath implements Streamable { /** * Returns the name of the {@link PropertyPath}. - * + * * @return the name will never be {@literal null}. */ public String getSegment() { @@ -108,7 +112,7 @@ public class PropertyPath implements Streamable { /** * Returns the leaf property of the {@link PropertyPath}. - * + * * @return will never be {@literal null}. */ public PropertyPath getLeafProperty() { @@ -125,7 +129,7 @@ public class PropertyPath implements Streamable { /** * Returns the type of the property will return the plain resolved type for simple properties, the component type for * any {@link Iterable} or the value type of a {@link java.util.Map} if the property is one. - * + * * @return */ public Class getType() { @@ -134,7 +138,7 @@ public class PropertyPath implements Streamable { /** * Returns the next nested {@link PropertyPath}. - * + * * @return the next nested {@link PropertyPath} or {@literal null} if no nested {@link PropertyPath} available. * @see #hasNext() */ @@ -145,7 +149,7 @@ public class PropertyPath implements Streamable { /** * Returns whether there is a nested {@link PropertyPath}. If this returns {@literal true} you can expect * {@link #next()} to return a non- {@literal null} value. - * + * * @return */ public boolean hasNext() { @@ -154,7 +158,7 @@ public class PropertyPath implements Streamable { /** * Returns the {@link PropertyPath} in dot notation. - * + * * @return */ public String toDotPath() { @@ -168,14 +172,14 @@ public class PropertyPath implements Streamable { /** * Returns whether the {@link PropertyPath} is actually a collection. - * + * * @return */ public boolean isCollection() { return isCollection; } - /* + /* * (non-Javadoc) * @see java.lang.Iterable#iterator() */ @@ -202,7 +206,7 @@ public class PropertyPath implements Streamable { /** * Extracts the {@link PropertyPath} chain from the given source {@link String} and type. - * + * * @param source * @param type * @return @@ -213,7 +217,8 @@ public class PropertyPath implements Streamable { /** * Extracts the {@link PropertyPath} chain from the given source {@link String} and {@link TypeInformation}.
- * Uses {@link #SPLITTER} by default and {@link #SPLITTER_FOR_QUOTED} for {@link Pattern#quote(String) quoted} literals. + * Uses {@link #SPLITTER} by default and {@link #SPLITTER_FOR_QUOTED} for {@link Pattern#quote(String) quoted} + * literals. * * @param source must not be {@literal null}. * @param type @@ -256,7 +261,7 @@ public class PropertyPath implements Streamable { /** * Creates a new {@link PropertyPath} as subordinary of the given {@link PropertyPath}. - * + * * @param source * @param base * @return @@ -275,7 +280,7 @@ public class PropertyPath implements Streamable { * the given source for camel-case parts and traverse the {@link String} along its parts starting with the entire one * and chewing off parts from the right side then. Whenever a valid property for the given class is found, the tail * will be traversed for subordinary properties of the just found one and so on. - * + * * @param source * @param type * @return @@ -288,7 +293,7 @@ public class PropertyPath implements Streamable { * Tries to look up a chain of {@link PropertyPath}s by trying the givne source first. If that fails it will split the * source apart at camel case borders (starting from the right side) and try to look up a {@link PropertyPath} from * the calculated head and recombined new tail and additional tail. - * + * * @param source * @param type * @param addTail @@ -344,7 +349,7 @@ public class PropertyPath implements Streamable { throw exception; } - /* + /* * (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java b/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java index fd7c4bcb0..65f52e22a 100644 --- a/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java @@ -268,7 +268,16 @@ public abstract class AbstractPersistentProperty

*/ @Override public Class getMapValueType() { - return isMap() ? information.getMapValueType().map(TypeInformation::getType).orElse(null) : null; + + if (isMap()) { + + TypeInformation mapValueType = information.getMapValueType(); + if (mapValueType != null) { + return mapValueType.getType(); + } + } + + return null; } /* diff --git a/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/src/main/java/org/springframework/data/repository/query/QueryMethod.java index 62831a4ed..46cd5b866 100644 --- a/src/main/java/org/springframework/data/repository/query/QueryMethod.java +++ b/src/main/java/org/springframework/data/repository/query/QueryMethod.java @@ -37,11 +37,12 @@ import org.springframework.util.Assert; /** * Abstraction of a method that is designated to execute a finder query. Enriches the standard {@link Method} interface * with specific information that is necessary to construct {@link RepositoryQuery}s for the method. - * + * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl * @author Maciek Opała + * @author Mark Paluch */ public class QueryMethod { @@ -55,7 +56,7 @@ public class QueryMethod { /** * Creates a new {@link QueryMethod} from the given parameters. Looks up the correct query to use for following * invocations of the method given. - * + * * @param method must not be {@literal null}. * @param metadata must not be {@literal null}. * @param factory must not be {@literal null}. @@ -113,7 +114,7 @@ public class QueryMethod { /** * Creates a {@link Parameters} instance. - * + * * @param method * @return must not return {@literal null}. */ @@ -123,7 +124,7 @@ public class QueryMethod { /** * Returns the method's name. - * + * * @return */ public String getName() { @@ -137,7 +138,7 @@ public class QueryMethod { /** * Returns the name of the named query this method belongs to. - * + * * @return */ public String getNamedQueryName() { @@ -146,7 +147,7 @@ public class QueryMethod { /** * Returns the domain class the query method is targeted at. - * + * * @return will never be {@literal null}. */ protected Class getDomainClass() { @@ -155,7 +156,7 @@ public class QueryMethod { /** * Returns the type of the object that will be returned. - * + * * @return */ public Class getReturnedObjectType() { @@ -164,7 +165,7 @@ public class QueryMethod { /** * Returns whether the finder will actually return a collection of entities or a single one. - * + * * @return */ public boolean isCollectionQuery() { @@ -190,7 +191,7 @@ public class QueryMethod { /** * Returns whether the query method will return a {@link Slice}. - * + * * @return * @since 1.8 */ @@ -200,7 +201,7 @@ public class QueryMethod { /** * Returns whether the finder will return a {@link Page} of results. - * + * * @return */ public final boolean isPageQuery() { @@ -209,7 +210,7 @@ public class QueryMethod { /** * Returns whether the query method is a modifying one. - * + * * @return */ public boolean isModifyingQuery() { @@ -218,7 +219,7 @@ public class QueryMethod { /** * Returns whether the query for this method actually returns entities. - * + * * @return */ public boolean isQueryForEntity() { @@ -227,7 +228,7 @@ public class QueryMethod { /** * Returns whether the method returns a Stream. - * + * * @return * @since 1.10 */ @@ -237,7 +238,7 @@ public class QueryMethod { /** * Returns the {@link Parameters} wrapper to gain additional information about {@link Method} parameters. - * + * * @return */ public Parameters getParameters() { @@ -246,7 +247,7 @@ public class QueryMethod { /** * Returns the {@link ResultProcessor} to be used with the query method. - * + * * @return the resultFactory */ public ResultProcessor getResultProcessor() { @@ -265,10 +266,17 @@ public class QueryMethod { private static Class potentiallyUnwrapReturnTypeFor(Method method) { if (QueryExecutionConverters.supports(method.getReturnType())) { + // unwrap only one level to handle cases like Future> correctly. - return ClassTypeInformation.fromReturnTypeOf(method).getComponentType().map(TypeInformation::getType) - .orElseThrow(() -> new IllegalStateException( - String.format("Couldn't find component type for return value of method %s!", method))); + + TypeInformation componentType = ClassTypeInformation.fromReturnTypeOf(method).getComponentType(); + + if (componentType == null) { + throw new IllegalStateException( + String.format("Couldn't find component type for return value of method %s!", method)); + } + + return componentType.getType(); } return method.getReturnType(); diff --git a/src/main/java/org/springframework/data/util/GenericArrayTypeInformation.java b/src/main/java/org/springframework/data/util/GenericArrayTypeInformation.java index dad78db6c..821e1af8b 100644 --- a/src/main/java/org/springframework/data/util/GenericArrayTypeInformation.java +++ b/src/main/java/org/springframework/data/util/GenericArrayTypeInformation.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014 the original author or authors. + * Copyright 2011-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. @@ -20,11 +20,10 @@ import java.lang.reflect.GenericArrayType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.Map; -import java.util.Optional; /** * Special {@link TypeDiscoverer} handling {@link GenericArrayType}s. - * + * * @author Oliver Gierke */ class GenericArrayTypeInformation extends ParentTypeAwareTypeInformation { @@ -34,7 +33,7 @@ class GenericArrayTypeInformation extends ParentTypeAwareTypeInformation { /** * Creates a new {@link GenericArrayTypeInformation} for the given {@link GenericArrayTypeInformation} and * {@link TypeDiscoverer}. - * + * * @param type must not be {@literal null}. * @param parent must not be {@literal null}. * @param typeVariableMap must not be {@literal null}. @@ -61,13 +60,13 @@ class GenericArrayTypeInformation extends ParentTypeAwareTypeInformation { * @see org.springframework.data.util.TypeDiscoverer#doGetComponentType() */ @Override - protected Optional> doGetComponentType() { + protected TypeInformation doGetComponentType() { Type componentType = type.getGenericComponentType(); - return Optional.of(createInfo(componentType)); + return createInfo(componentType); } - /* + /* * (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/src/main/java/org/springframework/data/util/ParameterizedTypeInformation.java b/src/main/java/org/springframework/data/util/ParameterizedTypeInformation.java index 63949f369..75719eec8 100644 --- a/src/main/java/org/springframework/data/util/ParameterizedTypeInformation.java +++ b/src/main/java/org/springframework/data/util/ParameterizedTypeInformation.java @@ -31,7 +31,7 @@ import org.springframework.util.StringUtils; /** * Base class for all types that include parameterization of some kind. Crucial as we have to take note of the parent * class we will have to resolve generic parameters against. - * + * * @author Oliver Gierke * @author Mark Paluch * @author Christoph Strobl @@ -43,7 +43,7 @@ class ParameterizedTypeInformation extends ParentTypeAwareTypeInformation /** * Creates a new {@link ParameterizedTypeInformation} for the given {@link Type} and parent {@link TypeDiscoverer}. - * + * * @param type must not be {@literal null} * @param parent must not be {@literal null} */ @@ -59,14 +59,14 @@ class ParameterizedTypeInformation extends ParentTypeAwareTypeInformation * @see org.springframework.data.util.TypeDiscoverer#doGetMapValueType() */ @Override - protected Optional> doGetMapValueType() { + protected TypeInformation doGetMapValueType() { if (Map.class.isAssignableFrom(getType())) { Type[] arguments = type.getActualTypeArguments(); if (arguments.length > 1) { - return Optional.of(createInfo(arguments[1])); + return createInfo(arguments[1]); } } @@ -79,14 +79,14 @@ class ParameterizedTypeInformation extends ParentTypeAwareTypeInformation Optional> result = supertypes.stream()// .map(it -> Pair.of(it, resolveType(it)))// .filter(it -> Map.class.isAssignableFrom(it.getSecond()))// - .>map(it -> { + .> map(it -> { ParameterizedType parameterizedSupertype = (ParameterizedType) it.getFirst(); Type[] arguments = parameterizedSupertype.getActualTypeArguments(); return createInfo(arguments[1]); }).findFirst(); - return result.isPresent() ? result : super.doGetMapValueType(); + return result.orElseGet(super::doGetMapValueType); } /* @@ -105,7 +105,7 @@ class ParameterizedTypeInformation extends ParentTypeAwareTypeInformation return result; } - /* + /* * (non-Javadoc) * @see org.springframework.data.util.TypeDiscoverer#isAssignableFrom(org.springframework.data.util.TypeInformation) */ @@ -147,11 +147,11 @@ class ParameterizedTypeInformation extends ParentTypeAwareTypeInformation * @see org.springframework.data.util.TypeDiscoverer#doGetComponentType() */ @Override - protected Optional> doGetComponentType() { - return Optional.of(createInfo(type.getActualTypeArguments()[0])); + protected TypeInformation doGetComponentType() { + return createInfo(type.getActualTypeArguments()[0]); } - /* + /* * (non-Javadoc) * @see org.springframework.data.util.ParentTypeAwareTypeInformation#equals(java.lang.Object) */ @@ -175,7 +175,7 @@ class ParameterizedTypeInformation extends ParentTypeAwareTypeInformation return super.equals(obj); } - /* + /* * (non-Javadoc) * @see org.springframework.data.util.ParentTypeAwareTypeInformation#hashCode() */ @@ -184,7 +184,7 @@ class ParameterizedTypeInformation extends ParentTypeAwareTypeInformation return isResolvedCompletely() ? this.type.hashCode() : super.hashCode(); } - /* + /* * (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/src/main/java/org/springframework/data/util/TypeDiscoverer.java b/src/main/java/org/springframework/data/util/TypeDiscoverer.java index 39697c3de..d936ade19 100644 --- a/src/main/java/org/springframework/data/util/TypeDiscoverer.java +++ b/src/main/java/org/springframework/data/util/TypeDiscoverer.java @@ -28,7 +28,16 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -43,6 +52,7 @@ import org.springframework.util.ReflectionUtils; * * @author Oliver Gierke * @author Christoph Strobl + * @author Mark Paluch */ class TypeDiscoverer implements TypeInformation { @@ -68,8 +78,8 @@ class TypeDiscoverer implements TypeInformation { private final int hashCode; private final Lazy> resolvedType; - private final Lazy>> componentType; - private final Lazy>> valueType; + private final Lazy> componentType; + private final Lazy> valueType; /** * Creates a new {@link TypeDiscoverer} for the given type, type variable map and parent. @@ -99,19 +109,17 @@ class TypeDiscoverer implements TypeInformation { return typeVariableMap; } - private TypeInformation createInfo(Optional fieldType) { - return fieldType.map(this::createInfo).orElseThrow(IllegalArgumentException::new); - } - /** * Creates {@link TypeInformation} for the given {@link Type}. * - * @param fieldType + * @param fieldType must not be {@literal null}. * @return */ @SuppressWarnings({ "rawtypes", "unchecked", "deprecation" }) protected TypeInformation createInfo(Type fieldType) { + Assert.notNull(fieldType, "Field type must not be null!"); + if (fieldType.equals(this.type)) { return this; } @@ -203,18 +211,22 @@ class TypeDiscoverer implements TypeInformation { * (non-Javadoc) * @see org.springframework.data.util.TypeInformation#getProperty(java.lang.String) */ - public Optional> getProperty(String fieldname) { + public TypeInformation getProperty(String fieldname) { int separatorIndex = fieldname.indexOf('.'); if (separatorIndex == -1) { - return fieldTypes.computeIfAbsent(fieldname, this::getPropertyInformation); + return fieldTypes.computeIfAbsent(fieldname, this::getPropertyInformation).orElse(null); } String head = fieldname.substring(0, separatorIndex); - Optional> info = getProperty(head); + TypeInformation info = getProperty(head); - return info.map(it -> it.getProperty(fieldname.substring(separatorIndex + 1))).orElseGet(Optional::empty); + if (info == null) { + return null; + } + + return info.getProperty(fieldname.substring(separatorIndex + 1)); } /** @@ -235,7 +247,6 @@ class TypeDiscoverer implements TypeInformation { } return findPropertyDescriptor(rawType, fieldname).map(it -> createInfo(getGenericType(it))); - } /** @@ -269,22 +280,22 @@ class TypeDiscoverer implements TypeInformation { * @param descriptor must not be {@literal null} * @return */ - private static Optional getGenericType(PropertyDescriptor descriptor) { + private static Type getGenericType(PropertyDescriptor descriptor) { Method method = descriptor.getReadMethod(); if (method != null) { - return Optional.of(method.getGenericReturnType()); + return method.getGenericReturnType(); } method = descriptor.getWriteMethod(); if (method == null) { - return Optional.empty(); + return null; } Type[] parameterTypes = method.getGenericParameterTypes(); - return Optional.ofNullable(parameterTypes.length == 0 ? null : parameterTypes[0]); + return parameterTypes.length == 0 ? null : parameterTypes[0]; } /* @@ -311,11 +322,11 @@ class TypeDiscoverer implements TypeInformation { public TypeInformation getActualType() { if (isMap()) { - return getMapValueType().orElse(null); + return getMapValueType(); } if (isCollectionLike()) { - return getComponentType().orElse(null); + return getComponentType(); } return this; @@ -342,12 +353,13 @@ class TypeDiscoverer implements TypeInformation { * (non-Javadoc) * @see org.springframework.data.util.TypeInformation#getMapValueType() */ - public Optional> getMapValueType() { + public TypeInformation getMapValueType() { return valueType.get(); } - protected Optional> doGetMapValueType() { - return isMap() ? getTypeArgument(getBaseType(MAP_TYPES), 1) : getTypeArguments().stream().skip(1).findFirst(); + protected TypeInformation doGetMapValueType() { + return isMap() ? getTypeArgument(getBaseType(MAP_TYPES), 1) + : getTypeArguments().stream().skip(1).findFirst().orElse(null); } /* @@ -365,16 +377,16 @@ class TypeDiscoverer implements TypeInformation { * (non-Javadoc) * @see org.springframework.data.util.TypeInformation#getComponentType() */ - public final Optional> getComponentType() { + public final TypeInformation getComponentType() { return componentType.get(); } - protected Optional> doGetComponentType() { + protected TypeInformation doGetComponentType() { Class rawType = getType(); if (rawType.isArray()) { - return Optional.of(createInfo(rawType.getComponentType())); + return createInfo(rawType.getComponentType()); } if (isMap()) { @@ -387,7 +399,7 @@ class TypeDiscoverer implements TypeInformation { List> arguments = getTypeArguments(); - return arguments.size() > 0 ? Optional.of(arguments.get(0)) : Optional.empty(); + return arguments.size() > 0 ? arguments.get(0) : null; } /* @@ -486,16 +498,16 @@ class TypeDiscoverer implements TypeInformation { : createInfo(new SyntheticParamterizedType(type, arguments))); } - private Optional> getTypeArgument(Class bound, int index) { + private TypeInformation getTypeArgument(Class bound, int index) { Class[] arguments = GenericTypeResolver.resolveTypeArguments(getType(), bound); if (arguments == null) { - return Optional.ofNullable( - getSuperTypeInformation(bound) instanceof ParameterizedTypeInformation ? ClassTypeInformation.OBJECT : null); + return getSuperTypeInformation(bound) instanceof ParameterizedTypeInformation ? ClassTypeInformation.OBJECT + : null; } - return Optional.of(createInfo(arguments[index])); + return createInfo(arguments[index]); } private Class getBaseType(Class[] candidates) { diff --git a/src/main/java/org/springframework/data/util/TypeInformation.java b/src/main/java/org/springframework/data/util/TypeInformation.java index e04de66ba..f212861df 100644 --- a/src/main/java/org/springframework/data/util/TypeInformation.java +++ b/src/main/java/org/springframework/data/util/TypeInformation.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2015 the original author or authors. + * Copyright 2008-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. @@ -18,19 +18,19 @@ package org.springframework.data.util; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.List; -import java.util.Optional; /** * Interface to access property types and resolving generics on the way. Starting with a {@link ClassTypeInformation} * you can traverse properties using {@link #getProperty(String)} to access type information. - * + * * @author Oliver Gierke + * @author Mark Paluch */ public interface TypeInformation { /** * Returns the {@link TypeInformation}s for the parameters of the given {@link Constructor}. - * + * * @param constructor must not be {@literal null}. * @return */ @@ -39,69 +39,106 @@ public interface TypeInformation { /** * Returns the property information for the property with the given name. Supports property traversal through dot * notation. - * + * * @param property * @return */ - Optional> getProperty(String property); + TypeInformation getProperty(String property); + /** + * Returns the property information for the property with the given name or throw {@link IllegalArgumentException} if + * the type information cannot be resolved. Supports property traversal through dot notation. + * + * @param property + * @return + * @throws IllegalArgumentException if the type information cannot be resolved. + * @since 2.0 + */ default TypeInformation getRequiredProperty(String property) { - return getProperty(property).orElseThrow(() -> new IllegalArgumentException( - String.format("Could not find required property %s on %s!", property, getType()))); + + TypeInformation typeInformation = getProperty(property); + + if (typeInformation != null) { + return typeInformation; + } + + throw new IllegalArgumentException( + String.format("Could not find required property %s on %s!", property, getType())); } /** * Returns whether the type can be considered a collection, which means it's a container of elements, e.g. a * {@link java.util.Collection} and {@link java.lang.reflect.Array} or anything implementing {@link Iterable}. If this * returns {@literal true} you can expect {@link #getComponentType()} to return a non-{@literal null} value. - * + * * @return */ boolean isCollectionLike(); /** * Returns the component type for {@link java.util.Collection}s or the key type for {@link java.util.Map}s. - * + * * @return */ - Optional> getComponentType(); + TypeInformation getComponentType(); /** * Returns the component type for {@link java.util.Collection}s, the key type for {@link java.util.Map}s or the single - * generic type if available throwing an exception if it can't be resolved. - * + * generic type if available. Throws {@link IllegalStateException} if the component value type cannot be resolved. + * * @return * @throws IllegalStateException if the component type cannot be resolved, e.g. if a raw type is used or the type is * not generic in the first place. + * @since 2.0 */ default TypeInformation getRequiredComponentType() { - return getComponentType().orElseThrow( - () -> new IllegalStateException(String.format("Can't resolve required component type for %s!", getType()))); + + TypeInformation componentType = getComponentType(); + + if (componentType != null) { + return getComponentType(); + } + + throw new IllegalStateException(String.format("Can't resolve required component type for %s!", getType())); } /** * Returns whether the property is a {@link java.util.Map}. If this returns {@literal true} you can expect * {@link #getComponentType()} as well as {@link #getMapValueType()} to return something not {@literal null}. - * + * * @return */ boolean isMap(); /** * Will return the type of the value in case the underlying type is a {@link java.util.Map}. - * + * * @return */ - Optional> getMapValueType(); + TypeInformation getMapValueType(); + /** + * Will return the type of the value in case the underlying type is a {@link java.util.Map} or throw + * {@link IllegalStateException} if the map value type cannot be resolved. + * + * @return + * @throws IllegalStateException if the map value type cannot be resolved. + * @since 2.0 + */ default TypeInformation getRequiredMapValueType() { - return getMapValueType().orElseThrow( - () -> new IllegalStateException(String.format("Can't resolve required map value type for %s!", getType()))); + + TypeInformation mapValueType = getMapValueType(); + + if (mapValueType != null) { + return mapValueType; + } + + throw new IllegalStateException(String.format("Can't resolve required map value type for %s!", getType())); } /** * Returns the type of the property. Will resolve generics and the generic context of - * + * * @return */ Class getType(); @@ -109,7 +146,7 @@ public interface TypeInformation { /** * Returns a {@link ClassTypeInformation} to represent the {@link TypeInformation} of the raw type of the current * instance. - * + * * @return */ ClassTypeInformation getRawTypeInformation(); @@ -117,7 +154,7 @@ public interface TypeInformation { /** * Transparently returns the {@link java.util.Map} value type if the type is a {@link java.util.Map}, returns the * component type if the type {@link #isCollectionLike()} or the simple type if none of this applies. - * + * * @return */ TypeInformation getActualType(); @@ -125,7 +162,7 @@ public interface TypeInformation { /** * Returns a {@link TypeInformation} for the return type of the given {@link Method}. Will potentially resolve * generics information against the current types type parameter bindings. - * + * * @param method must not be {@literal null}. * @return */ @@ -133,7 +170,7 @@ public interface TypeInformation { /** * Returns the {@link TypeInformation}s for the parameters of the given {@link Method}. - * + * * @param method must not be {@literal null}. * @return */ @@ -141,7 +178,7 @@ public interface TypeInformation { /** * Returns the {@link TypeInformation} for the given raw super type. - * + * * @param superType must not be {@literal null}. * @return the {@link TypeInformation} for the given raw super type or {@literal null} in case the current * {@link TypeInformation} does not implement the given type. @@ -152,7 +189,7 @@ public interface TypeInformation { * Returns if the current {@link TypeInformation} can be safely assigned to the given one. Mimics semantics of * {@link Class#isAssignableFrom(Class)} but takes generics into account. Thus it will allow to detect that a * {@code List} is assignable to {@code List}. - * + * * @param target * @return */ @@ -160,7 +197,7 @@ public interface TypeInformation { /** * Returns the {@link TypeInformation} for the type arguments of the current {@link TypeInformation}. - * + * * @return */ List> getTypeArguments(); @@ -169,7 +206,7 @@ public interface TypeInformation { * Specializes the given (raw) {@link ClassTypeInformation} using the context of the current potentially parameterized * type, basically turning the given raw type into a parameterized one. Will return the given type as is if no * generics are involved. - * + * * @param type must not be {@literal null}. * @return will never be {@literal null}. */ diff --git a/src/test/java/org/springframework/data/convert/DefaultTypeMapperUnitTests.java b/src/test/java/org/springframework/data/convert/DefaultTypeMapperUnitTests.java index 0ea5dcc2c..96edb202a 100755 --- a/src/test/java/org/springframework/data/convert/DefaultTypeMapperUnitTests.java +++ b/src/test/java/org/springframework/data/convert/DefaultTypeMapperUnitTests.java @@ -34,6 +34,7 @@ import org.springframework.data.util.TypeInformation; * Unit tests for {@link DefaultTypeMapper}. * * @author Oliver Gierke + * @author Mark Paluch */ @RunWith(MockitoJUnitRunner.class) public class DefaultTypeMapperUnitTests { @@ -81,8 +82,7 @@ public class DefaultTypeMapperUnitTests { public void specializesRawSourceTypeUsingGenericContext() { ClassTypeInformation root = ClassTypeInformation.from(Foo.class); - TypeInformation propertyType = root.getProperty("abstractBar") - .orElseThrow(() -> new IllegalStateException("Property abstractBar not found!")); + TypeInformation propertyType = root.getProperty("abstractBar"); TypeInformation barType = ClassTypeInformation.from(Bar.class); doReturn(Alias.of(barType)).when(accessor).readAliasFrom(source); @@ -95,8 +95,7 @@ public class DefaultTypeMapperUnitTests { TypeInformation typeInformation = TypeInformation.class.cast(result); assertThat(typeInformation.getType()).isEqualTo(Bar.class); - assertThat(typeInformation.getProperty("field")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Character.class)); + assertThat(typeInformation.getProperty("field").getType()).isEqualTo(Character.class); } static class TypeWithAbstractGenericType { diff --git a/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java b/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java index 988c68b0f..1ad870e38 100755 --- a/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java +++ b/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java @@ -16,7 +16,7 @@ package org.springframework.data.util; import static org.assertj.core.api.Assertions.*; -import static org.springframework.data.util.ClassTypeInformation.from; +import static org.springframework.data.util.ClassTypeInformation.*; import javaslang.collection.Traversable; @@ -28,14 +28,14 @@ import java.util.Map; import java.util.Set; import java.util.SortedMap; -import org.assertj.core.api.OptionalAssert; import org.junit.Test; import org.springframework.data.mapping.Person; /** * Unit tests for {@link ClassTypeInformation}. - * + * * @author Oliver Gierke + * @author Mark Paluch */ public class ClassTypeInformationUnitTests { @@ -46,11 +46,11 @@ public class ClassTypeInformationUnitTests { assertThat(discoverer.getType()).isEqualTo(ConcreteType.class); - OptionalAssert> assertThat = assertThat(discoverer.getProperty("content")); + TypeInformation content = discoverer.getProperty("content"); - assertThat.hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); - assertThat.flatMap(TypeInformation::getComponentType).isNotPresent(); - assertThat.flatMap(TypeInformation::getMapValueType).isNotPresent(); + assertThat(content.getType()).isEqualTo(String.class); + assertThat(content.getComponentType()).isNull(); + assertThat(content.getMapValueType()).isNull(); } @Test @@ -59,14 +59,13 @@ public class ClassTypeInformationUnitTests { TypeInformation discoverer = ClassTypeInformation.from(ConcreteWrapper.class); assertThat(discoverer.getType()).isEqualTo(ConcreteWrapper.class); - assertThat(discoverer.getProperty("wrapped")).hasValueSatisfying(it -> { + assertThat(discoverer.getProperty("wrapped")).satisfies(it -> { assertThat(it.getType()).isEqualTo(GenericType.class); - assertThat(it.getProperty("content")) - .hasValueSatisfying(nested -> assertThat(nested.getType()).isEqualTo(String.class)); + assertThat(it.getProperty("content")).satisfies(nested -> assertThat(nested.getType()).isEqualTo(String.class)); }); assertThat(discoverer.getProperty("wrapped.content")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + .satisfies(it -> assertThat(it.getType()).isEqualTo(String.class)); } @Test @@ -74,8 +73,7 @@ public class ClassTypeInformationUnitTests { public void discoversBoundType() { TypeInformation information = ClassTypeInformation.from(GenericTypeWithBound.class); - assertThat(information.getProperty("person")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Person.class)); + assertThat(information.getProperty("person")).satisfies(it -> assertThat(it.getType()).isEqualTo(Person.class)); } @Test @@ -84,7 +82,7 @@ public class ClassTypeInformationUnitTests { TypeInformation information = ClassTypeInformation .from(SpecialGenericTypeWithBound.class); assertThat(information.getProperty("person")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(SpecialPerson.class)); + .satisfies(it -> assertThat(it.getType()).isEqualTo(SpecialPerson.class)); } @Test @@ -94,9 +92,9 @@ public class ClassTypeInformationUnitTests { TypeInformation information = ClassTypeInformation.from(AnotherGenericType.class); assertThat(information.getProperty("nested")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(GenericTypeWithBound.class)); + .satisfies(it -> assertThat(it.getType()).isEqualTo(GenericTypeWithBound.class)); assertThat(information.getProperty("nested.person")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Person.class)); + .satisfies(it -> assertThat(it.getType()).isEqualTo(Person.class)); } @Test @@ -104,47 +102,41 @@ public class ClassTypeInformationUnitTests { TypeInformation information = ClassTypeInformation.from(StringCollectionContainer.class); - OptionalAssert> optional = assertThat(information.getProperty("array")); + TypeInformation array = information.getProperty("array"); - optional.flatMap(TypeInformation::getComponentType) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); - optional.map(TypeInformation::getType).hasValueSatisfying(it -> { - assertThat(it).isEqualTo(String[].class); - assertThat(it.isArray()).isTrue(); - }); + assertThat(array.getComponentType().getType()).isEqualTo(String.class); + assertThat(array.getType()).isEqualTo(String[].class); + assertThat(array.getType().isArray()).isTrue(); - optional = assertThat(information.getProperty("foo")); + TypeInformation foo = information.getProperty("foo"); - optional.hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Collection[].class)); - optional.flatMap(TypeInformation::getComponentType).hasValueSatisfying(it -> { + assertThat(foo.getType()).isEqualTo(Collection[].class); + assertThat(foo.getComponentType()).satisfies(it -> { assertThat(it.getType()).isEqualTo(Collection.class); - assertThat(it.getComponentType()) - .hasValueSatisfying(nested -> assertThat(nested.getType()).isEqualTo(String.class)); + assertThat(it.getComponentType()).satisfies(nested -> assertThat(nested.getType()).isEqualTo(String.class)); }); - optional = assertThat(information.getProperty("rawSet")); + TypeInformation rawSet = information.getProperty("rawSet"); - optional.hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Set.class)); - optional.flatMap(TypeInformation::getComponentType) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Object.class)); - optional.flatMap(TypeInformation::getMapValueType).isNotPresent(); + assertThat(rawSet.getType()).isEqualTo(Set.class); + assertThat(rawSet.getComponentType().getType()).isEqualTo(Object.class); + assertThat(rawSet.getMapValueType()).isNull(); } @Test public void discoversMapValueType() { TypeInformation information = ClassTypeInformation.from(StringMapContainer.class); - OptionalAssert> assertion = assertThat(information.getProperty("genericMap")); - assertion.hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Map.class)); - assertion.flatMap(TypeInformation::getMapValueType) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + TypeInformation genericMap = information.getProperty("genericMap"); - assertion = assertThat(information.getProperty("map")); + assertThat(genericMap.getType()).isEqualTo(Map.class); + assertThat(genericMap.getMapValueType().getType()).isEqualTo(String.class); - assertion.hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Map.class)); - assertion.flatMap(TypeInformation::getMapValueType) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Calendar.class)); + TypeInformation map = information.getProperty("map"); + + assertThat(map.getType()).isEqualTo(Map.class); + assertThat(map.getMapValueType().getType()).isEqualTo(Calendar.class); } @Test @@ -161,8 +153,8 @@ public class ClassTypeInformationUnitTests { TypeInformation from = ClassTypeInformation.from(PropertyGetter.class); - assertThat(from.getProperty("_name")).hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); - assertThat(from.getProperty("name")).hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(byte[].class)); + assertThat(from.getProperty("_name")).satisfies(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(from.getProperty("name")).satisfies(it -> assertThat(it.getType()).isEqualTo(byte[].class)); } @Test // DATACMNS-77 @@ -177,19 +169,17 @@ public class ClassTypeInformationUnitTests { TypeInformation information = ClassTypeInformation.from(ClassWithWildCardBound.class); - OptionalAssert> assertion = assertThat(information.getProperty("wildcard")); + TypeInformation wildcard = information.getProperty("wildcard"); - assertion.map(TypeInformation::isCollectionLike).hasValue(true); - assertion.flatMap(TypeInformation::getComponentType) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(wildcard.isCollectionLike()).isTrue(); + assertThat(wildcard.getComponentType().getType()).isEqualTo(String.class); - assertion = assertThat(information.getProperty("complexWildcard")); + TypeInformation complexWildcard = information.getProperty("complexWildcard"); - assertion.map(TypeInformation::isCollectionLike).hasValue(true); - assertion.flatMap(TypeInformation::getComponentType).hasValueSatisfying(it -> { + assertThat(complexWildcard.isCollectionLike()).isTrue(); + assertThat(complexWildcard.getComponentType()).satisfies(it -> { assertThat(it.isCollectionLike()).isEqualTo(true); - assertThat(it.getComponentType()) - .hasValueSatisfying(nested -> assertThat(nested.getType()).isEqualTo(String.class)); + assertThat(it.getComponentType()).satisfies(nested -> assertThat(nested.getType()).isEqualTo(String.class)); }); } @@ -279,8 +269,7 @@ public class ClassTypeInformationUnitTests { TypeInformation information = from(String[][].class); assertThat(information.getType()).isEqualTo(String[][].class); - assertThat(information.getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String[].class)); + assertThat(information.getComponentType()).satisfies(it -> assertThat(it.getType()).isEqualTo(String[].class)); assertThat(information.getActualType().getActualType().getType()).isEqualTo(String.class); } @@ -289,7 +278,7 @@ public class ClassTypeInformationUnitTests { TypeInformation information = from(Product.class); - assertThat(information.getProperty("category.id")).hasValue(from(Long.class)); + assertThat(information.getProperty("category.id")).isEqualTo(from(Long.class)); } @Test(expected = IllegalArgumentException.class) // DATACMNS-387 @@ -300,30 +289,28 @@ public class ClassTypeInformationUnitTests { @Test // DATACMNS-422 public void returnsEmptyOptionalForRawTypesOnly() { - assertThat(from(MyRawIterable.class).getComponentType()).isNotPresent(); - assertThat(from(MyIterable.class).getComponentType()).isPresent(); + assertThat(from(MyRawIterable.class).getComponentType()).isNull(); + assertThat(from(MyIterable.class).getComponentType()).isNotNull(); } @Test // DATACMNS-440 public void detectsSpecialMapAsMapValueType() { - OptionalAssert> assertion = assertThat( - ClassTypeInformation.from(SuperGenerics.class).getProperty("seriously")); + TypeInformation seriously = ClassTypeInformation.from(SuperGenerics.class).getProperty("seriously"); - assertion// - // Type - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(SortedMap.class))// + // Type + assertThat(seriously.getType()).isEqualTo(SortedMap.class); - // Map value type - .flatMap(TypeInformation::getMapValueType).hasValueSatisfying(value -> { - assertThat(value.getType()).isEqualTo(SortedMap.class); - assertThat(value.getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); - }).flatMap(TypeInformation::getMapValueType).hasValueSatisfying(nestedValue -> { - assertThat(nestedValue.getType()).isEqualTo(List.class); - assertThat(nestedValue.getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Person.class)); - }); + // Map value type + assertThat(seriously.getMapValueType()).satisfies(value -> { + assertThat(value.getType()).isEqualTo(SortedMap.class); + assertThat(value.getComponentType()).satisfies(it -> assertThat(it.getType()).isEqualTo(String.class)); + }); + + assertThat(seriously.getMapValueType().getMapValueType()).satisfies(nestedValue -> { + assertThat(nestedValue.getType()).isEqualTo(List.class); + assertThat(nestedValue.getComponentType()).satisfies(it -> assertThat(it.getType()).isEqualTo(Person.class)); + }); } @Test // DATACMNS-446 @@ -337,18 +324,16 @@ public class ClassTypeInformationUnitTests { ClassTypeInformation rootType = from(ConcreteRoot.class); - assertThat(rootType.getProperty("subs"))// - .map(TypeInformation::getActualType)// - .flatMap(it -> it.getProperty("subSub"))// - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(ConcreteSubSub.class)); + assertThat(rootType.getProperty("subs").getActualType().getProperty("subSub").getType())// + .isEqualTo(ConcreteSubSub.class); } @Test // DATACMNS-594 public void considersGenericsOfTypeBounds() { assertThat(ClassTypeInformation.from(ConcreteRootIntermediate.class) - .getProperty("intermediate.content.intermediate.content"))// - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Leaf.class)); + .getProperty("intermediate.content.intermediate.content").getType())// + .isEqualTo(Leaf.class); } @Test // DATACMNS-783, DATACMNS-853 @@ -356,14 +341,11 @@ public class ClassTypeInformationUnitTests { ClassTypeInformation root = ClassTypeInformation.from(Foo.class); - assertThat(root.getProperty("abstractBar"))// - .map(it -> it.specialize(ClassTypeInformation.from(Bar.class)))// - .hasValueSatisfying(it -> { + assertThat(root.getProperty("abstractBar").specialize(ClassTypeInformation.from(Bar.class)))// + .satisfies(it -> { assertThat(it.getType()).isEqualTo(Bar.class); - assertThat(it.getProperty("field")) - .hasValueSatisfying(nested -> assertThat(nested.getType()).isEqualTo(Character.class)); - assertThat(it.getProperty("anotherField")) - .hasValueSatisfying(nested -> assertThat(nested.getType()).isEqualTo(Integer.class)); + assertThat(it.getProperty("field").getType()).isEqualTo(Character.class); + assertThat(it.getProperty("anotherField").getType()).isEqualTo(Integer.class); }); } @@ -373,7 +355,7 @@ public class ClassTypeInformationUnitTests { ClassTypeInformation root = ClassTypeInformation.from(Foo.class); ClassTypeInformation from = ClassTypeInformation.from(Bar.class); - assertThat(root.getProperty("object")).hasValueSatisfying(it -> assertThat(it.specialize(from)).isEqualTo(from)); + assertThat(root.getProperty("object").specialize(from)).isEqualTo(from); } @Test // DATACMNS-855 @@ -381,12 +363,10 @@ public class ClassTypeInformationUnitTests { ClassTypeInformation root = ClassTypeInformation.from(Foo.class); - OptionalAssert> assertion = assertThat(root.getProperty("abstractBar")); + TypeInformation abstractBar = root.getProperty("abstractBar"); - assertion - .map(it -> Pair.of(it.specialize(ClassTypeInformation.from(Bar.class)), - it.specialize(ClassTypeInformation.from(Bar.class))))// - .hasValueSatisfying(pair -> { + assertThat(Pair.of(abstractBar.specialize(ClassTypeInformation.from(Bar.class)), + abstractBar.specialize(ClassTypeInformation.from(Bar.class)))).satisfies(pair -> { assertThat(pair.getFirst()).isEqualTo(pair.getSecond()); assertThat(pair.getSecond()).isEqualTo(pair.getFirst()); assertThat(pair.getFirst().hashCode()).isEqualTo(pair.getSecond().hashCode()); @@ -398,8 +378,7 @@ public class ClassTypeInformationUnitTests { ClassTypeInformation information = ClassTypeInformation.from(Concrete.class); - assertThat(information.getProperty("field")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Nested.class)); + assertThat(information.getProperty("field").getType()).isEqualTo(Nested.class); } @Test // DATACMNS-940 @@ -407,8 +386,7 @@ public class ClassTypeInformationUnitTests { ClassTypeInformation information = ClassTypeInformation.from(SampleTraversable.class); - assertThat(information.getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isAssignableFrom(Integer.class)); + assertThat(information.getComponentType().getType()).isAssignableFrom(Integer.class); } @Test // DATACMNS-940 @@ -416,11 +394,9 @@ public class ClassTypeInformationUnitTests { ClassTypeInformation information = ClassTypeInformation.from(SampleMap.class); - assertThat(information.getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isAssignableFrom(String.class)); + assertThat(information.getComponentType().getType()).isAssignableFrom(String.class); - assertThat(information.getMapValueType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isAssignableFrom(Integer.class)); + assertThat(information.getMapValueType().getType()).isAssignableFrom(Integer.class); } static class StringMapContainer extends MapContainer { diff --git a/src/test/java/org/springframework/data/util/DataCmns511Tests.java b/src/test/java/org/springframework/data/util/DataCmns511Tests.java index e13ba858a..b9abed9d8 100755 --- a/src/test/java/org/springframework/data/util/DataCmns511Tests.java +++ b/src/test/java/org/springframework/data/util/DataCmns511Tests.java @@ -18,36 +18,30 @@ package org.springframework.data.util; import static org.assertj.core.api.Assertions.*; import java.util.HashSet; -import java.util.Optional; import java.util.Set; -import org.assertj.core.api.OptionalAssert; import org.junit.Test; /** * Unit tests to reproduce issues reported in DATACMNS-511. - * + * * @author Oliver Gierke + * @author Mark Paluch */ public class DataCmns511Tests { @Test // DATACMNS-511 public void detectsEqualTypeVariableTypeInformationInstances() { - OptionalAssert> assertion = assertThat( - ClassTypeInformation.from(AbstractRole.class).getProperty("createdBy")); + TypeInformation createdBy = ClassTypeInformation.from(AbstractRole.class).getProperty("createdBy"); - assertion.flatMap(it -> it.getProperty("roles"))// - .map(TypeInformation::getActualType)// - .flatMap(it -> it.getProperty("createdBy"))// - .hasValueSatisfying(second -> { + assertThat(createdBy.getProperty("roles").getActualType().getProperty("createdBy"))// + .satisfies(second -> { - Optional> third = second.getProperty("roles")// - .map(TypeInformation::getActualType)// - .flatMap(it -> it.getProperty("createdBy")); + TypeInformation third = second.getProperty("roles").getActualType().getProperty("createdBy"); - assertThat(third).hasValue(second); - assertThat(third).map(Object::hashCode).hasValue(second.hashCode()); + assertThat(third).isEqualTo(second); + assertThat(third.hashCode()).isEqualTo(second.hashCode()); }); } diff --git a/src/test/java/org/springframework/data/util/ParameterizedTypeUnitTests.java b/src/test/java/org/springframework/data/util/ParameterizedTypeUnitTests.java index 5883e9dda..7b598ae88 100755 --- a/src/test/java/org/springframework/data/util/ParameterizedTypeUnitTests.java +++ b/src/test/java/org/springframework/data/util/ParameterizedTypeUnitTests.java @@ -27,9 +27,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Optional; -import org.assertj.core.api.OptionalAssert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -38,7 +36,7 @@ import org.mockito.junit.MockitoJUnitRunner; /** * Unit tests for {@link ParameterizedTypeInformation}. - * + * * @author Oliver Gierke * @author Mark Paluch */ @@ -81,48 +79,44 @@ public class ParameterizedTypeUnitTests { public void resolvesMapValueTypeCorrectly() { TypeInformation type = ClassTypeInformation.from(Foo.class); - Optional> propertyType = type.getProperty("param"); + TypeInformation propertyType = type.getProperty("param"); + TypeInformation value = propertyType.getProperty("value"); - OptionalAssert> assertion = assertThat(propertyType); - - assertion.flatMap(it -> it.getProperty("value")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); - assertion.flatMap(TypeInformation::getMapValueType) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(value.getType()).isEqualTo(String.class); + assertThat(propertyType.getMapValueType().getType()).isEqualTo(String.class); propertyType = type.getProperty("param2"); + value = propertyType.getProperty("value"); - assertion.flatMap(it -> it.getProperty("value")) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); - assertion.flatMap(TypeInformation::getMapValueType) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(value.getType()).isEqualTo(String.class); + assertThat(propertyType.getMapValueType().getType()).isEqualTo(Locale.class); } @Test // DATACMNS-446 public void createsToStringRepresentation() { - assertThat(from(Foo.class).getProperty("param")).map(Object::toString) - .hasValue("org.springframework.data.util.ParameterizedTypeUnitTests$Localized"); + assertThat(from(Foo.class).getProperty("param").toString()) + .isEqualTo("org.springframework.data.util.ParameterizedTypeUnitTests$Localized"); } @Test // DATACMNS-485 public void hashCodeShouldBeConsistentWithEqualsForResolvedTypes() { - Optional> first = from(First.class).getProperty("property"); - Optional> second = from(Second.class).getProperty("property"); + TypeInformation first = from(First.class).getProperty("property"); + TypeInformation second = from(Second.class).getProperty("property"); assertThat(first).isEqualTo(second); - assertThat(first).hasValueSatisfying(left -> assertThat(second) - .hasValueSatisfying(right -> assertThat(left.hashCode()).isEqualTo(right.hashCode()))); + assertThat(first).satisfies( + left -> assertThat(second).satisfies(right -> assertThat(left.hashCode()).isEqualTo(right.hashCode()))); } @Test // DATACMNS-485 public void getActualTypeShouldNotUnwrapParameterizedTypes() { - Optional> type = from(First.class).getProperty("property"); + TypeInformation type = from(First.class).getProperty("property"); - assertThat(type).map(TypeInformation::getActualType).isEqualTo(type); + assertThat(type.getActualType()).isEqualTo(type); } @Test // DATACMNS-697 @@ -130,20 +124,16 @@ public class ParameterizedTypeUnitTests { TypeInformation information = ClassTypeInformation.from(NormalizedProfile.class); - assertThat(information.getProperty("education2.data"))// - .flatMap(TypeInformation::getComponentType)// - .flatMap(it -> it.getProperty("value"))// - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Education.class)); + assertThat(information.getProperty("education2.data").getComponentType().getProperty("value"))// + .satisfies(it -> assertThat(it.getType()).isEqualTo(Education.class)); } @Test // DATACMNS-899 public void returnsEmptyOptionalMapValueTypeForNonMapProperties() { - OptionalAssert> assertion = assertThat( - ClassTypeInformation.from(Bar.class).getProperty("param")); - - assertion.hasValueSatisfying(it -> assertThat(it).isInstanceOf(ParameterizedTypeInformation.class)); - assertion.flatMap(TypeInformation::getMapValueType).isEmpty(); + TypeInformation typeInformation = ClassTypeInformation.from(Bar.class).getProperty("param"); + assertThat(typeInformation).isInstanceOf(ParameterizedTypeInformation.class); + assertThat(typeInformation.getMapValueType()).isNull(); } @SuppressWarnings("serial") diff --git a/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java b/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java index 1d34fd5b2..c1a1fc811 100755 --- a/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java +++ b/src/test/java/org/springframework/data/util/TypeDiscovererUnitTests.java @@ -26,7 +26,6 @@ import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; @@ -35,7 +34,7 @@ import org.mockito.junit.MockitoJUnitRunner; /** * Unit tests for {@link TypeDiscoverer}. - * + * * @author Oliver Gierke */ @RunWith(MockitoJUnitRunner.class) @@ -75,9 +74,8 @@ public class TypeDiscovererUnitTests { public void dealsWithTypesReferencingThemselves() { TypeInformation information = from(SelfReferencing.class); - Optional> first = information.getProperty("parent").flatMap(TypeInformation::getMapValueType); - Optional> second = first.flatMap(it -> it.getProperty("map")) - .flatMap(TypeInformation::getMapValueType); + TypeInformation first = information.getProperty("parent").getMapValueType(); + TypeInformation second = first.getProperty("map").getMapValueType(); assertThat(second).isEqualTo(first); } @@ -86,9 +84,9 @@ public class TypeDiscovererUnitTests { public void dealsWithTypesReferencingThemselvesInAMap() { TypeInformation information = from(SelfReferencingMap.class); - Optional> property = information.getProperty("map"); + TypeInformation property = information.getProperty("map"); - assertThat(property).hasValueSatisfying(it -> assertThat(it.getMapValueType()).hasValue(information)); + assertThat(property.getMapValueType()).isEqualTo(information); } @Test @@ -96,10 +94,8 @@ public class TypeDiscovererUnitTests { TypeInformation discoverer = new TypeDiscoverer<>(CustomMap.class, EMPTY_MAP); - assertThat(discoverer.getMapValueType()).hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(Locale.class)); - - assertThat(discoverer.getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(discoverer.getMapValueType().getType()).isEqualTo(Locale.class); + assertThat(discoverer.getComponentType().getType()).isEqualTo(String.class); } @Test @@ -107,8 +103,7 @@ public class TypeDiscovererUnitTests { TypeDiscoverer discoverer = new TypeDiscoverer<>(CustomCollection.class, firstMap); - assertThat(discoverer.getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(discoverer.getComponentType().getType()).isEqualTo(String.class); } @Test @@ -116,8 +111,7 @@ public class TypeDiscovererUnitTests { TypeDiscoverer discoverer = new TypeDiscoverer<>(String[].class, EMPTY_MAP); - assertThat(discoverer.getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(discoverer.getComponentType().getType()).isEqualTo(String.class); } @Test // DATACMNS-57 @@ -129,8 +123,7 @@ public class TypeDiscovererUnitTests { assertThat(types).hasSize(2); assertThat(types.get(0).getType()).isEqualTo(List.class); - assertThat(types.get(0).getComponentType()) - .hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(types.get(0).getComponentType().getType()).isEqualTo(String.class); } @Test @@ -139,8 +132,8 @@ public class TypeDiscovererUnitTests { TypeDiscoverer discoverer = new TypeDiscoverer<>(Map.class, EMPTY_MAP); - assertThat(discoverer.getComponentType()).isEmpty(); - assertThat(discoverer.getMapValueType()).isEmpty(); + assertThat(discoverer.getComponentType()).isNull(); + assertThat(discoverer.getMapValueType()).isNull(); } @Test // DATACMNS-167 @@ -150,18 +143,18 @@ public class TypeDiscovererUnitTests { TypeDiscoverer discoverer = new TypeDiscoverer<>(Person.class, EMPTY_MAP); TypeInformation reference = from(Address.class); - Optional> addresses = discoverer.getProperty("addresses"); + TypeInformation addresses = discoverer.getProperty("addresses"); - assertThat(addresses).hasValueSatisfying(it -> { + assertThat(addresses).satisfies(it -> { assertThat(it.isCollectionLike()).isFalse(); - assertThat(it.getComponentType()).hasValue(reference); + assertThat(it.getComponentType()).isEqualTo(reference); }); - Optional> adressIterable = discoverer.getProperty("addressIterable"); + TypeInformation adressIterable = discoverer.getProperty("addressIterable"); - assertThat(adressIterable).hasValueSatisfying(it -> { + assertThat(adressIterable).satisfies(it -> { assertThat(it.isCollectionLike()).isTrue(); - assertThat(it.getComponentType()).hasValue(reference); + assertThat(it.getComponentType()).isEqualTo(reference); }); } diff --git a/src/test/java/org/springframework/data/util/TypeInformationAssert.java b/src/test/java/org/springframework/data/util/TypeInformationAssert.java deleted file mode 100644 index e7f48116f..000000000 --- a/src/test/java/org/springframework/data/util/TypeInformationAssert.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.springframework.data.util; - -import java.util.Optional; - -import org.assertj.core.api.AbstractAssert; -import org.assertj.core.api.AbstractObjectAssert; -import org.assertj.core.api.Assertions; - -public class TypeInformationAssert extends AbstractAssert> { - - /** - * @param actual - * @param selfType - */ - public TypeInformationAssert(TypeInformation actual) { - super(actual, TypeInformationAssert.class); - } - - public static TypeInformationAssert assertThat(TypeInformation information) { - return new TypeInformationAssert(information); - } - - public TypeInformationAssert hasComponentType(Class type) { - - Assertions.assertThat(actual.getComponentType()).hasValueSatisfying(it -> Assertions.assertThat(it.getType()).isEqualTo(type)); - - return this; - } - - public AbstractObjectAssert> hasProperty(String property) { - - Optional> property2 = actual.getProperty(property); - - return Assertions.assertThat(property2.orElseGet(() -> { - failWithMessage("Property %s not found!", property); - return null; - })); - } -}