Browse Source

DATACMNS-867 - Second draft.

pull/194/head
Oliver Gierke 10 years ago
parent
commit
d4811e29d9
  1. 1
      pom.xml
  2. 2
      src/main/java/org/springframework/data/auditing/AnnotationAuditingMetadata.java
  3. 15
      src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java
  4. 2
      src/main/java/org/springframework/data/config/TypeFilterParser.java
  5. 7
      src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java
  6. 45
      src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java
  7. 97
      src/main/java/org/springframework/data/convert/DefaultTypeMapper.java
  8. 108
      src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java
  9. 2
      src/main/java/org/springframework/data/convert/ReflectionEntityInstantiator.java
  10. 50
      src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java
  11. 4
      src/main/java/org/springframework/data/convert/TypeAliasAccessor.java
  12. 7
      src/main/java/org/springframework/data/convert/TypeInformationMapper.java
  13. 4
      src/main/java/org/springframework/data/convert/TypeMapper.java
  14. 2
      src/main/java/org/springframework/data/domain/AbstractPageRequest.java
  15. 35
      src/main/java/org/springframework/data/domain/Chunk.java
  16. 4
      src/main/java/org/springframework/data/domain/Example.java
  17. 2
      src/main/java/org/springframework/data/domain/ExampleMatcher.java
  18. 2
      src/main/java/org/springframework/data/domain/Page.java
  19. 16
      src/main/java/org/springframework/data/domain/PageImpl.java
  20. 33
      src/main/java/org/springframework/data/domain/PageRequest.java
  21. 49
      src/main/java/org/springframework/data/domain/Pageable.java
  22. 5
      src/main/java/org/springframework/data/domain/Slice.java
  23. 5
      src/main/java/org/springframework/data/domain/SliceImpl.java
  24. 64
      src/main/java/org/springframework/data/domain/Sort.java
  25. 8
      src/main/java/org/springframework/data/domain/jaxb/PageableAdapter.java
  26. 4
      src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java
  27. 8
      src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java
  28. 2
      src/main/java/org/springframework/data/geo/Distance.java
  29. 4
      src/main/java/org/springframework/data/geo/Polygon.java
  30. 66
      src/main/java/org/springframework/data/mapping/Alias.java
  31. 2
      src/main/java/org/springframework/data/mapping/IdentifierAccessor.java
  32. 2
      src/main/java/org/springframework/data/mapping/PersistentEntity.java
  33. 4
      src/main/java/org/springframework/data/mapping/PersistentProperty.java
  34. 2
      src/main/java/org/springframework/data/mapping/PersistentPropertyAccessor.java
  35. 8
      src/main/java/org/springframework/data/mapping/PreferredConstructor.java
  36. 28
      src/main/java/org/springframework/data/mapping/PropertyPath.java
  37. 2
      src/main/java/org/springframework/data/mapping/PropertyReferenceException.java
  38. 110
      src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java
  39. 16
      src/main/java/org/springframework/data/mapping/context/DefaultPersistentPropertyPath.java
  40. 24
      src/main/java/org/springframework/data/mapping/context/MappingContext.java
  41. 119
      src/main/java/org/springframework/data/mapping/context/MappingContextIsNewStrategyFactory.java
  42. 48
      src/main/java/org/springframework/data/mapping/context/PersistentEntities.java
  43. 69
      src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java
  44. 33
      src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java
  45. 18
      src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java
  46. 2
      src/main/java/org/springframework/data/mapping/model/BeanWrapper.java
  47. 2
      src/main/java/org/springframework/data/mapping/model/BeanWrapperPropertyAccessorFactory.java
  48. 2
      src/main/java/org/springframework/data/mapping/model/CamelCaseSplittingFieldNamingStrategy.java
  49. 17
      src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java
  50. 2
      src/main/java/org/springframework/data/mapping/model/ConvertingPropertyAccessor.java
  51. 4
      src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java
  52. 138
      src/main/java/org/springframework/data/mapping/model/Property.java
  53. 11
      src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java
  54. 6
      src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java
  55. 2
      src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java
  56. 2
      src/main/java/org/springframework/data/projection/SpelAwareProxyProjectionFactory.java
  57. 11
      src/main/java/org/springframework/data/querydsl/QPageRequest.java
  58. 25
      src/main/java/org/springframework/data/querydsl/QSort.java
  59. 10
      src/main/java/org/springframework/data/querydsl/QuerydslRepositoryInvokerAdapter.java
  60. 4
      src/main/java/org/springframework/data/querydsl/binding/MultiValueBinding.java
  61. 10
      src/main/java/org/springframework/data/querydsl/binding/QuerydslBindings.java
  62. 36
      src/main/java/org/springframework/data/querydsl/binding/QuerydslPredicateBuilder.java
  63. 2
      src/main/java/org/springframework/data/repository/PagingAndSortingRepository.java
  64. 6
      src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java
  65. 2
      src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java
  66. 6
      src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java
  67. 2
      src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java
  68. 3
      src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java
  69. 4
      src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java
  70. 2
      src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java
  71. 2
      src/main/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupport.java
  72. 2
      src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java
  73. 3
      src/main/java/org/springframework/data/repository/core/EntityInformation.java
  74. 17
      src/main/java/org/springframework/data/repository/core/support/AbstractEntityInformation.java
  75. 2
      src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java
  76. 7
      src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java
  77. 3
      src/main/java/org/springframework/data/repository/core/support/DelegatingEntityInformation.java
  78. 40
      src/main/java/org/springframework/data/repository/core/support/PersistableEntityInformation.java
  79. 5
      src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java
  80. 17
      src/main/java/org/springframework/data/repository/core/support/ReflectionEntityInformation.java
  81. 5
      src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java
  82. 47
      src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java
  83. 4
      src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryProxyPostProcessor.java
  84. 6
      src/main/java/org/springframework/data/repository/init/Jackson2ResourceReader.java
  85. 12
      src/main/java/org/springframework/data/repository/query/EvaluationContextExtensionInformation.java
  86. 2
      src/main/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProvider.java
  87. 3
      src/main/java/org/springframework/data/repository/query/ParameterAccessor.java
  88. 6
      src/main/java/org/springframework/data/repository/query/Parameters.java
  89. 20
      src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java
  90. 4
      src/main/java/org/springframework/data/repository/query/QueryMethod.java
  91. 46
      src/main/java/org/springframework/data/repository/query/ResultProcessor.java
  92. 4
      src/main/java/org/springframework/data/repository/query/ReturnedType.java
  93. 9
      src/main/java/org/springframework/data/repository/query/parser/AbstractQueryCreator.java
  94. 37
      src/main/java/org/springframework/data/repository/query/parser/OrderBySource.java
  95. 2
      src/main/java/org/springframework/data/repository/query/parser/Part.java
  96. 18
      src/main/java/org/springframework/data/repository/query/parser/PartTree.java
  97. 2
      src/main/java/org/springframework/data/repository/support/CrudRepositoryInvoker.java
  98. 13
      src/main/java/org/springframework/data/repository/support/DefaultRepositoryInvokerFactory.java
  99. 41
      src/main/java/org/springframework/data/repository/support/DomainClassConverter.java
  100. 72
      src/main/java/org/springframework/data/repository/support/MethodParameters.java
  101. Some files were not shown because too many files have changed in this diff Show More

1
pom.xml

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
<properties>
<javaslang>2.0.4</javaslang>
<scala>2.11.7</scala>
<mockito>2.1.0-RC.1</mockito>
<xmlbeam>1.4.8</xmlbeam>
</properties>

2
src/main/java/org/springframework/data/auditing/AnnotationAuditingMetadata.java

@ -60,7 +60,7 @@ final class AnnotationAuditingMetadata { @@ -60,7 +60,7 @@ final class AnnotationAuditingMetadata {
static {
List<String> types = new ArrayList<String>(5);
List<String> types = new ArrayList<>(5);
types.add("org.joda.time.DateTime");
types.add("org.joda.time.LocalDateTime");
types.add(Date.class.getName());

15
src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java

@ -73,17 +73,16 @@ public class MappingAuditableBeanWrapperFactory extends DefaultAuditableBeanWrap @@ -73,17 +73,16 @@ public class MappingAuditableBeanWrapperFactory extends DefaultAuditableBeanWrap
}
Class<?> type = it.getClass();
PersistentEntity<?, ?> entity = entities.getPersistentEntity(type);
if (entity == null) {
return super.getBeanWrapperFor(source);
}
return entities.getPersistentEntity(type).map(entity -> {
MappingAuditingMetadata metadata = metadataCache.computeIfAbsent(type,
key -> new MappingAuditingMetadata(entity));
MappingAuditingMetadata metadata = metadataCache.computeIfAbsent(type,
foo -> new MappingAuditingMetadata(entity));
return Optional.<AuditableBeanWrapper>ofNullable(metadata.isAuditable()
? new MappingMetadataAuditableBeanWrapper(entity.getPropertyAccessor(it), metadata) : null);
return Optional.ofNullable(metadata.isAuditable()
? new MappingMetadataAuditableBeanWrapper(entity.getPropertyAccessor(it), metadata) : null);
}).orElseGet(() -> super.getBeanWrapperFor(source));
});
}

2
src/main/java/org/springframework/data/config/TypeFilterParser.java

@ -85,7 +85,7 @@ public class TypeFilterParser { @@ -85,7 +85,7 @@ public class TypeFilterParser {
public Collection<TypeFilter> parseTypeFilters(Element element, Type type) {
NodeList nodeList = element.getChildNodes();
Collection<TypeFilter> filters = new HashSet<TypeFilter>();
Collection<TypeFilter> filters = new HashSet<>();
for (int i = 0; i < nodeList.getLength(); i++) {

7
src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java

@ -284,11 +284,8 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { @@ -284,11 +284,8 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
private ObjectInstantiatorClassGenerator() {
this.classLoader = AccessController.doPrivileged(new PrivilegedAction<ByteArrayClassLoader>() {
public ByteArrayClassLoader run() {
return new ByteArrayClassLoader(ClassUtils.getDefaultClassLoader());
}
});
this.classLoader = AccessController.doPrivileged(
(PrivilegedAction<ByteArrayClassLoader>) () -> new ByteArrayClassLoader(ClassUtils.getDefaultClassLoader()));
}
/**

45
src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java

@ -18,7 +18,9 @@ package org.springframework.data.convert; @@ -18,7 +18,9 @@ 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;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
@ -34,7 +36,8 @@ import org.springframework.util.Assert; @@ -34,7 +36,8 @@ import org.springframework.util.Assert;
*/
public class ConfigurableTypeInformationMapper implements TypeInformationMapper {
private final Map<ClassTypeInformation<?>, Object> typeMap;
private final Map<ClassTypeInformation<?>, Alias> typeToAlias;
private final Map<Alias, ClassTypeInformation<?>> aliasToType;
/**
* Creates a new {@link ConfigurableTypeInformationMapper} for the given type map.
@ -44,18 +47,22 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper @@ -44,18 +47,22 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper
public ConfigurableTypeInformationMapper(Map<? extends Class<?>, String> sourceTypeMap) {
Assert.notNull(sourceTypeMap, "SourceTypeMap must not be null!");
this.typeMap = new HashMap<ClassTypeInformation<?>, Object>(sourceTypeMap.size());
this.typeToAlias = new HashMap<>(sourceTypeMap.size());
this.aliasToType = new HashMap<>(sourceTypeMap.size());
for (Entry<? extends Class<?>, String> entry : sourceTypeMap.entrySet()) {
ClassTypeInformation<?> key = ClassTypeInformation.from(entry.getKey());
String value = entry.getValue();
if (typeMap.containsValue(value)) {
throw new IllegalArgumentException(String.format(
"Detected mapping ambiguity! String %s cannot be mapped to more than one type!", value));
ClassTypeInformation<?> type = ClassTypeInformation.from(entry.getKey());
Alias alias = Alias.of(entry.getValue());
if (typeToAlias.containsValue(alias)) {
throw new IllegalArgumentException(
String.format("Detected mapping ambiguity! String %s cannot be mapped to more than one type!", alias));
}
this.typeMap.put(key, value);
this.typeToAlias.put(type, alias);
this.aliasToType.put(alias, type);
}
}
@ -63,26 +70,16 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper @@ -63,26 +70,16 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#createAliasFor(org.springframework.data.util.TypeInformation)
*/
public Object createAliasFor(TypeInformation<?> type) {
return typeMap.get(type);
public Alias createAliasFor(TypeInformation<?> type) {
return typeToAlias.getOrDefault(type, Alias.NONE);
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.lang.Object)
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(org.springframework.data.mapping.Alias)
*/
public ClassTypeInformation<?> resolveTypeFrom(Object alias) {
if (alias == null) {
return null;
}
for (Entry<ClassTypeInformation<?>, Object> entry : typeMap.entrySet()) {
if (entry.getValue().equals(alias)) {
return entry.getKey();
}
}
return null;
@Override
public Optional<TypeInformation<?>> resolveTypeFrom(Alias alias) {
return Optional.ofNullable(aliasToType.get(alias));
}
}

97
src/main/java/org/springframework/data/convert/DefaultTypeMapper.java

@ -20,11 +20,14 @@ import java.util.Arrays; @@ -20,11 +20,14 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@ -41,7 +44,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -41,7 +44,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
private final TypeAliasAccessor<S> accessor;
private final List<? extends TypeInformationMapper> mappers;
private final Map<Object, TypeInformation<?>> typeCache;
private final Map<Alias, Optional<TypeInformation<?>>> typeCache;
/**
* Creates a new {@link DefaultTypeMapper} using the given {@link TypeAliasAccessor}. It will use a
@ -80,7 +83,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -80,7 +83,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
Assert.notNull(accessor, "Accessor must not be null!");
Assert.notNull(additionalMappers, "AdditionalMappers must not be null!");
List<TypeInformationMapper> mappers = new ArrayList<TypeInformationMapper>(additionalMappers.size() + 1);
List<TypeInformationMapper> mappers = new ArrayList<>(additionalMappers.size() + 1);
if (mappingContext != null) {
mappers.add(new MappingContextTypeInformationMapper(mappingContext));
}
@ -88,19 +91,18 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -88,19 +91,18 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
this.mappers = Collections.unmodifiableList(mappers);
this.accessor = accessor;
this.typeCache = new ConcurrentHashMap<Object, TypeInformation<?>>();
this.typeCache = new ConcurrentHashMap<>();
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeMapper#readType(java.lang.Object)
*/
public TypeInformation<?> readType(S source) {
public Optional<TypeInformation<?>> readType(S source) {
Assert.notNull(source, "Source object must not be null!");
Object alias = accessor.readAliasFrom(source);
return alias == null ? null : getFromCacheOrCreate(alias);
return getFromCacheOrCreate(accessor.readAliasFrom(source));
}
/**
@ -110,53 +112,41 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -110,53 +112,41 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* @param alias
* @return
*/
private TypeInformation<?> getFromCacheOrCreate(Object alias) {
TypeInformation<?> typeInformation = typeCache.get(alias);
if (typeInformation != null) {
return typeInformation;
}
for (TypeInformationMapper mapper : mappers) {
typeInformation = mapper.resolveTypeFrom(alias);
if (typeInformation != null) {
typeCache.put(alias, typeInformation);
return typeInformation;
}
}
return typeInformation;
private Optional<TypeInformation<?>> getFromCacheOrCreate(Alias alias) {
return typeCache.computeIfAbsent(alias, key -> Optionals.firstNonEmpty(mappers, it -> it.resolveTypeFrom(alias)));
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeMapper#readType(java.lang.Object, org.springframework.data.util.TypeInformation)
*/
@SuppressWarnings("unchecked")
public <T> TypeInformation<? extends T> readType(S source, TypeInformation<T> basicType) {
Assert.notNull(source, "Source object must not be null!");
Class<?> documentsTargetType = getDefaultedTypeToBeUsed(source);
Assert.notNull(source, "Source must not be null!");
Assert.notNull(basicType, "Basic type must not be null!");
if (documentsTargetType == null) {
return basicType;
}
Optional<TypeInformation<? extends T>> calculated = getDefaultedTypeToBeUsed(source)//
.map(it -> foo(it, basicType));
Class<T> rawType = basicType == null ? null : basicType.getType();
return calculated.orElse(basicType);
}
boolean isMoreConcreteCustomType = rawType == null ? true
: rawType.isAssignableFrom(documentsTargetType) && !rawType.equals(documentsTargetType);
// @SuppressWarnings("unchecked")
private static <T> TypeInformation<? extends T> foo(Class<?> sourceType, TypeInformation<T> type) {
if (!isMoreConcreteCustomType) {
return basicType;
}
return specializeOrDefault(sourceType, type);
// return type//
// .<TypeInformation<? extends T>>map(it -> specializeOrDefault(sourceType, it))
// .orElseGet(() -> (TypeInformation<? extends T>) ClassTypeInformation.from(sourceType));
}
private static <T> TypeInformation<? extends T> specializeOrDefault(Class<?> it, TypeInformation<T> type) {
ClassTypeInformation<?> targetType = ClassTypeInformation.from(documentsTargetType);
ClassTypeInformation<?> targetType = ClassTypeInformation.from(it);
Class<T> rawType = type.getType();
return (TypeInformation<? extends T>) (basicType != null ? basicType.specialize(targetType) : targetType);
return rawType.isAssignableFrom(it) && !rawType.equals(it) ? type.specialize(targetType) : type;
}
/**
@ -166,12 +156,9 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -166,12 +156,9 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* @param source
* @return
*/
private Class<?> getDefaultedTypeToBeUsed(S source) {
TypeInformation<?> documentsTargetTypeInformation = readType(source);
documentsTargetTypeInformation = documentsTargetTypeInformation == null ? getFallbackTypeFor(source)
: documentsTargetTypeInformation;
return documentsTargetTypeInformation == null ? null : documentsTargetTypeInformation.getType();
private Optional<Class<?>> getDefaultedTypeToBeUsed(S source) {
return readType(source).map(it -> readType(source)).orElseGet(() -> getFallbackTypeFor(source))
.map(it -> it.getType());
}
/**
@ -180,8 +167,8 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -180,8 +167,8 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* @param source will never be {@literal null}.
* @return
*/
protected TypeInformation<?> getFallbackTypeFor(S source) {
return null;
protected Optional<TypeInformation<?>> getFallbackTypeFor(S source) {
return Optional.empty();
}
/*
@ -200,10 +187,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -200,10 +187,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
Assert.notNull(info, "TypeInformation must not be null!");
Object alias = getAliasFor(info);
if (alias != null) {
accessor.writeTypeTo(sink, alias);
}
getAliasFor(info).getValue().ifPresent(it -> accessor.writeTypeTo(sink, it));
}
/**
@ -213,17 +197,10 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -213,17 +197,10 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* @return the alias for the given {@link TypeInformation} or {@literal null} of none was found or all mappers
* returned {@literal null}.
*/
protected final Object getAliasFor(TypeInformation<?> info) {
protected final Alias getAliasFor(TypeInformation<?> info) {
Assert.notNull(info, "TypeInformation must not be null!");
for (TypeInformationMapper mapper : mappers) {
Object alias = mapper.createAliasFor(info);
if (alias != null) {
return alias;
}
}
return null;
return Optionals.firstNonEmpty(mappers, it -> it.createAliasFor(info), Alias.NONE);
}
}

108
src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java

@ -17,11 +17,12 @@ package org.springframework.data.convert; @@ -17,11 +17,12 @@ 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;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.CacheValue;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@ -35,7 +36,7 @@ import org.springframework.util.Assert; @@ -35,7 +36,7 @@ import org.springframework.util.Assert;
*/
public class MappingContextTypeInformationMapper implements TypeInformationMapper {
private final Map<ClassTypeInformation<?>, CacheValue<Object>> typeMap;
private final Map<ClassTypeInformation<?>, Alias> typeMap;
private final MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext;
/**
@ -48,11 +49,11 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe @@ -48,11 +49,11 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe
Assert.notNull(mappingContext, "MappingContext must not be null!");
this.typeMap = new ConcurrentHashMap<ClassTypeInformation<?>, CacheValue<Object>>();
this.typeMap = new ConcurrentHashMap<>();
this.mappingContext = mappingContext;
for (PersistentEntity<?, ?> entity : mappingContext.getPersistentEntities()) {
safelyAddToCache(entity.getTypeInformation().getRawTypeInformation(), entity.getTypeAlias());
verify(entity.getTypeInformation().getRawTypeInformation(), entity.getTypeAlias());
}
}
@ -60,24 +61,11 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe @@ -60,24 +61,11 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#createAliasFor(org.springframework.data.util.TypeInformation)
*/
public Object createAliasFor(TypeInformation<?> type) {
public Alias createAliasFor(TypeInformation<?> type) {
CacheValue<Object> key = typeMap.get(type);
if (key != null) {
return key.getValue();
}
PersistentEntity<?, ?> entity = mappingContext.getPersistentEntity(type);
if (entity == null) {
return null;
}
Object alias = entity.getTypeAlias();
safelyAddToCache(type.getRawTypeInformation(), alias);
return alias;
return typeMap.computeIfAbsent(type.getRawTypeInformation(), key -> {
return verify(key, mappingContext.getPersistentEntity(key).map(it -> it.getTypeAlias()).orElse(Alias.NONE));
});
}
/**
@ -86,73 +74,59 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe @@ -86,73 +74,59 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe
* @param key must not be {@literal null}.
* @param alias can be {@literal null}.
*/
private void safelyAddToCache(ClassTypeInformation<?> key, Object alias) {
CacheValue<Object> aliasToBeCached = CacheValue.ofNullable(alias);
private Alias verify(ClassTypeInformation<?> key, Alias alias) {
if (alias == null && !typeMap.containsKey(key)) {
typeMap.put(key, aliasToBeCached);
return;
}
// Reject second alias for same type
CacheValue<Object> alreadyCachedAlias = typeMap.get(key);
Alias existingAlias = typeMap.getOrDefault(key, Alias.NONE);
// Reject second alias for same type
if (existingAlias.isPresentButDifferent(alias)) {
if (alreadyCachedAlias != null && alreadyCachedAlias.isPresent() && !alreadyCachedAlias.hasValue(alias)) {
throw new IllegalArgumentException(String.format(
"Trying to register alias '%s', but found already registered alias '%s' for type %s!", alias,
alreadyCachedAlias, key));
throw new IllegalArgumentException(
String.format("Trying to register alias '%s', but found already registered alias '%s' for type %s!", alias,
existingAlias, key));
}
// Reject second type for same alias
if (typeMap.containsValue(aliasToBeCached)) {
for (Entry<ClassTypeInformation<?>, CacheValue<Object>> entry : typeMap.entrySet()) {
if (typeMap.containsValue(alias)) {
CacheValue<Object> value = entry.getValue();
if (!value.isPresent()) {
continue;
}
typeMap.entrySet().stream()//
.filter(it -> it.getValue().hasSamePresentValueAs(alias) && !it.getKey().equals(key))//
.findFirst().ifPresent(it -> {
if (value.hasValue(alias) && !entry.getKey().equals(key)) {
throw new IllegalArgumentException(String.format(
"Detected existing type mapping of %s to alias '%s' but attempted to bind the same alias to %s!", key,
alias, entry.getKey()));
}
}
throw new IllegalArgumentException(String.format(
"Detected existing type mapping of %s to alias '%s' but attempted to bind the same alias to %s!", key,
alias, it.getKey()));
});
}
typeMap.put(key, aliasToBeCached);
return alias;
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.lang.Object)
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.util.Optional)
*/
public ClassTypeInformation<?> resolveTypeFrom(Object alias) {
if (alias == null) {
return null;
}
for (Entry<ClassTypeInformation<?>, CacheValue<Object>> entry : typeMap.entrySet()) {
@Override
public Optional<TypeInformation<?>> resolveTypeFrom(Alias alias) {
CacheValue<Object> cachedAlias = entry.getValue();
return alias.getValue().map(it -> {
if (cachedAlias.hasValue(alias)) {
return entry.getKey();
for (Entry<ClassTypeInformation<?>, Alias> entry : typeMap.entrySet()) {
if (entry.getValue().hasValue(it)) {
return entry.getKey();
}
}
}
for (PersistentEntity<?, ?> entity : mappingContext.getPersistentEntities()) {
if (alias.equals(entity.getTypeAlias())) {
return entity.getTypeInformation().getRawTypeInformation();
for (PersistentEntity<?, ?> entity : mappingContext.getPersistentEntities()) {
if (entity.getTypeAlias().hasValue(it)) {
return entity.getTypeInformation().getRawTypeInformation();
}
}
}
return null;
return null;
});
}
}

2
src/main/java/org/springframework/data/convert/ReflectionEntityInstantiator.java

@ -49,7 +49,7 @@ public enum ReflectionEntityInstantiator implements EntityInstantiator { @@ -49,7 +49,7 @@ public enum ReflectionEntityInstantiator implements EntityInstantiator {
.map(it -> constructor.getParameters().stream()//
.map(parameter -> it.getParameterValue(parameter).orElse(null))//
.collect(Collectors.toList()))//
.orElse(Collections.emptyList());
.orElseGet(() -> Collections.emptyList());
try {
return (T) BeanUtils.instantiateClass(constructor.getConstructor(), params.toArray());

50
src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java

@ -16,12 +16,13 @@ @@ -16,12 +16,13 @@
package org.springframework.data.convert;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.data.mapping.Alias;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Basic {@link TypeInformationMapper} implementation that interprets the alias handles as fully qualified class name
@ -32,7 +33,7 @@ import org.springframework.util.StringUtils; @@ -32,7 +33,7 @@ import org.springframework.util.StringUtils;
*/
public class SimpleTypeInformationMapper implements TypeInformationMapper {
private final Map<String, ClassTypeInformation<?>> CACHE = new ConcurrentHashMap<String, ClassTypeInformation<?>>();
private final Map<String, Optional<ClassTypeInformation<?>>> CACHE = new ConcurrentHashMap<>();
/**
* Returns the {@link TypeInformation} that shall be used when the given {@link String} value is found as type hint.
@ -43,35 +44,11 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper { @@ -43,35 +44,11 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper {
* @return the type to be used for the given {@link String} representation or {@literal null} if nothing found or the
* class cannot be loaded.
*/
public ClassTypeInformation<?> resolveTypeFrom(Object alias) {
@Override
public Optional<TypeInformation<?>> resolveTypeFrom(Alias alias) {
if (!(alias instanceof String)) {
return null;
}
String value = (String) alias;
if (!StringUtils.hasText(value)) {
return null;
}
ClassTypeInformation<?> information = CACHE.get(value);
if (information != null) {
return information;
}
try {
information = ClassTypeInformation.from(ClassUtils.forName(value, null));
} catch (ClassNotFoundException e) {
return null;
}
if (information != null) {
CACHE.put(value, information);
}
return information;
return alias.mapTyped(String.class)//
.flatMap(it -> CACHE.computeIfAbsent(it, SimpleTypeInformationMapper::loadClass).map(type -> type));
}
/**
@ -81,7 +58,16 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper { @@ -81,7 +58,16 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper {
* @param typeInformation must not be {@literal null}.
* @return the String representation to be stored or {@literal null} if no type information shall be stored.
*/
public String createAliasFor(TypeInformation<?> type) {
return type.getType().getName();
public Alias createAliasFor(TypeInformation<?> type) {
return Alias.of(type.getType().getName());
}
private static Optional<ClassTypeInformation<?>> loadClass(String typeName) {
try {
return Optional.of(ClassTypeInformation.from(ClassUtils.forName(typeName, null)));
} catch (ClassNotFoundException e) {
return Optional.empty();
}
}
}

4
src/main/java/org/springframework/data/convert/TypeAliasAccessor.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.convert;
import org.springframework.data.mapping.Alias;
/**
* Interface to abstract implementations of how to access a type alias from a given source or sink.
*
@ -28,7 +30,7 @@ public interface TypeAliasAccessor<S> { @@ -28,7 +30,7 @@ public interface TypeAliasAccessor<S> {
* @param source
* @return can be {@literal null} in case no alias was found.
*/
Object readAliasFrom(S source);
Alias readAliasFrom(S source);
/**
* Writes the given type alias to the given sink.

7
src/main/java/org/springframework/data/convert/TypeInformationMapper.java

@ -15,6 +15,9 @@ @@ -15,6 +15,9 @@
*/
package org.springframework.data.convert;
import java.util.Optional;
import org.springframework.data.mapping.Alias;
import org.springframework.data.util.TypeInformation;
/**
@ -30,7 +33,7 @@ public interface TypeInformationMapper { @@ -30,7 +33,7 @@ public interface TypeInformationMapper {
* @param alias can be {@literal null}.
* @return
*/
TypeInformation<?> resolveTypeFrom(Object alias);
Optional<TypeInformation<?>> resolveTypeFrom(Alias alias);
/**
* Returns the alias to be used for the given {@link TypeInformation}.
@ -38,5 +41,5 @@ public interface TypeInformationMapper { @@ -38,5 +41,5 @@ public interface TypeInformationMapper {
* @param type
* @return
*/
Object createAliasFor(TypeInformation<?> type);
Alias createAliasFor(TypeInformation<?> type);
}

4
src/main/java/org/springframework/data/convert/TypeMapper.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.convert;
import java.util.Optional;
import org.springframework.data.util.TypeInformation;
/**
@ -30,7 +32,7 @@ public interface TypeMapper<S> { @@ -30,7 +32,7 @@ public interface TypeMapper<S> {
* @param source must not be {@literal null}.
* @return
*/
TypeInformation<?> readType(S source);
Optional<TypeInformation<?>> readType(S source);
/**
* Returns the {@link TypeInformation} from the given source if it is a more concrete type than the given default one.

2
src/main/java/org/springframework/data/domain/AbstractPageRequest.java

@ -71,7 +71,7 @@ public abstract class AbstractPageRequest implements Pageable, Serializable { @@ -71,7 +71,7 @@ public abstract class AbstractPageRequest implements Pageable, Serializable {
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getOffset()
*/
public int getOffset() {
public long getOffset() {
return page * size;
}

35
src/main/java/org/springframework/data/domain/Chunk.java

@ -20,6 +20,7 @@ import java.util.ArrayList; @@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.Assert;
@ -34,14 +35,14 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -34,14 +35,14 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
private static final long serialVersionUID = 867755909294344406L;
private final List<T> content = new ArrayList<T>();
private final List<T> content = new ArrayList<>();
private final Pageable pageable;
/**
* Creates a new {@link Chunk} with the given content and the given governing {@link Pageable}.
*
* @param content must not be {@literal null}.
* @param pageable can be {@literal null}.
* @param pageable must not be {@literal null}.
*/
public Chunk(List<T> content, Pageable pageable) {
@ -56,7 +57,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -56,7 +57,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
* @see org.springframework.data.domain.Slice#getNumber()
*/
public int getNumber() {
return pageable == null ? 0 : pageable.getPageNumber();
return pageable == Pageable.NONE ? 0 : pageable.getPageNumber();
}
/*
@ -64,7 +65,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -64,7 +65,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
* @see org.springframework.data.domain.Slice#getSize()
*/
public int getSize() {
return pageable == null ? 0 : pageable.getPageSize();
return pageable == Pageable.NONE ? 0 : pageable.getPageSize();
}
/*
@ -104,7 +105,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -104,7 +105,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
* @see org.springframework.data.domain.Slice#nextPageable()
*/
public Pageable nextPageable() {
return hasNext() ? pageable.next() : null;
return hasNext() ? pageable.next() : Pageable.NONE;
}
/*
@ -112,12 +113,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -112,12 +113,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
* @see org.springframework.data.domain.Slice#previousPageable()
*/
public Pageable previousPageable() {
if (hasPrevious()) {
return pageable.previousOrFirst();
}
return null;
return hasPrevious() ? pageable.previousOrFirst() : Pageable.NONE;
}
/*
@ -140,8 +136,9 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -140,8 +136,9 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
* (non-Javadoc)
* @see org.springframework.data.domain.Slice#getSort()
*/
@Override
public Sort getSort() {
return pageable == null ? null : pageable.getSort();
return pageable.getSort();
}
/*
@ -158,17 +155,11 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -158,17 +155,11 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
* @param converter must not be {@literal null}.
* @return
*/
protected <S> List<S> getConvertedContent(Converter<? super T, ? extends S> converter) {
protected <U> List<U> getConvertedContent(Converter<? super T, ? extends U> converter) {
Assert.notNull(converter, "Converter must not be null!");
List<S> result = new ArrayList<S>(content.size());
for (T element : this) {
result.add(converter.convert(element));
}
return result;
return this.stream().map(it -> converter.convert(it)).collect(Collectors.toList());
}
/*
@ -189,7 +180,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -189,7 +180,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
Chunk<?> that = (Chunk<?>) obj;
boolean contentEqual = this.content.equals(that.content);
boolean pageableEqual = this.pageable == null ? that.pageable == null : this.pageable.equals(that.pageable);
boolean pageableEqual = this.pageable.equals(that.pageable);
return contentEqual && pageableEqual;
}
@ -203,7 +194,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -203,7 +194,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
int result = 17;
result += 31 * (pageable == null ? 0 : pageable.hashCode());
result += 31 * pageable.hashCode();
result += 31 * content.hashCode();
return result;

4
src/main/java/org/springframework/data/domain/Example.java

@ -48,7 +48,7 @@ public class Example<T> { @@ -48,7 +48,7 @@ public class Example<T> {
* @return
*/
public static <T> Example<T> of(T probe) {
return new Example<T>(probe, ExampleMatcher.matching());
return new Example<>(probe, ExampleMatcher.matching());
}
/**
@ -59,7 +59,7 @@ public class Example<T> { @@ -59,7 +59,7 @@ public class Example<T> {
* @return
*/
public static <T> Example<T> of(T probe, ExampleMatcher matcher) {
return new Example<T>(probe, matcher);
return new Example<>(probe, matcher);
}
/**

2
src/main/java/org/springframework/data/domain/ExampleMatcher.java

@ -112,7 +112,7 @@ public class ExampleMatcher { @@ -112,7 +112,7 @@ public class ExampleMatcher {
Assert.notEmpty(ignoredPaths, "IgnoredPaths must not be empty!");
Assert.noNullElements(ignoredPaths, "IgnoredPaths must not contain null elements!");
Set<String> newIgnoredPaths = new LinkedHashSet<String>(this.ignoredPaths);
Set<String> newIgnoredPaths = new LinkedHashSet<>(this.ignoredPaths);
newIgnoredPaths.addAll(Arrays.asList(ignoredPaths));
return new ExampleMatcher(nullHandler, defaultStringMatcher, propertySpecifiers, newIgnoredPaths, defaultIgnoreCase,

2
src/main/java/org/springframework/data/domain/Page.java

@ -47,5 +47,5 @@ public interface Page<T> extends Slice<T> { @@ -47,5 +47,5 @@ public interface Page<T> extends Slice<T> {
* @return a new {@link Page} with the content of the current one mapped by the given {@link Converter}.
* @since 1.10
*/
<S> Page<S> map(Converter<? super T, ? extends S> converter);
<U> Page<U> map(Converter<? super T, ? extends U> converter);
}

16
src/main/java/org/springframework/data/domain/PageImpl.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.domain;
import java.util.List;
import java.util.Optional;
import org.springframework.core.convert.converter.Converter;
@ -45,8 +46,13 @@ public class PageImpl<T> extends Chunk<T> implements Page<T> { @@ -45,8 +46,13 @@ public class PageImpl<T> extends Chunk<T> implements Page<T> {
super(content, pageable);
this.pageable = pageable;
this.total = !content.isEmpty() && pageable != null && pageable.getOffset() + pageable.getPageSize() > total
? pageable.getOffset() + content.size() : total;
Optional<Pageable> foo = Pageable.NONE == pageable ? Optional.empty() : Optional.of(pageable);
this.total = foo.filter(it -> !content.isEmpty())//
.filter(it -> it.getOffset() + it.getPageSize() > total)//
.map(it -> it.getOffset() + content.size())//
.orElse(total);
}
/**
@ -56,7 +62,7 @@ public class PageImpl<T> extends Chunk<T> implements Page<T> { @@ -56,7 +62,7 @@ public class PageImpl<T> extends Chunk<T> implements Page<T> {
* @param content must not be {@literal null}.
*/
public PageImpl(List<T> content) {
this(content, null, null == content ? 0 : content.size());
this(content, Pageable.NONE, null == content ? 0 : content.size());
}
/*
@ -100,8 +106,8 @@ public class PageImpl<T> extends Chunk<T> implements Page<T> { @@ -100,8 +106,8 @@ public class PageImpl<T> extends Chunk<T> implements Page<T> {
* @see org.springframework.data.domain.Slice#transform(org.springframework.core.convert.converter.Converter)
*/
@Override
public <S> Page<S> map(Converter<? super T, ? extends S> converter) {
return new PageImpl<S>(getConvertedContent(converter), pageable, total);
public <U> Page<U> map(Converter<? super T, ? extends U> converter) {
return new PageImpl<>(getConvertedContent(converter), pageable, total);
}
/*

33
src/main/java/org/springframework/data/domain/PageRequest.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.domain;
import java.util.Optional;
import org.springframework.data.domain.Sort.Direction;
/**
@ -35,9 +37,11 @@ public class PageRequest extends AbstractPageRequest { @@ -35,9 +37,11 @@ public class PageRequest extends AbstractPageRequest {
*
* @param page zero-based page index.
* @param size the size of the page to be returned.
* @deprecated use {@link #of(int, int)} instead.
*/
@Deprecated
public PageRequest(int page, int size) {
this(page, size, null);
this(page, size, Sort.unsorted());
}
/**
@ -47,7 +51,9 @@ public class PageRequest extends AbstractPageRequest { @@ -47,7 +51,9 @@ public class PageRequest extends AbstractPageRequest {
* @param size the size of the page to be returned.
* @param direction the direction of the {@link Sort} to be specified, can be {@literal null}.
* @param properties the properties to sort by, must not be {@literal null} or empty.
* @deprecated use {@link #of(int, int, Direction, String...)} instead.
*/
@Deprecated
public PageRequest(int page, int size, Direction direction, String... properties) {
this(page, size, new Sort(direction, properties));
}
@ -58,12 +64,28 @@ public class PageRequest extends AbstractPageRequest { @@ -58,12 +64,28 @@ public class PageRequest extends AbstractPageRequest {
* @param page zero-based page index.
* @param size the size of the page to be returned.
* @param sort can be {@literal null}.
* @deprecated use {@link #of(int, int, Optional)} instead.
*/
@Deprecated
public PageRequest(int page, int size, Sort sort) {
super(page, size);
this.sort = sort;
}
public static PageRequest of(int page, int site) {
return of(page, site, Sort.unsorted());
}
public static PageRequest of(int page, int site, Sort sort) {
return new PageRequest(page, site, sort);
}
public static PageRequest of(int page, int size, Direction direction, String... properties) {
return of(page, size, new Sort(direction, properties));
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getSort()
@ -113,9 +135,7 @@ public class PageRequest extends AbstractPageRequest { @@ -113,9 +135,7 @@ public class PageRequest extends AbstractPageRequest {
PageRequest that = (PageRequest) obj;
boolean sortEqual = this.sort == null ? that.sort == null : this.sort.equals(that.sort);
return super.equals(that) && sortEqual;
return super.equals(that) && this.sort.equals(that.sort);
}
/*
@ -124,7 +144,7 @@ public class PageRequest extends AbstractPageRequest { @@ -124,7 +144,7 @@ public class PageRequest extends AbstractPageRequest {
*/
@Override
public int hashCode() {
return 31 * super.hashCode() + (null == sort ? 0 : sort.hashCode());
return 31 * super.hashCode() + sort.hashCode();
}
/*
@ -133,7 +153,6 @@ public class PageRequest extends AbstractPageRequest { @@ -133,7 +153,6 @@ public class PageRequest extends AbstractPageRequest {
*/
@Override
public String toString() {
return String.format("Page request [number: %d, size %d, sort: %s]", getPageNumber(), getPageSize(),
sort == null ? null : sort.toString());
return String.format("Page request [number: %d, size %d, sort: %s]", getPageNumber(), getPageSize(), sort);
}
}

49
src/main/java/org/springframework/data/domain/Pageable.java

@ -41,7 +41,7 @@ public interface Pageable { @@ -41,7 +41,7 @@ public interface Pageable {
*
* @return the offset to be taken
*/
int getOffset();
long getOffset();
/**
* Returns the sorting parameters.
@ -50,6 +50,10 @@ public interface Pageable { @@ -50,6 +50,10 @@ public interface Pageable {
*/
Sort getSort();
default Sort getSortOr(Sort sort) {
return getSort().isSorted() ? getSort() : sort;
}
/**
* Returns the {@link Pageable} requesting the next {@link Page}.
*
@ -78,4 +82,47 @@ public interface Pageable { @@ -78,4 +82,47 @@ public interface Pageable {
* @return
*/
boolean hasPrevious();
public static Pageable NONE = new Pageable() {
@Override
public Pageable previousOrFirst() {
return this;
}
@Override
public Pageable next() {
return this;
}
@Override
public boolean hasPrevious() {
return false;
}
@Override
public Sort getSort() {
return Sort.unsorted();
}
@Override
public int getPageSize() {
throw new UnsupportedOperationException();
}
@Override
public int getPageNumber() {
throw new UnsupportedOperationException();
}
@Override
public long getOffset() {
throw new UnsupportedOperationException();
}
@Override
public Pageable first() {
return this;
}
};
}

5
src/main/java/org/springframework/data/domain/Slice.java

@ -18,6 +18,7 @@ package org.springframework.data.domain; @@ -18,6 +18,7 @@ package org.springframework.data.domain;
import java.util.List;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.util.Streamable;
/**
* A slice of data that indicates whether there's a next or previous slice available. Allows to obtain a
@ -26,7 +27,7 @@ import org.springframework.core.convert.converter.Converter; @@ -26,7 +27,7 @@ import org.springframework.core.convert.converter.Converter;
* @author Oliver Gierke
* @since 1.8
*/
public interface Slice<T> extends Iterable<T> {
public interface Slice<T> extends Streamable<T> {
/**
* Returns the number of the current {@link Slice}. Is always non-negative.
@ -123,5 +124,5 @@ public interface Slice<T> extends Iterable<T> { @@ -123,5 +124,5 @@ public interface Slice<T> extends Iterable<T> {
* @return a new {@link Slice} with the content of the current one mapped by the given {@link Converter}.
* @since 1.10
*/
<S> Slice<S> map(Converter<? super T, ? extends S> converter);
<U> Slice<U> map(Converter<? super T, ? extends U> converter);
}

5
src/main/java/org/springframework/data/domain/SliceImpl.java

@ -42,6 +42,7 @@ public class SliceImpl<T> extends Chunk<T> { @@ -42,6 +42,7 @@ public class SliceImpl<T> extends Chunk<T> {
public SliceImpl(List<T> content, Pageable pageable, boolean hasNext) {
super(content, pageable);
this.hasNext = hasNext;
this.pageable = pageable;
}
@ -69,8 +70,8 @@ public class SliceImpl<T> extends Chunk<T> { @@ -69,8 +70,8 @@ public class SliceImpl<T> extends Chunk<T> {
* @see org.springframework.data.domain.Slice#transform(org.springframework.core.convert.converter.Converter)
*/
@Override
public <S> Slice<S> map(Converter<? super T, ? extends S> converter) {
return new SliceImpl<S>(getConvertedContent(converter), pageable, hasNext);
public <U> Slice<U> map(Converter<? super T, ? extends U> converter) {
return new SliceImpl<>(getConvertedContent(converter), pageable, hasNext);
}
/*

64
src/main/java/org/springframework/data/domain/Sort.java

@ -18,10 +18,14 @@ package org.springframework.data.domain; @@ -18,10 +18,14 @@ package org.springframework.data.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -34,6 +38,9 @@ import org.springframework.util.StringUtils; @@ -34,6 +38,9 @@ import org.springframework.util.StringUtils;
public class Sort implements Iterable<org.springframework.data.domain.Sort.Order>, Serializable {
private static final long serialVersionUID = 5737186511678863905L;
private static final Sort UNSORTED = new Sort(new Order[0]);
public static final Direction DEFAULT_DIRECTION = Direction.ASC;
private final List<Order> orders;
@ -43,6 +50,7 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order @@ -43,6 +50,7 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order
*
* @param orders must not be {@literal null}.
*/
@Deprecated
public Sort(Order... orders) {
this(Arrays.asList(orders));
}
@ -51,21 +59,23 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order @@ -51,21 +59,23 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order
* Creates a new {@link Sort} instance.
*
* @param orders must not be {@literal null} or contain {@literal null}.
* @deprecated see {@link Sort#by(List)}
*/
@Deprecated
public Sort(List<Order> orders) {
if (null == orders || orders.isEmpty()) {
throw new IllegalArgumentException("You have to provide at least one sort property to sort by!");
}
Assert.notNull(orders, "Orders must not be null!");
this.orders = orders;
this.orders = Collections.unmodifiableList(orders);
}
/**
* Creates a new {@link Sort} instance. Order defaults to {@value Direction#ASC}.
*
* @param properties must not be {@literal null} or contain {@literal null} or empty strings
* @deprecated use {@link Sort#by(String...)}
*/
@Deprecated
public Sort(String... properties) {
this(DEFAULT_DIRECTION, properties);
}
@ -77,7 +87,7 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order @@ -77,7 +87,7 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order
* @param properties must not be {@literal null}, empty or contain {@literal null} or empty strings.
*/
public Sort(Direction direction, String... properties) {
this(direction, properties == null ? new ArrayList<String>() : Arrays.asList(properties));
this(direction, properties == null ? new ArrayList<>() : Arrays.asList(properties));
}
/**
@ -92,13 +102,45 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order @@ -92,13 +102,45 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order
throw new IllegalArgumentException("You have to provide at least one property to sort by!");
}
this.orders = new ArrayList<Order>(properties.size());
this.orders = new ArrayList<>(properties.size());
for (String property : properties) {
this.orders.add(new Order(direction, property));
}
}
public static Sort by(String... properties) {
return properties.length == 0 ? Sort.unsorted() : new Sort(properties);
}
public static Sort by(List<Order> orders) {
return orders.isEmpty() ? Sort.unsorted() : new Sort(orders);
}
public static Sort by(Order... orders) {
return new Sort(orders);
}
public static Sort unsorted() {
return UNSORTED;
}
public Sort descending() {
return withDirection(Direction.DESC);
}
public Sort ascending() {
return withDirection(Direction.ASC);
}
private Sort withDirection(Direction direction) {
return new Sort(orders.stream().map(it -> new Order(direction, it.getProperty())).collect(Collectors.toList()));
}
public boolean isSorted() {
return !orders.isEmpty();
}
/**
* Returns a new {@link Sort} consisting of the {@link Order}s of the current {@link Sort} combined with the given
* ones.
@ -112,7 +154,7 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order @@ -112,7 +154,7 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order
return this;
}
ArrayList<Order> these = new ArrayList<Order>(this.orders);
ArrayList<Order> these = new ArrayList<>(this.orders);
for (Order order : sort) {
these.add(order);
@ -184,7 +226,7 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order @@ -184,7 +226,7 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order
*/
@Override
public String toString() {
return StringUtils.collectionToCommaDelimitedString(orders);
return orders.isEmpty() ? "UNSORTED" : StringUtils.collectionToCommaDelimitedString(orders);
}
/**
@ -240,12 +282,12 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order @@ -240,12 +282,12 @@ public class Sort implements Iterable<org.springframework.data.domain.Sort.Order
* @param value
* @return
*/
public static Direction fromStringOrNull(String value) {
public static Optional<Direction> fromOptionalString(String value) {
try {
return fromString(value);
return Optional.of(fromString(value));
} catch (IllegalArgumentException e) {
return null;
return Optional.empty();
}
}
}

8
src/main/java/org/springframework/data/domain/jaxb/PageableAdapter.java

@ -21,7 +21,6 @@ import javax.xml.bind.annotation.adapters.XmlAdapter; @@ -21,7 +21,6 @@ import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.jaxb.SpringDataJaxb.OrderDto;
import org.springframework.data.domain.jaxb.SpringDataJaxb.PageRequestDto;
import org.springframework.data.domain.jaxb.SpringDataJaxb.SortDto;
@ -43,7 +42,7 @@ class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> { @@ -43,7 +42,7 @@ class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> {
SortDto sortDto = SortAdapter.INSTANCE.marshal(request.getSort());
PageRequestDto dto = new PageRequestDto();
dto.orders = sortDto == null ? Collections.<OrderDto> emptyList() : sortDto.orders;
dto.orders = sortDto == null ? Collections.<OrderDto>emptyList() : sortDto.orders;
dto.page = request.getPageNumber();
dto.size = request.getPageSize();
@ -58,13 +57,12 @@ class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> { @@ -58,13 +57,12 @@ class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> {
public Pageable unmarshal(PageRequestDto v) {
if (v.orders.isEmpty()) {
return new PageRequest(v.page, v.size);
return PageRequest.of(v.page, v.size);
}
SortDto sortDto = new SortDto();
sortDto.orders = v.orders;
Sort sort = SortAdapter.INSTANCE.unmarshal(sortDto);
return new PageRequest(v.page, v.size, sort);
return PageRequest.of(v.page, v.size, SortAdapter.INSTANCE.unmarshal(sortDto));
}
}

4
src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2016 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.
@ -52,6 +52,6 @@ public class SortAdapter extends XmlAdapter<SortDto, Sort> { @@ -52,6 +52,6 @@ public class SortAdapter extends XmlAdapter<SortDto, Sort> {
*/
@Override
public Sort unmarshal(SortDto source) {
return source == null ? null : new Sort(SpringDataJaxb.unmarshal(source.orders, OrderAdapter.INSTANCE));
return source == null ? Sort.unsorted() : Sort.by(SpringDataJaxb.unmarshal(source.orders, OrderAdapter.INSTANCE));
}
}

8
src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java

@ -60,7 +60,7 @@ public abstract class SpringDataJaxb { @@ -60,7 +60,7 @@ public abstract class SpringDataJaxb {
public static class PageRequestDto {
@XmlAttribute int page, size;
@XmlElement(name = "order", namespace = NAMESPACE) List<OrderDto> orders = new ArrayList<OrderDto>();
@XmlElement(name = "order", namespace = NAMESPACE) List<OrderDto> orders = new ArrayList<>();
}
/**
@ -72,7 +72,7 @@ public abstract class SpringDataJaxb { @@ -72,7 +72,7 @@ public abstract class SpringDataJaxb {
@XmlAccessorType(XmlAccessType.FIELD)
public static class SortDto {
@XmlElement(name = "order", namespace = SpringDataJaxb.NAMESPACE) List<OrderDto> orders = new ArrayList<OrderDto>();
@XmlElement(name = "order", namespace = SpringDataJaxb.NAMESPACE) List<OrderDto> orders = new ArrayList<>();
}
/**
@ -116,7 +116,7 @@ public abstract class SpringDataJaxb { @@ -116,7 +116,7 @@ public abstract class SpringDataJaxb {
return Collections.emptyList();
}
List<T> result = new ArrayList<T>(source.size());
List<T> result = new ArrayList<>(source.size());
for (S element : source) {
try {
@ -144,7 +144,7 @@ public abstract class SpringDataJaxb { @@ -144,7 +144,7 @@ public abstract class SpringDataJaxb {
return Collections.emptyList();
}
List<S> result = new ArrayList<S>();
List<S> result = new ArrayList<>();
for (T element : source) {
try {

2
src/main/java/org/springframework/data/geo/Distance.java

@ -63,7 +63,7 @@ public class Distance implements Serializable, Comparable<Distance> { @@ -63,7 +63,7 @@ public class Distance implements Serializable, Comparable<Distance> {
* @return will never be {@literal null}.
*/
public static Range<Distance> between(Distance min, Distance max) {
return new Range<Distance>(min, max);
return new Range<>(min, max);
}
/**

4
src/main/java/org/springframework/data/geo/Polygon.java

@ -53,7 +53,7 @@ public class Polygon implements Iterable<Point>, Shape { @@ -53,7 +53,7 @@ public class Polygon implements Iterable<Point>, Shape {
Assert.notNull(z, "Z coordinate must not be null!");
Assert.notNull(others, "Others must not be null!");
List<Point> points = new ArrayList<Point>(3 + others.length);
List<Point> points = new ArrayList<>(3 + others.length);
points.addAll(Arrays.asList(x, y, z));
points.addAll(Arrays.asList(others));
@ -70,7 +70,7 @@ public class Polygon implements Iterable<Point>, Shape { @@ -70,7 +70,7 @@ public class Polygon implements Iterable<Point>, Shape {
Assert.notNull(points, "Points must not be null!");
List<Point> pointsToSet = new ArrayList<Point>(points.size());
List<Point> pointsToSet = new ArrayList<>(points.size());
for (Point point : points) {

66
src/main/java/org/springframework/data/mapping/Alias.java

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
/*
* Copyright 2016 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import java.util.Optional;
/**
* @author Oliver Gierke
*/
@Value
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class Alias {
public static Alias NONE = new Alias(Optional.empty());
Optional<? extends Object> value;
public static Alias of(Object alias) {
return ofOptional(Optional.of(alias));
}
public static Alias ofOptional(Optional<? extends Object> optional) {
return optional.isPresent() ? new Alias(optional) : NONE;
}
public boolean isPresentButDifferent(Alias other) {
return isPresent() && !hasValue(other.value);
}
public boolean hasValue(Object that) {
return value.filter(it -> it.equals(that)).isPresent();
}
public boolean hasSamePresentValueAs(Alias other) {
return isPresent() && hasValue(other.value);
}
public boolean isPresent() {
return value.isPresent();
}
public <T> Optional<T> mapTyped(Class<T> type) {
return value.filter(it -> type.isInstance(it)).map(it -> type.cast(it));
}
public String toString() {
return value.map(Object::toString).orElse("NONE");
}
}

2
src/main/java/org/springframework/data/mapping/IdentifierAccessor.java

@ -29,5 +29,5 @@ public interface IdentifierAccessor { @@ -29,5 +29,5 @@ public interface IdentifierAccessor {
*
* @return
*/
Optional<? extends Object> getIdentifier();
Optional<Object> getIdentifier();
}

2
src/main/java/org/springframework/data/mapping/PersistentEntity.java

@ -135,7 +135,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> { @@ -135,7 +135,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> {
*
* @return
*/
Optional<? extends Object> getTypeAlias();
Alias getTypeAlias();
/**
* Returns the {@link TypeInformation} backing this {@link PersistentEntity}.

4
src/main/java/org/springframework/data/mapping/PersistentProperty.java

@ -89,7 +89,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> { @@ -89,7 +89,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
Optional<String> getSpelExpression();
Association<P> getAssociation();
Optional<Association<P>> getAssociation();
/**
* Returns whether the type of the {@link PersistentProperty} is actually to be regarded as {@link PersistentEntity}
@ -199,7 +199,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> { @@ -199,7 +199,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
* 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 if present or {@literal null} otherwise.
* @return the annotation of the given type.
* @see AnnotationUtils#findAnnotation(Method, Class)
*/
<A extends Annotation> Optional<A> findAnnotation(Class<A> annotationType);

2
src/main/java/org/springframework/data/mapping/PersistentPropertyAccessor.java

@ -49,7 +49,7 @@ public interface PersistentPropertyAccessor { @@ -49,7 +49,7 @@ public interface PersistentPropertyAccessor {
* @param property must not be {@literal null}.
* @return can be {@literal null}.
*/
Optional<? extends Object> getProperty(PersistentProperty<?> property);
Optional<Object> getProperty(PersistentProperty<?> property);
/**
* Returns the underlying bean.

8
src/main/java/org/springframework/data/mapping/PreferredConstructor.java

@ -226,9 +226,11 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> { @@ -226,9 +226,11 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
}
private static Optional<String> getValue(Annotation[] annotations) {
return Arrays.stream(annotations).//
filter(it -> it.annotationType() == Value.class).//
findFirst().map(it -> ((Value) it).value());
return Arrays.stream(annotations)//
.filter(it -> it.annotationType() == Value.class)//
.findFirst().map(it -> ((Value) it).value())//
.filter(it -> StringUtils.hasText(it));
}
/**

28
src/main/java/org/springframework/data/mapping/PropertyPath.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.mapping;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Collections;
@ -45,7 +46,8 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -45,7 +46,8 @@ public class PropertyPath implements Streamable<PropertyPath> {
private final TypeInformation<?> owningType;
private final String name;
private final TypeInformation<?> type;
private final @Getter TypeInformation<?> typeInformation;
private final TypeInformation<?> actualTypeInformation;
private final boolean isCollection;
private PropertyPath next;
@ -57,7 +59,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -57,7 +59,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
* @param owningType must not be {@literal null}.
*/
PropertyPath(String name, Class<?> owningType) {
this(name, ClassTypeInformation.from(owningType), Collections.<PropertyPath> emptyList());
this(name, ClassTypeInformation.from(owningType), Collections.<PropertyPath>emptyList());
}
/**
@ -74,15 +76,13 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -74,15 +76,13 @@ public class PropertyPath implements Streamable<PropertyPath> {
Assert.notNull(base, "Perviously found properties must not be null!");
String propertyName = name.matches(ALL_UPPERCASE) ? name : StringUtils.uncapitalize(name);
TypeInformation<?> propertyType = owningType.getProperty(propertyName);
if (propertyType == null) {
throw new PropertyReferenceException(propertyName, owningType, base);
}
TypeInformation<?> propertyType = owningType.getProperty(propertyName)
.orElseThrow(() -> new PropertyReferenceException(propertyName, owningType, base));
this.owningType = owningType;
this.typeInformation = propertyType;
this.isCollection = propertyType.isCollectionLike();
this.type = propertyType.getActualType();
this.actualTypeInformation = propertyType.getActualType();
this.name = propertyName;
}
@ -127,7 +127,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -127,7 +127,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
* @return
*/
public Class<?> getType() {
return this.type.getType();
return this.actualTypeInformation.getType();
}
/**
@ -221,7 +221,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -221,7 +221,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
Assert.hasText(source, "Source must not be null or empty!");
Assert.notNull(type, "TypeInformation must not be null or empty!");
List<String> iteratorSource = new ArrayList<String>();
List<String> iteratorSource = new ArrayList<>();
Matcher matcher = SPLITTER.matcher("_" + source);
while (matcher.find()) {
@ -231,7 +231,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -231,7 +231,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
Iterator<String> parts = iteratorSource.iterator();
PropertyPath result = null;
Stack<PropertyPath> current = new Stack<PropertyPath>();
Stack<PropertyPath> current = new Stack<>();
while (parts.hasNext()) {
if (result == null) {
@ -256,7 +256,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -256,7 +256,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
PropertyPath previous = base.peek();
PropertyPath propertyPath = create(source, previous.type, base);
PropertyPath propertyPath = create(source, previous.typeInformation.getActualType(), base);
previous.next = propertyPath;
return propertyPath;
}
@ -298,11 +298,11 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -298,11 +298,11 @@ public class PropertyPath implements Streamable<PropertyPath> {
base.get(base.size() - 1).next = current;
}
List<PropertyPath> newBase = new ArrayList<PropertyPath>(base);
List<PropertyPath> newBase = new ArrayList<>(base);
newBase.add(current);
if (StringUtils.hasText(addTail)) {
current.next = create(addTail, current.type, newBase);
current.next = create(addTail, current.actualTypeInformation, newBase);
}
return current;

2
src/main/java/org/springframework/data/mapping/PropertyReferenceException.java

@ -142,7 +142,7 @@ public class PropertyReferenceException extends RuntimeException { @@ -142,7 +142,7 @@ public class PropertyReferenceException extends RuntimeException {
*/
private static Set<String> detectPotentialMatches(String propertyName, Class<?> type) {
Set<String> result = new HashSet<String>();
Set<String> result = new HashSet<>();
result.addAll(Arrays.asList(PropertyMatches.forField(propertyName, type).getPossibleMatches()));
result.addAll(Arrays.asList(PropertyMatches.forProperty(propertyName, type).getPossibleMatches()));

110
src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java

@ -29,6 +29,7 @@ import java.util.Optional; @@ -29,6 +29,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
@ -42,8 +43,10 @@ import org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFac @@ -42,8 +43,10 @@ import org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFac
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.MutablePersistentEntity;
import org.springframework.data.mapping.model.PersistentPropertyAccessorFactory;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.Pair;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@ -72,7 +75,8 @@ import org.springframework.util.StringUtils; @@ -72,7 +75,8 @@ import org.springframework.util.StringUtils;
public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?, P>, P extends PersistentProperty<P>>
implements MappingContext<E, P>, ApplicationEventPublisherAware, InitializingBean {
private final Map<TypeInformation<?>, E> persistentEntities = new HashMap<TypeInformation<?>, E>();
private final Optional<E> NONE = Optional.empty();
private final Map<TypeInformation<?>, Optional<E>> persistentEntities = new HashMap<>();
private final PersistentPropertyAccessorFactory persistentPropertyAccessorFactory = new ClassGeneratingPropertyAccessorFactory();
private ApplicationEventPublisher applicationEventPublisher;
@ -132,8 +136,13 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -132,8 +136,13 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
public Collection<E> getPersistentEntities() {
try {
read.lock();
return Collections.unmodifiableSet(new HashSet<E>(persistentEntities.values()));
return persistentEntities.values().stream()//
.flatMap(it -> Optionals.toStream(it))//
.collect(Collectors.toSet());
} finally {
read.unlock();
}
@ -143,10 +152,21 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -143,10 +152,21 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContext#getPersistentEntity(java.lang.Class)
*/
public E getPersistentEntity(Class<?> type) {
public Optional<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)
@ -160,13 +180,15 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -160,13 +180,15 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContext#getPersistentEntity(org.springframework.data.util.TypeInformation)
*/
public E getPersistentEntity(TypeInformation<?> type) {
public Optional<E> getPersistentEntity(TypeInformation<?> type) {
Assert.notNull(type, "Type must not be null!");
try {
read.lock();
E entity = persistentEntities.get(type);
Optional<E> entity = persistentEntities.get(type);
if (entity != null) {
return entity;
@ -177,7 +199,15 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -177,7 +199,15 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
}
if (!shouldCreatePersistentEntityFor(type)) {
return null;
try {
write.lock();
persistentEntities.put(type, NONE);
} finally {
write.unlock();
}
return NONE;
}
if (strict) {
@ -187,20 +217,40 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -187,20 +217,40 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
return addPersistentEntity(type);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Override
public E getRequiredPersistentEntity(TypeInformation<?> type) {
return getPersistentEntity(type)
.orElseThrow(() -> new MappingException(String.format("Couldn't find PersistentEntity for type %s!", type)));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getPersistentEntity(org.springframework.data.mapping.PersistentProperty)
*/
public E getPersistentEntity(P persistentProperty) {
public Optional<E> getPersistentEntity(P persistentProperty) {
if (persistentProperty == null) {
return null;
}
Assert.notNull(persistentProperty, "PersistentProperty must not be null!");
TypeInformation<?> typeInfo = persistentProperty.getTypeInformation();
return getPersistentEntity(typeInfo.getActualType());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(org.springframework.data.mapping.PersistentProperty)
*/
@Override
public E getRequiredPersistentEntity(P persistentProperty) {
return getPersistentEntity(persistentProperty).orElseThrow(() -> 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)
@ -248,7 +298,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -248,7 +298,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
DefaultPersistentPropertyPath<P> path = DefaultPersistentPropertyPath.empty();
Iterator<String> iterator = parts.iterator();
E current = getPersistentEntity(type);
E current = getRequiredPersistentEntity(type);
while (iterator.hasNext()) {
@ -277,8 +327,11 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -277,8 +327,11 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
Optional<P> persistentProperty = entity.getPersistentProperty(segment);
return persistentProperty.map(it -> Pair.of(path.append(it),
iterator.hasNext() ? getPersistentEntity(it.getTypeInformation().getActualType()) : entity));
return persistentProperty.map(it -> {
TypeInformation<?> type = it.getTypeInformation().getActualType();
return Pair.of(path.append(it), iterator.hasNext() ? getRequiredPersistentEntity(type) : entity);
});
}
/**
@ -287,7 +340,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -287,7 +340,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* @param type must not be {@literal null}.
* @return
*/
protected E addPersistentEntity(Class<?> type) {
protected Optional<E> addPersistentEntity(Class<?> type) {
return addPersistentEntity(ClassTypeInformation.from(type));
}
@ -297,7 +350,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -297,7 +350,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* @param typeInformation must not be {@literal null}.
* @return
*/
protected E addPersistentEntity(TypeInformation<?> typeInformation) {
protected Optional<E> addPersistentEntity(TypeInformation<?> typeInformation) {
Assert.notNull(typeInformation, "TypeInformation must not be null!");
@ -305,11 +358,12 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -305,11 +358,12 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
read.lock();
E persistentEntity = persistentEntities.get(typeInformation);
Optional<E> persistentEntity = persistentEntities.get(typeInformation);
if (persistentEntity != null) {
return persistentEntity;
}
} finally {
read.unlock();
}
@ -323,7 +377,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -323,7 +377,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
final E entity = createPersistentEntity(typeInformation);
// Eagerly cache the entity as we might have to find it during recursive lookups.
persistentEntities.put(typeInformation, entity);
persistentEntities.put(typeInformation, Optional.of(entity));
PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(type);
@ -354,7 +408,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -354,7 +408,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
applicationEventPublisher.publishEvent(new MappingContextEvent<E, P>(this, entity));
}
return entity;
return Optional.of(entity);
} catch (BeansException e) {
throw new MappingException(e.getMessage(), e);
@ -398,8 +452,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -398,8 +452,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* @param simpleTypeHolder
* @return
*/
protected abstract P createPersistentProperty(Optional<Field> field, PropertyDescriptor descriptor, E owner,
SimpleTypeHolder simpleTypeHolder);
protected abstract P createPersistentProperty(Property property, E owner, SimpleTypeHolder simpleTypeHolder);
/*
* (non-Javadoc)
@ -471,7 +524,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -471,7 +524,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
String fieldName = field.getName();
ReflectionUtils.makeAccessible(field);
createAndRegisterProperty(Optional.of(field), descriptors.get(fieldName));
createAndRegisterProperty(Property.of(field, Optional.ofNullable(descriptors.get(fieldName))));
this.remainingDescriptors.remove(fieldName);
}
@ -486,28 +539,25 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -486,28 +539,25 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
for (PropertyDescriptor descriptor : remainingDescriptors.values()) {
if (PersistentPropertyFilter.INSTANCE.matches(descriptor)) {
createAndRegisterProperty(Optional.empty(), descriptor);
createAndRegisterProperty(Property.of(descriptor));
}
}
}
private void createAndRegisterProperty(Optional<Field> field, PropertyDescriptor descriptor) {
private void createAndRegisterProperty(Property input) {
P property = createPersistentProperty(field, descriptor, entity, simpleTypeHolder);
P property = createPersistentProperty(input, entity, simpleTypeHolder);
if (property.isTransient()) {
return;
}
if (field == null && !property.usePropertyAccess()) {
if (!input.isFieldBacked() && !property.usePropertyAccess()) {
return;
}
entity.addPersistentProperty(property);
if (property.isAssociation()) {
entity.addAssociation(property.getAssociation());
}
property.getAssociation().ifPresent(it -> entity.addAssociation(it));
if (entity.getType().equals(property.getRawType())) {
return;
@ -533,7 +583,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -533,7 +583,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
static {
Set<PropertyMatch> matches = new HashSet<PropertyMatch>();
Set<PropertyMatch> matches = new HashSet<>();
matches.add(new PropertyMatch("class", null));
matches.add(new PropertyMatch("this\\$.*", null));
matches.add(new PropertyMatch("metaClass", "groovy.lang.MetaClass"));

16
src/main/java/org/springframework/data/mapping/context/DefaultPersistentPropertyPath.java

@ -62,7 +62,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -62,7 +62,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* @return
*/
public static <T extends PersistentProperty<T>> DefaultPersistentPropertyPath<T> empty() {
return new DefaultPersistentPropertyPath<T>(Collections.<T> emptyList());
return new DefaultPersistentPropertyPath<>(Collections.<T> emptyList());
}
/**
@ -77,17 +77,17 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -77,17 +77,17 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
Assert.notNull(property, "Property must not be null!");
if (isEmpty()) {
return new DefaultPersistentPropertyPath<T>(Arrays.asList(property));
return new DefaultPersistentPropertyPath<>(Arrays.asList(property));
}
Class<?> leafPropertyType = getLeafProperty().getActualType();
Assert.isTrue(property.getOwner().getType().equals(leafPropertyType),
String.format("Cannot append property %s to type %s!", property.getName(), leafPropertyType.getName()));
List<T> properties = new ArrayList<T>(this.properties);
List<T> properties = new ArrayList<>(this.properties);
properties.add(property);
return new DefaultPersistentPropertyPath<T>(properties);
return new DefaultPersistentPropertyPath<>(properties);
}
/*
@ -125,7 +125,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -125,7 +125,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
? PropertyNameConverter.INSTANCE : converter);
String delimiterToUse = delimiter == null ? "." : delimiter;
List<String> result = new ArrayList<String>();
List<String> result = new ArrayList<>();
for (T property : properties) {
@ -193,7 +193,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -193,7 +193,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
return this;
}
List<T> result = new ArrayList<T>();
List<T> result = new ArrayList<>();
Iterator<T> iterator = iterator();
for (int i = 0; i < base.getLength(); i++) {
@ -204,7 +204,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -204,7 +204,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
result.add(iterator.next());
}
return new DefaultPersistentPropertyPath<T>(result);
return new DefaultPersistentPropertyPath<>(result);
}
/*
@ -216,7 +216,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -216,7 +216,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
if (size <= 1) {
return this;
}
return new DefaultPersistentPropertyPath<T>(properties.subList(0, size - 1));
return new DefaultPersistentPropertyPath<>(properties.subList(0, size - 1));
}
/*

24
src/main/java/org/springframework/data/mapping/context/MappingContext.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.mapping.context;
import java.util.Collection;
import java.util.Optional;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
@ -48,7 +49,9 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers @@ -48,7 +49,9 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
* @param type must not be {@literal null}.
* @return
*/
E getPersistentEntity(Class<?> type);
Optional<E> getPersistentEntity(Class<?> type);
E getRequiredPersistentEntity(Class<?> type);
/**
* Returns whether the {@link MappingContext} currently contains a {@link PersistentEntity} for the type.
@ -67,25 +70,30 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers @@ -67,25 +70,30 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
* @param type must not be {@literal null}.
* @return
*/
E getPersistentEntity(TypeInformation<?> type);
Optional<E> getPersistentEntity(TypeInformation<?> type);
E getRequiredPersistentEntity(TypeInformation<?> type);
/**
* Returns the {@link PersistentEntity} mapped by the given {@link PersistentProperty}.
*
* @param persistentProperty
* @param persistentProperty must not be {@literal null}.
* @return the {@link PersistentEntity} mapped by the given {@link PersistentProperty} or null if no
* {@link PersistentEntity} exists for it or the {@link PersistentProperty} does not refer to an entity (the
* type of the property is considered simple see
* {@link org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)}).
*/
E getPersistentEntity(P persistentProperty);
Optional<E> getPersistentEntity(P persistentProperty);
E getRequiredPersistentEntity(P persistentProperty);
/**
* Returns all {@link PersistentProperty}s for the given path expression based on the given {@link PropertyPath}.
*
* @param propertyPath must not be {@literal null}.
* @return the {@link PersistentPropertyPath} representing the given {@link PropertyPath}.
* @throws InvalidPersistentPropertyPath in case not all of the segments of the given {@link PropertyPath} can be resolved.
* @throws InvalidPersistentPropertyPath in case not all of the segments of the given {@link PropertyPath} can be
* resolved.
*/
PersistentPropertyPath<P> getPersistentPropertyPath(PropertyPath propertyPath);
@ -100,10 +108,12 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers @@ -100,10 +108,12 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
PersistentPropertyPath<P> getPersistentPropertyPath(String propertyPath, Class<?> type);
/**
* Returns the {@link PersistentPropertyPath} for the resolvable part of the given {@link InvalidPersistentPropertyPath}.
* Returns the {@link PersistentPropertyPath} for the resolvable part of the given
* {@link InvalidPersistentPropertyPath}.
*
* @param invalidPath must not be {@literal null}.
* @return the {@link PersistentPropertyPath} for the resolvable part of the given {@link InvalidPersistentPropertyPath}.
* @return the {@link PersistentPropertyPath} for the resolvable part of the given
* {@link InvalidPersistentPropertyPath}.
* @since 1.11
*/
PersistentPropertyPath<P> getPersistentPropertyPath(InvalidPersistentPropertyPath invalidPath);

119
src/main/java/org/springframework/data/mapping/context/MappingContextIsNewStrategyFactory.java

@ -15,12 +15,15 @@ @@ -15,12 +15,15 @@
*/
package org.springframework.data.mapping.context;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
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.PersistentPropertyAccessor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.support.IsNewStrategy;
import org.springframework.data.support.IsNewStrategyFactory;
@ -69,19 +72,25 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp @@ -69,19 +72,25 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
@Override
protected IsNewStrategy doGetIsNewStrategy(Class<?> type) {
PersistentEntity<?, ?> entity = context.getPersistentEntity(type);
return context.getPersistentEntity(type)//
.flatMap(it -> foo(it))//
.orElseThrow(() -> new MappingException(String.format("Cannot determine IsNewStrategy for type %s!", type)));
}
if (entity == null) {
return null;
}
private static Optional<IsNewStrategy> foo(PersistentEntity<?, ?> entity) {
if (entity.hasVersionProperty()) {
return new PropertyIsNullOrZeroNumberIsNewStrategy(entity.getVersionProperty().get());
return entity.getVersionProperty().map(it -> PersistentPropertyInspectingIsNewStrategy.of(it,
MappingContextIsNewStrategyFactory::propertyIsNullOrZeroNumber));
} else if (entity.hasIdProperty()) {
return new PropertyIsNullIsNewStrategy(entity.getIdProperty().get());
} else {
throw new MappingException(String.format("Cannot determine IsNewStrategy for type %s!", type));
return entity.getIdProperty().map(
it -> PersistentPropertyInspectingIsNewStrategy.of(it, MappingContextIsNewStrategyFactory::propertyIsNull));
}
return Optional.empty();
}
/**
@ -90,19 +99,11 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp @@ -90,19 +99,11 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
*
* @author Oliver Gierke
*/
static abstract class PersistentPropertyInspectingIsNewStrategy implements IsNewStrategy {
private final PersistentProperty<?> property;
@RequiredArgsConstructor(staticName = "of")
static class PersistentPropertyInspectingIsNewStrategy implements IsNewStrategy {
/**
* Creates a new {@link PersistentPropertyInspectingIsNewStrategy} using the given {@link PersistentProperty}.
*
* @param property must not be {@literal null}.
*/
public PersistentPropertyInspectingIsNewStrategy(PersistentProperty<?> property) {
Assert.notNull(property, "PersistentProperty must not be null!");
this.property = property;
}
private final @NonNull PersistentProperty<?> property;
private final @NonNull Function<Optional<Object>, Boolean> isNew;
/*
* (non-Javadoc)
@ -111,80 +112,26 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp @@ -111,80 +112,26 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
@Override
public boolean isNew(Optional<? extends Object> entity) {
return entity.map(it -> {
PersistentPropertyAccessor accessor = property.getOwner().getPropertyAccessor(it);
Object propertyValue = accessor.getProperty(property);
return decideIsNew(propertyValue);
}).orElse(false);
return entity//
.map(it -> isNew.apply(property.getOwner().getPropertyAccessor(it).getProperty(property)))//
.orElse(false);
}
protected abstract boolean decideIsNew(Object property);
}
/**
* {@link IsNewStrategy} that does a check against {@literal null} for the given value and considers the object new if
* the value given is {@literal null}.
*
* @author Oliver Gierke
*/
static class PropertyIsNullIsNewStrategy extends PersistentPropertyInspectingIsNewStrategy {
/**
* Creates a new {@link PropertyIsNullIsNewStrategy} using the given {@link PersistentProperty}.
*
* @param property must not be {@literal null}.
*/
public PropertyIsNullIsNewStrategy(PersistentProperty<?> property) {
super(property);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContextIsNewStrategyFactory.PersistentPropertyInspectingIsNewStrategy#decideIsNew(java.lang.Object)
*/
@Override
protected boolean decideIsNew(Object property) {
return property == null;
}
private static boolean propertyIsNull(Optional<Object> it) {
return !it.isPresent();
}
/**
* {@link IsNewStrategy} that considers property values of {@literal null} or 0 (in case of a {@link Number})
* implementation as indicators for the new state.
*
* @author Oliver Gierke
*/
static class PropertyIsNullOrZeroNumberIsNewStrategy extends PersistentPropertyInspectingIsNewStrategy {
/**
* Creates a new {@link PropertyIsNullOrZeroNumberIsNewStrategy} instance using the given {@link PersistentProperty}
* .
*
* @param property must not be {@literal null}.
*/
public PropertyIsNullOrZeroNumberIsNewStrategy(PersistentProperty<?> property) {
super(property);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContextIsNewStrategyFactory.PersistentPropertyInspectingIsNewStrategy#decideIsNew(java.lang.Object)
*/
@Override
protected boolean decideIsNew(Object property) {
private static boolean propertyIsNullOrZeroNumber(Optional<Object> it) {
if (property == null) {
return true;
}
return it.map(value -> {
if (!(property instanceof Number)) {
if (!(value instanceof Number)) {
return false;
}
return ((Number) property).longValue() == 0;
}
return ((Number) value).longValue() == 0;
}).orElse(true);
}
}

48
src/main/java/org/springframework/data/mapping/context/PersistentEntities.java

@ -15,14 +15,12 @@ @@ -15,14 +15,12 @@
*/
package org.springframework.data.mapping.context;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@ -32,9 +30,9 @@ import org.springframework.util.Assert; @@ -32,9 +30,9 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @since 1.8
*/
public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> {
private final Iterable<? extends MappingContext<?, ?>> contexts;
private final Streamable<? extends MappingContext<?, ?>> contexts;
/**
* Creates a new {@link PersistentEntities} for the given {@link MappingContext}s.
@ -44,7 +42,7 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> { @@ -44,7 +42,7 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
public PersistentEntities(Iterable<? extends MappingContext<?, ?>> contexts) {
Assert.notNull(contexts, "MappingContexts must not be null!");
this.contexts = contexts;
this.contexts = Streamable.of(contexts);
}
/**
@ -55,16 +53,11 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> { @@ -55,16 +53,11 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
* @param type can be {@literal null}.
* @return
*/
public PersistentEntity<?, ?> getPersistentEntity(Class<?> type) {
public Optional<PersistentEntity<?, ?>> getPersistentEntity(Class<?> type) {
for (MappingContext<?, ?> context : contexts) {
if (context.hasPersistentEntityFor(type)) {
return context.getPersistentEntity(type);
}
}
return null;
return contexts.stream()//
.filter(it -> it.hasPersistentEntityFor(type))//
.findFirst().map(it -> it.getRequiredPersistentEntity(type));
}
/**
@ -72,15 +65,11 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> { @@ -72,15 +65,11 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
*
* @return
*/
public Iterable<TypeInformation<?>> getManagedTypes() {
Set<TypeInformation<?>> informations = new HashSet<TypeInformation<?>>();
public Streamable<TypeInformation<?>> getManagedTypes() {
for (MappingContext<?, ?> context : contexts) {
informations.addAll(context.getManagedTypes());
}
return Collections.unmodifiableSet(informations);
return Streamable.of(contexts.stream()//
.flatMap(it -> it.getManagedTypes().stream())//
.collect(Collectors.toSet()));
}
/*
@ -90,12 +79,7 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> { @@ -90,12 +79,7 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
@Override
public Iterator<PersistentEntity<?, ?>> iterator() {
List<PersistentEntity<?, ?>> entities = new ArrayList<PersistentEntity<?, ?>>();
for (MappingContext<?, ?> context : contexts) {
entities.addAll(context.getPersistentEntities());
}
return entities.iterator();
return contexts.stream().<PersistentEntity<?, ?>>flatMap(it -> it.getPersistentEntities().stream())
.collect(Collectors.toList()).iterator();
}
}

69
src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java

@ -15,7 +15,9 @@ @@ -15,7 +15,9 @@
*/
package org.springframework.data.mapping.model;
import java.beans.PropertyDescriptor;
import lombok.AccessLevel;
import lombok.Getter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
@ -26,6 +28,8 @@ import org.springframework.data.annotation.Reference; @@ -26,6 +28,8 @@ import org.springframework.data.annotation.Reference;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@ -46,43 +50,33 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -46,43 +50,33 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
}
protected final String name;
protected final Optional<PropertyDescriptor> propertyDescriptor;
protected final TypeInformation<?> information;
protected final Class<?> rawType;
protected final Optional<Field> field;
protected final Association<P> association;
protected final PersistentEntity<?, P> owner;
protected final Optional<Association<P>> association;
private final @Getter PersistentEntity<?, P> owner;
private final @Getter(AccessLevel.PROTECTED) Property property;
private final SimpleTypeHolder simpleTypeHolder;
private final int hashCode;
private final Lazy<Integer> hashCode;
public AbstractPersistentProperty(Optional<Field> field, PropertyDescriptor propertyDescriptor,
PersistentEntity<?, P> owner, SimpleTypeHolder simpleTypeHolder) {
public AbstractPersistentProperty(Property property, PersistentEntity<?, P> owner,
SimpleTypeHolder simpleTypeHolder) {
Assert.notNull(simpleTypeHolder, "SimpleTypeHolder must not be null!");
Assert.notNull(owner, "Owner entity must not be null!");
this.name = field.map(Field::getName).orElseGet(() -> propertyDescriptor.getName());
this.rawType = field.<Class<?>> map(Field::getType).orElseGet(() -> propertyDescriptor.getPropertyType());
this.information = owner.getTypeInformation().getProperty(this.name);
this.propertyDescriptor = Optional.ofNullable(propertyDescriptor);
this.field = field;
this.association = isAssociation() ? createAssociation() : null;
this.name = property.getName();
this.rawType = property.getRawType();
this.information = PropertyPath.from(property.getName(), owner.getTypeInformation()).getTypeInformation();
this.property = property;
this.association = isAssociation() ? Optional.of(createAssociation()) : Optional.empty();
this.owner = owner;
this.simpleTypeHolder = simpleTypeHolder;
this.hashCode = this.field == null ? this.propertyDescriptor.hashCode() : this.field.hashCode();
this.hashCode = Lazy.of(() -> property.hashCode());
}
protected abstract Association<P> createAssociation();
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getOwner()
*/
@Override
public PersistentEntity<?, P> getOwner() {
return owner;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getName()
@ -131,7 +125,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -131,7 +125,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
}
TypeInformation<?> candidate = getTypeInformationIfEntityCandidate();
return candidate != null ? Collections.singleton(candidate) : Collections.<TypeInformation<?>> emptySet();
return candidate != null ? Collections.singleton(candidate) : Collections.<TypeInformation<?>>emptySet();
}
private TypeInformation<?> getTypeInformationIfEntityCandidate() {
@ -151,8 +145,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -151,8 +145,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Optional<Method> getGetter() {
return propertyDescriptor.map(it -> it.getReadMethod())//
.filter(it -> rawType.isAssignableFrom(it.getReturnType()));
return property.getGetter();
}
/*
@ -161,8 +154,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -161,8 +154,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Optional<Method> getSetter() {
return propertyDescriptor.map(it -> it.getWriteMethod())//
.filter(it -> it.getParameterTypes()[0].isAssignableFrom(rawType));
return property.getSetter();
}
/*
@ -171,7 +163,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -171,7 +163,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Optional<Field> getField() {
return field;
return property.getField();
}
/*
@ -215,7 +207,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -215,7 +207,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
* @see org.springframework.data.mapping.PersistentProperty#getAssociation()
*/
@Override
public Association<P> getAssociation() {
public Optional<Association<P>> getAssociation() {
return association;
}
@ -266,8 +258,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -266,8 +258,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
return null;
}
TypeInformation<?> componentType = information.getComponentType();
return componentType == null ? null : componentType.getType();
return information.getRequiredComponentType().getType();
}
/*
@ -276,7 +267,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -276,7 +267,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Class<?> getMapValueType() {
return isMap() ? information.getMapValueType().getType() : null;
return isMap() ? information.getMapValueType().map(it -> it.getType()).orElse(null) : null;
}
/*
@ -293,7 +284,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -293,7 +284,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
*/
public boolean usePropertyAccess() {
return owner.getType().isInterface() || CAUSE_FIELD.equals(getField());
return owner.getType().isInterface() || getField().map(it -> it.equals(CAUSE_FIELD)).orElse(false);
}
/*
@ -313,7 +304,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -313,7 +304,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
AbstractPersistentProperty<?> that = (AbstractPersistentProperty<?>) obj;
return this.field == null ? this.propertyDescriptor.equals(that.propertyDescriptor) : this.field.equals(that.field);
return this.property.equals(that.property);
}
/*
@ -322,7 +313,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -322,7 +313,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public int hashCode() {
return this.hashCode;
return this.hashCode.get();
}
/*
@ -331,8 +322,6 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -331,8 +322,6 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public String toString() {
return field.map(Object::toString)//
.orElseGet(() -> propertyDescriptor.map(Object::toString)//
.orElseThrow(() -> new IllegalStateException("Either Field or PropertyDescriptor has to be present!")));
return property.toString();
}
}

33
src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java

@ -15,10 +15,8 @@ @@ -15,10 +15,8 @@
*/
package org.springframework.data.mapping.model;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@ -63,15 +61,15 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -63,15 +61,15 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
* Creates a new {@link AnnotationBasedPersistentProperty}.
*
* @param field must not be {@literal null}.
* @param propertyDescriptor can be {@literal null}.
* @param propertyDescriptor must not be {@literal null}.
* @param owner must not be {@literal null}.
*/
public AnnotationBasedPersistentProperty(Optional<Field> field, PropertyDescriptor propertyDescriptor,
PersistentEntity<?, P> owner, SimpleTypeHolder simpleTypeHolder) {
public AnnotationBasedPersistentProperty(Property property, PersistentEntity<?, P> owner,
SimpleTypeHolder simpleTypeHolder) {
super(field, propertyDescriptor, owner, simpleTypeHolder);
super(property, owner, simpleTypeHolder);
populateAnnotationCache(field);
populateAnnotationCache(property);
this.usePropertyAccess = findPropertyOrOwnerAnnotation(AccessType.class).map(it -> Type.PROPERTY.equals(it.value()))
.orElse(false);
@ -85,9 +83,9 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -85,9 +83,9 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
* @param field
* @throws MappingException in case we find an ambiguous mapping on the accessor methods
*/
private final void populateAnnotationCache(Optional<Field> field) {
private final void populateAnnotationCache(Property property) {
Optionals.toStream(getGetter(), getSetter()).forEach(it -> {
Optionals.toStream(property.getGetter(), property.getSetter()).forEach(it -> {
for (Annotation annotation : it.getAnnotations()) {
@ -102,7 +100,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -102,7 +100,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
}
});
field.ifPresent(it -> {
property.getField().ifPresent(it -> {
for (Annotation annotation : it.getAnnotations()) {
@ -218,10 +216,11 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -218,10 +216,11 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
return (Optional<A>) annotationCache.get(annotationType);
}
return cacheAndReturn(annotationType, getAccessors()//
.map(it -> it.map(inner -> AnnotatedElementUtils.findMergedAnnotation(inner, annotationType)))//
.flatMap(it -> Optionals.toStream(it))//
.findFirst());
return cacheAndReturn(annotationType,
getAccessors()//
.map(it -> it.map(inner -> AnnotatedElementUtils.findMergedAnnotation(inner, annotationType)))//
.flatMap(it -> Optionals.toStream(it))//
.findFirst());
}
/*
@ -232,7 +231,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -232,7 +231,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
public <A extends Annotation> Optional<A> findPropertyOrOwnerAnnotation(Class<A> annotationType) {
Optional<A> annotation = findAnnotation(annotationType);
return annotation.isPresent() ? annotation : owner.findAnnotation(annotationType);
return annotation.isPresent() ? annotation : getOwner().findAnnotation(annotationType);
}
/**
@ -277,7 +276,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -277,7 +276,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
public String toString() {
if (annotationCache.isEmpty()) {
populateAnnotationCache(field);
populateAnnotationCache(getProperty());
}
StringBuilder builder = new StringBuilder().append(annotationCache.values().stream()//
@ -289,6 +288,6 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -289,6 +288,6 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
}
private Stream<Optional<? extends AnnotatedElement>> getAccessors() {
return Arrays.<Optional<? extends AnnotatedElement>> asList(getGetter(), getSetter(), getField()).stream();
return Arrays.<Optional<? extends AnnotatedElement>>asList(getGetter(), getSetter(), getField()).stream();
}
}

18
src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java

@ -35,6 +35,7 @@ import org.slf4j.Logger; @@ -35,6 +35,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.IdentifierAccessor;
@ -79,7 +80,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -79,7 +80,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
private Optional<P> versionProperty = Optional.empty();
private PersistentPropertyAccessorFactory propertyAccessorFactory;
private final Lazy<Optional<? extends Object>> typeAlias;
private final Lazy<Alias> typeAlias;
/**
* Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}.
@ -106,16 +107,17 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -106,16 +107,17 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
this.properties = new ArrayList<>();
this.comparator = comparator;
this.constructor = new PreferredConstructorDiscoverer<>(this).getConstructor();
this.associations = comparator.<Set<Association<P>>> map(it -> new TreeSet<>(new AssociationComparator<>(it)))
.orElse(new HashSet<>());
this.associations = comparator.<Set<Association<P>>>map(it -> new TreeSet<>(new AssociationComparator<>(it)))
.orElseGet(() -> new HashSet<>());
this.propertyCache = new HashMap<>();
this.annotationCache = new HashMap<>();
this.propertyAccessorFactory = BeanWrapperPropertyAccessorFactory.INSTANCE;
this.typeAlias = Lazy
.of(() -> Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(getType(), TypeAlias.class))//
.map(TypeAlias::value).filter(it -> StringUtils.hasText(it)));
this.typeAlias = Lazy.of(() -> Alias
.ofOptional(Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(getType(), TypeAlias.class))//
.map(TypeAlias::value)//
.filter(it -> StringUtils.hasText(it))));
}
/*
@ -304,7 +306,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -304,7 +306,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#getTypeAlias()
*/
public Optional<? extends Object> getTypeAlias() {
public Alias getTypeAlias() {
return typeAlias.get();
}
@ -441,7 +443,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -441,7 +443,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* @see org.springframework.data.mapping.IdentifierAccessor#getIdentifier()
*/
@Override
public Optional<? extends Object> getIdentifier() {
public Optional<Object> getIdentifier() {
return Optional.empty();
}
}

2
src/main/java/org/springframework/data/mapping/model/BeanWrapper.java

@ -80,7 +80,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor { @@ -80,7 +80,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getProperty(org.springframework.data.mapping.PersistentProperty)
*/
public Optional<? extends Object> getProperty(PersistentProperty<?> property) {
public Optional<Object> getProperty(PersistentProperty<?> property) {
return getProperty(property, property.getType());
}

2
src/main/java/org/springframework/data/mapping/model/BeanWrapperPropertyAccessorFactory.java

@ -33,7 +33,7 @@ enum BeanWrapperPropertyAccessorFactory implements PersistentPropertyAccessorFac @@ -33,7 +33,7 @@ enum BeanWrapperPropertyAccessorFactory implements PersistentPropertyAccessorFac
*/
@Override
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
return new BeanWrapper<Object>(bean);
return new BeanWrapper<>(bean);
}
/*

2
src/main/java/org/springframework/data/mapping/model/CamelCaseSplittingFieldNamingStrategy.java

@ -53,7 +53,7 @@ public class CamelCaseSplittingFieldNamingStrategy implements FieldNamingStrateg @@ -53,7 +53,7 @@ public class CamelCaseSplittingFieldNamingStrategy implements FieldNamingStrateg
public String getFieldName(PersistentProperty<?> property) {
List<String> parts = ParsingUtils.splitCamelCaseToLower(property.getName());
List<String> result = new ArrayList<String>();
List<String> result = new ArrayList<>();
for (String part : parts) {

17
src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java

@ -64,9 +64,6 @@ import org.springframework.util.ReflectionUtils; @@ -64,9 +64,6 @@ import org.springframework.util.ReflectionUtils;
*/
public class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccessorFactory {
private static final boolean IS_JAVA_7_OR_BETTER = org.springframework.util.ClassUtils
.isPresent("java.lang.invoke.MethodHandle", ClassGeneratingPropertyAccessorFactory.class.getClassLoader());
private volatile Map<TypeInformation<?>, Class<PersistentPropertyAccessor>> propertyAccessorClasses = new HashMap<TypeInformation<?>, Class<PersistentPropertyAccessor>>(
32);
@ -103,15 +100,11 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -103,15 +100,11 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
Assert.notNull(entity, "PersistentEntity must not be null!");
if (!IS_JAVA_7_OR_BETTER) {
return false;
}
if (entity.getType().getClassLoader() == null || entity.getType().getPackage().getName().startsWith("java")) {
return false;
}
final Set<Integer> hashCodes = new HashSet<Integer>();
final Set<Integer> hashCodes = new HashSet<>();
final AtomicInteger propertyCount = new AtomicInteger();
entity.doWithProperties(new SimplePropertyHandler() {
@ -821,7 +814,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -821,7 +814,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
int[] hashes = new int[propertyStackMap.size()];
Label[] switchJumpLabels = new Label[propertyStackMap.size()];
List<PropertyStackAddress> stackmap = new ArrayList<PropertyStackAddress>(propertyStackMap.values());
List<PropertyStackAddress> stackmap = new ArrayList<>(propertyStackMap.values());
Collections.sort(stackmap);
for (int i = 0; i < stackmap.size(); i++) {
@ -983,8 +976,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -983,8 +976,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
mv.visitLocalVariable(THIS_REF, referenceName(internalClassName), null, l0, l1, 0);
mv.visitLocalVariable("property", "Lorg/springframework/data/mapping/PersistentProperty;",
"Lorg/springframework/data/mapping/PersistentProperty<*>;", l0, l1, 1);
mv.visitLocalVariable("optional", referenceName(JAVA_UTIL_OPTIONAL),
"Ljava/util/Optional<+Ljava/lang/Object;>;", l0, l1, 2);
mv.visitLocalVariable("optional", referenceName(JAVA_UTIL_OPTIONAL), "Ljava/util/Optional<+Ljava/lang/Object;>;",
l0, l1, 2);
if (isAccessible(entity)) {
mv.visitLocalVariable(BEAN_FIELD, referenceName(entity.getType()), null, l0, l1, 3);
@ -1022,7 +1015,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -1022,7 +1015,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
int[] hashes = new int[propertyStackMap.size()];
Label[] switchJumpLabels = new Label[propertyStackMap.size()];
List<PropertyStackAddress> stackmap = new ArrayList<PropertyStackAddress>(propertyStackMap.values());
List<PropertyStackAddress> stackmap = new ArrayList<>(propertyStackMap.values());
Collections.sort(stackmap);
for (int i = 0; i < stackmap.size(); i++) {

2
src/main/java/org/springframework/data/mapping/model/ConvertingPropertyAccessor.java

@ -65,7 +65,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor { @@ -65,7 +65,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getProperty(org.springframework.data.mapping.PersistentProperty)
*/
@Override
public Optional<? extends Object> getProperty(PersistentProperty<?> property) {
public Optional<Object> getProperty(PersistentProperty<?> property) {
return accessor.getProperty(property);
}

4
src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java

@ -56,7 +56,7 @@ public class IdPropertyIdentifierAccessor implements IdentifierAccessor { @@ -56,7 +56,7 @@ public class IdPropertyIdentifierAccessor implements IdentifierAccessor {
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.IdentifierAccessor#getIdentifier()
*/
public Optional<? extends Object> getIdentifier() {
return idProperty.map(it -> accessor.getProperty(it));
public Optional<Object> getIdentifier() {
return idProperty.flatMap(it -> accessor.getProperty(it));
}
}

138
src/main/java/org/springframework/data/mapping/model/Property.java

@ -0,0 +1,138 @@ @@ -0,0 +1,138 @@
/*
* Copyright 2016 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping.model;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Optional;
import org.springframework.data.util.Lazy;
import org.springframework.util.Assert;
/**
* @author Oliver Gierke
*/
@RequiredArgsConstructor
public class Property {
private final @Getter Optional<Field> field;
private final Optional<PropertyDescriptor> descriptor;
private final Lazy<Class<?>> rawType;
private final Lazy<Integer> hashCode;
private Property(Optional<Field> field, Optional<PropertyDescriptor> descriptor) {
this.field = field;
this.descriptor = descriptor;
this.hashCode = Lazy.of(() -> computeHashCode());
this.rawType = Lazy
.of(() -> field.<Class<?>>map(Field::getType).orElseGet(() -> descriptor.map(it -> it.getPropertyType())//
.orElseThrow(() -> new IllegalStateException())));
}
public static Property of(Field field) {
return of(field, Optional.empty());
}
public static Property of(Field field, Optional<PropertyDescriptor> descriptor) {
Assert.notNull(field, "Field must not be null!");
return new Property(Optional.of(field), descriptor);
}
public static Property of(PropertyDescriptor descriptor) {
Assert.notNull(descriptor, "PropertyDescriptor must not be null!");
return new Property(Optional.empty(), Optional.of(descriptor));
}
public boolean isFieldBacked() {
return field.isPresent();
}
public Optional<Method> getGetter() {
return descriptor.map(it -> it.getReadMethod())//
.filter(it -> getRawType().isAssignableFrom(it.getReturnType()));
}
public Optional<Method> getSetter() {
return descriptor.map(it -> it.getWriteMethod())//
.filter(it -> it.getParameterTypes()[0].isAssignableFrom(getRawType()));
}
/**
* @return
*/
public String getName() {
return field.map(Field::getName).orElseGet(() -> descriptor.map(it -> it.getName())//
.orElseThrow(() -> new IllegalStateException()));
}
public Class<?> getRawType() {
return rawType.get();
}
private int computeHashCode() {
return this.field.map(it -> it.hashCode())
.orElseGet(() -> this.descriptor.map(it -> it.hashCode()).orElseThrow(() -> new IllegalStateException()));
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return hashCode.get();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Property)) {
return false;
}
Property that = (Property) obj;
return this.field.isPresent() ? this.field.equals(that.field) : this.descriptor.equals(that.descriptor);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return field.map(Object::toString)
.orElseGet(() -> descriptor.map(Object::toString).orElseThrow(() -> new IllegalStateException()));
}
}

11
src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java

@ -62,13 +62,10 @@ public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P @@ -62,13 +62,10 @@ public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P
*/
public <T> Optional<T> getParameterValue(Parameter<T, P> parameter) {
if (!parameter.hasSpelExpression()) {
return delegate.getParameterValue(parameter);
}
Optional<Object> object = Optional.ofNullable(evaluator.evaluate(parameter.getSpelExpression().orElse(null)));
return object.map(it -> potentiallyConvertSpelValue(object, parameter));
return parameter.getSpelExpression()//
.map(it -> Optional.ofNullable(evaluator.evaluate(it))//
.map(result -> potentiallyConvertSpelValue(result, parameter)))
.orElseGet(() -> delegate.getParameterValue(parameter));
}
/**

6
src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java

@ -107,11 +107,11 @@ class ProjectingMethodInterceptor implements MethodInterceptor { @@ -107,11 +107,11 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
sources.size());
for (Object source : sources) {
result.add(getProjection(source, type.getComponentType().getType()));
result.add(getProjection(source, type.getRequiredComponentType().getType()));
}
if (rawType.isArray()) {
return result.toArray((Object[]) Array.newInstance(type.getComponentType().getType(), result.size()));
return result.toArray((Object[]) Array.newInstance(type.getRequiredComponentType().getType(), result.size()));
}
return result;
@ -130,7 +130,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor { @@ -130,7 +130,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
Map<Object, Object> result = CollectionFactory.createMap(type.getType(), sources.size());
for (Entry<?, ?> source : sources.entrySet()) {
result.put(source.getKey(), getProjection(source.getValue(), type.getMapValueType().getType()));
result.put(source.getKey(), getProjection(source.getValue(), type.getRequiredMapValueType().getType()));
}
return result;

2
src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java

@ -144,7 +144,7 @@ class ProxyProjectionFactory implements ProjectionFactory, ResourceLoaderAware, @@ -144,7 +144,7 @@ class ProxyProjectionFactory implements ProjectionFactory, ResourceLoaderAware,
Assert.notNull(projectionType, "Projection type must not be null!");
List<String> result = new ArrayList<String>();
List<String> result = new ArrayList<>();
for (PropertyDescriptor descriptor : getProjectionInformation(projectionType).getInputProperties()) {
result.add(descriptor.getName());

2
src/main/java/org/springframework/data/projection/SpelAwareProxyProjectionFactory.java

@ -70,7 +70,7 @@ public class SpelAwareProxyProjectionFactory extends ProxyProjectionFactory impl @@ -70,7 +70,7 @@ public class SpelAwareProxyProjectionFactory extends ProxyProjectionFactory impl
if (!typeCache.containsKey(projectionType)) {
AnnotationDetectionMethodCallback<Value> callback = new AnnotationDetectionMethodCallback<Value>(Value.class);
AnnotationDetectionMethodCallback<Value> callback = new AnnotationDetectionMethodCallback<>(Value.class);
ReflectionUtils.doWithMethods(projectionType, callback);
typeCache.put(projectionType, callback.hasFoundAnnotation());

11
src/main/java/org/springframework/data/querydsl/QPageRequest.java

@ -17,6 +17,7 @@ package org.springframework.data.querydsl; @@ -17,6 +17,7 @@ package org.springframework.data.querydsl;
import org.springframework.data.domain.AbstractPageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import com.querydsl.core.types.OrderSpecifier;
@ -39,7 +40,7 @@ public class QPageRequest extends AbstractPageRequest { @@ -39,7 +40,7 @@ public class QPageRequest extends AbstractPageRequest {
* @param size
*/
public QPageRequest(int page, int size) {
this(page, size, (QSort) null);
this(page, size, QSort.unsorted());
}
/**
@ -71,7 +72,7 @@ public class QPageRequest extends AbstractPageRequest { @@ -71,7 +72,7 @@ public class QPageRequest extends AbstractPageRequest {
* @see org.springframework.data.domain.Pageable#getSort()
*/
@Override
public QSort getSort() {
public Sort getSort() {
return sort;
}
@ -81,7 +82,7 @@ public class QPageRequest extends AbstractPageRequest { @@ -81,7 +82,7 @@ public class QPageRequest extends AbstractPageRequest {
*/
@Override
public Pageable next() {
return new QPageRequest(getPageNumber() + 1, getPageSize(), getSort());
return new QPageRequest(getPageNumber() + 1, getPageSize(), sort);
}
/*
@ -90,7 +91,7 @@ public class QPageRequest extends AbstractPageRequest { @@ -90,7 +91,7 @@ public class QPageRequest extends AbstractPageRequest {
*/
@Override
public Pageable previous() {
return new QPageRequest(getPageNumber() - 1, getPageSize(), getSort());
return new QPageRequest(getPageNumber() - 1, getPageSize(), sort);
}
/*
@ -99,6 +100,6 @@ public class QPageRequest extends AbstractPageRequest { @@ -99,6 +100,6 @@ public class QPageRequest extends AbstractPageRequest {
*/
@Override
public Pageable first() {
return new QPageRequest(0, getPageSize(), getSort());
return new QPageRequest(0, getPageSize(), sort);
}
}

25
src/main/java/org/springframework/data/querydsl/QSort.java

@ -19,6 +19,7 @@ import java.io.Serializable; @@ -19,6 +19,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.data.domain.Sort;
import org.springframework.util.Assert;
@ -36,13 +37,14 @@ import com.querydsl.core.types.Path; @@ -36,13 +37,14 @@ import com.querydsl.core.types.Path;
public class QSort extends Sort implements Serializable {
private static final long serialVersionUID = -6701117396842171930L;
private static final QSort UNSORTED = new QSort();
private final List<OrderSpecifier<?>> orderSpecifiers;
/**
* Creates a new {@link QSort} instance with the given {@link OrderSpecifier}s.
*
* @param orderSpecifiers must not be {@literal null} or empty.
* @param orderSpecifiers must not be {@literal null} .
*/
public QSort(OrderSpecifier<?>... orderSpecifiers) {
this(Arrays.asList(orderSpecifiers));
@ -51,16 +53,24 @@ public class QSort extends Sort implements Serializable { @@ -51,16 +53,24 @@ public class QSort extends Sort implements Serializable {
/**
* Creates a new {@link QSort} instance with the given {@link OrderSpecifier}s.
*
* @param orderSpecifiers must not be {@literal null} or empty.
* @param orderSpecifiers must not be {@literal null}.
*/
public QSort(List<OrderSpecifier<?>> orderSpecifiers) {
super(toOrders(orderSpecifiers));
Assert.notEmpty(orderSpecifiers, "Order specifiers must not be null or empty!");
this.orderSpecifiers = orderSpecifiers;
}
public static QSort by(OrderSpecifier<?>... orderSpecifiers) {
return new QSort(orderSpecifiers);
}
public static QSort unsorted() {
return UNSORTED;
}
/**
* Converts the given {@link OrderSpecifier}s into a list of {@link Order}s.
*
@ -69,14 +79,9 @@ public class QSort extends Sort implements Serializable { @@ -69,14 +79,9 @@ public class QSort extends Sort implements Serializable {
*/
private static List<Order> toOrders(List<OrderSpecifier<?>> orderSpecifiers) {
Assert.notEmpty(orderSpecifiers, "Order specifiers must not be null or empty!");
List<Order> orders = new ArrayList<Sort.Order>();
for (OrderSpecifier<?> orderSpecifier : orderSpecifiers) {
orders.add(toOrder(orderSpecifier));
}
Assert.notNull(orderSpecifiers, "Order specifiers must not be null!");
return orders;
return orderSpecifiers.stream().map(QSort::toOrder).collect(Collectors.toList());
}
/**

10
src/main/java/org/springframework/data/querydsl/QuerydslRepositoryInvokerAdapter.java

@ -57,18 +57,18 @@ public class QuerydslRepositoryInvokerAdapter implements RepositoryInvoker { @@ -57,18 +57,18 @@ public class QuerydslRepositoryInvokerAdapter implements RepositoryInvoker {
this.predicate = predicate;
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeFindAll(org.springframework.data.domain.Pageable)
* @see org.springframework.data.repository.support.RepositoryInvoker#invokePagedFindAll(org.springframework.data.domain.Pageable)
*/
@Override
public Iterable<Object> invokeFindAll(Pageable pageable) {
return executor.findAll(predicate, pageable);
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeFindAll(org.springframework.data.domain.Sort)
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeSortedFindAll(org.springframework.data.domain.Sort)
*/
@Override
public Iterable<Object> invokeFindAll(Sort sort) {
@ -129,7 +129,7 @@ public class QuerydslRepositoryInvokerAdapter implements RepositoryInvoker { @@ -129,7 +129,7 @@ public class QuerydslRepositoryInvokerAdapter implements RepositoryInvoker {
return delegate.invokeFindOne(id);
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryInvoker#invokeQueryMethod(java.lang.reflect.Method, org.springframework.util.MultiValueMap, org.springframework.data.domain.Pageable, org.springframework.data.domain.Sort)
*/

4
src/main/java/org/springframework/data/querydsl/binding/MultiValueBinding.java

@ -38,8 +38,8 @@ public interface MultiValueBinding<T extends Path<? extends S>, S> { @@ -38,8 +38,8 @@ public interface MultiValueBinding<T extends Path<? extends S>, S> {
*
* @param path {@link Path} to the property. Will not be {@literal null}.
* @param value the value that should be bound. Will not be {@literal null} or empty.
* @return can be {@literal null}, in which case the binding will not be incorporated in the overall {@link Predicate}
* .
* @return can be {@literal null}, in which case the binding will not be incorporated in the overall
* {@link Predicate}.
*/
Optional<Predicate> bind(T path, Collection<? extends S> value);
}

10
src/main/java/org/springframework/data/querydsl/binding/QuerydslBindings.java

@ -81,9 +81,9 @@ public class QuerydslBindings { @@ -81,9 +81,9 @@ public class QuerydslBindings {
this.pathSpecs = new LinkedHashMap<String, PathAndBinding<?, ?>>();
this.typeSpecs = new LinkedHashMap<Class<?>, PathAndBinding<?, ?>>();
this.whiteList = new HashSet<String>();
this.blackList = new HashSet<String>();
this.aliases = new HashSet<String>();
this.whiteList = new HashSet<>();
this.blackList = new HashSet<>();
this.aliases = new HashSet<>();
}
@ -115,7 +115,7 @@ public class QuerydslBindings { @@ -115,7 +115,7 @@ public class QuerydslBindings {
* @return
*/
public final <T> TypeBinder<T> bind(Class<T> type) {
return new TypeBinder<T>(type);
return new TypeBinder<>(type);
}
/**
@ -502,7 +502,7 @@ public class QuerydslBindings { @@ -502,7 +502,7 @@ public class QuerydslBindings {
Assert.notNull(binding, "Binding must not be null!");
QuerydslBindings.this.typeSpecs.put(type, PathAndBinding.<T, P> withoutPath().with(binding));
QuerydslBindings.this.typeSpecs.put(type, PathAndBinding.<T, P>withoutPath().with(binding));
}
}

36
src/main/java/org/springframework/data/querydsl/binding/QuerydslPredicateBuilder.java

@ -148,7 +148,37 @@ public class QuerydslPredicateBuilder { @@ -148,7 +148,37 @@ public class QuerydslPredicateBuilder {
Optional<Path<?>> resolvedPath = bindings.getExistingPath(path);
return resolvedPath.orElseGet(() -> paths.computeIfAbsent(path, it -> path.reifyPath(resolver)));
return resolvedPath.orElseGet(() -> paths.computeIfAbsent(path, it -> reifyPath(path, Optional.empty())));
}
/**
* Tries to reify a Querydsl {@link Path} from the given {@link PropertyPath} and base.
*
* @param path must not be {@literal null}.
* @param base can be empty.
* @return
*/
private Path<?> reifyPath(PropertyPath path, Optional<Path<?>> base) {
Optional<Path<?>> map = base.filter(it -> it instanceof CollectionPathBase)
.map(it -> CollectionPathBase.class.cast(it))//
.map(CollectionPathBase::any)//
.map(it -> Path.class.cast(it))//
.map(it -> reifyPath(path, Optional.of(it)));
return map.orElseGet(() -> {
Path<?> entityPath = base.orElseGet(() -> resolver.createPath(path.getOwningType().getType()));
Field field = ReflectionUtils.findField(entityPath.getClass(), path.getSegment());
Object value = ReflectionUtils.getField(field, entityPath);
if (path.hasNext()) {
return reifyPath(path.next(), Optional.of((Path<?>) value));
}
return (Path<?>) value;
});
}
/**
@ -162,13 +192,13 @@ public class QuerydslPredicateBuilder { @@ -162,13 +192,13 @@ public class QuerydslPredicateBuilder {
*/
private Collection<Object> convertToPropertyPathSpecificType(List<String> source, PathInformation path) {
Class<?> targetType = path.getLeafType();
Class<?> targetType = path.getLeafProperty().getType();
if (source.isEmpty() || isSingleElementCollectionWithoutText(source)) {
return Collections.emptyList();
}
Collection<Object> target = new ArrayList<Object>(source.size());
Collection<Object> target = new ArrayList<>(source.size());
for (String value : source) {

2
src/main/java/org/springframework/data/repository/PagingAndSortingRepository.java

@ -47,5 +47,5 @@ public interface PagingAndSortingRepository<T, ID extends Serializable> extends @@ -47,5 +47,5 @@ public interface PagingAndSortingRepository<T, ID extends Serializable> extends
* @param pageable
* @return a page of entities
*/
Page<T> findAll(Pageable pageable);
<S extends Sort> Page<T> findAll(Pageable pageable);
}

6
src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java

@ -110,7 +110,7 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl @@ -110,7 +110,7 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
*/
private final String createPassivationId(Set<Annotation> qualifiers, Class<?> repositoryType) {
List<String> qualifierNames = new ArrayList<String>(qualifiers.size());
List<String> qualifierNames = new ArrayList<>(qualifiers.size());
for (Annotation qualifier : qualifiers) {
qualifierNames.add(qualifier.annotationType().getName());
@ -131,11 +131,11 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl @@ -131,11 +131,11 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
@SuppressWarnings("rawtypes")
public Set<Type> getTypes() {
Set<Class> interfaces = new HashSet<Class>();
Set<Class> interfaces = new HashSet<>();
interfaces.add(repositoryType);
interfaces.addAll(Arrays.asList(repositoryType.getInterfaces()));
return new HashSet<Type>(interfaces);
return new HashSet<>(interfaces);
}
/**

2
src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java

@ -119,7 +119,7 @@ public abstract class CdiRepositoryExtensionSupport implements Extension { @@ -119,7 +119,7 @@ public abstract class CdiRepositoryExtensionSupport implements Extension {
*/
private Set<Annotation> getQualifiers(final Class<?> type) {
Set<Annotation> qualifiers = new HashSet<Annotation>();
Set<Annotation> qualifiers = new HashSet<>();
Annotation[] annotations = type.getAnnotations();
for (Annotation annotation : annotations) {
Class<? extends Annotation> annotationType = annotation.annotationType();

6
src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java

@ -124,7 +124,7 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura @@ -124,7 +124,7 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura
return Collections.singleton(ClassUtils.getPackageName(className));
}
Set<String> packages = new HashSet<String>();
Set<String> packages = new HashSet<>();
packages.addAll(Arrays.asList(value));
packages.addAll(Arrays.asList(basePackages));
@ -187,7 +187,7 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura @@ -187,7 +187,7 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura
private Set<TypeFilter> parseFilters(String attributeName) {
Set<TypeFilter> result = new HashSet<TypeFilter>();
Set<TypeFilter> result = new HashSet<>();
AnnotationAttributes[] filters = attributes.getAnnotationArray(attributeName);
for (AnnotationAttributes filter : filters) {
@ -259,7 +259,7 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura @@ -259,7 +259,7 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura
*/
private List<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {
List<TypeFilter> typeFilters = new ArrayList<TypeFilter>();
List<TypeFilter> typeFilters = new ArrayList<>();
FilterType filterType = filterAttributes.getEnum("type");
for (Class<?> filterClass : filterAttributes.getClassArray("value")) {

2
src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java

@ -94,7 +94,7 @@ public class CustomRepositoryImplementationDetector { @@ -94,7 +94,7 @@ public class CustomRepositoryImplementationDetector {
provider.addExcludeFilter(excludeFilter);
}
Set<BeanDefinition> definitions = new HashSet<BeanDefinition>();
Set<BeanDefinition> definitions = new HashSet<>();
for (String basePackage : basePackages) {
definitions.addAll(provider.findCandidateComponents(basePackage));

3
src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java

@ -89,7 +89,8 @@ class RepositoryBeanDefinitionBuilder { @@ -89,7 +89,8 @@ class RepositoryBeanDefinitionBuilder {
builder.addConstructorArgValue(configuration.getRepositoryInterface());
builder.addPropertyValue("queryLookupStrategyKey", configuration.getQueryLookupStrategyKey());
builder.addPropertyValue("lazyInit", configuration.isLazyInit());
builder.addPropertyValue("repositoryBaseClass", configuration.getRepositoryBaseClassName());
builder.addPropertyValue("repositoryBaseClass",
configuration.getRepositoryBaseClassName().orElseGet(() -> extension.getRepositoryFactoryClassName()));
NamedQueriesBeanDefinitionBuilder definitionBuilder = new NamedQueriesBeanDefinitionBuilder(
extension.getDefaultNamedQueryLocation());

4
src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java

@ -85,13 +85,13 @@ class RepositoryComponentProvider extends ClassPathScanningCandidateComponentPro @@ -85,13 +85,13 @@ class RepositoryComponentProvider extends ClassPathScanningCandidateComponentPro
@Override
public void addIncludeFilter(TypeFilter includeFilter) {
List<TypeFilter> filterPlusInterface = new ArrayList<TypeFilter>(2);
List<TypeFilter> filterPlusInterface = new ArrayList<>(2);
filterPlusInterface.add(includeFilter);
filterPlusInterface.add(new InterfaceTypeFilter(Repository.class));
super.addIncludeFilter(new AllTypeFilter(filterPlusInterface));
List<TypeFilter> filterPlusAnnotation = new ArrayList<TypeFilter>(2);
List<TypeFilter> filterPlusAnnotation = new ArrayList<>(2);
filterPlusAnnotation.add(includeFilter);
filterPlusAnnotation.add(new AnnotationTypeFilter(RepositoryDefinition.class, true, true));

2
src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java

@ -117,7 +117,7 @@ public class RepositoryConfigurationDelegate { @@ -117,7 +117,7 @@ public class RepositoryConfigurationDelegate {
RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader,
environment);
List<BeanComponentDefinition> definitions = new ArrayList<BeanComponentDefinition>();
List<BeanComponentDefinition> definitions = new ArrayList<>();
for (RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration : extension
.getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode)) {

2
src/main/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupport.java

@ -239,7 +239,7 @@ public abstract class RepositoryConfigurationExtensionSupport implements Reposit @@ -239,7 +239,7 @@ public abstract class RepositoryConfigurationExtensionSupport implements Reposit
*/
protected <T extends RepositoryConfigurationSource> RepositoryConfiguration<T> getRepositoryConfiguration(
BeanDefinition definition, T configSource) {
return new DefaultRepositoryConfiguration<T>(configSource, definition);
return new DefaultRepositoryConfiguration<>(configSource, definition);
}
/**

2
src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java

@ -65,7 +65,7 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository @@ -65,7 +65,7 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository
scanner.addExcludeFilter(filter);
}
Set<BeanDefinition> result = new HashSet<BeanDefinition>();
Set<BeanDefinition> result = new HashSet<>();
for (String basePackage : getBasePackages()) {
Set<BeanDefinition> candidate = scanner.findCandidateComponents(basePackage);

3
src/main/java/org/springframework/data/repository/core/EntityInformation.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.repository.core;
import java.io.Serializable;
import java.util.Optional;
/**
* Extension of {@link EntityMetadata} to add functionality to query information of entity instances.
@ -38,7 +39,7 @@ public interface EntityInformation<T, ID extends Serializable> extends EntityMet @@ -38,7 +39,7 @@ public interface EntityInformation<T, ID extends Serializable> extends EntityMet
* @param entity must never be {@literal null}
* @return
*/
ID getId(T entity);
Optional<ID> getId(T entity);
/**
* Returns the type of the id of the entity.

17
src/main/java/org/springframework/data/repository/core/support/AbstractEntityInformation.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.repository.core.support;
import java.io.Serializable;
import java.util.Optional;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.util.Assert;
@ -48,18 +49,22 @@ public abstract class AbstractEntityInformation<T, ID extends Serializable> impl @@ -48,18 +49,22 @@ public abstract class AbstractEntityInformation<T, ID extends Serializable> impl
*/
public boolean isNew(T entity) {
ID id = getId(entity);
Optional<ID> id = getId(entity);
Class<ID> idType = getIdType();
if (!idType.isPrimitive()) {
return id == null;
return !id.isPresent();
}
if (id instanceof Number) {
return ((Number) id).longValue() == 0L;
}
return id.map(it -> {
if (it instanceof Number) {
return ((Number) it).longValue() == 0L;
}
return null;
throw new IllegalArgumentException(String.format("Unsupported primitive id type %s!", idType));
}).orElseThrow(() -> new IllegalArgumentException(String.format("Unsupported primitive id type %s!", idType)));
}
/*

2
src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java

@ -149,6 +149,6 @@ public abstract class AbstractRepositoryMetadata implements RepositoryMetadata { @@ -149,6 +149,6 @@ public abstract class AbstractRepositoryMetadata implements RepositoryMetadata {
boolean needToUnwrap = Iterable.class.isAssignableFrom(rawType) || rawType.isArray()
|| QueryExecutionConverters.supports(rawType) || ReflectionUtils.isJava8StreamType(rawType);
return needToUnwrap ? unwrapWrapperTypes(type.getComponentType()) : rawType;
return needToUnwrap ? unwrapWrapperTypes(type.getRequiredComponentType()) : rawType;
}
}

7
src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java

@ -76,8 +76,9 @@ class DefaultRepositoryInformation implements RepositoryInformation { @@ -76,8 +76,9 @@ class DefaultRepositoryInformation implements RepositoryInformation {
public DefaultRepositoryInformation(RepositoryMetadata metadata, Class<?> repositoryBaseClass,
Optional<Class<?>> customImplementationClass) {
Assert.notNull(metadata, "Metadata must not be null!");
Assert.notNull(repositoryBaseClass, "RepositoryBaseClass must not be null!");
Assert.notNull(metadata, "Repository metadata must not be null!");
Assert.notNull(repositoryBaseClass, "Repository base class must not be null!");
Assert.notNull(customImplementationClass, "Custom implementation class must not be null!");
this.metadata = metadata;
this.repositoryBaseClass = repositoryBaseClass;
@ -162,7 +163,7 @@ class DefaultRepositoryInformation implements RepositoryInformation { @@ -162,7 +163,7 @@ class DefaultRepositoryInformation implements RepositoryInformation {
@Override
public Streamable<Method> getQueryMethods() {
Set<Method> result = new HashSet<Method>();
Set<Method> result = new HashSet<>();
for (Method method : getRepositoryInterface().getMethods()) {
method = ClassUtils.getMostSpecificMethod(method, getRepositoryInterface());

3
src/main/java/org/springframework/data/repository/core/support/DelegatingEntityInformation.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.repository.core.support;
import java.io.Serializable;
import java.util.Optional;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.util.Assert;
@ -62,7 +63,7 @@ public class DelegatingEntityInformation<T, ID extends Serializable> implements @@ -62,7 +63,7 @@ public class DelegatingEntityInformation<T, ID extends Serializable> implements
* (non-Javadoc)
* @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object)
*/
public ID getId(T entity) {
public Optional<ID> getId(T entity) {
return delegate.getId(entity);
}

40
src/main/java/org/springframework/data/repository/core/support/PersistableEntityInformation.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.repository.core.support;
import java.io.Serializable;
import java.util.Optional;
import org.springframework.core.GenericTypeResolver;
import org.springframework.data.domain.Persistable;
@ -27,8 +28,8 @@ import org.springframework.data.repository.core.EntityMetadata; @@ -27,8 +28,8 @@ import org.springframework.data.repository.core.EntityMetadata;
*
* @author Oliver Gierke
*/
public class PersistableEntityInformation<T extends Persistable<ID>, ID extends Serializable> extends
AbstractEntityInformation<T, ID> {
public class PersistableEntityInformation<T extends Persistable<ID>, ID extends Serializable>
extends AbstractEntityInformation<T, ID> {
private Class<ID> idClass;
@ -45,34 +46,29 @@ public class PersistableEntityInformation<T extends Persistable<ID>, ID extends @@ -45,34 +46,29 @@ public class PersistableEntityInformation<T extends Persistable<ID>, ID extends
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.IsNewAware#isNew(java.lang
* .Object)
*/
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.AbstractEntityInformation#isNew(java.lang.Object)
*/
@Override
public boolean isNew(T entity) {
return entity.isNew();
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.IdAware#getId(java.lang.Object
* )
*/
public ID getId(T entity) {
return entity.getId();
* (non-Javadoc)
* @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object)
*/
@Override
public Optional<ID> getId(T entity) {
return Optional.ofNullable(entity.getId());
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getIdType()
*/
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.EntityInformation#getIdType()
*/
@Override
public Class<ID> getIdType() {
return this.idClass;
}
}
}

5
src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.repository.core.support;
import java.io.Serializable;
import java.util.Optional;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.repository.core.EntityInformation;
@ -47,8 +48,8 @@ public class PersistentEntityInformation<T, ID extends Serializable> extends Abs @@ -47,8 +48,8 @@ public class PersistentEntityInformation<T, ID extends Serializable> extends Abs
* @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object)
*/
@Override
public ID getId(T entity) {
return (ID) persistentEntity.getIdentifierAccessor(entity).getIdentifier().orElse(null);
public Optional<ID> getId(T entity) {
return persistentEntity.getIdentifierAccessor(entity).getIdentifier().map(it -> (ID) it);
}
/*

17
src/main/java/org/springframework/data/repository/core/support/ReflectionEntityInformation.java

@ -18,13 +18,12 @@ package org.springframework.data.repository.core.support; @@ -18,13 +18,12 @@ package org.springframework.data.repository.core.support;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Optional;
import org.springframework.data.annotation.Id;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.core.support.AbstractEntityInformation;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
/**
* {@link EntityInformation} implementation that inspects fields for an annotation and looks up this field's value to
@ -60,12 +59,10 @@ public class ReflectionEntityInformation<T, ID extends Serializable> extends Abs @@ -60,12 +59,10 @@ public class ReflectionEntityInformation<T, ID extends Serializable> extends Abs
super(domainClass);
Assert.notNull(annotation, "Annotation must not be null!");
ReflectionUtils.doWithFields(domainClass, new FieldCallback() {
public void doWith(Field field) {
if (field.getAnnotation(annotation) != null) {
ReflectionEntityInformation.this.field = field;
return;
}
ReflectionUtils.doWithFields(domainClass, field -> {
if (field.getAnnotation(annotation) != null) {
ReflectionEntityInformation.this.field = field;
return;
}
});
@ -78,8 +75,8 @@ public class ReflectionEntityInformation<T, ID extends Serializable> extends Abs @@ -78,8 +75,8 @@ public class ReflectionEntityInformation<T, ID extends Serializable> extends Abs
* @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object)
*/
@SuppressWarnings("unchecked")
public ID getId(Object entity) {
return entity == null ? null : (ID) ReflectionUtils.getField(field, entity);
public Optional<ID> getId(Object entity) {
return entity == null ? null : Optional.of((ID) ReflectionUtils.getField(field, entity));
}
/*

5
src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java

@ -199,9 +199,8 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -199,9 +199,8 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
*/
public PersistentEntity<?, ?> getPersistentEntity() {
return mappingContext//
.map(context -> context.getPersistentEntity(repositoryMetadata.getDomainType()))//
.orElseGet(null);
return mappingContext.orElseThrow(() -> new IllegalStateException("No MappingContext available!"))
.getRequiredPersistentEntity(repositoryMetadata.getDomainType());
}
/* (non-Javadoc)

47
src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java

@ -40,8 +40,8 @@ import org.springframework.beans.BeansException; @@ -40,8 +40,8 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
@ -73,8 +73,6 @@ import org.springframework.util.Assert; @@ -73,8 +73,6 @@ import org.springframework.util.Assert;
*/
public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, BeanFactoryAware {
private static final boolean IS_JAVA_8 = org.springframework.util.ClassUtils.isPresent("java.util.Optional",
RepositoryFactorySupport.class.getClassLoader());
private static final Class<?> TRANSACTION_PROXY_TYPE = getTransactionProxyType();
private final Map<RepositoryInformationCacheKey, RepositoryInformation> repositoryInformationCache;
@ -197,6 +195,19 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, @@ -197,6 +195,19 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
return getRepository(repositoryInterface, Optional.empty());
}
/**
* Returns a repository instance for the given interface backed by an instance providing implementation logic for
* custom logic.
*
* @param <T>
* @param repositoryInterface
* @param customImplementation
* @return
*/
public <T> T getRepository(Class<T> repositoryInterface, Object customImplementation) {
return getRepository(repositoryInterface, Optional.of(customImplementation));
}
/**
* Returns a repository instance for the given interface backed by an instance providing implementation logic for
* custom logic.
@ -207,7 +218,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, @@ -207,7 +218,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
* @return
*/
@SuppressWarnings({ "unchecked" })
public <T> T getRepository(Class<T> repositoryInterface, Optional<Object> customImplementation) {
protected <T> T getRepository(Class<T> repositoryInterface, Optional<Object> customImplementation) {
RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
RepositoryInformation information = getRepositoryInformation(metadata, customImplementation.map(Object::getClass));
@ -230,10 +241,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, @@ -230,10 +241,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
postProcessors.forEach(processor -> processor.postProcess(result, information));
if (IS_JAVA_8) {
result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
}
result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
result.addAdvice(new QueryExecutorMethodInterceptor(information));
result.addAdvice(information.isReactiveRepository()
@ -265,15 +273,14 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, @@ -265,15 +273,14 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
RepositoryInformationCacheKey cacheKey = new RepositoryInformationCacheKey(metadata, customImplementationClass);
return repositoryInformationCache.computeIfAbsent(cacheKey, key -> new DefaultRepositoryInformation(metadata,
repositoryBaseClass.orElse(getRepositoryBaseClass(metadata)), customImplementationClass));
return repositoryInformationCache.computeIfAbsent(cacheKey, key -> {
/*
repositoryInformation = metadata.isReactiveRepository()
? new ReactiveRepositoryInformation(metadata, repositoryBaseClass, customImplementationClass)
: new DefaultRepositoryInformation(metadata, repositoryBaseClass, customImplementationClass);
*/
Class<?> baseClass = repositoryBaseClass.orElse(getRepositoryBaseClass(metadata));
return metadata.isReactiveRepository()
? new ReactiveRepositoryInformation(metadata, baseClass, customImplementationClass)
: new DefaultRepositoryInformation(metadata, baseClass, customImplementationClass);
});
}
protected List<QueryMethod> getQueryMethods() {
@ -432,9 +439,11 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, @@ -432,9 +439,11 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
private void invokeListeners(RepositoryQuery query) {
for (QueryCreationListener listener : queryPostProcessors) {
Class<?> typeArgument = GenericTypeResolver.resolveTypeArgument(listener.getClass(),
QueryCreationListener.class);
if (typeArgument != null && typeArgument.isAssignableFrom(query.getClass())) {
ResolvableType typeArgument = ResolvableType.forClass(QueryCreationListener.class, listener.getClass())
.getGeneric(0);
if (typeArgument != null && typeArgument.isAssignableFrom(ResolvableType.forClass(query.getClass()))) {
listener.onCreation(query);
}
}
@ -620,7 +629,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, @@ -620,7 +629,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
/**
* All {@link QueryMethod}s.
*/
private List<QueryMethod> queryMethods = new ArrayList<QueryMethod>();
private List<QueryMethod> queryMethods = new ArrayList<>();
/* (non-Javadoc)
* @see org.springframework.data.repository.core.support.QueryCreationListener#onCreation(org.springframework.data.repository.query.RepositoryQuery)

4
src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryProxyPostProcessor.java

@ -157,7 +157,7 @@ class TransactionalRepositoryProxyPostProcessor implements RepositoryProxyPostPr @@ -157,7 +157,7 @@ class TransactionalRepositoryProxyPostProcessor implements RepositoryProxyPostPr
*/
public CustomAnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2);
this.annotationParsers = new LinkedHashSet<>(2);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
@ -186,7 +186,7 @@ class TransactionalRepositoryProxyPostProcessor implements RepositoryProxyPostPr @@ -186,7 +186,7 @@ class TransactionalRepositoryProxyPostProcessor implements RepositoryProxyPostPr
public CustomAnnotationTransactionAttributeSource(TransactionAnnotationParser... annotationParsers) {
this.publicMethodsOnly = true;
Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
Set<TransactionAnnotationParser> parsers = new LinkedHashSet<TransactionAnnotationParser>(
Set<TransactionAnnotationParser> parsers = new LinkedHashSet<>(
annotationParsers.length);
Collections.addAll(parsers, annotationParsers);
this.annotationParsers = parsers;

6
src/main/java/org/springframework/data/repository/init/Jackson2ResourceReader.java

@ -80,12 +80,12 @@ public class Jackson2ResourceReader implements ResourceReader { @@ -80,12 +80,12 @@ public class Jackson2ResourceReader implements ResourceReader {
public Object readFrom(Resource resource, ClassLoader classLoader) throws Exception {
InputStream stream = resource.getInputStream();
JsonNode node = mapper.reader(JsonNode.class).readTree(stream);
JsonNode node = mapper.readerFor(JsonNode.class).readTree(stream);
if (node.isArray()) {
Iterator<JsonNode> elements = node.elements();
List<Object> result = new ArrayList<Object>();
List<Object> result = new ArrayList<>();
while (elements.hasNext()) {
JsonNode element = elements.next();
@ -112,6 +112,6 @@ public class Jackson2ResourceReader implements ResourceReader { @@ -112,6 +112,6 @@ public class Jackson2ResourceReader implements ResourceReader {
Class<?> type = ClassUtils.resolveClassName(typeName, classLoader);
return mapper.reader(type).readValue(node);
return mapper.readerFor(type).readValue(node);
}
}

12
src/main/java/org/springframework/data/repository/query/EvaluationContextExtensionInformation.java

@ -91,7 +91,7 @@ class EvaluationContextExtensionInformation { @@ -91,7 +91,7 @@ class EvaluationContextExtensionInformation {
*/
public RootObjectInformation getRootObjectInformation(Optional<Object> target) {
return target.map(it -> rootObjectInformation.orElse(new RootObjectInformation(it.getClass())))
return target.map(it -> rootObjectInformation.orElseGet(() -> new RootObjectInformation(it.getClass())))
.orElse(RootObjectInformation.NONE);
}
@ -215,8 +215,8 @@ class EvaluationContextExtensionInformation { @@ -215,8 +215,8 @@ class EvaluationContextExtensionInformation {
Assert.notNull(type, "Type must not be null!");
this.accessors = new HashMap<String, Method>();
this.methods = new HashSet<Method>();
this.fields = new ArrayList<Field>();
this.methods = new HashSet<>();
this.fields = new ArrayList<>();
if (Object.class.equals(type)) {
return;
@ -232,7 +232,7 @@ class EvaluationContextExtensionInformation { @@ -232,7 +232,7 @@ class EvaluationContextExtensionInformation {
.filter(it -> method.equals(it.getReadMethod()))//
.forEach(it -> RootObjectInformation.this.accessors.put(it.getName(), method));
} , PublicMethodAndFieldFilter.NON_STATIC);
}, PublicMethodAndFieldFilter.NON_STATIC);
ReflectionUtils.doWithFields(type, field -> RootObjectInformation.this.fields.add(field),
PublicMethodAndFieldFilter.NON_STATIC);
@ -250,7 +250,7 @@ class EvaluationContextExtensionInformation { @@ -250,7 +250,7 @@ class EvaluationContextExtensionInformation {
.collect(Collectors.toMap(//
Method::getName, //
method -> new Function(method, it))))
.orElse(Collections.emptyMap());
.orElseGet(() -> Collections.emptyMap());
}
/**
@ -271,7 +271,7 @@ class EvaluationContextExtensionInformation { @@ -271,7 +271,7 @@ class EvaluationContextExtensionInformation {
return Collections.unmodifiableMap(properties);
}).orElse(Collections.emptyMap());
}).orElseGet(() -> Collections.emptyMap());
}
}

2
src/main/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProvider.java

@ -163,7 +163,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex @@ -163,7 +163,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex
this.extensions = Collections.emptyList();
beanFactory.ifPresent(it -> {
this.extensions = new ArrayList<EvaluationContextExtension>(
this.extensions = new ArrayList<>(
it.getBeansOfType(EvaluationContextExtension.class, true, false).values());
});

3
src/main/java/org/springframework/data/repository/query/ParameterAccessor.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.repository.query;
import java.util.Iterator;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
@ -48,7 +49,7 @@ public interface ParameterAccessor extends Iterable<Object> { @@ -48,7 +49,7 @@ public interface ParameterAccessor extends Iterable<Object> {
* @return
* @since 1.12
*/
Class<?> getDynamicProjection();
Optional<Class<?>> getDynamicProjection();
/**
* Returns the bindable value with the given index. Bindable means, that {@link Pageable} and {@link Sort} values are

6
src/main/java/org/springframework/data/repository/query/Parameters.java

@ -64,7 +64,7 @@ public abstract class Parameters<S extends Parameters<S, T>, T extends Parameter @@ -64,7 +64,7 @@ public abstract class Parameters<S extends Parameters<S, T>, T extends Parameter
List<Class<?>> types = Arrays.asList(method.getParameterTypes());
this.parameters = new ArrayList<T>(types.size());
this.parameters = new ArrayList<>(types.size());
this.dynamicProjectionIndex = -1;
for (int i = 0; i < types.size(); i++) {
@ -98,7 +98,7 @@ public abstract class Parameters<S extends Parameters<S, T>, T extends Parameter @@ -98,7 +98,7 @@ public abstract class Parameters<S extends Parameters<S, T>, T extends Parameter
*/
protected Parameters(List<T> originals) {
this.parameters = new ArrayList<T>(originals.size());
this.parameters = new ArrayList<>(originals.size());
int pageableIndexTemp = -1;
int sortIndexTemp = -1;
@ -251,7 +251,7 @@ public abstract class Parameters<S extends Parameters<S, T>, T extends Parameter @@ -251,7 +251,7 @@ public abstract class Parameters<S extends Parameters<S, T>, T extends Parameter
*/
public S getBindableParameters() {
List<T> bindables = new ArrayList<T>();
List<T> bindables = new ArrayList<>();
for (T candidate : this) {

20
src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java

@ -18,6 +18,7 @@ package org.springframework.data.repository.query; @@ -18,6 +18,7 @@ package org.springframework.data.repository.query;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.data.domain.Pageable;
@ -70,10 +71,12 @@ public class ParametersParameterAccessor implements ParameterAccessor { @@ -70,10 +71,12 @@ public class ParametersParameterAccessor implements ParameterAccessor {
public Pageable getPageable() {
if (!parameters.hasPageableParameter()) {
return null;
return Pageable.NONE;
}
return (Pageable) values.get(parameters.getPageableIndex());
Pageable pageable = (Pageable) values.get(parameters.getPageableIndex());
return pageable == null ? Pageable.NONE : pageable;
}
/*
@ -83,14 +86,16 @@ public class ParametersParameterAccessor implements ParameterAccessor { @@ -83,14 +86,16 @@ public class ParametersParameterAccessor implements ParameterAccessor {
public Sort getSort() {
if (parameters.hasSortParameter()) {
return (Sort) values.get(parameters.getSortIndex());
Sort sort = (Sort) values.get(parameters.getSortIndex());
return sort == null ? Sort.unsorted() : sort;
}
if (parameters.hasPageableParameter() && getPageable() != null) {
if (parameters.hasPageableParameter()) {
return getPageable().getSort();
}
return null;
return Sort.unsorted();
}
/**
@ -98,8 +103,9 @@ public class ParametersParameterAccessor implements ParameterAccessor { @@ -98,8 +103,9 @@ public class ParametersParameterAccessor implements ParameterAccessor {
*
* @return
*/
public Class<?> getDynamicProjection() {
return parameters.hasDynamicProjection() ? (Class<?>) values.get(parameters.getDynamicProjectionIndex()) : null;
public Optional<Class<?>> getDynamicProjection() {
return Optional.ofNullable(
parameters.hasDynamicProjection() ? (Class<?>) values.get(parameters.getDynamicProjectionIndex()) : null);
}
/**

4
src/main/java/org/springframework/data/repository/query/QueryMethod.java

@ -265,7 +265,9 @@ public class QueryMethod { @@ -265,7 +265,9 @@ public class QueryMethod {
if (QueryExecutionConverters.supports(method.getReturnType())) {
// unwrap only one level to handle cases like Future<List<Entity>> correctly.
return ClassTypeInformation.fromReturnTypeOf(method).getComponentType().getType();
return ClassTypeInformation.fromReturnTypeOf(method).getComponentType().map(it -> it.getType())
.orElseThrow(() -> new IllegalStateException(
String.format("Couldn't find component type for return value of method %s!", method)));
}
return method.getReturnType();

46
src/main/java/org/springframework/data/repository/query/ResultProcessor.java

@ -23,6 +23,7 @@ import java.util.Collection; @@ -23,6 +23,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import org.springframework.core.CollectionFactory;
@ -48,8 +49,7 @@ public class ResultProcessor { @@ -48,8 +49,7 @@ public class ResultProcessor {
private final QueryMethod method;
private final ProjectingConverter converter;
private final ProjectionFactory factory;
private ReturnedType type;
private final ReturnedType type;
/**
* Creates a new {@link ResultProcessor} from the given {@link QueryMethod} and {@link ProjectionFactory}.
@ -86,15 +86,11 @@ public class ResultProcessor { @@ -86,15 +86,11 @@ public class ResultProcessor {
* @param accessor can be {@literal null}.
* @return
*/
public ResultProcessor withDynamicProjection(ParameterAccessor accessor) {
if (accessor == null) {
return this;
}
public ResultProcessor withDynamicProjection(Optional<ParameterAccessor> accessor) {
Class<?> projectionType = accessor.getDynamicProjection();
return projectionType == null ? this : new ResultProcessor(method, factory, projectionType);
return accessor.flatMap(it -> it.getDynamicProjection())//
.map(it -> new ResultProcessor(method, factory, it))//
.orElse(this);
}
/**
@ -280,34 +276,4 @@ public class ResultProcessor { @@ -280,34 +276,4 @@ public class ResultProcessor {
return result;
}
}
/**
* Handler for Repository query methods returning a Java 8 Stream result by ensuring the {@link Stream} elements match
* the expected return type of the query method.
*
* @author John Blum
* @author Oliver Gierke
*/
@RequiredArgsConstructor
static class StreamQueryResultHandler {
private final @NonNull ReturnedType returnType;
private final @NonNull Converter<Object, Object> converter;
/**
* Processes the given source object as a {@link Stream}, mapping each element to the required return type,
* converting if necessary.
*
* @param source the {@link Stream} of elements to process, must not be {@literal null}.
* @return a new {@link Stream} with the source {@link Stream}'s elements mapped to the target type.
*/
@SuppressWarnings("unchecked")
public Object handle(Object source) {
Assert.isInstanceOf(Stream.class, source, "Source must not be null and an instance of Stream!");
return ((Stream<Object>) source)
.map(element -> returnType.isInstance(element) ? element : converter.convert(element));
}
}
}

4
src/main/java/org/springframework/data/repository/query/ReturnedType.java

@ -189,7 +189,7 @@ public abstract class ReturnedType { @@ -189,7 +189,7 @@ public abstract class ReturnedType {
@Override
public List<String> getInputProperties() {
List<String> properties = new ArrayList<String>();
List<String> properties = new ArrayList<>();
for (PropertyDescriptor descriptor : information.getInputProperties()) {
if (!properties.contains(descriptor.getName())) {
@ -291,7 +291,7 @@ public abstract class ReturnedType { @@ -291,7 +291,7 @@ public abstract class ReturnedType {
.flatMap(parameter -> Optionals.toStream(parameter.getName()))//
.collect(Collectors.toList());
}).orElse(Collections.emptyList());
}).orElseGet(() -> Collections.emptyList());
}
private boolean isDto() {

9
src/main/java/org/springframework/data/repository/query/parser/AbstractQueryCreator.java

@ -68,9 +68,7 @@ public abstract class AbstractQueryCreator<T, S> { @@ -68,9 +68,7 @@ public abstract class AbstractQueryCreator<T, S> {
* @return
*/
public T createQuery() {
Sort dynamicSort = parameters != null ? parameters.getSort() : null;
return createQuery(dynamicSort);
return createQuery(parameters.getSort());
}
/**
@ -82,10 +80,7 @@ public abstract class AbstractQueryCreator<T, S> { @@ -82,10 +80,7 @@ public abstract class AbstractQueryCreator<T, S> {
*/
public T createQuery(Sort dynamicSort) {
Sort staticSort = tree.getSort();
Sort sort = staticSort != null ? staticSort.and(dynamicSort) : dynamicSort;
return complete(createCriteria(tree), sort);
return complete(createCriteria(tree), tree.getSort().and(dynamicSort));
}
/**

37
src/main/java/org/springframework/data/repository/query/parser/OrderBySource.java

@ -39,10 +39,12 @@ import org.springframework.util.StringUtils; @@ -39,10 +39,12 @@ import org.springframework.util.StringUtils;
*/
class OrderBySource {
public static OrderBySource EMPTY = new OrderBySource("");
private static final String BLOCK_SPLIT = "(?<=Asc|Desc)(?=\\p{Lu})";
private static final Pattern DIRECTION_SPLIT = Pattern.compile("(.+?)(Asc|Desc)?$");
private static final String INVALID_ORDER_SYNTAX = "Invalid order syntax for part %s!";
private static final Set<String> DIRECTION_KEYWORDS = new HashSet<String>(Arrays.asList("Asc", "Desc"));
private static final Set<String> DIRECTION_KEYWORDS = new HashSet<>(Arrays.asList("Asc", "Desc"));
private final List<Order> orders;
@ -53,7 +55,7 @@ class OrderBySource { @@ -53,7 +55,7 @@ class OrderBySource {
* @param clause must not be {@literal null}.
*/
public OrderBySource(String clause) {
this(clause, null);
this(clause, Optional.empty());
}
/**
@ -61,12 +63,16 @@ class OrderBySource { @@ -61,12 +63,16 @@ class OrderBySource {
* type.
*
* @param clause must not be {@literal null}.
* @param domainClass can be {@literal null}.
* @param domainClass must not be {@literal null}.
*/
public OrderBySource(String clause, Class<?> domainClass) {
public OrderBySource(String clause, Optional<Class<?>> domainClass) {
this.orders = new ArrayList<Sort.Order>();
if (!StringUtils.hasText(clause)) {
return;
}
for (String part : clause.split(BLOCK_SPLIT)) {
Matcher matcher = DIRECTION_SPLIT.matcher(part);
@ -83,8 +89,7 @@ class OrderBySource { @@ -83,8 +89,7 @@ class OrderBySource {
throw new IllegalArgumentException(String.format(INVALID_ORDER_SYNTAX, part));
}
Direction direction = StringUtils.hasText(directionString) ? Direction.fromString(directionString) : null;
this.orders.add(createOrder(propertyString, direction, domainClass));
this.orders.add(createOrder(propertyString, Direction.fromOptionalString(directionString), domainClass));
}
}
@ -98,13 +103,17 @@ class OrderBySource { @@ -98,13 +103,17 @@ class OrderBySource {
* @return
* @see PropertyPath#from(String, Class)
*/
private Order createOrder(String propertySource, Direction direction, Class<?> domainClass) {
private Order createOrder(String propertySource, Optional<Direction> direction, Optional<Class<?>> domainClass) {
if (null == domainClass) {
return new Order(direction, StringUtils.uncapitalize(propertySource));
}
PropertyPath propertyPath = PropertyPath.from(propertySource, domainClass);
return new Order(direction, propertyPath.toDotPath());
return domainClass.map(type -> {
PropertyPath propertyPath = PropertyPath.from(propertySource, type);
return direction.map(it -> new Order(it, propertyPath.toDotPath()))
.orElseGet(() -> new Order(propertyPath.toDotPath()));
}).orElseGet(() -> direction//
.map(it -> new Order(it, StringUtils.uncapitalize(propertySource)))
.orElseGet(() -> new Order(StringUtils.uncapitalize(propertySource))));
}
/**
@ -112,8 +121,8 @@ class OrderBySource { @@ -112,8 +121,8 @@ class OrderBySource {
*
* @return the {@link Sort}.
*/
public Optional<Sort> toSort() {
return this.orders.isEmpty() ? Optional.empty() : Optional.of(new Sort(this.orders));
public Sort toSort() {
return Sort.by(this.orders);
}
/*

2
src/main/java/org/springframework/data/repository/query/parser/Part.java

@ -169,7 +169,7 @@ public class Part { @@ -169,7 +169,7 @@ public class Part {
public static final Collection<String> ALL_KEYWORDS;
static {
List<String> allKeywords = new ArrayList<String>();
List<String> allKeywords = new ArrayList<>();
for (Type type : ALL) {
allKeywords.addAll(type.keywords);
}

18
src/main/java/org/springframework/data/repository/query/parser/PartTree.java

@ -110,7 +110,7 @@ public class PartTree implements Streamable<OrPart> { @@ -110,7 +110,7 @@ public class PartTree implements Streamable<OrPart> {
* @return the sort
*/
public Sort getSort() {
return predicate.getOrderBySource().flatMap(OrderBySource::toSort).orElse(null);
return predicate.getOrderBySource().toSort();
}
/**
@ -193,12 +193,15 @@ public class PartTree implements Streamable<OrPart> { @@ -193,12 +193,15 @@ public class PartTree implements Streamable<OrPart> {
.collect(Collectors.toList()));
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
Optional<OrderBySource> orderBySource = predicate.getOrderBySource();
return String.format("%s%s", StringUtils.collectionToDelimitedString(predicate.nodes, " or "),
orderBySource.map(it -> " ".concat(it.toString())).orElse(""));
return String.format("%s %s", StringUtils.collectionToDelimitedString(predicate.nodes, " or "),
predicate.getOrderBySource().toString()).trim();
}
/**
@ -347,13 +350,13 @@ public class PartTree implements Streamable<OrPart> { @@ -347,13 +350,13 @@ public class PartTree implements Streamable<OrPart> {
* @author Oliver Gierke
* @author Phil Webb
*/
private static class Predicate implements Iterable<OrPart> {
private static class Predicate implements Streamable<OrPart> {
private static final Pattern ALL_IGNORE_CASE = Pattern.compile("AllIgnor(ing|e)Case");
private static final String ORDER_BY = "OrderBy";
private final List<OrPart> nodes;
private final @Getter Optional<OrderBySource> orderBySource;
private final @Getter OrderBySource orderBySource;
private boolean alwaysIgnoreCase;
public Predicate(String predicate, Class<?> domainClass) {
@ -368,7 +371,8 @@ public class PartTree implements Streamable<OrPart> { @@ -368,7 +371,8 @@ public class PartTree implements Streamable<OrPart> {
.map(part -> new OrPart(part, domainClass, alwaysIgnoreCase))//
.collect(Collectors.toList());
this.orderBySource = Optional.ofNullable(parts.length == 2 ? new OrderBySource(parts[1], domainClass) : null);
this.orderBySource = parts.length == 2 ? new OrderBySource(parts[1], Optional.of(domainClass))
: OrderBySource.EMPTY;
}
private String detectAndSetAllIgnoreCase(String predicate) {

2
src/main/java/org/springframework/data/repository/support/CrudRepositoryInvoker.java

@ -88,7 +88,7 @@ class CrudRepositoryInvoker extends ReflectionRepositoryInvoker { @@ -88,7 +88,7 @@ class CrudRepositoryInvoker extends ReflectionRepositoryInvoker {
@Override
@SuppressWarnings("unchecked")
public <T> T invokeFindOne(Serializable id) {
return customFindOneMethod ? super.<T> invokeFindOne(id) : (T) repository.findOne(convertId(id));
return customFindOneMethod ? super.<T>invokeFindOne(id) : (T) repository.findOne(convertId(id));
}
/*

13
src/main/java/org/springframework/data/repository/support/DefaultRepositoryInvokerFactory.java

@ -18,11 +18,14 @@ package org.springframework.data.repository.support; @@ -18,11 +18,14 @@ package org.springframework.data.repository.support;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.Pair;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.util.Assert;
@ -84,11 +87,13 @@ public class DefaultRepositoryInvokerFactory implements RepositoryInvokerFactory @@ -84,11 +87,13 @@ public class DefaultRepositoryInvokerFactory implements RepositoryInvokerFactory
*/
private RepositoryInvoker prepareInvokers(Class<?> domainType) {
Object repository = repositories.getRepositoryFor(domainType);
Assert.notNull(repository, String.format("No repository found for domain type: %s", domainType));
RepositoryInformation information = repositories.getRepositoryInformationFor(domainType);
Optional<Pair<Object, RepositoryInformation>> repositoryAndInformation = Optionals
.withBoth(repositories.getRepositoryFor(domainType), repositories.getRepositoryInformationFor(domainType));
return createInvoker(information, repository);
return repositoryAndInformation//
.map(it -> createInvoker(it.getSecond(), it.getFirst())) //
.orElseThrow(
() -> new IllegalArgumentException(String.format("No repository found for domain type: %s", domainType)));
}
@SuppressWarnings("unchecked")

41
src/main/java/org/springframework/data/repository/support/DomainClassConverter.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.repository.support;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import org.springframework.context.ApplicationContext;
@ -150,11 +151,12 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr @@ -150,11 +151,12 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
}
Class<?> domainType = targetType.getType();
RepositoryInformation info = repositories.getRepositoryInformationFor(domainType);
RepositoryInvoker invoker = repositoryInvokerFactory.getInvokerFor(domainType);
return invoker.invokeFindOne(conversionService.convert(source, info.getIdType()));
return repositories.getRepositoryInformationFor(domainType)//
.map(it -> invoker.invokeFindOne(conversionService.convert(source, it.getIdType())))//
.orElseThrow(() -> new IllegalStateException(
String.format("Couldn't find RepositoryInformation for %s!", domainType)));
}
/*
@ -168,14 +170,22 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr @@ -168,14 +170,22 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
return false;
}
if (!repositories.hasRepositoryFor(targetType.getType())) {
Class<?> domainType = targetType.getType();
if (!repositories.hasRepositoryFor(domainType)) {
return false;
}
Class<?> rawIdType = repositories.getRepositoryInformationFor(targetType.getType()).getIdType();
Optional<RepositoryInformation> repositoryInformation = repositories.getRepositoryInformationFor(domainType);
return repositoryInformation.map(it -> {
Class<?> rawIdType = it.getIdType();
return sourceType.equals(TypeDescriptor.valueOf(rawIdType))
|| conversionService.canConvert(sourceType.getType(), rawIdType);
return sourceType.equals(TypeDescriptor.valueOf(rawIdType))
|| conversionService.canConvert(sourceType.getType(), rawIdType);
}).orElseThrow(
() -> new IllegalStateException(String.format("Couldn't find RepositoryInformation for %s!", domainType)));
}
}
@ -229,14 +239,23 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr @@ -229,14 +239,23 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
return false;
}
if (!repositories.hasRepositoryFor(sourceType.getType())) {
Class<?> domainType = sourceType.getType();
if (!repositories.hasRepositoryFor(domainType)) {
return false;
}
Class<?> rawIdType = repositories.getRepositoryInformationFor(sourceType.getType()).getIdType();
Optional<RepositoryInformation> information = repositories.getRepositoryInformationFor(domainType);
return information.map(it -> {
Class<?> rawIdType = it.getIdType();
return targetType.equals(TypeDescriptor.valueOf(rawIdType))
|| conversionService.canConvert(rawIdType, targetType.getType());
return targetType.equals(TypeDescriptor.valueOf(rawIdType))
|| conversionService.canConvert(rawIdType, targetType.getType());
}).orElseThrow(
() -> new IllegalStateException(String.format("Couldn't find RepositoryInformation for %s!", domainType)));
}
}
}

72
src/main/java/org/springframework/data/repository/support/MethodParameters.java

@ -19,10 +19,13 @@ import java.lang.annotation.Annotation; @@ -19,10 +19,13 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.data.util.Lazy;
import org.springframework.util.Assert;
/**
@ -42,7 +45,7 @@ class MethodParameters { @@ -42,7 +45,7 @@ class MethodParameters {
* @param method must not be {@literal null}.
*/
public MethodParameters(Method method) {
this(method, null);
this(method, Optional.empty());
}
/**
@ -50,12 +53,12 @@ class MethodParameters { @@ -50,12 +53,12 @@ class MethodParameters {
* is given, method parameter names will be looked up from the annotation attribute if present.
*
* @param method must not be {@literal null}.
* @param namingAnnotation can be {@literal null}.
* @param namingAnnotation must not be {@literal null}.
*/
public MethodParameters(Method method, AnnotationAttribute namingAnnotation) {
public MethodParameters(Method method, Optional<AnnotationAttribute> namingAnnotation) {
Assert.notNull(method, "Method must not be null!");
this.parameters = new ArrayList<MethodParameter>();
this.parameters = new ArrayList<>();
for (int i = 0; i < method.getParameterTypes().length; i++) {
@ -80,17 +83,12 @@ class MethodParameters { @@ -80,17 +83,12 @@ class MethodParameters {
* @param name must not be {@literal null} or empty.
* @return
*/
public MethodParameter getParameter(String name) {
public Optional<MethodParameter> getParameter(String name) {
Assert.hasText(name, "Parameter name must not be null!");
for (MethodParameter parameter : parameters) {
if (name.equals(parameter.getParameterName())) {
return parameter;
}
}
return null;
return getParameters().stream()//
.filter(it -> name.equals(it.getParameterName())).findFirst();
}
/**
@ -103,15 +101,10 @@ class MethodParameters { @@ -103,15 +101,10 @@ class MethodParameters {
public List<MethodParameter> getParametersOfType(Class<?> type) {
Assert.notNull(type, "Type must not be null!");
List<MethodParameter> result = new ArrayList<MethodParameter>();
for (MethodParameter parameter : getParameters()) {
if (parameter.getParameterType().equals(type)) {
result.add(parameter);
}
}
return result;
return getParameters().stream()//
.filter(it -> it.getParameterType().equals(type))//
.collect(Collectors.toList());
}
/**
@ -123,15 +116,10 @@ class MethodParameters { @@ -123,15 +116,10 @@ class MethodParameters {
public List<MethodParameter> getParametersWith(Class<? extends Annotation> annotation) {
Assert.notNull(annotation, "Annotation must not be null!");
List<MethodParameter> result = new ArrayList<MethodParameter>();
for (MethodParameter parameter : getParameters()) {
if (parameter.hasParameterAnnotation(annotation)) {
result.add(parameter);
}
}
return result;
return getParameters().stream()//
.filter(it -> it.hasParameterAnnotation(annotation))//
.collect(Collectors.toList());
}
/**
@ -142,8 +130,8 @@ class MethodParameters { @@ -142,8 +130,8 @@ class MethodParameters {
*/
private static class AnnotationNamingMethodParameter extends MethodParameter {
private final AnnotationAttribute attribute;
private String name;
private final Optional<AnnotationAttribute> attribute;
private final Lazy<String> name;
/**
* Creates a new {@link AnnotationNamingMethodParameter} for the given {@link Method}'s parameter with the given
@ -153,11 +141,17 @@ class MethodParameters { @@ -153,11 +141,17 @@ class MethodParameters {
* @param parameterIndex
* @param attribute can be {@literal null}
*/
public AnnotationNamingMethodParameter(Method method, int parameterIndex, AnnotationAttribute attribute) {
public AnnotationNamingMethodParameter(Method method, int parameterIndex, Optional<AnnotationAttribute> attribute) {
super(method, parameterIndex);
this.attribute = attribute;
this.name = Lazy.of(() -> {
return this.attribute.//
flatMap(it -> it.getValueFrom(this).map(Object::toString)).//
orElseGet(() -> super.getParameterName());
});
}
/*
@ -166,21 +160,7 @@ class MethodParameters { @@ -166,21 +160,7 @@ class MethodParameters {
*/
@Override
public String getParameterName() {
if (name != null) {
return name;
}
if (attribute != null) {
Object foundName = attribute.getValueFrom(this);
if (foundName != null) {
name = foundName.toString();
return name;
}
}
name = super.getParameterName();
return name;
return name.get();
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save