diff --git a/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java b/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java index 9d4ba8ebc..78d69a0b9 100644 --- a/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java +++ b/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java @@ -108,10 +108,10 @@ public class MappingAuditableBeanWrapperFactory extends DefaultAuditableBeanWrap Assert.notNull(entity, "PersistentEntity must not be null!"); - this.createdByProperty = entity.getPersistentProperty(CreatedBy.class); - this.createdDateProperty = entity.getPersistentProperty(CreatedDate.class); - this.lastModifiedByProperty = entity.getPersistentProperty(LastModifiedBy.class); - this.lastModifiedDateProperty = entity.getPersistentProperty(LastModifiedDate.class); + this.createdByProperty = Optional.ofNullable(entity.getPersistentProperty(CreatedBy.class)); + this.createdDateProperty = Optional.ofNullable(entity.getPersistentProperty(CreatedDate.class)); + this.lastModifiedByProperty = Optional.ofNullable(entity.getPersistentProperty(LastModifiedBy.class)); + this.lastModifiedDateProperty = Optional.ofNullable(entity.getPersistentProperty(LastModifiedDate.class)); } /** diff --git a/src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java b/src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java index 6adbeb392..4f6ed2e95 100644 --- a/src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java +++ b/src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java @@ -21,10 +21,11 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Optional; import org.springframework.asm.ClassWriter; import org.springframework.asm.MethodVisitor; @@ -33,6 +34,7 @@ import org.springframework.asm.Type; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PreferredConstructor; +import org.springframework.data.mapping.PreferredConstructor.Parameter; import org.springframework.data.mapping.model.MappingInstantiationException; import org.springframework.data.mapping.model.ParameterValueProvider; import org.springframework.data.util.TypeInformation; @@ -139,15 +141,17 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { return true; } - return entity.getPersistenceConstructor()// - .map(PreferredConstructor::getConstructor)// - .map(Constructor::getModifiers)// - .map(modifier -> !Modifier.isPublic(modifier)).orElse(false); + PreferredConstructor persistenceConstructor = entity.getPersistenceConstructor(); + if (persistenceConstructor == null || !Modifier.isPublic(persistenceConstructor.getConstructor().getModifiers())) { + return true; + } + + return false; } /** - * Creates a dynamically generated {@link ObjectInstantiator} for the given {@link InstantiatorKey}. There will always - * be exactly one {@link ObjectInstantiator} instance per {@link PersistentEntity}. + * Creates a dynamically generated {@link ObjectInstantiator} for the given {@link PersistentEntity}. There will + * always be exactly one {@link ObjectInstantiator} instance per {@link PersistentEntity}. *

* * @param entity @@ -202,26 +206,26 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { } /** - * Extracts the arguments required to invoce the given constructor from the given {@link ParameterValueProvider}. + * Extracts the arguments required to invoke the given constructor from the given {@link ParameterValueProvider}. * * @param constructor can be {@literal null}. * @param provider can be {@literal null}. * @return */ private

, T> Object[] extractInvocationArguments( - Optional> constructor, ParameterValueProvider

provider) { + PreferredConstructor constructor, ParameterValueProvider

provider) { - return constructor.map(it -> { + if (provider == null || constructor == null || !constructor.hasParameters()) { + return EMPTY_ARRAY; + } - if (provider == null || !it.hasParameters()) { - return EMPTY_ARRAY; - } + List params = new ArrayList<>(constructor.getConstructor().getParameterCount()); - return it.getParameters().stream()// - .map(provider::getParameterValue)// - .toArray(); + for (Parameter parameter : constructor.getParameters()) { + params.add(provider.getParameterValue(parameter)); + } - }).orElse(EMPTY_ARRAY); + return params.toArray(); } } @@ -292,9 +296,9 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { } /** - * Generate a new class for the given {@link InstantiatorKey}. + * Generate a new class for the given {@link PersistentEntity}. * - * @param key + * @param entity * @return */ public Class generateCustomInstantiatorClass(PersistentEntity entity) { @@ -306,7 +310,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { } /** - * @param key + * @param entity * @return */ private String generateClassName(PersistentEntity entity) { @@ -314,9 +318,10 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { } /** - * Generate a new class for the given {@link InstantiatorKey}. + * Generate a new class for the given {@link PersistentEntity}. * - * @param key + * @param internalClassName + * @param entity * @return */ public byte[] generateBytecode(String internalClassName, PersistentEntity entity) { @@ -362,7 +367,9 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { mv.visitTypeInsn(NEW, entityTypeResourcePath); mv.visitInsn(DUP); - entity.getPersistenceConstructor().ifPresent(constructor -> { + PreferredConstructor constructor = entity.getPersistenceConstructor(); + + if (constructor != null) { Constructor ctor = constructor.getConstructor(); Class[] parameterTypes = ctor.getParameterTypes(); @@ -386,7 +393,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); // (0, 0) = computed via ClassWriter.COMPUTE_MAXS mv.visitEnd(); - }); + } } /** diff --git a/src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java b/src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java index 5de207612..c8270115b 100644 --- a/src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.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. @@ -18,7 +18,6 @@ package org.springframework.data.convert; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import java.util.Optional; import org.springframework.data.mapping.Alias; import org.springframework.data.mapping.PersistentEntity; @@ -31,7 +30,7 @@ import org.springframework.util.Assert; * {@link TypeInformationMapper} implementation that can be either set up using a {@link MappingContext} or manually set * up {@link Map} of {@link String} aliases to types. If a {@link MappingContext} is used the {@link Map} will be build * inspecting the {@link PersistentEntity} instances for type alias information. - * + * * @author Oliver Gierke */ public class ConfigurableTypeInformationMapper implements TypeInformationMapper { @@ -41,7 +40,7 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper /** * Creates a new {@link ConfigurableTypeInformationMapper} for the given type map. - * + * * @param sourceTypeMap must not be {@literal null}. */ public ConfigurableTypeInformationMapper(Map, String> sourceTypeMap) { @@ -66,7 +65,7 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper } } - /* + /* * (non-Javadoc) * @see org.springframework.data.convert.TypeInformationMapper#createAliasFor(org.springframework.data.util.TypeInformation) */ @@ -79,7 +78,7 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper * @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(org.springframework.data.mapping.Alias) */ @Override - public Optional> resolveTypeFrom(Alias alias) { - return Optional.ofNullable(aliasToType.get(alias)); + public TypeInformation resolveTypeFrom(Alias alias) { + return aliasToType.get(alias); } } diff --git a/src/main/java/org/springframework/data/convert/CustomConversions.java b/src/main/java/org/springframework/data/convert/CustomConversions.java index c17e1d4de..376b98ae6 100644 --- a/src/main/java/org/springframework/data/convert/CustomConversions.java +++ b/src/main/java/org/springframework/data/convert/CustomConversions.java @@ -22,16 +22,7 @@ import lombok.RequiredArgsConstructor; import lombok.Value; import lombok.extern.slf4j.Slf4j; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import org.springframework.core.GenericTypeResolver; @@ -52,7 +43,7 @@ import org.springframework.util.Assert; * around them. The converters build up two sets of types which store-specific basic types can be converted into and * from. These types will be considered simple ones (which means they neither need deeper inspection nor nested * conversion. Thus the {@link CustomConversions} also act as factory for {@link SimpleTypeHolder} . - * + * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl @@ -91,7 +82,7 @@ public class CustomConversions { /** * Creates a new {@link CustomConversions} instance registering the given converters. - * + * * @param storeConversions must not be {@literal null}. * @param converters must not be {@literal null}. */ @@ -126,7 +117,7 @@ public class CustomConversions { /** * Returns the underlying {@link SimpleTypeHolder}. - * + * * @return */ public SimpleTypeHolder getSimpleTypeHolder() { @@ -136,7 +127,7 @@ public class CustomConversions { /** * Returns whether the given type is considered to be simple. That means it's either a general simple type or we have * a writing {@link Converter} registered for a particular type. - * + * * @see SimpleTypeHolder#isSimpleType(Class) * @param type * @return @@ -150,7 +141,7 @@ public class CustomConversions { /** * Populates the given {@link GenericConversionService} with the converters registered. - * + * * @param conversionService */ public void registerConvertersIn(ConverterRegistry conversionService) { @@ -162,7 +153,7 @@ public class CustomConversions { /** * Registers the given converter in the given {@link GenericConversionService}. - * + * * @param candidate must not be {@literal null}. * @param conversionService must not be {@literal null}. */ @@ -198,8 +189,8 @@ public class CustomConversions { /** * Registers the given {@link ConvertiblePair} as reading or writing pair depending on the type sides being basic * Mongo types. - * - * @param pair + * + * @param converterRegistration */ private void register(ConverterRegistration converterRegistration) { @@ -230,7 +221,7 @@ public class CustomConversions { /** * Returns the target type to convert to in case we have a custom conversion registered to convert the given source * type into a Mongo native one. - * + * * @param sourceType must not be {@literal null} * @return */ @@ -246,7 +237,7 @@ public class CustomConversions { * Returns the target type we can readTargetWriteLocl an inject of the given source type to. The returned type might * be a subclass of the given expected type though. If {@code expectedTargetType} is {@literal null} we will simply * return the first target type matching or {@literal null} if no conversion can be found. - * + * * @param sourceType must not be {@literal null} * @param requestedTargetType must not be {@literal null}. * @return @@ -263,7 +254,7 @@ public class CustomConversions { /** * Returns whether we have a custom conversion registered to readTargetWriteLocl into a Mongo native type. The * returned type might be a subclass of the given expected type though. - * + * * @param sourceType must not be {@literal null} * @return */ @@ -277,7 +268,7 @@ public class CustomConversions { /** * Returns whether we have a custom conversion registered to readTargetWriteLocl an object of the given source type * into an object of the given Mongo native target type. - * + * * @param sourceType must not be {@literal null}. * @param targetType must not be {@literal null}. * @return @@ -293,7 +284,7 @@ public class CustomConversions { /** * Returns whether we have a custom conversion registered to readTargetReadLock the given source into the given target * type. - * + * * @param sourceType must not be {@literal null} * @param targetType must not be {@literal null} * @return @@ -309,7 +300,7 @@ public class CustomConversions { /** * Returns the actual target type for the given {@code sourceType} and {@code requestedTargetType}. Note that the * returned {@link Class} could be an assignable type to the given {@code requestedTargetType}. - * + * * @param sourceType must not be {@literal null}. * @param targetType must not be {@literal null}. * @return @@ -323,7 +314,7 @@ public class CustomConversions { /** * Inspects the given {@link ConvertiblePair}s for ones that have a source compatible type as source. Additionally * checks assignability of the target type if one is given. - * + * * @param sourceType must not be {@literal null}. * @param targetType can be {@literal null}. * @param pairs must not be {@literal null}. @@ -357,7 +348,7 @@ public class CustomConversions { /** * Conversion registration information. - * + * * @author Oliver Gierke * @author Mark Paluch */ @@ -371,7 +362,7 @@ public class CustomConversions { /** * Returns whether the converter shall be used for writing. - * + * * @return */ public boolean isWriting() { @@ -380,7 +371,7 @@ public class CustomConversions { /** * Returns whether the converter shall be used for reading. - * + * * @return */ public boolean isReading() { @@ -389,7 +380,7 @@ public class CustomConversions { /** * Returns the actual conversion pair. - * + * * @return */ public ConvertiblePair getConvertiblePair() { @@ -398,7 +389,7 @@ public class CustomConversions { /** * Returns whether the source type is a Mongo simple one. - * + * * @return */ public boolean isSimpleSourceType() { @@ -407,7 +398,7 @@ public class CustomConversions { /** * Returns whether the target type is a Mongo simple one. - * + * * @return */ public boolean isSimpleTargetType() { @@ -434,7 +425,7 @@ public class CustomConversions { /** * Creates a new {@link StoreConversions} for the given store-specific {@link SimpleTypeHolder} and the given * converters. - * + * * @param storeTypeHolder must not be {@literal null}. * @param converters must not be {@literal null}. * @return @@ -450,7 +441,7 @@ public class CustomConversions { /** * Creates a new {@link StoreConversions} for the given store-specific {@link SimpleTypeHolder} and the given * converters. - * + * * @param storeTypeHolder must not be {@literal null}. * @param converters must not be {@literal null}. * @return @@ -465,7 +456,7 @@ public class CustomConversions { /** * Returns {@link ConverterRegistration}s for the given converter. - * + * * @param converter must not be {@literal null}. * @return */ diff --git a/src/main/java/org/springframework/data/convert/DefaultTypeMapper.java b/src/main/java/org/springframework/data/convert/DefaultTypeMapper.java index 8e57cabee..f494b68d6 100644 --- a/src/main/java/org/springframework/data/convert/DefaultTypeMapper.java +++ b/src/main/java/org/springframework/data/convert/DefaultTypeMapper.java @@ -16,7 +16,6 @@ package org.springframework.data.convert; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -33,7 +32,7 @@ import org.springframework.util.Assert; /** * Default implementation of {@link TypeMapper}. - * + * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl @@ -47,7 +46,7 @@ public class DefaultTypeMapper implements TypeMapper { /** * Creates a new {@link DefaultTypeMapper} using the given {@link TypeAliasAccessor}. It will use a * {@link SimpleTypeInformationMapper} to calculate type aliases. - * + * * @param accessor must not be {@literal null}. */ public DefaultTypeMapper(TypeAliasAccessor accessor) { @@ -57,7 +56,7 @@ public class DefaultTypeMapper implements TypeMapper { /** * Creates a new {@link DefaultTypeMapper} using the given {@link TypeAliasAccessor} and {@link TypeInformationMapper} * s. - * + * * @param accessor must not be {@literal null}. * @param mappers must not be {@literal null}. */ @@ -69,7 +68,7 @@ public class DefaultTypeMapper implements TypeMapper { * Creates a new {@link DefaultTypeMapper} using the given {@link TypeAliasAccessor}, {@link MappingContext} and * additional {@link TypeInformationMapper}s. Will register a {@link MappingContextTypeInformationMapper} before the * given additional mappers. - * + * * @param accessor must not be {@literal null}. * @param mappingContext * @param additionalMappers must not be {@literal null}. @@ -96,7 +95,7 @@ public class DefaultTypeMapper implements TypeMapper { * (non-Javadoc) * @see org.springframework.data.convert.TypeMapper#readType(java.lang.Object) */ - public Optional> readType(S source) { + public TypeInformation readType(S source) { Assert.notNull(source, "Source object must not be null!"); @@ -106,12 +105,23 @@ public class DefaultTypeMapper implements TypeMapper { /** * Tries to lookup a {@link TypeInformation} for the given alias from the cache and return it if found. If none is * found it'll consult the {@link TypeInformationMapper}s and cache the value found. - * + * * @param alias * @return */ - private Optional> getFromCacheOrCreate(Alias alias) { - return typeCache.computeIfAbsent(alias, key -> Optionals.firstNonEmpty(mappers, it -> it.resolveTypeFrom(alias))); + private TypeInformation getFromCacheOrCreate(Alias alias) { + return typeCache.computeIfAbsent(alias, key -> { + + for (TypeInformationMapper mapper : mappers) { + TypeInformation typeInformation = mapper.resolveTypeFrom(alias); + + if (typeInformation != null) { + return Optional.of(typeInformation); + } + } + return Optional.empty(); + + }).orElse(null); } /* @@ -123,43 +133,49 @@ public class DefaultTypeMapper implements TypeMapper { Assert.notNull(source, "Source must not be null!"); Assert.notNull(basicType, "Basic type must not be null!"); - Optional> calculated = getDefaultedTypeToBeUsed(source)// - .map(it -> specializeOrDefault(it, basicType)); + Class documentsTargetType = getDefaultedTypeToBeUsed(source); - return calculated.orElse(basicType); - } + if (documentsTargetType == null) { + return basicType; + } - private static TypeInformation specializeOrDefault(Class it, TypeInformation type) { + Class rawType = basicType.getType(); - ClassTypeInformation targetType = ClassTypeInformation.from(it); - Class rawType = type.getType(); + boolean isMoreConcreteCustomType = rawType == null + || rawType.isAssignableFrom(documentsTargetType) && !rawType.equals(documentsTargetType); - return rawType.isAssignableFrom(it) && !rawType.equals(it) ? type.specialize(targetType) : type; + if (!isMoreConcreteCustomType) { + return basicType; + } + + ClassTypeInformation targetType = ClassTypeInformation.from(documentsTargetType); + + return (TypeInformation) (basicType != null ? basicType.specialize(targetType) : targetType); } /** * Returns the type discovered through {@link #readType(Object)} but defaulted to the one returned by * {@link #getFallbackTypeFor(Object)}. - * + * * @param source * @return */ - private Optional> getDefaultedTypeToBeUsed(S source) { + private Class getDefaultedTypeToBeUsed(S source) { - return readType(source)// - .map(it -> readType(source))// - .orElseGet(() -> getFallbackTypeFor(source))// - .map(TypeInformation::getType); + TypeInformation documentsTargetTypeInformation = readType(source); + documentsTargetTypeInformation = documentsTargetTypeInformation == null ? getFallbackTypeFor(source) + : documentsTargetTypeInformation; + return documentsTargetTypeInformation == null ? null : documentsTargetTypeInformation.getType(); } /** * Returns the type fallback {@link TypeInformation} in case none could be extracted from the given source. - * + * * @param source will never be {@literal null}. * @return */ - protected Optional> getFallbackTypeFor(S source) { - return Optional.empty(); + protected TypeInformation getFallbackTypeFor(S source) { + return null; } /* @@ -183,7 +199,7 @@ public class DefaultTypeMapper implements TypeMapper { /** * Returns the alias to be used for the given {@link TypeInformation}. - * + * * @param info must not be {@literal null} * @return the alias for the given {@link TypeInformation} or {@literal null} of none was found or all mappers * returned {@literal null}. diff --git a/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java b/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java index 8c44d317c..ca6a6ff70 100644 --- a/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java @@ -17,7 +17,6 @@ package org.springframework.data.convert; import java.util.Map; import java.util.Map.Entry; -import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import org.springframework.data.mapping.Alias; @@ -31,7 +30,7 @@ import org.springframework.util.Assert; * {@link TypeInformationMapper} implementation that can be either set up using a {@link MappingContext} or manually set * up {@link Map} of {@link String} aliases to types. If a {@link MappingContext} is used the {@link Map} will be build * inspecting the {@link PersistentEntity} instances for type alias information. - * + * * @author Oliver Gierke * @author Christoph Strobl */ @@ -43,7 +42,7 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe /** * Creates a {@link MappingContextTypeInformationMapper} from the given {@link MappingContext}. Inspects all * {@link PersistentEntity} instances for alias information and builds a {@link Map} of aliases to types from it. - * + * * @param mappingContext must not be {@literal null}. */ public MappingContextTypeInformationMapper(MappingContext, ?> mappingContext) { @@ -58,18 +57,27 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe } } - /* + /* * (non-Javadoc) * @see org.springframework.data.convert.TypeInformationMapper#createAliasFor(org.springframework.data.util.TypeInformation) */ public Alias createAliasFor(TypeInformation type) { - return typeMap.computeIfAbsent(type.getRawTypeInformation(), key -> verify(key, mappingContext.getPersistentEntity(key).map(PersistentEntity::getTypeAlias).orElse(Alias.NONE))); + return typeMap.computeIfAbsent(type.getRawTypeInformation(), key -> { + + PersistentEntity entity = mappingContext.getPersistentEntity(key); + + if (entity == null || entity.getTypeAlias() == null) { + return Alias.NONE; + } + + return verify(key, entity.getTypeAlias()); + }); } /** * Adds the given alias to the cache in a {@literal null}-safe manner. - * + * * @param key must not be {@literal null}. * @param alias can be {@literal null}. */ @@ -103,29 +111,26 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe return alias; } - /* + /* * (non-Javadoc) * @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.util.Optional) */ @Override - public Optional> resolveTypeFrom(Alias alias) { + public TypeInformation resolveTypeFrom(Alias alias) { - return alias.getValue().map(it -> { - - for (Entry, Alias> entry : typeMap.entrySet()) { - if (entry.getValue().hasValue(it)) { - return entry.getKey(); - } + for (Entry, Alias> entry : typeMap.entrySet()) { + if (entry.getValue().hasSamePresentValueAs(alias)) { + return entry.getKey(); } + } - for (PersistentEntity entity : mappingContext.getPersistentEntities()) { + for (PersistentEntity entity : mappingContext.getPersistentEntities()) { - if (entity.getTypeAlias().hasValue(it)) { - return entity.getTypeInformation().getRawTypeInformation(); - } + if (entity.getTypeAlias().hasSamePresentValueAs(alias)) { + return entity.getTypeInformation().getRawTypeInformation(); } + } - return null; - }); + return null; } } diff --git a/src/main/java/org/springframework/data/convert/ReflectionEntityInstantiator.java b/src/main/java/org/springframework/data/convert/ReflectionEntityInstantiator.java index 5f07e6638..5ed93267c 100644 --- a/src/main/java/org/springframework/data/convert/ReflectionEntityInstantiator.java +++ b/src/main/java/org/springframework/data/convert/ReflectionEntityInstantiator.java @@ -44,7 +44,7 @@ public enum ReflectionEntityInstantiator implements EntityInstantiator { public , P extends PersistentProperty

> T createInstance(E entity, ParameterValueProvider

provider) { - PreferredConstructor constructor = entity.getPersistenceConstructor().orElse(null); + PreferredConstructor constructor = entity.getPersistenceConstructor(); if (constructor == null) { diff --git a/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java b/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java index b3bfbb186..ffd4f1b0b 100644 --- a/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 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. @@ -28,8 +28,9 @@ import org.springframework.util.ClassUtils; * Basic {@link TypeInformationMapper} implementation that interprets the alias handles as fully qualified class name * and tries to load a class with the given name to build {@link TypeInformation}. Returns the fully qualified class * name for alias creation. - * + * * @author Oliver Gierke + * @author Mark Paluch */ public class SimpleTypeInformationMapper implements TypeInformationMapper { @@ -39,23 +40,23 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper { * Returns the {@link TypeInformation} that shall be used when the given {@link String} value is found as type hint. * The implementation will simply interpret the given value as fully-qualified class name and try to load the class. * Will return {@literal null} in case the given {@link String} is empty. - * - * @param value the type to load, must not be {@literal null}. + * + * @param alias the type to load, must not be {@literal null}. * @return the type to be used for the given {@link String} representation or {@literal null} if nothing found or the * class cannot be loaded. */ @Override - public Optional> resolveTypeFrom(Alias alias) { + public TypeInformation resolveTypeFrom(Alias alias) { return alias.mapTyped(String.class)// - .flatMap(it -> CACHE.computeIfAbsent(it, SimpleTypeInformationMapper::loadClass).map(type -> type)); + .flatMap(it -> CACHE.computeIfAbsent(it, SimpleTypeInformationMapper::loadClass)).orElse(null); } /** * Turn the given type information into the String representation that shall be stored. Default implementation simply * returns the fully-qualified class name. - * - * @param typeInformation must not be {@literal null}. + * + * @param type must not be {@literal null}. * @return the String representation to be stored or {@literal null} if no type information shall be stored. */ public Alias createAliasFor(TypeInformation type) { diff --git a/src/main/java/org/springframework/data/convert/TypeInformationMapper.java b/src/main/java/org/springframework/data/convert/TypeInformationMapper.java index b6374bb76..fd8bcdbe4 100644 --- a/src/main/java/org/springframework/data/convert/TypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/TypeInformationMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 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. @@ -15,29 +15,27 @@ */ package org.springframework.data.convert; -import java.util.Optional; - import org.springframework.data.mapping.Alias; import org.springframework.data.util.TypeInformation; /** * Interface to abstract the mapping from a type alias to the actual type. - * + * * @author Oliver Gierke */ public interface TypeInformationMapper { /** * Returns the actual {@link TypeInformation} to be used for the given alias. - * + * * @param alias can be {@literal null}. * @return */ - Optional> resolveTypeFrom(Alias alias); + TypeInformation resolveTypeFrom(Alias alias); /** * Returns the alias to be used for the given {@link TypeInformation}. - * + * * @param type * @return */ diff --git a/src/main/java/org/springframework/data/convert/TypeMapper.java b/src/main/java/org/springframework/data/convert/TypeMapper.java index 557d6be9f..16b15dc8e 100644 --- a/src/main/java/org/springframework/data/convert/TypeMapper.java +++ b/src/main/java/org/springframework/data/convert/TypeMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 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. @@ -15,28 +15,26 @@ */ package org.springframework.data.convert; -import java.util.Optional; - import org.springframework.data.util.TypeInformation; /** * Interface to define strategies how to store type information in a store specific sink or source. - * + * * @author Oliver Gierke */ public interface TypeMapper { /** * Reads the {@link TypeInformation} from the given source. - * + * * @param source must not be {@literal null}. * @return */ - Optional> readType(S source); + TypeInformation readType(S source); /** * Returns the {@link TypeInformation} from the given source if it is a more concrete type than the given default one. - * + * * @param source must not be {@literal null}. * @param defaultType * @return @@ -45,7 +43,7 @@ public interface TypeMapper { /** * Writes type information for the given type into the given sink. - * + * * @param type must not be {@literal null}. * @param dbObject must not be {@literal null}. */ @@ -53,7 +51,7 @@ public interface TypeMapper { /** * Writes type information for the given {@link TypeInformation} into the given sink. - * + * * @param type must not be {@literal null}. * @param dbObject must not be {@literal null}. */ diff --git a/src/main/java/org/springframework/data/mapping/Alias.java b/src/main/java/org/springframework/data/mapping/Alias.java index 84df2bd92..c86f1498c 100644 --- a/src/main/java/org/springframework/data/mapping/Alias.java +++ b/src/main/java/org/springframework/data/mapping/Alias.java @@ -50,7 +50,7 @@ public class Alias { } public boolean hasSamePresentValueAs(Alias other) { - return isPresent() && hasValue(other.value); + return isPresent() && value.equals(other.value); } public boolean isPresent() { @@ -64,4 +64,5 @@ public class Alias { public String toString() { return value.map(Object::toString).orElse("NONE"); } + } diff --git a/src/main/java/org/springframework/data/mapping/Association.java b/src/main/java/org/springframework/data/mapping/Association.java index e7885329f..df9ae2342 100644 --- a/src/main/java/org/springframework/data/mapping/Association.java +++ b/src/main/java/org/springframework/data/mapping/Association.java @@ -1,11 +1,11 @@ /* - * Copyright (c) 2011 by the original author(s). + * 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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,9 +18,10 @@ package org.springframework.data.mapping; /** * Value object to capture {@link Association}s. - * - * @param the {@link PersistentProperty}s the association connects. + * + * @param

{@link PersistentProperty}s the association connects. * @author Jon Brisbin + * @author Mark Paluch */ public class Association

> { @@ -29,7 +30,7 @@ public class Association

> { /** * Creates a new {@link Association} between the two given {@link PersistentProperty}s. - * + * * @param inverse * @param obverse */ diff --git a/src/main/java/org/springframework/data/mapping/AssociationHandler.java b/src/main/java/org/springframework/data/mapping/AssociationHandler.java index 2ca024575..26ad9776d 100644 --- a/src/main/java/org/springframework/data/mapping/AssociationHandler.java +++ b/src/main/java/org/springframework/data/mapping/AssociationHandler.java @@ -1,11 +1,11 @@ /* - * Copyright (c) 2011 by the original author(s). + * 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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.mapping; /** * Callback interface to implement functionality to be applied to a collection of {@link Association}s. - * + * * @author Jon Brisbin * @author Oliver Gierke */ @@ -26,7 +25,7 @@ public interface AssociationHandler

> { /** * Processes the given {@link Association}. - * + * * @param association */ void doWithAssociation(Association

association); diff --git a/src/main/java/org/springframework/data/mapping/PersistentEntity.java b/src/main/java/org/springframework/data/mapping/PersistentEntity.java index 64fa4971b..a97f54406 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/PersistentEntity.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. @@ -16,42 +16,41 @@ package org.springframework.data.mapping; import java.lang.annotation.Annotation; -import java.util.Optional; -import java.util.stream.Stream; import org.springframework.data.convert.EntityInstantiator; import org.springframework.data.util.TypeInformation; /** * Represents a persistent entity. - * + * * @author Oliver Gierke * @author Graeme Rocher * @author Jon Brisbin * @author Patryk Wasik + * @author Mark Paluch */ public interface PersistentEntity> { /** * The entity name including any package prefix. - * + * * @return must never return {@literal null} */ String getName(); /** * Returns the {@link PreferredConstructor} to be used to instantiate objects of this {@link PersistentEntity}. - * - * @return An empty {@link Optional} in case no suitable constructor for automatic construction can be found. This - * usually indicates that the instantiation of the object of that persistent entity is done through either a - * customer {@link EntityInstantiator} or handled by custom conversion mechanisms entirely. + * + * @return {@literal null} in case no suitable constructor for automatic construction can be found. This usually + * indicates that the instantiation of the object of that persistent entity is done through either a customer + * {@link EntityInstantiator} or handled by custom conversion mechanisms entirely. */ - Optional> getPersistenceConstructor(); + PreferredConstructor getPersistenceConstructor(); /** * Returns whether the given {@link PersistentProperty} is referred to by a constructor argument of the * {@link PersistentEntity}. - * + * * @param property * @return true if the given {@link PersistentProperty} is referred to by a constructor argument or {@literal false} * if not or {@literal null}. @@ -60,7 +59,7 @@ public interface PersistentEntity> { /** * Returns whether the given {@link PersistentProperty} is the id property of the entity. - * + * * @param property * @return */ @@ -68,7 +67,7 @@ public interface PersistentEntity> { /** * Returns whether the given {@link PersistentProperty} is the version property of the entity. - * + * * @param property * @return */ @@ -77,59 +76,80 @@ public interface PersistentEntity> { /** * Returns the id property of the {@link PersistentEntity}. Can be {@literal null} in case this is an entity * completely handled by a custom conversion. - * + * * @return the id property of the {@link PersistentEntity}. */ - Optional

getIdProperty(); + P getIdProperty(); default P getRequiredIdProperty() { - return getIdProperty().orElseThrow( - () -> new IllegalStateException(String.format("Required identifier property not found for %s!", getType()))); + P property = getIdProperty(); + + if (property != null) { + return property; + } + + throw new IllegalStateException(String.format("Required identifier property not found for %s!", getType())); } /** * Returns the version property of the {@link PersistentEntity}. Can be {@literal null} in case no version property is * available on the entity. - * + * * @return the version property of the {@link PersistentEntity}. */ - Optional

getVersionProperty(); + P getVersionProperty(); + + default P getRequiredVersionProperty() { + + P property = getVersionProperty(); + + if (property != null) { + return property; + } + + throw new IllegalStateException(String.format("Required version property not found for %s!", getType())); + } /** * Obtains a {@link PersistentProperty} instance by name. - * + * * @param name The name of the property - * @return the {@link PersistentProperty} or {@literal Optional#empty()} if it doesn't exist. + * @return the {@link PersistentProperty} or {@literal null} if it doesn't exist. */ - Optional

getPersistentProperty(String name); + P getPersistentProperty(String name); /** * Returns the {@link PersistentProperty} with the given name. - * + * * @param name the name of the property, must not be {@literal null} or empty. * @return the {@link PersistentProperty} with the given name. * @throws IllegalArgumentException in case no property with the given name exists. */ default P getRequiredPersistentProperty(String name) { - return getPersistentProperty(name).orElseThrow( - () -> new IllegalArgumentException(String.format("No property %s found for type %s!", name, getType()))); + P property = getPersistentProperty(name); + + if (property != null) { + return property; + } + + throw new IllegalStateException(String.format("Required identifier property not found for %s!", getType())); } /** * Returns the property equipped with an annotation of the given type. - * + * * @param annotationType must not be {@literal null}. * @return * @since 1.8 */ - Optional

getPersistentProperty(Class annotationType); + P getPersistentProperty(Class annotationType); /** * Returns whether the {@link PersistentEntity} has an id property. If this call returns {@literal true}, * {@link #getIdProperty()} will return a non-{@literal null} value. - * + * * @return */ boolean hasIdProperty(); @@ -137,14 +157,14 @@ public interface PersistentEntity> { /** * Returns whether the {@link PersistentEntity} has a version property. If this call returns {@literal true}, * {@link #getVersionProperty()} will return a non-{@literal null} value. - * + * * @return */ boolean hasVersionProperty(); /** * Returns the resolved Java type of this entity. - * + * * @return The underlying Java class for this entity */ Class getType(); @@ -152,14 +172,14 @@ public interface PersistentEntity> { /** * Returns the alias to be used when storing type information. Might be {@literal null} to indicate that there was no * alias defined through the mapping metadata. - * + * * @return */ Alias getTypeAlias(); /** * Returns the {@link TypeInformation} backing this {@link PersistentEntity}. - * + * * @return */ TypeInformation getTypeInformation(); @@ -167,38 +187,47 @@ public interface PersistentEntity> { /** * Applies the given {@link PropertyHandler} to all {@link PersistentProperty}s contained in this * {@link PersistentEntity}. - * + * * @param handler must not be {@literal null}. */ void doWithProperties(PropertyHandler

handler); void doWithProperties(SimplePropertyHandler handler); - Stream

getPersistentProperties(); + Iterable

getPersistentProperties(); /** * Applies the given {@link AssociationHandler} to all {@link Association} contained in this {@link PersistentEntity}. - * + * * @param handler must not be {@literal null}. */ void doWithAssociations(AssociationHandler

handler); void doWithAssociations(SimpleAssociationHandler handler); - Stream> getAssociations(); + Iterable> getAssociations(); /** * Looks up the annotation of the given type on the {@link PersistentEntity}. - * + * * @param annotationType must not be {@literal null}. * @return * @since 1.8 */ - Optional findAnnotation(Class annotationType); + A findAnnotation(Class annotationType); + + /** + * Checks whether the annotation of the given type is present on the {@link PersistentEntity}. + * + * @param annotationType must not be {@literal null}. + * @return + * @since 2.0 + */ + boolean isAnnotationPresent(Class annotationType); /** * Returns a {@link PersistentPropertyAccessor} to access property values of the given bean. - * + * * @param bean must not be {@literal null}. * @return * @since 1.10 @@ -207,7 +236,7 @@ public interface PersistentEntity> { /** * Returns the {@link IdentifierAccessor} for the given bean. - * + * * @param bean must not be {@literal null}. * @return * @since 1.10 diff --git a/src/main/java/org/springframework/data/mapping/PersistentProperty.java b/src/main/java/org/springframework/data/mapping/PersistentProperty.java index 39e9e6897..907e993db 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/PersistentProperty.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. @@ -29,33 +29,34 @@ import org.springframework.data.util.TypeInformation; * @author Graeme Rocher * @author Jon Brisbin * @author Oliver Gierke + * @author Mark Paluch */ public interface PersistentProperty

> { /** * Returns the {@link PersistentEntity} owning the current {@link PersistentProperty}. - * + * * @return */ PersistentEntity getOwner(); /** * The name of the property - * + * * @return The property name */ String getName(); /** * The type of the property - * + * * @return The property type */ Class getType(); /** * Returns the {@link TypeInformation} of the property. - * + * * @return */ TypeInformation getTypeInformation(); @@ -64,7 +65,7 @@ public interface PersistentProperty

> { * Returns the {@link TypeInformation} if the property references a {@link PersistentEntity}. Will return * {@literal null} in case it refers to a simple type. Will return {@link Collection}'s component type or the * {@link Map}'s value type transparently. - * + * * @return */ Iterable> getPersistentEntityType(); @@ -72,33 +73,40 @@ public interface PersistentProperty

> { /** * Returns the getter method to access the property value if available. Might return {@literal null} in case there is * no getter method with a return type assignable to the actual property's type. - * + * * @return the getter method to access the property value if available, otherwise {@literal null}. */ - Optional getGetter(); + Method getGetter(); /** * Returns the setter method to set a property value. Might return {@literal null} in case there is no setter * available. - * + * * @return the setter method to set a property value if available, otherwise {@literal null}. */ - Optional getSetter(); + Method getSetter(); - Optional getField(); + Field getField(); - Optional getSpelExpression(); + String getSpelExpression(); - Optional> getAssociation(); + Association

getAssociation(); default Association

getRequiredAssociation() { - return getAssociation().orElseThrow(() -> new IllegalStateException("No association found!")); + + Association

association = getAssociation(); + + if (association != null) { + return association; + } + + throw new IllegalStateException("No association found!"); } /** * Returns whether the type of the {@link PersistentProperty} is actually to be regarded as {@link PersistentEntity} * in turn. - * + * * @return */ boolean isEntity(); @@ -108,7 +116,7 @@ public interface PersistentProperty

> { * This method is mainly used by {@link PersistentEntity} implementation to discover id property candidates on * {@link PersistentEntity} creation you should rather call {@link PersistentEntity#isIdProperty(PersistentProperty)} * to determine whether the current property is the id property of that {@link PersistentEntity} under consideration. - * + * * @return */ boolean isIdProperty(); @@ -119,42 +127,42 @@ public interface PersistentProperty

> { * property candidates on {@link PersistentEntity} creation you should rather call * {@link PersistentEntity#isVersionProperty(PersistentProperty)} to determine whether the current property is the * version property of that {@link PersistentEntity} under consideration. - * + * * @return */ boolean isVersionProperty(); /** * Returns whether the property is a {@link Collection}, {@link Iterable} or an array. - * + * * @return */ boolean isCollectionLike(); /** * Returns whether the property is a {@link Map}. - * + * * @return */ boolean isMap(); /** * Returns whether the property is an array. - * + * * @return */ boolean isArray(); /** * Returns whether the property is transient. - * + * * @return */ boolean isTransient(); /** * Returns whether the current property is writable, i.e. if the value held for it shall be written to the data store. - * + * * @return * @since 1.9 */ @@ -162,7 +170,7 @@ public interface PersistentProperty

> { /** * Returns whether the property is an {@link Association}. - * + * * @return */ boolean isAssociation(); @@ -170,7 +178,7 @@ public interface PersistentProperty

> { /** * Returns the component type of the type if it is a {@link java.util.Collection}. Will return the type of the key if * the property is a {@link java.util.Map}. - * + * * @return the component type, the map's key type or {@link Optional#empty()} if neither {@link java.util.Collection} * nor {@link java.util.Map}. */ @@ -178,14 +186,14 @@ public interface PersistentProperty

> { /** * Returns the raw type as it's pulled from from the reflected property. - * + * * @return the raw type of the property. */ Class getRawType(); /** * Returns the type of the values if the property is a {@link java.util.Map}. - * + * * @return the map's value type or {@link Optional#empty()} if no {@link java.util.Map} */ Optional> getMapValueType(); @@ -193,7 +201,7 @@ public interface PersistentProperty

> { /** * Returns the actual type of the property. This will be the original property type if no generics were used, the * component type for collection-like types and arrays as well as the value type for map properties. - * + * * @return */ Class getActualType(); @@ -201,25 +209,25 @@ public interface PersistentProperty

> { /** * Looks up the annotation of the given type on the {@link PersistentProperty}. Will inspect accessors and the * potentially backing field and traverse accessor methods to potentially available super types. - * + * * @param annotationType the annotation to look up, must not be {@literal null}. * @return the annotation of the given type. * @see AnnotationUtils#findAnnotation(Method, Class) */ - Optional findAnnotation(Class annotationType); + A findAnnotation(Class annotationType); /** * Looks up the annotation of the given type on the property and the owning type if no annotation can be found on it. * Usefull to lookup annotations that can be configured on the type but overridden on an individual property. - * + * * @param annotationType must not be {@literal null}. * @return */ - Optional findPropertyOrOwnerAnnotation(Class annotationType); + A findPropertyOrOwnerAnnotation(Class annotationType); /** * Returns whether the {@link PersistentProperty} has an annotation of the given type. - * + * * @param annotationType the annotation to lookup, must not be {@literal null}. * @return whether the {@link PersistentProperty} has an annotation of the given type. */ @@ -228,7 +236,7 @@ public interface PersistentProperty

> { /** * Returns whether property access shall be used for reading the property value. This means it will use the getter * instead of field access. - * + * * @return */ boolean usePropertyAccess(); diff --git a/src/main/java/org/springframework/data/mapping/PreferredConstructor.java b/src/main/java/org/springframework/data/mapping/PreferredConstructor.java index df284e624..e9c4587ea 100644 --- a/src/main/java/org/springframework/data/mapping/PreferredConstructor.java +++ b/src/main/java/org/springframework/data/mapping/PreferredConstructor.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -38,11 +37,12 @@ import org.springframework.util.StringUtils; /** * Value object to encapsulate the constructor to be used when mapping persistent data to objects. - * + * * @author Oliver Gierke * @author Jon Brisbin * @author Thomas Darimont * @author Christoph Strobl + * @author Mark Paluch */ public class PreferredConstructor> { @@ -56,7 +56,7 @@ public class PreferredConstructor> { /** * Creates a new {@link PreferredConstructor} from the given {@link Constructor} and {@link Parameter}s. - * + * * @param constructor must not be {@literal null}. * @param parameters must not be {@literal null}. */ @@ -73,7 +73,7 @@ public class PreferredConstructor> { /** * Returns the underlying {@link Constructor}. - * + * * @return */ public Constructor getConstructor() { @@ -82,7 +82,7 @@ public class PreferredConstructor> { /** * Returns the {@link Parameter}s of the constructor. - * + * * @return */ public Streamable> getParameters() { @@ -91,7 +91,7 @@ public class PreferredConstructor> { /** * Returns whether the constructor has {@link Parameter}s. - * + * * @see #isNoArgConstructor() * @return */ @@ -101,7 +101,7 @@ public class PreferredConstructor> { /** * Returns whether the constructor does not have any arguments. - * + * * @see #hasParameters() * @return */ @@ -111,7 +111,7 @@ public class PreferredConstructor> { /** * Returns whether the constructor was explicitly selected (by {@link PersistenceConstructor}). - * + * * @return */ public boolean isExplicitlyAnnotated() { @@ -121,7 +121,7 @@ public class PreferredConstructor> { /** * Returns whether the given {@link PersistentProperty} is referenced in a constructor argument of the * {@link PersistentEntity} backing this {@link PreferredConstructor}. - * + * * @param property must not be {@literal null}. * @return */ @@ -165,7 +165,7 @@ public class PreferredConstructor> { * Returns whether the given {@link Parameter} is one referring to an enclosing class. That is in case the class this * {@link PreferredConstructor} belongs to is a member class actually. If that's the case the compiler creates a first * constructor argument of the enclosing class type. - * + * * @param parameter must not be {@literal null}. * @return */ @@ -182,17 +182,17 @@ public class PreferredConstructor> { /** * Value object to represent constructor parameters. - * + * * @param the type of the parameter * @author Oliver Gierke */ @EqualsAndHashCode(exclude = { "enclosingClassCache", "hasSpelExpression" }) public static class Parameter> { - private final Optional name; + private final String name; private final TypeInformation type; - private final Optional key; - private final Optional> entity; + private final String key; + private final PersistentEntity entity; private final Lazy enclosingClassCache; private final Lazy hasSpelExpression; @@ -201,14 +201,13 @@ public class PreferredConstructor> { * Creates a new {@link Parameter} with the given name, {@link TypeInformation} as well as an array of * {@link Annotation}s. Will insprect the annotations for an {@link Value} annotation to lookup a key or an SpEL * expression to be evaluated. - * + * * @param name the name of the parameter, can be {@literal null} * @param type must not be {@literal null} * @param annotations must not be {@literal null} but can be empty * @param entity must not be {@literal null}. */ - public Parameter(Optional name, TypeInformation type, Annotation[] annotations, - Optional> entity) { + public Parameter(String name, TypeInformation type, Annotation[] annotations, PersistentEntity entity) { Assert.notNull(type, "Type must not be null!"); Assert.notNull(annotations, "Annotations must not be null!"); @@ -219,33 +218,38 @@ public class PreferredConstructor> { this.entity = entity; this.enclosingClassCache = Lazy.of(() -> { - Class owningType = entity.orElseThrow(IllegalStateException::new).getType(); + + if (entity == null) { + throw new IllegalStateException(); + } + + Class owningType = entity.getType(); return owningType.isMemberClass() && type.getType().equals(owningType.getEnclosingClass()); }); - this.hasSpelExpression = Lazy.of(() -> getSpelExpression().map(StringUtils::hasText).orElse(false)); + this.hasSpelExpression = Lazy.of(() -> StringUtils.hasText(getSpelExpression())); } - private static Optional getValue(Annotation[] annotations) { + private static String getValue(Annotation[] annotations) { return Arrays.stream(annotations)// .filter(it -> it.annotationType() == Value.class)// .findFirst().map(it -> ((Value) it).value())// - .filter(StringUtils::hasText); + .filter(StringUtils::hasText).orElse(null); } /** * Returns the name of the parameter. - * + * * @return */ - public Optional getName() { + public String getName() { return name; } /** * Returns the {@link TypeInformation} of the parameter. - * + * * @return */ public TypeInformation getType() { @@ -254,7 +258,7 @@ public class PreferredConstructor> { /** * Returns the raw resolved type of the parameter. - * + * * @return */ public Class getRawType() { @@ -263,35 +267,32 @@ public class PreferredConstructor> { /** * Returns the key to be used when looking up a source data structure to populate the actual parameter value. - * + * * @return */ - public Optional getSpelExpression() { + public String getSpelExpression() { return key; } /** * Returns whether the constructor parameter is equipped with a SpEL expression. - * + * * @return */ public boolean hasSpelExpression() { - return hasSpelExpression.get(); + return this.hasSpelExpression.get(); } /** * Returns whether the {@link Parameter} maps the given {@link PersistentProperty}. - * + * * @param property * @return */ boolean maps(PersistentProperty property) { - // -// - return name.map(s -> entity - .flatMap(it -> it.getPersistentProperty(s)) - .map(property::equals).orElse(false)).orElse(false); + P referencedProperty = entity == null ? null : entity.getPersistentProperty(name); + return property != null && property.equals(referencedProperty); } private boolean isEnclosingClassParameter() { diff --git a/src/main/java/org/springframework/data/mapping/TargetAwareIdentifierAccessor.java b/src/main/java/org/springframework/data/mapping/TargetAwareIdentifierAccessor.java index 2d9db54eb..64eb6d2b8 100644 --- a/src/main/java/org/springframework/data/mapping/TargetAwareIdentifierAccessor.java +++ b/src/main/java/org/springframework/data/mapping/TargetAwareIdentifierAccessor.java @@ -17,8 +17,6 @@ package org.springframework.data.mapping; import lombok.RequiredArgsConstructor; -import java.util.function.Supplier; - /** * {@link IdentifierAccessor} that is aware of the target bean to obtain the identifier from so that it can generate a * more meaningful exception in case of an absent identifier and a call to {@link #getRequiredIdentifier()}. @@ -31,7 +29,7 @@ import java.util.function.Supplier; @RequiredArgsConstructor public abstract class TargetAwareIdentifierAccessor implements IdentifierAccessor { - private final Supplier target; + private final Object target; /* * (non-Javadoc) @@ -46,6 +44,6 @@ public abstract class TargetAwareIdentifierAccessor implements IdentifierAccesso return identifier; } - throw new IllegalStateException(String.format("Could not obtain identifier from %s!", target.get())); + throw new IllegalStateException(String.format("Could not obtain identifier from %s!", target)); } } diff --git a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java index 23345d6b2..27aef19db 100644 --- a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java +++ b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java @@ -160,21 +160,10 @@ public abstract class AbstractMappingContext getPersistentEntity(Class type) { + public E getPersistentEntity(Class type) { return getPersistentEntity(ClassTypeInformation.from(type)); } - /* - * (non-Javadoc) - * @see org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(java.lang.Class) - */ - @Override - public E getRequiredPersistentEntity(Class type) { - - return getPersistentEntity(type).orElseThrow( - () -> new IllegalArgumentException(String.format("Couldn't find PersistentEntity for type %s!", type))); - } - /* * (non-Javadoc) * @see org.springframework.data.mapping.context.MappingContext#hasPersistentEntityFor(java.lang.Class) @@ -191,7 +180,7 @@ public abstract class AbstractMappingContext getPersistentEntity(TypeInformation type) { + public E getPersistentEntity(TypeInformation type) { Assert.notNull(type, "Type must not be null!"); @@ -202,7 +191,7 @@ public abstract class AbstractMappingContext entity = persistentEntities.get(type); if (entity != null) { - return entity; + return entity.orElse(null); } } finally { @@ -218,32 +207,21 @@ public abstract class AbstractMappingContext type) { - - return getPersistentEntity(type) - .orElseThrow(() -> new MappingException(String.format("Couldn't find PersistentEntity for type %s!", type))); + return addPersistentEntity(type).orElse(null); } /* * (non-Javadoc) * @see org.springframework.data.mapping.context.MappingContext#getPersistentEntity(org.springframework.data.mapping.PersistentProperty) */ - public Optional getPersistentEntity(P persistentProperty) { + public E getPersistentEntity(P persistentProperty) { Assert.notNull(persistentProperty, "PersistentProperty must not be null!"); @@ -251,17 +229,6 @@ public abstract class AbstractMappingContext new IllegalArgumentException( - String.format("Couldn't find PersistentEntity for type %s!", persistentProperty))); - } - /* * (non-Javadoc) * @see org.springframework.data.mapping.context.MappingContext#getPersistentPropertyPath(java.lang.Class, java.lang.String) @@ -317,14 +284,16 @@ public abstract class AbstractMappingContext foo = path; final E bar = current; - Pair, E> pair = getPair(path, iterator, segment, current).orElseThrow(() -> { + Pair, E> pair = getPair(path, iterator, segment, current); + + if (pair == null) { String source = StringUtils.collectionToDelimitedString(parts, "."); String resolvedPath = foo.toDotPath(); - return new InvalidPersistentPropertyPath(source, type, segment, resolvedPath, + throw new InvalidPersistentPropertyPath(source, type, segment, resolvedPath, String.format("No property %s found on %s!", segment, bar.getName())); - }); + } path = pair.getFirst(); current = pair.getSecond(); @@ -333,16 +302,17 @@ public abstract class AbstractMappingContext, E>> getPair(DefaultPersistentPropertyPath

path, + private Pair, E> getPair(DefaultPersistentPropertyPath

path, Iterator iterator, String segment, E entity) { - Optional

persistentProperty = entity.getPersistentProperty(segment); + P property = entity.getPersistentProperty(segment); - return persistentProperty.map(it -> { + if (property == null) { + return null; + } - TypeInformation type = it.getTypeInformation().getActualType(); - return Pair.of(path.append(it), iterator.hasNext() ? getRequiredPersistentEntity(type) : entity); - }); + TypeInformation type = property.getTypeInformation().getActualType(); + return Pair.of(path.append(property), iterator.hasNext() ? getRequiredPersistentEntity(type) : entity); } /** @@ -556,7 +526,10 @@ public abstract class AbstractMappingContext, P extends Pers Collection getPersistentEntities(); /** - * Returns a {@link PersistentEntity} for the given {@link Class}. Will return {@link Optional#empty()} for types that - * are considered simple ones. + * Returns a {@link PersistentEntity} for the given {@link Class}. Will return {@code null} for types that are + * considered simple ones. * * @see org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class) * @param type must not be {@literal null}. * @return */ - Optional getPersistentEntity(Class type); + E getPersistentEntity(Class type); /** * Returns a required {@link PersistentEntity} for the given {@link Class}. Will throw @@ -60,7 +59,16 @@ public interface MappingContext, P extends Pers * @param type must not be {@literal null}. * @return */ - E getRequiredPersistentEntity(Class type); + default E getRequiredPersistentEntity(Class type) { + + E entity = getPersistentEntity(type); + + if (entity != null) { + return entity; + } + + throw new IllegalArgumentException(String.format("Couldn't find PersistentEntity for type %s!", type)); + } /** * Returns whether the {@link MappingContext} currently contains a {@link PersistentEntity} for the type. @@ -72,14 +80,14 @@ public interface MappingContext, P extends Pers boolean hasPersistentEntityFor(Class type); /** - * Returns a {@link PersistentEntity} for the given {@link TypeInformation}. Will return {@link Optional#empty()} for - * types that are considered simple ones. + * Returns a {@link PersistentEntity} for the given {@link TypeInformation}. Will return {@code null} for types that + * are considered simple ones. * * @see org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class) * @param type must not be {@literal null}. * @return */ - Optional getPersistentEntity(TypeInformation type); + E getPersistentEntity(TypeInformation type); /** * Returns a {@link PersistentEntity} for the given {@link TypeInformation}. Will throw @@ -89,7 +97,16 @@ public interface MappingContext, P extends Pers * @param type must not be {@literal null}. * @return */ - E getRequiredPersistentEntity(TypeInformation type); + default E getRequiredPersistentEntity(TypeInformation type) { + + E entity = getPersistentEntity(type); + + if (entity != null) { + return entity; + } + + throw new IllegalArgumentException(String.format("Couldn't find PersistentEntity for type %s!", type)); + } /** * Returns the {@link PersistentEntity} mapped by the given {@link PersistentProperty}. @@ -100,7 +117,7 @@ public interface MappingContext, P extends Pers * type of the property is considered simple see * {@link org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)}). */ - Optional getPersistentEntity(P persistentProperty); + E getPersistentEntity(P persistentProperty); /** * Returns the {@link PersistentEntity} mapped by the given {@link PersistentProperty}. @@ -111,7 +128,17 @@ public interface MappingContext, P extends Pers * type of the property is considered simple see * {@link org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)}). */ - E getRequiredPersistentEntity(P persistentProperty); + default E getRequiredPersistentEntity(P persistentProperty) { + + E entity = getPersistentEntity(persistentProperty); + + if (entity != null) { + return entity; + } + + throw new IllegalArgumentException( + String.format("Couldn't find PersistentEntity for property %s!", persistentProperty)); + } /** * Returns all {@link PersistentProperty}s for the given path expression based on the given {@link PropertyPath}. diff --git a/src/main/java/org/springframework/data/mapping/context/MappingContextIsNewStrategyFactory.java b/src/main/java/org/springframework/data/mapping/context/MappingContextIsNewStrategyFactory.java index 8d2b63dbd..ab558e5f5 100644 --- a/src/main/java/org/springframework/data/mapping/context/MappingContextIsNewStrategyFactory.java +++ b/src/main/java/org/springframework/data/mapping/context/MappingContextIsNewStrategyFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-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. @@ -19,12 +19,10 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import java.util.Collections; -import java.util.Optional; import java.util.function.Function; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; -import org.springframework.data.mapping.model.MappingException; import org.springframework.data.support.IsNewStrategy; import org.springframework.data.support.IsNewStrategyFactory; import org.springframework.data.support.IsNewStrategyFactorySupport; @@ -72,26 +70,25 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp */ @Override protected IsNewStrategy doGetIsNewStrategy(Class type) { - - return context.getPersistentEntity(type)// - .flatMap(MappingContextIsNewStrategyFactory::getIsNewStrategy)// - .orElseThrow(() -> new MappingException(String.format("Cannot determine IsNewStrategy for type %s!", type))); + return MappingContextIsNewStrategyFactory.getIsNewStrategy(context.getRequiredPersistentEntity(type)); } - private static Optional getIsNewStrategy(PersistentEntity entity) { + private static IsNewStrategy getIsNewStrategy(PersistentEntity entity) { if (entity.hasVersionProperty()) { - return entity.getVersionProperty().map(it -> PersistentPropertyInspectingIsNewStrategy.of(it, - MappingContextIsNewStrategyFactory::propertyIsNullOrZeroNumber)); + return PersistentPropertyInspectingIsNewStrategy.of(entity.getRequiredVersionProperty(), + MappingContextIsNewStrategyFactory::propertyIsNullOrZeroNumber); - } else if (entity.hasIdProperty()) { - - return entity.getIdProperty().map( - it -> PersistentPropertyInspectingIsNewStrategy.of(it, MappingContextIsNewStrategyFactory::propertyIsNull)); } - return Optional.empty(); + if (entity.hasIdProperty()) { + + return PersistentPropertyInspectingIsNewStrategy.of(entity.getRequiredIdProperty(), + MappingContextIsNewStrategyFactory::propertyIsNull); + } + + return null; } /** 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 892174bbc..190d0c385 100644 --- a/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java @@ -54,13 +54,17 @@ public abstract class AbstractPersistentProperty

private final String name; private final TypeInformation information; private final Class rawType; - private final Lazy>> association; + private final Lazy> association; private final @Getter PersistentEntity owner; private final @Getter(AccessLevel.PROTECTED) Property property; private final Lazy hashCode; private final Lazy usePropertyAccess; private final Lazy>> entityTypeInformation; + private final Method getter; + private final Method setter; + private final Field field; + public AbstractPersistentProperty(Property property, PersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { @@ -72,16 +76,19 @@ public abstract class AbstractPersistentProperty

this.information = PropertyPath.from(Pattern.quote(property.getName()), owner.getTypeInformation()) .getTypeInformation(); this.property = property; - this.association = Lazy.of(() -> isAssociation() ? Optional.of(createAssociation()) : Optional.empty()); + this.association = Lazy.of(() -> isAssociation() ? createAssociation() : null); this.owner = owner; this.hashCode = Lazy.of(property::hashCode); - this.usePropertyAccess = Lazy - .of(() -> owner.getType().isInterface() || getField().map(it -> it.equals(CAUSE_FIELD)).orElse(false)); + this.usePropertyAccess = Lazy.of(() -> owner.getType().isInterface() || CAUSE_FIELD.equals(getField())); this.entityTypeInformation = Lazy.of(() -> Optional.ofNullable(information.getActualType())// .filter(it -> !simpleTypeHolder.isSimpleType(it.getType()))// .filter(it -> !it.isCollectionLike())// .filter(it -> !it.isMap())); + + this.getter = property.getGetter().orElse(null); + this.setter = property.getSetter().orElse(null); + this.field = property.getField().orElse(null); } protected abstract Association

createAssociation(); @@ -143,8 +150,8 @@ public abstract class AbstractPersistentProperty

* @see org.springframework.data.mapping.PersistentProperty#getGetter() */ @Override - public Optional getGetter() { - return property.getGetter(); + public Method getGetter() { + return getter; } /* @@ -152,8 +159,8 @@ public abstract class AbstractPersistentProperty

* @see org.springframework.data.mapping.PersistentProperty#getSetter() */ @Override - public Optional getSetter() { - return property.getSetter(); + public Method getSetter() { + return setter; } /* @@ -161,8 +168,8 @@ public abstract class AbstractPersistentProperty

* @see org.springframework.data.mapping.PersistentProperty#getField() */ @Override - public Optional getField() { - return property.getField(); + public Field getField() { + return field; } /* @@ -170,8 +177,8 @@ public abstract class AbstractPersistentProperty

* @see org.springframework.data.mapping.PersistentProperty#getSpelExpression() */ @Override - public Optional getSpelExpression() { - return Optional.empty(); + public String getSpelExpression() { + return null; } /* @@ -206,7 +213,7 @@ public abstract class AbstractPersistentProperty

* @see org.springframework.data.mapping.PersistentProperty#getAssociation() */ @Override - public Optional> getAssociation() { + public Association

getAssociation() { return association.get(); } diff --git a/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java b/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java index db45638e0..03702b56c 100644 --- a/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java @@ -52,12 +52,16 @@ public abstract class AnnotationBasedPersistentProperty

value; + private final Value value; private final Map, Optional> annotationCache = new HashMap<>(); - private final Lazy usePropertyAccess = Lazy.of(() -> findPropertyOrOwnerAnnotation(AccessType.class)// - .map(it -> Type.PROPERTY.equals(it.value()))// - .orElse(super.usePropertyAccess())); + private final Lazy usePropertyAccess = Lazy.of(() -> { + + AccessType accessType = findPropertyOrOwnerAnnotation(AccessType.class); + + return accessType != null && Type.PROPERTY.equals(accessType.value()) || super.usePropertyAccess(); + }); + private final Lazy isTransient = Lazy.of(() -> super.isTransient() || isAnnotationPresent(Transient.class) || isAnnotationPresent(Value.class) || isAnnotationPresent(Autowired.class)); @@ -147,8 +151,13 @@ public abstract class AnnotationBasedPersistentProperty

getSpelExpression() { - return value.map(Value::value); + public String getSpelExpression() { + + if (value != null) { + return value.value(); + } + + return null; } /** @@ -203,20 +212,33 @@ public abstract class AnnotationBasedPersistentProperty

Optional findAnnotation(Class annotationType) { + + public A findAnnotation(Class annotationType) { Assert.notNull(annotationType, "Annotation type must not be null!"); + return doFindAnnotation(annotationType).orElse(null); + } + + @SuppressWarnings("unchecked") + private Optional doFindAnnotation(Class annotationType) { + if (annotationCache != null && annotationCache.containsKey(annotationType)) { return (Optional) annotationCache.get(annotationType); } - return cacheAndReturn(annotationType, - getAccessors()// - .map(it -> it.map(inner -> AnnotatedElementUtils.findMergedAnnotation(inner, annotationType)))// - .flatMap(Optionals::toStream)// - .findFirst()); + return cacheAndReturn(annotationType, getAccessors()// + .flatMap(it -> { + + A mergedAnnotation = AnnotatedElementUtils.findMergedAnnotation(it, annotationType); + + if (mergedAnnotation == null) { + return Stream.empty(); + } + + return Stream.of(mergedAnnotation); + })// + .findFirst()); } /* @@ -224,10 +246,11 @@ public abstract class AnnotationBasedPersistentProperty

Optional findPropertyOrOwnerAnnotation(Class annotationType) { + public A findPropertyOrOwnerAnnotation(Class annotationType) { - Optional annotation = findAnnotation(annotationType); - return annotation.isPresent() ? annotation : getOwner().findAnnotation(annotationType); + A annotation = findAnnotation(annotationType); + + return annotation != null ? annotation : getOwner().findAnnotation(annotationType); } /** @@ -249,7 +272,7 @@ public abstract class AnnotationBasedPersistentProperty

annotationType) { - return findAnnotation(annotationType).isPresent(); + return doFindAnnotation(annotationType).isPresent(); } /* @@ -280,7 +303,9 @@ public abstract class AnnotationBasedPersistentProperty

> getAccessors() { - return Stream.of(getGetter(), getSetter(), getField()); + private Stream getAccessors() { + + return Optionals.toStream(Optional.ofNullable(getGetter()), Optional.ofNullable(getSetter()), + Optional.ofNullable(getField())); } } diff --git a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java index 8d215ad0d..0d0710648 100644 --- a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -29,7 +29,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeSet; -import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,17 +56,18 @@ public class BasicPersistentEntity> implement private static final String TYPE_MISMATCH = "Target bean of type %s is not of type of the persistent entity (%s)!"; private static final String NULL_ASSOCIATION = "%s.addAssociation(…) was called with a null association! Usually indicates a problem in a Spring Data MappingContext implementation. Be sure to file a bug at https://jira.spring.io!"; - private final Optional> constructor; + private final PreferredConstructor constructor; private final TypeInformation information; private final List

properties; - private final Optional> comparator; + private final List

persistentPropertiesCache; + private final Comparator

comparator; private final Set> associations; - private final Map> propertyCache; + private final Map propertyCache; private final Map, Optional> annotationCache; - private Optional

idProperty = Optional.empty(); - private Optional

versionProperty = Optional.empty(); + private P idProperty; + private P versionProperty; private PersistentPropertyAccessorFactory propertyAccessorFactory; private final Lazy typeAlias; @@ -78,7 +78,7 @@ public class BasicPersistentEntity> implement * @param information must not be {@literal null}. */ public BasicPersistentEntity(TypeInformation information) { - this(information, Optional.empty()); + this(information, null); } /** @@ -89,16 +89,16 @@ public class BasicPersistentEntity> implement * @param information must not be {@literal null}. * @param comparator can be {@literal null}. */ - public BasicPersistentEntity(TypeInformation information, Optional> comparator) { + public BasicPersistentEntity(TypeInformation information, Comparator

comparator) { Assert.notNull(information, "Information must not be null!"); this.information = information; this.properties = new ArrayList<>(); + this.persistentPropertiesCache = new ArrayList<>(); this.comparator = comparator; this.constructor = new PreferredConstructorDiscoverer<>(this).getConstructor(); - this.associations = comparator.>> map(it -> new TreeSet<>(new AssociationComparator<>(it))) - .orElseGet(HashSet::new); + this.associations = comparator == null ? new HashSet<>() : new TreeSet<>(new AssociationComparator

(comparator)); this.propertyCache = new HashMap<>(); this.annotationCache = new HashMap<>(); @@ -114,7 +114,7 @@ public class BasicPersistentEntity> implement * (non-Javadoc) * @see org.springframework.data.mapping.PersistentEntity#getPersistenceConstructor() */ - public Optional> getPersistenceConstructor() { + public PreferredConstructor getPersistenceConstructor() { return constructor; } @@ -123,7 +123,7 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#isConstructorArgument(org.springframework.data.mapping.PersistentProperty) */ public boolean isConstructorArgument(PersistentProperty property) { - return constructor.map(it -> it.isConstructorParameter(property)).orElse(false); + return constructor != null && constructor.isConstructorParameter(property); } /* @@ -131,7 +131,7 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#isIdProperty(org.springframework.data.mapping.PersistentProperty) */ public boolean isIdProperty(PersistentProperty property) { - return this.idProperty.map(it -> it.equals(property)).orElse(false); + return idProperty != null && idProperty.equals(property); } /* @@ -139,7 +139,7 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#isVersionProperty(org.springframework.data.mapping.PersistentProperty) */ public boolean isVersionProperty(PersistentProperty property) { - return this.versionProperty.map(it -> it.equals(property)).orElse(false); + return versionProperty != null && versionProperty.equals(property); } /* @@ -154,7 +154,7 @@ public class BasicPersistentEntity> implement * (non-Javadoc) * @see org.springframework.data.mapping.PersistentEntity#getIdProperty() */ - public Optional

getIdProperty() { + public P getIdProperty() { return idProperty; } @@ -162,7 +162,7 @@ public class BasicPersistentEntity> implement * (non-Javadoc) * @see org.springframework.data.mapping.PersistentEntity#getVersionProperty() */ - public Optional

getVersionProperty() { + public P getVersionProperty() { return versionProperty; } @@ -171,7 +171,7 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#hasIdProperty() */ public boolean hasIdProperty() { - return idProperty.isPresent(); + return idProperty != null; } /* @@ -179,7 +179,7 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#hasVersionProperty() */ public boolean hasVersionProperty() { - return versionProperty.isPresent(); + return versionProperty != null; } /* @@ -196,26 +196,31 @@ public class BasicPersistentEntity> implement properties.add(property); + if (!property.isTransient() && !property.isAssociation()) { + persistentPropertiesCache.add(property); + } + if (!propertyCache.containsKey(property.getName())) { - propertyCache.put(property.getName(), Optional.of(property)); + propertyCache.put(property.getName(), property); } P candidate = returnPropertyIfBetterIdPropertyCandidateOrNull(property); if (candidate != null) { - this.idProperty = Optional.of(candidate); + this.idProperty = candidate; } if (property.isVersionProperty()) { - this.versionProperty.ifPresent(it -> { + if (this.versionProperty != null) { - throw new MappingException( - String.format("Attempt to add version property %s but already have property %s registered " - + "as version. Check your mapping configuration!", property.getField(), it.getField())); - }); + throw new MappingException(String.format( + "Attempt to add version property %s but already have property %s registered " + + "as version. Check your mapping configuration!", + property.getField(), this.versionProperty.getField())); + } - this.versionProperty = Optional.of(property); + this.versionProperty = property; } } @@ -231,10 +236,10 @@ public class BasicPersistentEntity> implement return null; } - this.idProperty.ifPresent(it -> { + if (this.idProperty != null) { throw new MappingException(String.format("Attempt to add id property %s but already have property %s registered " - + "as id. Check your mapping configuration!", property.getField(), it.getField())); - }); + + "as id. Check your mapping configuration!", property.getField(), this.idProperty.getField())); + } return property; } @@ -256,15 +261,15 @@ public class BasicPersistentEntity> implement * (non-Javadoc) * @see org.springframework.data.mapping.PersistentEntity#getPersistentProperty(java.lang.String) */ - public Optional

getPersistentProperty(String name) { + public P getPersistentProperty(String name) { - Optional

property = propertyCache.get(name); + P property = propertyCache.get(name); if (property != null) { return property; } - return Optional.empty(); + return null; } /* @@ -272,7 +277,7 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#getPersistentProperty(java.lang.Class) */ @Override - public Optional

getPersistentProperty(Class annotationType) { + public P getPersistentProperty(Class annotationType) { Assert.notNull(annotationType, "Annotation type must not be null!"); @@ -280,12 +285,8 @@ public class BasicPersistentEntity> implement .filter(it -> it.isAnnotationPresent(annotationType))// .findAny(); - if (property.isPresent()) { - return property; - } - - return associations.stream().map(Association::getInverse)// - .filter(it -> it.isAnnotationPresent(annotationType)).findAny(); + return property.orElseGet(() -> associations.stream().map(Association::getInverse)// + .filter(it -> it.isAnnotationPresent(annotationType)).findAny().orElse(null)); } /* @@ -320,10 +321,8 @@ public class BasicPersistentEntity> implement Assert.notNull(handler, "PropertyHandler must not be null!"); - for (P property : properties) { - if (!property.isTransient() && !property.isAssociation()) { - handler.doWithPersistentProperty(property); - } + for (P property : persistentPropertiesCache) { + handler.doWithPersistentProperty(property); } } @@ -336,10 +335,8 @@ public class BasicPersistentEntity> implement Assert.notNull(handler, "Handler must not be null!"); - for (PersistentProperty property : properties) { - if (!property.isTransient() && !property.isAssociation()) { - handler.doWithPersistentProperty(property); - } + for (PersistentProperty property : persistentPropertiesCache) { + handler.doWithPersistentProperty(property); } } @@ -348,10 +345,8 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#getPersistentProperties() */ @Override - public Stream

getPersistentProperties() { - - return properties.stream()// - .filter(it -> !it.isTransient() && !it.isAssociation()); + public Iterable

getPersistentProperties() { + return persistentPropertiesCache; } /* @@ -385,8 +380,8 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.PersistentEntity#getAssociations() */ @Override - public Stream> getAssociations() { - return associations.stream(); + public Iterable> getAssociations() { + return associations; } /* @@ -395,9 +390,22 @@ public class BasicPersistentEntity> implement */ @Override @SuppressWarnings("unchecked") - public Optional findAnnotation(Class annotationType) { + public A findAnnotation(Class annotationType) { + return (A) doFindAnnotation(annotationType).orElse(null); + } - return (Optional) annotationCache.computeIfAbsent(annotationType, + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.PersistentEntity#isAnnotationPresent(java.lang.Class) + */ + @Override + public boolean isAnnotationPresent(Class annotationType) { + return doFindAnnotation(annotationType).isPresent(); + } + + private Optional doFindAnnotation(Class annotationType) { + + return annotationCache.computeIfAbsent(annotationType, it -> Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(getType(), it))); } @@ -406,7 +414,11 @@ public class BasicPersistentEntity> implement * @see org.springframework.data.mapping.MutablePersistentEntity#verify() */ public void verify() { - comparator.ifPresent(it -> properties.sort(it)); + + if (comparator != null) { + properties.sort(comparator); + persistentPropertiesCache.sort(comparator); + } } /* @@ -455,7 +467,7 @@ public class BasicPersistentEntity> implement private static class AbsentIdentifierAccessor extends TargetAwareIdentifierAccessor { public AbsentIdentifierAccessor(Object target) { - super(() -> target); + super(target); } /* diff --git a/src/main/java/org/springframework/data/mapping/model/BeanWrapper.java b/src/main/java/org/springframework/data/mapping/model/BeanWrapper.java index 68cfce55b..2935e09ce 100644 --- a/src/main/java/org/springframework/data/mapping/model/BeanWrapper.java +++ b/src/main/java/org/springframework/data/mapping/model/BeanWrapper.java @@ -17,7 +17,6 @@ package org.springframework.data.mapping.model; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.Optional; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; @@ -57,20 +56,20 @@ class BeanWrapper implements PersistentPropertyAccessor { if (!property.usePropertyAccess()) { - Field field = property.getField().get(); + Field field = property.getField(); ReflectionUtils.makeAccessible(field); ReflectionUtils.setField(field, bean, value); return; } - Optional setter = property.getSetter(); + Method setter = property.getSetter(); - setter.ifPresent(it -> { + if (setter != null) { - ReflectionUtils.makeAccessible(it); - ReflectionUtils.invokeMethod(it, bean, value); - }); + ReflectionUtils.makeAccessible(setter); + ReflectionUtils.invokeMethod(setter, bean, value); + } } catch (IllegalStateException e) { throw new MappingException("Could not set object property!", e); @@ -103,18 +102,20 @@ class BeanWrapper implements PersistentPropertyAccessor { if (!property.usePropertyAccess()) { - Field field = property.getField().get(); + Field field = property.getField(); ReflectionUtils.makeAccessible(field); return ReflectionUtils.getField(field, bean); } - Optional getter = property.getGetter(); + Method getter = property.getGetter(); - return getter.map(it -> { + if (getter != null) { - ReflectionUtils.makeAccessible(it); - return (S) ReflectionUtils.invokeMethod(it, bean); - }).orElse(null); + ReflectionUtils.makeAccessible(getter); + return ReflectionUtils.invokeMethod(getter, bean); + } + + return null; } catch (IllegalStateException e) { throw new MappingException( diff --git a/src/main/java/org/springframework/data/mapping/model/CamelCaseAbbreviatingFieldNamingStrategy.java b/src/main/java/org/springframework/data/mapping/model/CamelCaseAbbreviatingFieldNamingStrategy.java index e0068fec7..9ab3396f8 100644 --- a/src/main/java/org/springframework/data/mapping/model/CamelCaseAbbreviatingFieldNamingStrategy.java +++ b/src/main/java/org/springframework/data/mapping/model/CamelCaseAbbreviatingFieldNamingStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-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. @@ -17,8 +17,8 @@ package org.springframework.data.mapping.model; /** * {@link FieldNamingStrategy} that abbreviates field names by using the very first letter of the camel case parts of - * the {@link MongoPersistentProperty}'s name. - * + * the {@link org.springframework.data.mapping.PersistentProperty}'s name. + * * @since 1.9 * @author Oliver Gierke */ @@ -31,7 +31,7 @@ public class CamelCaseAbbreviatingFieldNamingStrategy extends CamelCaseSplitting super(""); } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.mapping.CamelCaseSplittingFieldNamingStrategy#preparePart(java.lang.String) */ diff --git a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java index 79de7ded2..d2ac59b91 100644 --- a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java +++ b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java @@ -350,20 +350,23 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert for (PersistentProperty property : persistentProperties) { - property.getSetter().filter(it -> generateMethodHandle(entity, it)) - .ifPresent(it -> cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, setterName(property), - referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd()); - property.getGetter().filter(it -> generateMethodHandle(entity, it)) - .ifPresent(it -> cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, getterName(property), - referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd()); + if (generateMethodHandle(entity, property.getSetter())) { + cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, setterName(property), + referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd(); + } - property.getField().filter(it -> generateSetterMethodHandle(entity, it)).ifPresent(it -> { + if (generateMethodHandle(entity, property.getGetter())) { + cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, getterName(property), + referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd(); + } + + if (generateSetterMethodHandle(entity, property.getField())) { cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, fieldSetterName(property), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd(); cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, fieldGetterName(property), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd(); - }); + } } } @@ -475,15 +478,18 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert if (property.usePropertyAccess()) { - property.getGetter().filter(it -> generateMethodHandle(entity, it)) - .ifPresent(it -> visitPropertyGetterInitializer(property, mv, entityClasses, internalClassName)); + if (generateMethodHandle(entity, property.getGetter())) { + visitPropertyGetterInitializer(property, mv, entityClasses, internalClassName); + } - property.getSetter().filter(it -> generateMethodHandle(entity, it)) - .ifPresent(it -> visitPropertySetterInitializer(property, mv, entityClasses, internalClassName)); + if (generateMethodHandle(entity, property.getSetter())) { + visitPropertySetterInitializer(property, mv, entityClasses, internalClassName); + } } - property.getField().filter(it -> generateSetterMethodHandle(entity, it)) - .ifPresent(it -> visitFieldGetterSetterInitializer(property, mv, entityClasses, internalClassName)); + if (generateSetterMethodHandle(entity, property.getField())) { + visitFieldGetterSetterInitializer(property, mv, entityClasses, internalClassName); + } } mv.visitLabel(l1); @@ -511,8 +517,13 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert private static List> getPropertyDeclaratingClasses(List> persistentProperties) { return persistentProperties.stream().flatMap(property -> { - return Optionals.toStream(property.getField(), property.getGetter(), property.getSetter()) + return Optionals + .toStream(Optional.ofNullable(property.getField()), Optional.ofNullable(property.getGetter()), + Optional.ofNullable(property.getSetter())) + // keep it a lambda to infer the correct types, preventing + // LambdaConversionException: Invalid receiver type class java.lang.reflect.AccessibleObject; not a subtype + // of implementation type interface java.lang.reflect.Member .map(it -> it.getDeclaringClass()); }).collect(Collectors.collectingAndThen(Collectors.toSet(), it -> new ArrayList<>(it))); @@ -526,12 +537,12 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert List> entityClasses, String internalClassName) { // getter = .class.getDeclaredMethod() - Optional getter = property.getGetter(); + Method getter = property.getGetter(); - getter.ifPresent(it -> { + if (getter != null) { - mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, it.getDeclaringClass())); - mv.visitLdcInsn(it.getName()); + mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, getter.getDeclaringClass())); + mv.visitLdcInsn(getter.getName()); mv.visitInsn(ICONST_0); mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_CLASS); @@ -549,9 +560,9 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert mv.visitVarInsn(ALOAD, 3); mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_LANG_INVOKE_METHOD_HANDLES_LOOKUP, "unreflect", String.format("(%s)%s", referenceName(JAVA_LANG_REFLECT_METHOD), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)), false); - }); + } - if (!getter.isPresent()) { + if (getter == null) { mv.visitInsn(ACONST_NULL); } @@ -566,22 +577,22 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert List> entityClasses, String internalClassName) { // setter = .class.getDeclaredMethod() - Optional setter = property.getSetter(); + Method setter = property.getSetter(); - setter.ifPresent(it -> { + if (setter != null) { - mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, it.getDeclaringClass())); - mv.visitLdcInsn(it.getName()); + mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, setter.getDeclaringClass())); + mv.visitLdcInsn(setter.getName()); mv.visitInsn(ICONST_1); mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_CLASS); mv.visitInsn(DUP); mv.visitInsn(ICONST_0); - Class parameterType = it.getParameterTypes()[0]; + Class parameterType = setter.getParameterTypes()[0]; if (parameterType.isPrimitive()) { - mv.visitFieldInsn(GETSTATIC, Type.getInternalName(autoboxType(it.getParameterTypes()[0])), "TYPE", + mv.visitFieldInsn(GETSTATIC, Type.getInternalName(autoboxType(setter.getParameterTypes()[0])), "TYPE", referenceName(JAVA_LANG_CLASS)); } else { mv.visitLdcInsn(Type.getType(referenceName(parameterType))); @@ -603,9 +614,9 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_LANG_INVOKE_METHOD_HANDLES_LOOKUP, "unreflect", String.format("(%s)%s", referenceName(JAVA_LANG_REFLECT_METHOD), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)), false); - }); + } - if (!setter.isPresent()) { + if (setter == null) { mv.visitInsn(ACONST_NULL); } @@ -620,10 +631,12 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert List> entityClasses, String internalClassName) { // field = .class.getDeclaredField() - property.getField().ifPresent(it -> { - mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, it.getDeclaringClass())); - mv.visitLdcInsn(it.getName()); + Field field = property.getField(); + if (field != null) { + + mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, field.getDeclaringClass())); + mv.visitLdcInsn(field.getName()); mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_LANG_CLASS, "getDeclaredField", String.format("(%s)%s", referenceName(JAVA_LANG_STRING), referenceName(JAVA_LANG_REFLECT_FIELD)), false); mv.visitVarInsn(ASTORE, 1); @@ -648,7 +661,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert "(%s)%s", referenceName(JAVA_LANG_REFLECT_FIELD), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)), false); mv.visitFieldInsn(PUTSTATIC, internalClassName, fieldSetterName(property), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)); - }); + } } private static void visitBeanGetter(PersistentEntity entity, String internalClassName, ClassWriter cw) { @@ -778,7 +791,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert mv.visitLabel(propertyStackMap.get(property.getName()).label); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); - if (property.getGetter().isPresent() || property.getField().isPresent()) { + if (property.getGetter() != null || property.getField() != null) { visitGetProperty0(entity, property, mv, internalClassName); } else { mv.visitJumpInsn(GOTO, dfltLabel); @@ -797,9 +810,10 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert private static void visitGetProperty0(PersistentEntity entity, PersistentProperty property, MethodVisitor mv, String internalClassName) { - property.getGetter().filter(it -> property.usePropertyAccess()).map(it -> { + Method getter = property.getGetter(); + if (property.usePropertyAccess() && getter != null) { - if (generateMethodHandle(entity, it)) { + if (generateMethodHandle(entity, getter)) { // $getter.invoke(bean) mv.visitFieldInsn(GETSTATIC, internalClassName, getterName(property), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)); @@ -811,42 +825,35 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert mv.visitVarInsn(ALOAD, 2); int invokeOpCode = INVOKEVIRTUAL; - Class declaringClass = it.getDeclaringClass(); + Class declaringClass = getter.getDeclaringClass(); boolean interfaceDefinition = declaringClass.isInterface(); if (interfaceDefinition) { invokeOpCode = INVOKEINTERFACE; } - mv.visitMethodInsn(invokeOpCode, Type.getInternalName(declaringClass), it.getName(), - String.format("()%s", signatureTypeName(it.getReturnType())), interfaceDefinition); - autoboxIfNeeded(it.getReturnType(), autoboxType(it.getReturnType()), mv); + mv.visitMethodInsn(invokeOpCode, Type.getInternalName(declaringClass), getter.getName(), + String.format("()%s", signatureTypeName(getter.getReturnType())), interfaceDefinition); + autoboxIfNeeded(getter.getReturnType(), autoboxType(getter.getReturnType()), mv); } + } else { - return null; - - }).orElseGet(() -> { - - property.getField().ifPresent(it -> { - - if (generateMethodHandle(entity, it)) { - // $fieldGetter.invoke(bean) - mv.visitFieldInsn(GETSTATIC, internalClassName, fieldGetterName(property), - referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)); - mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_LANG_INVOKE_METHOD_HANDLE, "invoke", - String.format("(%s)%s", referenceName(JAVA_LANG_OBJECT), referenceName(JAVA_LANG_OBJECT)), false); - } else { - // bean.field - mv.visitVarInsn(ALOAD, 2); - mv.visitFieldInsn(GETFIELD, Type.getInternalName(it.getDeclaringClass()), it.getName(), - signatureTypeName(it.getType())); - autoboxIfNeeded(it.getType(), autoboxType(it.getType()), mv); - } - }); - - return null; - }); + Field field = property.getField(); + if (generateMethodHandle(entity, field)) { + // $fieldGetter.invoke(bean) + mv.visitFieldInsn(GETSTATIC, internalClassName, fieldGetterName(property), + referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_LANG_INVOKE_METHOD_HANDLE, "invoke", + String.format("(%s)%s", referenceName(JAVA_LANG_OBJECT), referenceName(JAVA_LANG_OBJECT)), false); + } else { + // bean.field + mv.visitVarInsn(ALOAD, 2); + mv.visitFieldInsn(GETFIELD, Type.getInternalName(field.getDeclaringClass()), field.getName(), + signatureTypeName(field.getType())); + autoboxIfNeeded(field.getType(), autoboxType(field.getType()), mv); + } + } mv.visitInsn(ARETURN); } @@ -947,7 +954,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert mv.visitLabel(propertyStackMap.get(property.getName()).label); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); - if (property.getSetter().isPresent() || property.getField().isPresent()) { + if (property.getSetter() != null || property.getField() != null) { visitSetProperty0(entity, property, mv, internalClassName); } else { mv.visitJumpInsn(GOTO, dfltLabel); @@ -966,11 +973,10 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert private static void visitSetProperty0(PersistentEntity entity, PersistentProperty property, MethodVisitor mv, String internalClassName) { - Optional setter = property.getSetter(); + Method setter = property.getSetter(); + if (property.usePropertyAccess() && setter != null) { - setter.filter(it -> property.usePropertyAccess()).map(it -> { - - if (generateMethodHandle(entity, it)) { + if (generateMethodHandle(entity, setter)) { // $setter.invoke(bean) mv.visitFieldInsn(GETSTATIC, internalClassName, setterName(property), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)); @@ -983,28 +989,26 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ALOAD, 2); - Class parameterType = it.getParameterTypes()[0]; + Class parameterType = setter.getParameterTypes()[0]; mv.visitTypeInsn(CHECKCAST, Type.getInternalName(autoboxType(parameterType))); autoboxIfNeeded(autoboxType(parameterType), parameterType, mv); int invokeOpCode = INVOKEVIRTUAL; - Class declaringClass = it.getDeclaringClass(); + Class declaringClass = setter.getDeclaringClass(); boolean interfaceDefinition = declaringClass.isInterface(); if (interfaceDefinition) { invokeOpCode = INVOKEINTERFACE; } - mv.visitMethodInsn(invokeOpCode, Type.getInternalName(it.getDeclaringClass()), it.getName(), + mv.visitMethodInsn(invokeOpCode, Type.getInternalName(setter.getDeclaringClass()), setter.getName(), String.format("(%s)V", signatureTypeName(parameterType)), interfaceDefinition); } + } else { - return null; - - }).orElseGet(() -> { - - property.getField().ifPresent(it -> { - if (generateSetterMethodHandle(entity, it)) { + Field field = property.getField(); + if (field != null) { + if (generateSetterMethodHandle(entity, field)) { // $fieldSetter.invoke(bean, object) mv.visitFieldInsn(GETSTATIC, internalClassName, fieldSetterName(property), referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE)); @@ -1017,17 +1021,15 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert mv.visitVarInsn(ALOAD, 3); mv.visitVarInsn(ALOAD, 2); - Class fieldType = it.getType(); + Class fieldType = field.getType(); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(autoboxType(fieldType))); autoboxIfNeeded(autoboxType(fieldType), fieldType, mv); - mv.visitFieldInsn(PUTFIELD, Type.getInternalName(it.getDeclaringClass()), it.getName(), + mv.visitFieldInsn(PUTFIELD, Type.getInternalName(field.getDeclaringClass()), field.getName(), signatureTypeName(fieldType)); } - }); - - return null; - }); + } + } mv.visitInsn(RETURN); } @@ -1094,6 +1096,11 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert } private static boolean generateSetterMethodHandle(PersistentEntity entity, Field field) { + + if (field == null) { + return false; + } + return generateMethodHandle(entity, field) || Modifier.isFinal(field.getModifiers()); } @@ -1104,6 +1111,10 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert */ private static boolean generateMethodHandle(PersistentEntity entity, Member member) { + if (member == null) { + return false; + } + if (isAccessible(entity)) { if (Modifier.isProtected(member.getModifiers()) || isDefault(member.getModifiers())) { diff --git a/src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java b/src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java index d2980a3ae..26d287b16 100644 --- a/src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java +++ b/src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java @@ -1,11 +1,11 @@ /* - * Copyright (c) 2011 by the original author(s). + * 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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.data.mapping.model; import org.springframework.data.mapping.PreferredConstructor.Parameter; @@ -23,7 +24,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; /** * {@link ParameterValueProvider} implementation that evaluates the {@link Parameter}s key against * {@link SpelExpressionParser} and {@link EvaluationContext}. - * + * * @author Oliver Gierke */ public class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator { @@ -32,7 +33,7 @@ public class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator { private final SpELContext factory; /** - * @param parser + * @param source * @param factory */ public DefaultSpELExpressionEvaluator(Object source, SpELContext factory) { diff --git a/src/main/java/org/springframework/data/mapping/model/FieldNamingStrategy.java b/src/main/java/org/springframework/data/mapping/model/FieldNamingStrategy.java index 043833dfd..4f6658699 100644 --- a/src/main/java/org/springframework/data/mapping/model/FieldNamingStrategy.java +++ b/src/main/java/org/springframework/data/mapping/model/FieldNamingStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-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. @@ -19,7 +19,7 @@ import org.springframework.data.mapping.PersistentProperty; /** * SPI to determine how to name document fields in cases the field name is not manually defined. - * + * * @see PropertyNameFieldNamingStrategy * @see CamelCaseAbbreviatingFieldNamingStrategy * @see SnakeCaseFieldNamingStrategy @@ -29,8 +29,8 @@ import org.springframework.data.mapping.PersistentProperty; public interface FieldNamingStrategy { /** - * Returns the field name to be used for the given {@link MongoPersistentProperty}. - * + * Returns the field name to be used for the given {@link PersistentProperty}. + * * @param property must not be {@literal null} or empty; * @return */ diff --git a/src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java b/src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java index 477417ebf..2cdce0b01 100644 --- a/src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java +++ b/src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java @@ -43,7 +43,7 @@ public class IdPropertyIdentifierAccessor extends TargetAwareIdentifierAccessor */ public IdPropertyIdentifierAccessor(PersistentEntity entity, Object target) { - super(() -> target); + super(target); Assert.notNull(entity, "PersistentEntity must not be null!"); Assert.isTrue(entity.hasIdProperty(), "PersistentEntity must have an identifier property!"); diff --git a/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java b/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java index 2725f1807..9a9d3a57c 100644 --- a/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java +++ b/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java @@ -69,8 +69,8 @@ public class MappingInstantiationException extends RuntimeException { super(buildExceptionMessage(entity, arguments, message), cause); this.entityType = entity.map(PersistentEntity::getType).orElse(null); - this.constructor = entity.flatMap(PersistentEntity::getPersistenceConstructor) - .map(PreferredConstructor::getConstructor).orElse(null); + this.constructor = entity.map(PersistentEntity::getPersistenceConstructor).map(PreferredConstructor::getConstructor) + .orElse(null); this.constructorArguments = arguments; } @@ -79,7 +79,7 @@ public class MappingInstantiationException extends RuntimeException { return entity.map(it -> { - Optional> constructor = it.getPersistenceConstructor(); + Optional> constructor = Optional.ofNullable(it.getPersistenceConstructor()); List toStringArgs = new ArrayList<>(arguments.size()); for (Object o : arguments) { diff --git a/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java b/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java index 3ce83b057..b236def08 100644 --- a/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java +++ b/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java @@ -62,13 +62,13 @@ public class PersistentEntityParameterValueProvider

T getParameterValue(Parameter parameter) { - PreferredConstructor constructor = entity.getPersistenceConstructor().orElse(null); + PreferredConstructor constructor = entity.getPersistenceConstructor(); if (constructor.isEnclosingClassParameter(parameter)) { return (T) parent; } - P property = entity.getPersistentProperty(parameter.getName().orElse(null)).orElse(null); + P property = entity.getPersistentProperty(parameter.getName()); if (property == null) { throw new MappingException(String.format("No property %s found on entity %s to bind constructor parameter to!", diff --git a/src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java b/src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java index f0ed1c0f3..694a884cf 100644 --- a/src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java +++ b/src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java @@ -18,7 +18,6 @@ package org.springframework.data.mapping.model; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.util.List; -import java.util.Optional; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; @@ -31,20 +30,21 @@ import org.springframework.data.util.TypeInformation; /** * Helper class to find a {@link PreferredConstructor}. - * + * * @author Oliver Gierke * @author Christoph Strobl * @author Roman Rodov + * @author Mark Paluch */ public class PreferredConstructorDiscoverer> { private final ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); - private Optional> constructor; + private PreferredConstructor constructor; /** * Creates a new {@link PreferredConstructorDiscoverer} for the given type. - * + * * @param type must not be {@literal null}. */ public PreferredConstructorDiscoverer(Class type) { @@ -53,20 +53,20 @@ public class PreferredConstructorDiscoverer> /** * Creates a new {@link PreferredConstructorDiscoverer} for the given {@link PersistentEntity}. - * + * * @param entity must not be {@literal null}. */ public PreferredConstructorDiscoverer(PersistentEntity entity) { - this(entity.getTypeInformation(), Optional.ofNullable(entity)); + this(entity.getTypeInformation(), entity); } /** * Creates a new {@link PreferredConstructorDiscoverer} for the given type. - * + * * @param type must not be {@literal null}. * @param entity */ - protected PreferredConstructorDiscoverer(TypeInformation type, Optional> entity) { + protected PreferredConstructorDiscoverer(TypeInformation type, PersistentEntity entity) { boolean noArgConstructorFound = false; int numberOfArgConstructors = 0; @@ -83,13 +83,13 @@ public class PreferredConstructorDiscoverer> // Explicitly defined constructor trumps all if (preferredConstructor.isExplicitlyAnnotated()) { - this.constructor = Optional.of(preferredConstructor); + this.constructor = preferredConstructor; return; } // No-arg constructor trumps custom ones if (this.constructor == null || preferredConstructor.isNoArgConstructor()) { - this.constructor = Optional.of(preferredConstructor); + this.constructor = preferredConstructor; } if (preferredConstructor.isNoArgConstructor()) { @@ -100,13 +100,13 @@ public class PreferredConstructorDiscoverer> } if (!noArgConstructorFound && numberOfArgConstructors > 1) { - this.constructor = Optional.empty(); + this.constructor = null; } } @SuppressWarnings({ "unchecked", "rawtypes" }) private PreferredConstructor buildPreferredConstructor(Constructor constructor, - TypeInformation typeInformation, Optional> entity) { + TypeInformation typeInformation, PersistentEntity entity) { List> parameterTypes = typeInformation.getParameterTypes(constructor); @@ -121,7 +121,7 @@ public class PreferredConstructorDiscoverer> for (int i = 0; i < parameterTypes.size(); i++) { - Optional name = Optional.ofNullable(parameterNames == null ? null : parameterNames[i]); + String name = parameterNames == null ? null : parameterNames[i]; TypeInformation type = parameterTypes.get(i); Annotation[] annotations = parameterAnnotations[i]; @@ -133,10 +133,10 @@ public class PreferredConstructorDiscoverer> /** * Returns the discovered {@link PreferredConstructor}. - * + * * @return */ - public Optional> getConstructor() { + public PreferredConstructor getConstructor() { return constructor; } } diff --git a/src/main/java/org/springframework/data/mapping/model/PropertyNameFieldNamingStrategy.java b/src/main/java/org/springframework/data/mapping/model/PropertyNameFieldNamingStrategy.java index 88e54c7c6..9152762b4 100644 --- a/src/main/java/org/springframework/data/mapping/model/PropertyNameFieldNamingStrategy.java +++ b/src/main/java/org/springframework/data/mapping/model/PropertyNameFieldNamingStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-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,8 +18,8 @@ package org.springframework.data.mapping.model; import org.springframework.data.mapping.PersistentProperty; /** - * {@link FieldNamingStrategy} simply using the {@link MongoPersistentProperty}'s name. - * + * {@link FieldNamingStrategy} simply using the {@link PersistentProperty}'s name. + * * @since 1.9 * @author Oliver Gierke */ diff --git a/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java b/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java index ccaf4015a..67306d287 100644 --- a/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java +++ b/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java @@ -65,7 +65,7 @@ public class SpELExpressionParameterValueProvider

extends AbstractEntityInformatio */ @Override public Class getIdType() { - return (Class) persistentEntity.getIdProperty().map(PersistentProperty::getType).orElse(null); + return (Class) persistentEntity.getRequiredIdProperty().getType(); } } diff --git a/src/main/java/org/springframework/data/repository/query/ReturnedType.java b/src/main/java/org/springframework/data/repository/query/ReturnedType.java index 430b877f3..97e91df45 100644 --- a/src/main/java/org/springframework/data/repository/query/ReturnedType.java +++ b/src/main/java/org/springframework/data/repository/query/ReturnedType.java @@ -26,18 +26,17 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; +import org.springframework.data.mapping.PreferredConstructor; import org.springframework.data.mapping.model.PreferredConstructorDiscoverer; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.projection.ProjectionInformation; -import org.springframework.data.util.Optionals; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** * A representation of the type returned by a {@link QueryMethod}. - * + * * @author Oliver Gierke * @author Christoph Strobl * @since 1.12 @@ -49,7 +48,7 @@ public abstract class ReturnedType { /** * Creates a new {@link ReturnedType} for the given returned type, domain type and {@link ProjectionFactory}. - * + * * @param returnedType must not be {@literal null}. * @param domainType must not be {@literal null}. * @param factory must not be {@literal null}. @@ -68,7 +67,7 @@ public abstract class ReturnedType { /** * Returns the entity type. - * + * * @return */ public final Class getDomainType() { @@ -77,7 +76,7 @@ public abstract class ReturnedType { /** * Returns whether the given source object is an instance of the returned type. - * + * * @param source can be {@literal null}. * @return */ @@ -87,21 +86,21 @@ public abstract class ReturnedType { /** * Returns whether the type is projecting, i.e. not of the domain type. - * + * * @return */ public abstract boolean isProjecting(); /** * Returns the type of the individual objects to return. - * + * * @return */ public abstract Class getReturnedType(); /** * Returns whether the returned type will require custom construction. - * + * * @return */ public abstract boolean needsCustomConstruction(); @@ -109,14 +108,14 @@ public abstract class ReturnedType { /** * Returns the type that the query execution is supposed to pass to the underlying infrastructure. {@literal null} is * returned to indicate a generic type (a map or tuple-like type) shall be used. - * + * * @return */ public abstract Class getTypeToRead(); /** * Returns the properties required to be used to populate the result. - * + * * @return */ public abstract List getInputProperties(); @@ -134,7 +133,7 @@ public abstract class ReturnedType { /** * Creates a new {@link ReturnedInterface} from the given {@link ProjectionInformation} and domain type. - * + * * @param information must not be {@literal null}. * @param domainType must not be {@literal null}. */ @@ -148,7 +147,7 @@ public abstract class ReturnedType { this.domainType = domainType; } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.ResultFactory.ReturnedTypeInformation#getReturnedType() */ @@ -165,7 +164,7 @@ public abstract class ReturnedType { return isProjecting() && information.isClosed(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.ResultFactory.ReturnedType#isProjecting() */ @@ -174,7 +173,7 @@ public abstract class ReturnedType { return !information.getType().isAssignableFrom(domainType); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.ResultFactory.ReturnedTypeInformation#getTypeToRead() */ @@ -183,7 +182,7 @@ public abstract class ReturnedType { return isProjecting() && information.isClosed() ? null : domainType; } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.ResultFactory.ReturnedTypeInformation#getInputProperties() */ @@ -217,10 +216,9 @@ public abstract class ReturnedType { /** * Creates a new {@link ReturnedClass} instance for the given returned type and domain type. - * + * * @param returnedType must not be {@literal null}. * @param domainType must not be {@literal null}. - * @param projectionInformation */ public ReturnedClass(Class returnedType, Class domainType) { @@ -234,7 +232,7 @@ public abstract class ReturnedType { this.inputProperties = detectConstructorParameterNames(returnedType); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.ResultFactory.ReturnedTypeInformation#getReturnedType() */ @@ -251,7 +249,7 @@ public abstract class ReturnedType { return type; } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.ResultFactory.ReturnedType#isProjecting() */ @@ -268,7 +266,7 @@ public abstract class ReturnedType { return isDto() && !inputProperties.isEmpty(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.repository.query.ResultFactory.ReturnedTypeInformation#getInputProperties() */ @@ -285,10 +283,19 @@ public abstract class ReturnedType { } PreferredConstructorDiscoverer discoverer = new PreferredConstructorDiscoverer(type); + PreferredConstructor constructor = discoverer.getConstructor(); - return discoverer.getConstructor().map(it -> it.getParameters().stream()// - .flatMap(parameter -> Optionals.toStream(parameter.getName()))// - .collect(Collectors.toList())).orElseGet(Collections::emptyList); + if (constructor == null) { + return Collections.emptyList(); + } + + List properties = new ArrayList<>(constructor.getConstructor().getParameterCount()); + + for (PreferredConstructor.Parameter parameter : constructor.getParameters()) { + properties.add(parameter.getName()); + } + + return properties; } private boolean isDto() { diff --git a/src/main/java/org/springframework/data/util/Lazy.java b/src/main/java/org/springframework/data/util/Lazy.java index d02622471..8455dd52d 100644 --- a/src/main/java/org/springframework/data/util/Lazy.java +++ b/src/main/java/org/springframework/data/util/Lazy.java @@ -18,7 +18,6 @@ package org.springframework.data.util; import lombok.EqualsAndHashCode; import lombok.RequiredArgsConstructor; -import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; @@ -28,8 +27,9 @@ import org.springframework.util.Assert; * Simple value type to delay the creation of an object using a {@link Supplier} returning the produced object for * subsequent lookups. Note, that no concurrency control is applied during the lookup of {@link #get()}, which means in * concurrent access scenarios, the provided {@link Supplier} can be called multiple times. - * + * * @author Oliver Gierke + * @author Mark Paluch * @since 2.0 */ @RequiredArgsConstructor @@ -37,11 +37,11 @@ import org.springframework.util.Assert; public class Lazy implements Supplier { private final Supplier supplier; - private Optional value; + private T value; /** * Creates a new {@link Lazy} to produce an object lazily. - * + * * @param the type of which to produce an object of eventually. * @param supplier the {@link Supplier} to create the object lazily. * @return @@ -53,21 +53,21 @@ public class Lazy implements Supplier { /** * Returns the value created by the configured {@link Supplier}. Will return the calculated instance for subsequent * lookups. - * + * * @return */ public T get() { if (value == null) { - this.value = Optional.ofNullable(supplier.get()); + this.value = supplier.get(); } - return value.orElse(null); + return value; } /** * Creates a new {@link Lazy} with the given {@link Function} lazily applied to the current one. - * + * * @param function must not be {@literal null}. * @return */ @@ -80,7 +80,7 @@ public class Lazy implements Supplier { /** * Creates a new {@link Lazy} with the given {@link Function} lazily applied to the current one. - * + * * @param function must not be {@literal null}. * @return */ diff --git a/src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java b/src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java index 3a52689c2..1b63ab5a3 100755 --- a/src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java +++ b/src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java @@ -22,10 +22,8 @@ import static org.springframework.data.util.ClassTypeInformation.from; import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.List; -import java.util.Optional; import java.util.stream.IntStream; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -58,11 +56,6 @@ public class ClassGeneratingEntityInstantiatorUnitTests

constructor; @Mock Parameter parameter; - @Before - public void setUp() { - doReturn(Optional.empty()).when(entity).getPersistenceConstructor(); - } - @Test public void instantiatesSimpleObjectCorrectly() { @@ -82,7 +75,7 @@ public class ClassGeneratingEntityInstantiatorUnitTests

> constructor = new PreferredConstructorDiscoverer(Foo.class) + PreferredConstructor constructor = new PreferredConstructorDiscoverer(Foo.class) .getConstructor(); doReturn(Foo.class).when(entity).getType(); @@ -90,14 +83,14 @@ public class ClassGeneratingEntityInstantiatorUnitTests

verify(provider, times(1)).getParameterValue(it.getParameters().iterator().next())); + assertThat(constructor) + .satisfies(it -> verify(provider, times(1)).getParameterValue(it.getParameters().iterator().next())); } @Test(expected = MappingInstantiationException.class) // DATACMNS-300, DATACMNS-578 @SuppressWarnings({ "unchecked", "rawtypes" }) public void throwsExceptionOnBeanInstantiationException() { - doReturn(Optional.empty()).when(entity).getPersistenceConstructor(); doReturn(PersistentEntity.class).when(entity).getType(); this.instance.createInstance(entity, provider); @@ -107,7 +100,7 @@ public class ClassGeneratingEntityInstantiatorUnitTests

entity = new BasicPersistentEntity<>(from(Inner.class)); - assertThat(entity.getPersistenceConstructor()).hasValueSatisfying(constructor -> { + assertThat(entity.getPersistenceConstructor()).satisfies(constructor -> { Parameter parameter = constructor.getParameters().iterator().next(); diff --git a/src/test/java/org/springframework/data/convert/ConfigurableTypeInformationMapperUnitTests.java b/src/test/java/org/springframework/data/convert/ConfigurableTypeInformationMapperUnitTests.java index 51e0d51d9..fc6b399e1 100755 --- a/src/test/java/org/springframework/data/convert/ConfigurableTypeInformationMapperUnitTests.java +++ b/src/test/java/org/springframework/data/convert/ConfigurableTypeInformationMapperUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 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. @@ -30,9 +30,10 @@ import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.util.ClassTypeInformation; /** - * Unit tests for {@link ConfigurableTypeMapper}. - * + * Unit tests for {@link ConfigurableTypeInformationMapper}. + * * @author Oliver Gierke + * @author Mark Paluch */ @RunWith(MockitoJUnitRunner.class) public class ConfigurableTypeInformationMapperUnitTests> { @@ -69,7 +70,7 @@ public class ConfigurableTypeInformationMapperUnitTests> information = typeMapper.readType(source); - assertThat(information).hasValue(STRING_TYPE_INFO); + TypeInformation information = typeMapper.readType(source); + assertThat(information).isEqualTo(STRING_TYPE_INFO); verify(mapper, times(1)).resolveTypeFrom(ALIAS); typeMapper.readType(source); @@ -87,7 +86,7 @@ public class DefaultTypeMapperUnitTests { TypeInformation barType = ClassTypeInformation.from(Bar.class); doReturn(Alias.of(barType)).when(accessor).readAliasFrom(source); - doReturn(Optional.of(barType)).when(mapper).resolveTypeFrom(Alias.of(barType)); + doReturn(barType).when(mapper).resolveTypeFrom(Alias.of(barType)); TypeInformation result = typeMapper.readType(source, propertyType); diff --git a/src/test/java/org/springframework/data/convert/MappingContextTypeInformationMapperUnitTests.java b/src/test/java/org/springframework/data/convert/MappingContextTypeInformationMapperUnitTests.java index 6debca203..d6ea408c3 100755 --- a/src/test/java/org/springframework/data/convert/MappingContextTypeInformationMapperUnitTests.java +++ b/src/test/java/org/springframework/data/convert/MappingContextTypeInformationMapperUnitTests.java @@ -16,7 +16,7 @@ package org.springframework.data.convert; import static org.assertj.core.api.Assertions.*; -import static org.springframework.data.util.ClassTypeInformation.*; +import static org.springframework.data.util.ClassTypeInformation.from; import java.util.Collections; @@ -32,7 +32,7 @@ import org.springframework.data.util.ClassTypeInformation; /** * Unit tests for {@link MappingContextTypeInformationMapper}. - * + * * @author Oliver Gierke */ public class MappingContextTypeInformationMapperUnitTests { @@ -89,12 +89,12 @@ public class MappingContextTypeInformationMapperUnitTests { mappingContext.initialize(); mapper = new MappingContextTypeInformationMapper(mappingContext); - assertThat(mapper.resolveTypeFrom(Alias.of("foo"))).isEmpty(); + assertThat(mapper.resolveTypeFrom(Alias.of("foo"))).isNull(); PersistentEntity entity = mappingContext.getRequiredPersistentEntity(Entity.class); assertThat(entity).isNotNull(); - assertThat(mapper.resolveTypeFrom(Alias.of("foo"))).hasValue(from(Entity.class)); + assertThat(mapper.resolveTypeFrom(Alias.of("foo"))).isEqualTo(from(Entity.class)); } @Test // DATACMNS-485 diff --git a/src/test/java/org/springframework/data/convert/ReflectionEntityInstantiatorUnitTests.java b/src/test/java/org/springframework/data/convert/ReflectionEntityInstantiatorUnitTests.java index d65ec3a4d..1fade6e3b 100755 --- a/src/test/java/org/springframework/data/convert/ReflectionEntityInstantiatorUnitTests.java +++ b/src/test/java/org/springframework/data/convert/ReflectionEntityInstantiatorUnitTests.java @@ -23,9 +23,7 @@ import static org.springframework.data.util.ClassTypeInformation.from; import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.List; -import java.util.Optional; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -56,11 +54,6 @@ public class ReflectionEntityInstantiatorUnitTests

constructor; @Mock Parameter parameter; - @Before - public void setUp() { - doReturn(Optional.empty()).when(entity).getPersistenceConstructor(); - } - @Test public void instantiatesSimpleObjectCorrectly() { @@ -78,22 +71,21 @@ public class ReflectionEntityInstantiatorUnitTests

> constructor = new PreferredConstructorDiscoverer(Foo.class) - .getConstructor(); + PreferredConstructor constructor = new PreferredConstructorDiscoverer(Foo.class).getConstructor(); doReturn(constructor).when(entity).getPersistenceConstructor(); Object instance = INSTANCE.createInstance(entity, provider); assertThat(instance).isInstanceOf(Foo.class); - assertThat(constructor).hasValueSatisfying(it -> verify(provider, times(1)).getParameterValue(it.getParameters().iterator().next())); + assertThat(constructor) + .satisfies(it -> verify(provider, times(1)).getParameterValue(it.getParameters().iterator().next())); } @Test(expected = MappingInstantiationException.class) // DATACMNS-300 @SuppressWarnings({ "unchecked", "rawtypes" }) public void throwsExceptionOnBeanInstantiationException() { - doReturn(Optional.empty()).when(entity).getPersistenceConstructor(); doReturn(PersistentEntity.class).when(entity).getType(); INSTANCE.createInstance(entity, provider); @@ -103,7 +95,7 @@ public class ReflectionEntityInstantiatorUnitTests

entity = new BasicPersistentEntity<>(from(Inner.class)); - assertThat(entity.getPersistenceConstructor()).hasValueSatisfying(it -> { + assertThat(entity.getPersistenceConstructor()).satisfies(it -> { Parameter parameter = it.getParameters().iterator().next(); diff --git a/src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java b/src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java index 6fc744ac3..5f583735d 100755 --- a/src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java +++ b/src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java @@ -17,8 +17,6 @@ package org.springframework.data.convert; import static org.assertj.core.api.Assertions.*; -import java.util.Optional; - import org.junit.Test; import org.springframework.data.mapping.Alias; import org.springframework.data.util.ClassTypeInformation; @@ -26,7 +24,7 @@ import org.springframework.data.util.TypeInformation; /** * Unit tests for {@link SimpleTypeInformationMapper}. - * + * * @author Oliver Gierke */ public class SimpleTypeInformationMapperUnitTests { @@ -36,27 +34,27 @@ public class SimpleTypeInformationMapperUnitTests { @Test public void resolvesTypeByLoadingClass() { - Optional> type = mapper.resolveTypeFrom(Alias.of("java.lang.String")); + TypeInformation type = mapper.resolveTypeFrom(Alias.of("java.lang.String")); TypeInformation expected = ClassTypeInformation.from(String.class); - assertThat(type).hasValue(expected); + assertThat(type).isEqualTo(expected); } @Test public void returnsNullForNonStringKey() { - assertThat(mapper.resolveTypeFrom(Alias.of(new Object()))).isEmpty(); + assertThat(mapper.resolveTypeFrom(Alias.of(new Object()))).isNull(); } @Test public void returnsNullForEmptyTypeKey() { - assertThat(mapper.resolveTypeFrom(Alias.of(""))).isEmpty(); + assertThat(mapper.resolveTypeFrom(Alias.of(""))).isNull(); } @Test public void returnsNullForUnloadableClass() { - assertThat(mapper.resolveTypeFrom(Alias.of("Foo"))).isEmpty(); + assertThat(mapper.resolveTypeFrom(Alias.of("Foo"))).isNull(); } @Test diff --git a/src/test/java/org/springframework/data/mapping/MappingMetadataTests.java b/src/test/java/org/springframework/data/mapping/MappingMetadataTests.java index 1337fe091..90a5ca7d4 100755 --- a/src/test/java/org/springframework/data/mapping/MappingMetadataTests.java +++ b/src/test/java/org/springframework/data/mapping/MappingMetadataTests.java @@ -24,7 +24,7 @@ import org.springframework.data.mapping.context.SamplePersistentProperty; /** * Integration tests for Mapping metadata. - * + * * @author Jon Brisbin * @author Oliver Gierke */ @@ -42,7 +42,7 @@ public class MappingMetadataTests { PersistentEntity person = ctx.getRequiredPersistentEntity(PersonWithId.class); - assertThat(person.getIdProperty()).hasValueSatisfying(it -> assertThat(it.getType()).isEqualTo(String.class)); + assertThat(person.getIdProperty()).satisfies(it -> assertThat(it.getType()).isEqualTo(String.class)); } @Test diff --git a/src/test/java/org/springframework/data/mapping/ParameterUnitTests.java b/src/test/java/org/springframework/data/mapping/ParameterUnitTests.java index 198c63ddc..cc760008a 100755 --- a/src/test/java/org/springframework/data/mapping/ParameterUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/ParameterUnitTests.java @@ -18,7 +18,6 @@ package org.springframework.data.mapping; import static org.assertj.core.api.Assertions.*; import java.lang.annotation.Annotation; -import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,7 +29,7 @@ import org.springframework.data.util.TypeInformation; /** * Unit tests for {@link Parameter}. - * + * * @author Oliver Gierke */ @RunWith(MockitoJUnitRunner.class) @@ -45,8 +44,8 @@ public class ParameterUnitTests

> { @Test public void twoParametersWithIdenticalSetupEqual() { - Parameter left = new Parameter<>(Optional.of("name"), type, annotations, Optional.of(entity)); - Parameter right = new Parameter<>(Optional.of("name"), type, annotations, Optional.of(entity)); + Parameter left = new Parameter<>("name", type, annotations, entity); + Parameter right = new Parameter<>("name", type, annotations, entity); assertThat(left).isEqualTo(right); assertThat(left.hashCode()).isEqualTo(right.hashCode()); @@ -55,8 +54,8 @@ public class ParameterUnitTests

> { @Test public void twoParametersWithIdenticalSetupAndNullNameEqual() { - Parameter left = new Parameter<>(Optional.empty(), type, annotations, Optional.of(entity)); - Parameter right = new Parameter<>(Optional.empty(), type, annotations, Optional.of(entity)); + Parameter left = new Parameter<>(null, type, annotations, entity); + Parameter right = new Parameter<>(null, type, annotations, entity); assertThat(left).isEqualTo(right); assertThat(left.hashCode()).isEqualTo(right.hashCode()); @@ -65,8 +64,8 @@ public class ParameterUnitTests

> { @Test public void twoParametersWithIdenticalAndNullEntitySetupEqual() { - Parameter left = new Parameter<>(Optional.of("name"), type, annotations, Optional.empty()); - Parameter right = new Parameter<>(Optional.of("name"), type, annotations, Optional.empty()); + Parameter left = new Parameter<>("name", type, annotations, null); + Parameter right = new Parameter<>("name", type, annotations, null); assertThat(left).isEqualTo(right); assertThat(left.hashCode()).isEqualTo(right.hashCode()); @@ -75,9 +74,8 @@ public class ParameterUnitTests

> { @Test public void twoParametersWithDifferentNameAreNotEqual() { - Parameter left = new Parameter<>(Optional.of("first"), type, annotations, Optional.of(entity)); - Parameter right = new Parameter<>(Optional.of("second"), type, annotations, - Optional.of(entity)); + Parameter left = new Parameter<>("first", type, annotations, entity); + Parameter right = new Parameter<>("second", type, annotations, entity); assertThat(left).isNotEqualTo(right); } @@ -85,9 +83,9 @@ public class ParameterUnitTests

> { @Test public void twoParametersWithDifferenTypeAreNotEqual() { - Parameter left = new Parameter<>(Optional.of("name"), type, annotations, Optional.of(entity)); - Parameter right = new Parameter<>(Optional.of("name"), ClassTypeInformation.from(String.class), - annotations, Optional.of(stringEntity)); + Parameter left = new Parameter<>("name", type, annotations, entity); + Parameter right = new Parameter<>("name", ClassTypeInformation.from(String.class), annotations, + stringEntity); assertThat(left).isNotEqualTo(right); } diff --git a/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java b/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java index e04334e45..58a003437 100755 --- a/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java @@ -29,9 +29,10 @@ import org.springframework.data.util.ClassTypeInformation; /** * Unit tests for {@link PreferredConstructorDiscoverer}. - * + * * @author Oliver Gierke * @author Roman Rodov + * @author Mark Paluch */ public class PreferredConstructorDiscovererUnitTests

> { @@ -41,7 +42,7 @@ public class PreferredConstructorDiscovererUnitTests

discoverer = new PreferredConstructorDiscoverer<>( EntityWithoutConstructor.class); - assertThat(discoverer.getConstructor()).hasValueSatisfying(constructor -> { + assertThat(discoverer.getConstructor()).satisfies(constructor -> { assertThat(constructor).isNotNull(); assertThat(constructor.isNoArgConstructor()).isTrue(); @@ -55,7 +56,7 @@ public class PreferredConstructorDiscovererUnitTests

discoverer = new PreferredConstructorDiscoverer<>( ClassWithEmptyConstructor.class); - assertThat(discoverer.getConstructor()).hasValueSatisfying(constructor -> { + assertThat(discoverer.getConstructor()).satisfies(constructor -> { assertThat(constructor).isNotNull(); assertThat(constructor.isNoArgConstructor()).isTrue(); @@ -69,7 +70,7 @@ public class PreferredConstructorDiscovererUnitTests

discoverer = new PreferredConstructorDiscoverer<>( ClassWithMultipleConstructorsWithoutEmptyOne.class); - assertThat(discoverer.getConstructor()).isNotPresent(); + assertThat(discoverer.getConstructor()).isNull(); } @Test @@ -78,7 +79,7 @@ public class PreferredConstructorDiscovererUnitTests

discoverer = new PreferredConstructorDiscoverer<>( ClassWithMultipleConstructorsAndAnnotation.class); - assertThat(discoverer.getConstructor()).hasValueSatisfying(constructor -> { + assertThat(discoverer.getConstructor()).satisfies(constructor -> { assertThat(constructor).isNotNull(); assertThat(constructor.isNoArgConstructor()).isFalse(); @@ -100,7 +101,7 @@ public class PreferredConstructorDiscovererUnitTests

entity = new BasicPersistentEntity<>(ClassTypeInformation.from(Inner.class)); PreferredConstructorDiscoverer discoverer = new PreferredConstructorDiscoverer<>(entity); - assertThat(discoverer.getConstructor()).hasValueSatisfying(constructor -> { + assertThat(discoverer.getConstructor()).satisfies(constructor -> { Parameter parameter = constructor.getParameters().iterator().next(); assertThat(constructor.isEnclosingClassParameter(parameter)).isTrue(); @@ -113,7 +114,7 @@ public class PreferredConstructorDiscovererUnitTests

entity = new BasicPersistentEntity<>(ClassTypeInformation.from(SyntheticConstructor.class)); PreferredConstructorDiscoverer discoverer = new PreferredConstructorDiscoverer<>(entity); - assertThat(discoverer.getConstructor()).hasValueSatisfying(constructor -> { + assertThat(discoverer.getConstructor()).satisfies(constructor -> { PersistenceConstructor annotation = constructor.getConstructor().getAnnotation(PersistenceConstructor.class); assertThat(annotation).isNotNull(); diff --git a/src/test/java/org/springframework/data/mapping/TargetAwareIdentifierAccessorUnitTests.java b/src/test/java/org/springframework/data/mapping/TargetAwareIdentifierAccessorUnitTests.java index e55242027..a0984aa11 100644 --- a/src/test/java/org/springframework/data/mapping/TargetAwareIdentifierAccessorUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/TargetAwareIdentifierAccessorUnitTests.java @@ -33,7 +33,7 @@ public class TargetAwareIdentifierAccessorUnitTests { Object sample = new Object(); - IdentifierAccessor accessor = new TargetAwareIdentifierAccessor(() -> sample) { + IdentifierAccessor accessor = new TargetAwareIdentifierAccessor(sample) { @Override public Object getIdentifier() { diff --git a/src/test/java/org/springframework/data/mapping/context/AbstractMappingContextUnitTests.java b/src/test/java/org/springframework/data/mapping/context/AbstractMappingContextUnitTests.java index 57014caa3..7cb2530c6 100755 --- a/src/test/java/org/springframework/data/mapping/context/AbstractMappingContextUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/context/AbstractMappingContextUnitTests.java @@ -42,7 +42,7 @@ import org.springframework.util.StringUtils; /** * Unit test for {@link AbstractMappingContext}. - * + * * @author Oliver Gierke * @author Thomas Darimont */ @@ -111,7 +111,7 @@ public class AbstractMappingContextUnitTests { public void returnsNullPersistentEntityForSimpleTypes() { SampleMappingContext context = new SampleMappingContext(); - assertThat(context.getPersistentEntity(String.class)).isEmpty(); + assertThat(context.getPersistentEntity(String.class)).isNull(); } @Test(expected = IllegalArgumentException.class) // DATACMNS-214 @@ -132,7 +132,7 @@ public class AbstractMappingContextUnitTests { PersistentEntity entity = mappingContext .getRequiredPersistentEntity(Sample.class); - assertThat(entity.getPersistentProperty("metaClass")).isNotPresent(); + assertThat(entity.getPersistentProperty("metaClass")).isNull(); } @Test // DATACMNS-332 @@ -142,7 +142,7 @@ public class AbstractMappingContextUnitTests { PersistentEntity entity = mappingContext .getRequiredPersistentEntity(Extension.class); - assertThat(entity.getPersistentProperty("foo")).hasValueSatisfying(it -> assertThat(it.isIdProperty()).isTrue()); + assertThat(entity.getPersistentProperty("foo")).satisfies(it -> assertThat(it.isIdProperty()).isTrue()); } @Test // DATACMNS-345 @@ -154,8 +154,8 @@ public class AbstractMappingContextUnitTests { .getRequiredPersistentEntity(Sample.class); assertThat(entity.getPersistentProperty("persons")) - .hasValueSatisfying(it -> assertThat(mappingContext.getPersistentEntity(it)) - .hasValueSatisfying(inner -> assertThat(inner.getType()).isEqualTo(Person.class))); + .satisfies(it -> assertThat(mappingContext.getPersistentEntity(it)) + .satisfies(inner -> assertThat(inner.getType()).isEqualTo(Person.class))); } @Test // DATACMNS-380 @@ -193,7 +193,7 @@ public class AbstractMappingContextUnitTests { public void shouldReturnNullForSimpleTypesIfInStrictIsEnabled() { context.setStrict(true); - assertThat(context.getPersistentEntity(Integer.class)).isEmpty(); + assertThat(context.getPersistentEntity(Integer.class)).isNull(); } @Test // DATACMNS-462 diff --git a/src/test/java/org/springframework/data/mapping/model/AbstractPersistentPropertyUnitTests.java b/src/test/java/org/springframework/data/mapping/model/AbstractPersistentPropertyUnitTests.java index 47834f935..88497faba 100755 --- a/src/test/java/org/springframework/data/mapping/model/AbstractPersistentPropertyUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/AbstractPersistentPropertyUnitTests.java @@ -41,7 +41,7 @@ import org.springframework.util.ReflectionUtils; /** * Unit tests for {@link AbstractPersistentProperty}. - * + * * @author Oliver Gierke * @author Christoph Strobl */ @@ -99,8 +99,8 @@ public class AbstractPersistentPropertyUnitTests { SamplePersistentProperty property = getProperty(AccessorTestClass.class, "id"); - assertThat(property.getGetter()).isPresent(); - assertThat(property.getSetter()).isPresent(); + assertThat(property.getGetter()).isNotNull(); + assertThat(property.getSetter()).isNotNull(); } @Test // DATACMNS-206 @@ -108,8 +108,8 @@ public class AbstractPersistentPropertyUnitTests { SamplePersistentProperty property = getProperty(AccessorTestClass.class, "anotherId"); - assertThat(property.getGetter()).isNotPresent(); - assertThat(property.getSetter()).isNotPresent(); + assertThat(property.getGetter()).isNull(); + assertThat(property.getSetter()).isNull(); } @Test // DATACMNS-206 @@ -117,8 +117,8 @@ public class AbstractPersistentPropertyUnitTests { SamplePersistentProperty property = getProperty(AccessorTestClass.class, "yetAnotherId"); - assertThat(property.getGetter()).isPresent(); - assertThat(property.getSetter()).isNotPresent(); + assertThat(property.getGetter()).isNotNull(); + assertThat(property.getSetter()).isNull(); } @Test // DATACMNS-206 @@ -126,8 +126,8 @@ public class AbstractPersistentPropertyUnitTests { SamplePersistentProperty property = getProperty(AccessorTestClass.class, "yetYetAnotherId"); - assertThat(property.getGetter()).isNotPresent(); - assertThat(property.getSetter()).isPresent(); + assertThat(property.getGetter()).isNull(); + assertThat(property.getSetter()).isNotNull(); } @Test // DATACMNS-206 @@ -137,8 +137,8 @@ public class AbstractPersistentPropertyUnitTests { PersistentProperty property = new SamplePersistentProperty(Property.of(field), getEntity(AccessorTestClass.class), typeHolder); - assertThat(property.getGetter()).isNotPresent(); - assertThat(property.getSetter()).isNotPresent(); + assertThat(property.getGetter()).isNull(); + assertThat(property.getSetter()).isNull(); } @Test // DATACMNS-337 @@ -325,8 +325,8 @@ public class AbstractPersistentPropertyUnitTests { } @Override - public Optional findAnnotation(Class annotationType) { - return Optional.empty(); + public A findAnnotation(Class annotationType) { + return null; } @Override @@ -335,8 +335,8 @@ public class AbstractPersistentPropertyUnitTests { } @Override - public Optional findPropertyOrOwnerAnnotation(Class annotationType) { - return Optional.empty(); + public A findPropertyOrOwnerAnnotation(Class annotationType) { + return null; } } diff --git a/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java b/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java index 4f98b9943..4254266ef 100755 --- a/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java @@ -29,7 +29,6 @@ import javax.annotation.Nullable; import org.junit.Before; import org.junit.Test; - import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.annotation.AccessType; @@ -84,7 +83,7 @@ public class AnnotationBasedPersistentPropertyUnitTests

{ + assertThat(entity.getPersistentProperty("meta")).satisfies(property -> { // Assert direct annotations are cached on construction Map, Annotation> cache = getAnnotationCache(property); @@ -92,7 +91,8 @@ public class AnnotationBasedPersistentPropertyUnitTests

assertThat(cache.containsKey(MyAnnotation.class)).isTrue()); + assertThat(property.findAnnotation(MyAnnotation.class)) + .satisfies(annotation -> assertThat(cache.containsKey(MyAnnotation.class)).isTrue()); }); } @@ -110,25 +110,28 @@ public class AnnotationBasedPersistentPropertyUnitTests

assertThat(it.usePropertyAccess()).isFalse()); + assertThat(getProperty(FieldAccess.class, "name")).satisfies(it -> assertThat(it.usePropertyAccess()).isFalse()); } @Test // DATACMNS-243 public void usesAccessTypeDeclaredOnTypeAsDefault() { - assertThat(getProperty(PropertyAccess.class, "firstname")).hasValueSatisfying(it -> assertThat(it.usePropertyAccess()).isTrue()); + assertThat(getProperty(PropertyAccess.class, "firstname")) + .satisfies(it -> assertThat(it.usePropertyAccess()).isTrue()); } @Test // DATACMNS-243 public void propertyAnnotationOverridesTypeConfiguration() { - assertThat(getProperty(PropertyAccess.class, "lastname")).hasValueSatisfying(it -> assertThat(it.usePropertyAccess()).isFalse()); + assertThat(getProperty(PropertyAccess.class, "lastname")) + .satisfies(it -> assertThat(it.usePropertyAccess()).isFalse()); } @Test // DATACMNS-243 public void fieldAnnotationOverridesTypeConfiguration() { - assertThat(getProperty(PropertyAccess.class, "emailAddress")).hasValueSatisfying(it -> assertThat(it.usePropertyAccess()).isFalse()); + assertThat(getProperty(PropertyAccess.class, "emailAddress")) + .satisfies(it -> assertThat(it.usePropertyAccess()).isFalse()); } @Test // DATACMNS-243 @@ -139,24 +142,27 @@ public class AnnotationBasedPersistentPropertyUnitTests

assertThat(it.isWritable()).isTrue()); + assertThat(getProperty(ClassWithReadOnlyProperties.class, "noAnnotations")) + .satisfies(it -> assertThat(it.isWritable()).isTrue()); } @Test // DATACMNS-534 public void treatsTransientAsNotExisting() { - assertThat(getProperty(ClassWithReadOnlyProperties.class, "transientProperty")).isEmpty(); + assertThat(getProperty(ClassWithReadOnlyProperties.class, "transientProperty")).isNull(); } @Test // DATACMNS-534 public void treatsReadOnlyAsNonWritable() { - assertThat(getProperty(ClassWithReadOnlyProperties.class, "readOnlyProperty")).hasValueSatisfying(it -> assertThat(it.isWritable()).isFalse()); + assertThat(getProperty(ClassWithReadOnlyProperties.class, "readOnlyProperty")) + .satisfies(it -> assertThat(it.isWritable()).isFalse()); } @Test // DATACMNS-534 public void considersPropertyWithReadOnlyMetaAnnotationReadOnly() { - assertThat(getProperty(ClassWithReadOnlyProperties.class, "customReadOnlyProperty")).hasValueSatisfying(it -> assertThat(it.isWritable()).isFalse()); + assertThat(getProperty(ClassWithReadOnlyProperties.class, "customReadOnlyProperty")) + .satisfies(it -> assertThat(it.isWritable()).isFalse()); } @Test // DATACMNS-556 @@ -168,11 +174,11 @@ public class AnnotationBasedPersistentPropertyUnitTests

property = getProperty(Sample.class, "getterWithoutField"); + SamplePersistentProperty property = getProperty(Sample.class, "getterWithoutField"); - assertThat(property).hasValueSatisfying(it -> { + assertThat(property).satisfies(it -> { - assertThat(it.findAnnotation(MyAnnotation.class)).isNotPresent(); + assertThat(it.findAnnotation(MyAnnotation.class)).isNull(); Map, ?> field = (Map, ?>) ReflectionTestUtils.getField(it, "annotationCache"); @@ -184,7 +190,7 @@ public class AnnotationBasedPersistentPropertyUnitTests

{ + assertThat(entity.getPersistentProperty("metaAliased")).satisfies(property -> { // Assert direct annotations are cached on construction Map, Annotation> cache = getAnnotationCache(property); @@ -192,20 +198,24 @@ public class AnnotationBasedPersistentPropertyUnitTests

assertThat(cache.containsKey(MyAnnotation.class)).isTrue()); + assertThat(property.findAnnotation(MyAnnotation.class)) + .satisfies(it -> assertThat(cache.containsKey(MyAnnotation.class)).isTrue()); }); } @Test // DATACMNS-825 public void composedAnnotationWithAliasShouldHaveSynthesizedAttributeValues() { - assertThat(entity.getPersistentProperty("metaAliased")).hasValueSatisfying(property -> assertThat(property.findAnnotation(MyAnnotation.class)).hasValueSatisfying(annotation -> assertThat(AnnotationUtils.getValue(annotation)).isEqualTo("spring"))); + assertThat(entity.getPersistentProperty("metaAliased")) + .satisfies(property -> assertThat(property.findAnnotation(MyAnnotation.class)) + .satisfies(annotation -> assertThat(AnnotationUtils.getValue(annotation)).isEqualTo("spring"))); } @Test // DATACMNS-867 public void revisedAnnotationWithAliasShouldHaveSynthesizedAttributeValues() { - assertThat(entity.getPersistentProperty("setter")).hasValueSatisfying(property -> assertThat(property.findAnnotation(RevisedAnnnotationWithAliasFor.class)).hasValueSatisfying(annotation -> { + assertThat(entity.getPersistentProperty("setter")).satisfies( + property -> assertThat(property.findAnnotation(RevisedAnnnotationWithAliasFor.class)).satisfies(annotation -> { assertThat(annotation.name()).isEqualTo("my-value"); assertThat(annotation.value()).isEqualTo("my-value"); })); @@ -217,16 +227,16 @@ public class AnnotationBasedPersistentPropertyUnitTests

A assertAnnotationPresent(Class annotationType, - Optional> property) { + AnnotationBasedPersistentProperty property) { - Optional annotation = property.flatMap(it -> it.findAnnotation(annotationType)); + A annotation = property.findAnnotation(annotationType); - assertThat(annotation).isPresent(); + assertThat(annotation).isNotNull(); - return annotation.get(); + return annotation; } - private Optional getProperty(Class type, String name) { + private SamplePersistentProperty getProperty(Class type, String name) { return context.getRequiredPersistentEntity(type).getPersistentProperty(name); } diff --git a/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java b/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java index 08add50d4..b2b7c728f 100755 --- a/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java @@ -24,7 +24,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.Comparator; import java.util.Iterator; import java.util.List; -import java.util.Optional; import org.hamcrest.CoreMatchers; import org.junit.Rule; @@ -119,20 +118,20 @@ public class BasicPersistentEntityUnitTests> { assertThat(properties).hasSize(3); Iterator iterator = properties.iterator(); - assertThat(entity.getPersistentProperty("firstName")).hasValue(iterator.next()); - assertThat(entity.getPersistentProperty("lastName")).hasValue(iterator.next()); - assertThat(entity.getPersistentProperty("ssn")).hasValue(iterator.next()); + assertThat(entity.getPersistentProperty("firstName")).isEqualTo(iterator.next()); + assertThat(entity.getPersistentProperty("lastName")).isEqualTo(iterator.next()); + assertThat(entity.getPersistentProperty("ssn")).isEqualTo(iterator.next()); } @Test // DATACMNS-186 public void addingAndIdPropertySetsIdPropertyInternally() { MutablePersistentEntity entity = createEntity(Person.class); - assertThat(entity.getIdProperty()).isNotPresent(); + assertThat(entity.getIdProperty()).isNull(); when(property.isIdProperty()).thenReturn(true); entity.addPersistentProperty(property); - assertThat(entity.getIdProperty()).hasValue(property); + assertThat(entity.getIdProperty()).isEqualTo(property); } @Test // DATACMNS-186 @@ -154,15 +153,15 @@ public class BasicPersistentEntityUnitTests> { SampleMappingContext context = new SampleMappingContext(); PersistentEntity entity = context.getRequiredPersistentEntity(Entity.class); - Optional property = entity.getPersistentProperty(LastModifiedBy.class); + SamplePersistentProperty property = entity.getPersistentProperty(LastModifiedBy.class); - assertThat(property).hasValueSatisfying(it -> assertThat(it.getName()).isEqualTo("field")); + assertThat(property.getName()).isEqualTo("field"); property = entity.getPersistentProperty(CreatedBy.class); - assertThat(property).hasValueSatisfying(it -> assertThat(it.getName()).isEqualTo("property")); + assertThat(property.getName()).isEqualTo("property"); - assertThat(entity.getPersistentProperty(CreatedDate.class)).isNotPresent(); + assertThat(entity.getPersistentProperty(CreatedDate.class)).isNull(); } @Test // DATACMNS-596 @@ -253,7 +252,7 @@ public class BasicPersistentEntityUnitTests> { } private BasicPersistentEntity createEntity(Class type, Comparator comparator) { - return new BasicPersistentEntity<>(ClassTypeInformation.from(type), Optional.ofNullable(comparator)); + return new BasicPersistentEntity<>(ClassTypeInformation.from(type), comparator); } @TypeAlias("foo") diff --git a/src/test/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactoryDatatypeTests.java b/src/test/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactoryDatatypeTests.java index 9c23d6372..28c34c523 100755 --- a/src/test/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactoryDatatypeTests.java +++ b/src/test/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactoryDatatypeTests.java @@ -23,7 +23,6 @@ import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; @@ -124,7 +123,7 @@ public class ClassGeneratingPropertyAccessorFactoryDatatypeTests { @Test // DATACMNS-809 public void shouldSetAndGetProperty() throws Exception { - assertThat(getProperty(bean, propertyName)).hasValueSatisfying(property -> { + assertThat(getProperty(bean, propertyName)).satisfies(property -> { PersistentPropertyAccessor persistentPropertyAccessor = getPersistentPropertyAccessor(bean); @@ -147,7 +146,7 @@ public class ClassGeneratingPropertyAccessorFactoryDatatypeTests { return factory.getPropertyAccessor(mappingContext.getRequiredPersistentEntity(bean.getClass()), bean); } - private Optional> getProperty(Object bean, String name) { + private PersistentProperty getProperty(Object bean, String name) { BasicPersistentEntity persistentEntity = mappingContext .getRequiredPersistentEntity(bean.getClass()); diff --git a/src/test/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactoryTests.java b/src/test/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactoryTests.java index f66a77997..8945cbeda 100755 --- a/src/test/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactoryTests.java +++ b/src/test/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactoryTests.java @@ -97,7 +97,7 @@ public class ClassGeneratingPropertyAccessorFactoryTests { @Test // DATACMNS-809 public void shouldSetAndGetProperty() throws Exception { - assertThat(getProperty(bean, propertyName)).hasValueSatisfying(property -> { + assertThat(getProperty(bean, propertyName)).satisfies(property -> { PersistentPropertyAccessor persistentPropertyAccessor = getPersistentPropertyAccessor(bean); @@ -126,14 +126,16 @@ public class ClassGeneratingPropertyAccessorFactoryTests { @Test // DATACMNS-809 public void getPropertyShouldFailOnUnhandledProperty() { - assertThat(getProperty(new Dummy(), "dummy")).hasValueSatisfying(property -> assertThatExceptionOfType(UnsupportedOperationException.class)// + assertThat(getProperty(new Dummy(), "dummy")) + .satisfies(property -> assertThatExceptionOfType(UnsupportedOperationException.class)// .isThrownBy(() -> getPersistentPropertyAccessor(bean).getProperty(property))); } @Test // DATACMNS-809 public void setPropertyShouldFailOnUnhandledProperty() { - assertThat(getProperty(new Dummy(), "dummy")).hasValueSatisfying(property -> assertThatExceptionOfType(UnsupportedOperationException.class)// + assertThat(getProperty(new Dummy(), "dummy")) + .satisfies(property -> assertThatExceptionOfType(UnsupportedOperationException.class)// .isThrownBy(() -> getPersistentPropertyAccessor(bean).setProperty(property, Optional.empty()))); } @@ -151,7 +153,7 @@ public class ClassGeneratingPropertyAccessorFactoryTests { return factory.getPropertyAccessor(mappingContext.getRequiredPersistentEntity(bean.getClass()), bean); } - private Optional> getProperty(Object bean, String name) { + private PersistentProperty getProperty(Object bean, String name) { BasicPersistentEntity persistentEntity = mappingContext .getRequiredPersistentEntity(bean.getClass()); diff --git a/src/test/java/org/springframework/data/mapping/model/ConvertingPropertyAccessorUnitTests.java b/src/test/java/org/springframework/data/mapping/model/ConvertingPropertyAccessorUnitTests.java index 09208f133..8715f2029 100755 --- a/src/test/java/org/springframework/data/mapping/model/ConvertingPropertyAccessorUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/ConvertingPropertyAccessorUnitTests.java @@ -18,8 +18,6 @@ package org.springframework.data.mapping.model; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import java.util.Optional; - import org.junit.Test; import org.springframework.core.convert.ConversionService; import org.springframework.data.mapping.PersistentPropertyAccessor; @@ -60,7 +58,7 @@ public class ConvertingPropertyAccessorUnitTests { Entity entity = new Entity(); entity.id = 1L; - assertThat(getIdProperty()).hasValueSatisfying( + assertThat(getIdProperty()).satisfies( it -> assertThat(getAccessor(entity, CONVERSION_SERVICE).getProperty(it, String.class)).isEqualTo("1")); } @@ -69,7 +67,7 @@ public class ConvertingPropertyAccessorUnitTests { ConversionService conversionService = mock(ConversionService.class); - assertThat(getIdProperty()).hasValueSatisfying(it -> { + assertThat(getIdProperty()).satisfies(it -> { assertThat(getAccessor(new Entity(), conversionService).getProperty(it, Number.class)).isNull(); verify(conversionService, times(0)).convert(1L, Number.class); }); @@ -83,7 +81,7 @@ public class ConvertingPropertyAccessorUnitTests { ConversionService conversionService = mock(ConversionService.class); - assertThat(getIdProperty()).hasValueSatisfying(it -> { + assertThat(getIdProperty()).satisfies(it -> { assertThat(getAccessor(entity, conversionService).getProperty(it, Number.class)).isEqualTo(1L); verify(conversionService, times(0)).convert(1L, Number.class); }); @@ -94,7 +92,7 @@ public class ConvertingPropertyAccessorUnitTests { Entity entity = new Entity(); - assertThat(getIdProperty()).hasValueSatisfying(property -> { + assertThat(getIdProperty()).satisfies(property -> { getAccessor(entity, CONVERSION_SERVICE).setProperty(property, "1"); assertThat(entity.id).isEqualTo(1L); }); @@ -103,7 +101,7 @@ public class ConvertingPropertyAccessorUnitTests { @Test // DATACMNS-596 public void doesNotInvokeConversionIfTypeAlreadyMatchesOnSet() { - assertThat(getIdProperty()).hasValueSatisfying(it -> { + assertThat(getIdProperty()).satisfies(it -> { getAccessor(new Entity(), mock(ConversionService.class)).setProperty(it, 1L); verify(mock(ConversionService.class), times(0)).convert(1L, Long.class); }); @@ -115,7 +113,7 @@ public class ConvertingPropertyAccessorUnitTests { return new ConvertingPropertyAccessor(wrapper, conversionService); } - private static Optional getIdProperty() { + private static SamplePersistentProperty getIdProperty() { SampleMappingContext mappingContext = new SampleMappingContext(); BasicPersistentEntity entity = mappingContext diff --git a/src/test/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProviderUnitTests.java b/src/test/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProviderUnitTests.java index a396b98b2..9b8a455ed 100755 --- a/src/test/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProviderUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProviderUnitTests.java @@ -50,12 +50,12 @@ public class PersistentEntityParameterValueProviderUnitTests

entity = new BasicPersistentEntity(ClassTypeInformation.from(Inner.class)) { @Override - public Optional

getPersistentProperty(String name) { - return Optional.ofNullable(property); + public P getPersistentProperty(String name) { + return property; } }; - assertThat(entity.getPersistenceConstructor()).hasValueSatisfying(constructor -> { + assertThat(entity.getPersistenceConstructor()).satisfies(constructor -> { Iterator> iterator = constructor.getParameters().iterator(); ParameterValueProvider

provider = new PersistentEntityParameterValueProvider<>(entity, propertyValueProvider, @@ -75,7 +75,7 @@ public class PersistentEntityParameterValueProviderUnitTests

assertThatExceptionOfType(MappingException.class)// + .satisfies(constructor -> assertThatExceptionOfType(MappingException.class)// .isThrownBy(() -> provider.getParameterValue(constructor.getParameters().iterator().next()))// .withMessageContaining("bar")// .withMessageContaining(Entity.class.getName())); diff --git a/src/test/java/org/springframework/data/mapping/model/SpelExpressionParameterProviderUnitTests.java b/src/test/java/org/springframework/data/mapping/model/SpelExpressionParameterProviderUnitTests.java index 06c994b39..27c9aa2f0 100755 --- a/src/test/java/org/springframework/data/mapping/model/SpelExpressionParameterProviderUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/SpelExpressionParameterProviderUnitTests.java @@ -18,8 +18,6 @@ package org.springframework.data.mapping.model; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import java.util.Optional; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -71,7 +69,7 @@ public class SpelExpressionParameterProviderUnitTests { @Test public void evaluatesSpELExpression() { - when(parameter.getSpelExpression()).thenReturn(Optional.of("expression")); + when(parameter.getSpelExpression()).thenReturn("expression"); provider.getParameterValue(parameter); verify(delegate, times(0)).getParameterValue(parameter); @@ -81,7 +79,7 @@ public class SpelExpressionParameterProviderUnitTests { @Test public void handsSpELValueToConversionService() { - doReturn(Optional.of("source")).when(parameter).getSpelExpression(); + doReturn("source").when(parameter).getSpelExpression(); doReturn("value").when(evaluator).evaluate(any()); provider.getParameterValue(parameter); @@ -93,7 +91,7 @@ public class SpelExpressionParameterProviderUnitTests { @Test public void doesNotConvertNullValue() { - doReturn(Optional.of("source")).when(parameter).getSpelExpression(); + doReturn("source").when(parameter).getSpelExpression(); doReturn(null).when(evaluator).evaluate(any()); provider.getParameterValue(parameter); @@ -115,7 +113,7 @@ public class SpelExpressionParameterProviderUnitTests { } }; - doReturn(Optional.of("source")).when(parameter).getSpelExpression(); + doReturn("source").when(parameter).getSpelExpression(); doReturn("value").when(evaluator).evaluate(any()); assertThat(provider.getParameterValue(parameter)).isEqualTo("FOO");