Browse Source

DATACMNS-1114 - Introduced usage of nullable annotations for API validation.

Marked all packages with Spring Frameworks @NonNullApi. Added Spring's @Nullable to methods, parameters and fields that take or produce null values. Adapted using code to make sure the IDE can evaluate the null flow properly. Fixed Javadoc in places where an invalid null handling policy was advertised. Strengthened null requirements for types that expose null-instances.

Removed null handling from converters for JodaTime and ThreeTenBP. Introduced factory methods Page.empty() and Page.empty(Pageable). Introduced default methods getRequiredGetter(), …Setter() and …Field() on PersistentProperty to allow non-nullable lookups of members. The same for TypeInformation.getrequiredActualType(), …SuperTypeInformation().

Tweaked PersistentPropertyCreator.addPropertiesForRemainingDescriptors() to filter unsuitable PropertyDescriptors before actually trying to create a Property instance from them as the new stronger nullability requirements would cause exceptions downstream.

Lazy.get() now expects a non-null return value. Clients being able to cope with null need to call ….orElse(…).

Original pull request: #232.
pull/234/head
Oliver Gierke 9 years ago
parent
commit
049970874d
  1. 1
      pom.xml
  2. 3
      src/main/java/org/springframework/data/annotation/package-info.java
  3. 2
      src/main/java/org/springframework/data/auditing/AuditingHandler.java
  4. 7
      src/main/java/org/springframework/data/auditing/DefaultAuditableBeanWrapperFactory.java
  5. 11
      src/main/java/org/springframework/data/auditing/config/AnnotationAuditingConfiguration.java
  6. 4
      src/main/java/org/springframework/data/auditing/config/AuditingHandlerBeanDefinitionParser.java
  7. 5
      src/main/java/org/springframework/data/auditing/config/package-info.java
  8. 3
      src/main/java/org/springframework/data/auditing/package-info.java
  9. 15
      src/main/java/org/springframework/data/authentication/UserCredentials.java
  10. 3
      src/main/java/org/springframework/data/authentication/package-info.java
  11. 104
      src/main/java/org/springframework/data/config/ConfigurationUtils.java
  12. 3
      src/main/java/org/springframework/data/config/ParsingUtils.java
  13. 17
      src/main/java/org/springframework/data/config/TypeFilterParser.java
  14. 3
      src/main/java/org/springframework/data/config/package-info.java
  15. 5
      src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java
  16. 3
      src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java
  17. 15
      src/main/java/org/springframework/data/convert/CustomConversions.java
  18. 7
      src/main/java/org/springframework/data/convert/DefaultConverterBuilder.java
  19. 9
      src/main/java/org/springframework/data/convert/DefaultTypeMapper.java
  20. 47
      src/main/java/org/springframework/data/convert/JodaTimeConverters.java
  21. 32
      src/main/java/org/springframework/data/convert/Jsr310Converters.java
  22. 2
      src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java
  23. 2
      src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java
  24. 32
      src/main/java/org/springframework/data/convert/ThreeTenBackPortConverters.java
  25. 7
      src/main/java/org/springframework/data/convert/TypeInformationMapper.java
  26. 4
      src/main/java/org/springframework/data/convert/TypeMapper.java
  27. 3
      src/main/java/org/springframework/data/convert/package-info.java
  28. 4
      src/main/java/org/springframework/data/crossstore/ChangeSet.java
  29. 12
      src/main/java/org/springframework/data/crossstore/HashMapChangeSet.java
  30. 3
      src/main/java/org/springframework/data/crossstore/package-info.java
  31. 4
      src/main/java/org/springframework/data/domain/AbstractPageRequest.java
  32. 3
      src/main/java/org/springframework/data/domain/Chunk.java
  33. 16
      src/main/java/org/springframework/data/domain/ExampleMatcher.java
  34. 22
      src/main/java/org/springframework/data/domain/Page.java
  35. 4
      src/main/java/org/springframework/data/domain/PageImpl.java
  36. 3
      src/main/java/org/springframework/data/domain/PageRequest.java
  37. 4
      src/main/java/org/springframework/data/domain/SliceImpl.java
  38. 23
      src/main/java/org/springframework/data/domain/Sort.java
  39. 24
      src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java
  40. 7
      src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java
  41. 19
      src/main/java/org/springframework/data/domain/jaxb/PageableAdapter.java
  42. 8
      src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java
  43. 9
      src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java
  44. 8
      src/main/java/org/springframework/data/domain/jaxb/package-info.java
  45. 5
      src/main/java/org/springframework/data/domain/package-info.java
  46. 3
      src/main/java/org/springframework/data/geo/Box.java
  47. 38
      src/main/java/org/springframework/data/geo/Circle.java
  48. 79
      src/main/java/org/springframework/data/geo/Distance.java
  49. 20
      src/main/java/org/springframework/data/geo/GeoPage.java
  50. 78
      src/main/java/org/springframework/data/geo/GeoResult.java
  51. 56
      src/main/java/org/springframework/data/geo/GeoResults.java
  52. 3
      src/main/java/org/springframework/data/geo/Point.java
  53. 32
      src/main/java/org/springframework/data/geo/Polygon.java
  54. 4
      src/main/java/org/springframework/data/geo/format/DistanceFormatter.java
  55. 6
      src/main/java/org/springframework/data/geo/format/PointFormatter.java
  56. 8
      src/main/java/org/springframework/data/geo/format/package-info.java
  57. 3
      src/main/java/org/springframework/data/geo/package-info.java
  58. 9
      src/main/java/org/springframework/data/history/Revision.java
  59. 7
      src/main/java/org/springframework/data/history/RevisionSort.java
  60. 4
      src/main/java/org/springframework/data/history/package-info.java
  61. 8
      src/main/java/org/springframework/data/mapping/Alias.java
  62. 3
      src/main/java/org/springframework/data/mapping/IdentifierAccessor.java
  63. 9
      src/main/java/org/springframework/data/mapping/MappingException.java
  64. 7
      src/main/java/org/springframework/data/mapping/PersistentEntity.java
  65. 45
      src/main/java/org/springframework/data/mapping/PersistentProperty.java
  66. 7
      src/main/java/org/springframework/data/mapping/PersistentPropertyAccessor.java
  67. 17
      src/main/java/org/springframework/data/mapping/PreferredConstructor.java
  68. 50
      src/main/java/org/springframework/data/mapping/PropertyPath.java
  69. 2
      src/main/java/org/springframework/data/mapping/PropertyReferenceException.java
  70. 35
      src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java
  71. 86
      src/main/java/org/springframework/data/mapping/context/DefaultPersistentPropertyPath.java
  72. 5
      src/main/java/org/springframework/data/mapping/context/InvalidPersistentPropertyPath.java
  73. 6
      src/main/java/org/springframework/data/mapping/context/MappingContext.java
  74. 6
      src/main/java/org/springframework/data/mapping/context/MappingContextIsNewStrategyFactory.java
  75. 19
      src/main/java/org/springframework/data/mapping/context/PersistentPropertyPath.java
  76. 3
      src/main/java/org/springframework/data/mapping/context/package-info.java
  77. 52
      src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java
  78. 6
      src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java
  79. 50
      src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java
  80. 31
      src/main/java/org/springframework/data/mapping/model/BeanWrapper.java
  81. 19
      src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java
  82. 8
      src/main/java/org/springframework/data/mapping/model/ConvertingPropertyAccessor.java
  83. 22
      src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java
  84. 2
      src/main/java/org/springframework/data/mapping/model/IdPropertyIdentifierAccessor.java
  85. 9
      src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java
  86. 2
      src/main/java/org/springframework/data/mapping/model/ParameterValueProvider.java
  87. 46
      src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java
  88. 8
      src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java
  89. 101
      src/main/java/org/springframework/data/mapping/model/Property.java
  90. 16
      src/main/java/org/springframework/data/mapping/model/SpELContext.java
  91. 5
      src/main/java/org/springframework/data/mapping/model/SpELExpressionEvaluator.java
  92. 37
      src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java
  93. 3
      src/main/java/org/springframework/data/mapping/model/package-info.java
  94. 3
      src/main/java/org/springframework/data/mapping/package-info.java
  95. 10
      src/main/java/org/springframework/data/projection/Accessor.java
  96. 5
      src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java
  97. 7
      src/main/java/org/springframework/data/projection/MapAccessingMethodInterceptor.java
  98. 7
      src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java
  99. 16
      src/main/java/org/springframework/data/projection/ProjectionFactory.java
  100. 4
      src/main/java/org/springframework/data/projection/PropertyAccessingMethodInterceptor.java
  101. Some files were not shown because too many files have changed in this diff Show More

1
pom.xml

@ -293,7 +293,6 @@ @@ -293,7 +293,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>enforce-rules</id>

3
src/main/java/org/springframework/data/annotation/package-info.java

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/**
* Core annotations being used by Spring Data.
*/
package org.springframework.data.annotation;
@org.springframework.lang.NonNullApi
package org.springframework.data.annotation;

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

@ -226,7 +226,7 @@ public class AuditingHandler implements InitializingBean { @@ -226,7 +226,7 @@ public class AuditingHandler implements InitializingBean {
*/
public void afterPropertiesSet() {
if (auditorAware == null) {
if (!auditorAware.isPresent()) {
LOGGER.debug("No AuditorAware set! Auditing will not be applied!");
}
}

7
src/main/java/org/springframework/data/auditing/DefaultAuditableBeanWrapperFactory.java

@ -34,6 +34,7 @@ import org.springframework.data.convert.ThreeTenBackPortConverters; @@ -34,6 +34,7 @@ import org.springframework.data.convert.ThreeTenBackPortConverters;
import org.springframework.data.domain.Auditable;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -88,7 +89,7 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory @@ -88,7 +89,7 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
this.auditable = auditable;
this.type = (Class<? extends TemporalAccessor>) ResolvableType.forClass(Auditable.class, auditable.getClass())
.getGeneric(2).getRawClass();
.getGeneric(2).resolve(TemporalAccessor.class);
}
/*
@ -183,6 +184,7 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory @@ -183,6 +184,7 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
* @param source must not be {@literal null}.
* @return
*/
@Nullable
protected Object getDateValueToSet(TemporalAccessor value, Class<?> targetType, Object source) {
if (TemporalAccessor.class.equals(targetType)) {
@ -213,6 +215,7 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory @@ -213,6 +215,7 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
* Returns the given object as {@link Calendar}.
*
* @param source can be {@literal null}.
* @param target must not be {@literal null}.
* @return
*/
@SuppressWarnings("unchecked")
@ -299,7 +302,7 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory @@ -299,7 +302,7 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
return getAsTemporalAccessor(metadata.getLastModifiedDateField().map(field -> {
Object value = org.springframework.util.ReflectionUtils.getField(field, target);
return Optional.class.isInstance(value) ? ((Optional<?>) value).orElse(null) : value;
return value instanceof Optional ? ((Optional<?>) value).orElse(null) : value;
}), TemporalAccessor.class);
}

11
src/main/java/org/springframework/data/auditing/config/AnnotationAuditingConfiguration.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.auditing.config;
import java.lang.annotation.Annotation;
import java.util.Map;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
@ -30,6 +31,8 @@ import org.springframework.util.Assert; @@ -30,6 +31,8 @@ import org.springframework.util.Assert;
*/
public class AnnotationAuditingConfiguration implements AuditingConfiguration {
private static final String MISSING_ANNOTATION_ATTRIBUTES = "Couldn't find annotation attributes for %s in %s!";
private final AnnotationAttributes attributes;
/**
@ -44,7 +47,13 @@ public class AnnotationAuditingConfiguration implements AuditingConfiguration { @@ -44,7 +47,13 @@ public class AnnotationAuditingConfiguration implements AuditingConfiguration {
Assert.notNull(metadata, "AnnotationMetadata must not be null!");
Assert.notNull(annotation, "Annotation must not be null!");
this.attributes = new AnnotationAttributes(metadata.getAnnotationAttributes(annotation.getName()));
Map<String, Object> attributesSource = metadata.getAnnotationAttributes(annotation.getName());
if (attributesSource == null) {
throw new IllegalArgumentException(String.format(MISSING_ANNOTATION_ATTRIBUTES, annotation, metadata));
}
this.attributes = new AnnotationAttributes(attributesSource);
}
/*

4
src/main/java/org/springframework/data/auditing/config/AuditingHandlerBeanDefinitionParser.java

@ -17,6 +17,8 @@ package org.springframework.data.auditing.config; @@ -17,6 +17,8 @@ package org.springframework.data.auditing.config;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import javax.annotation.Nonnull;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.target.LazyInitTargetSource;
import org.springframework.beans.factory.config.BeanDefinition;
@ -51,6 +53,7 @@ public class AuditingHandlerBeanDefinitionParser extends AbstractSingleBeanDefin @@ -51,6 +53,7 @@ public class AuditingHandlerBeanDefinitionParser extends AbstractSingleBeanDefin
*
* @param mappingContextBeanName must not be {@literal null} or empty.
*/
@SuppressWarnings("null")
public AuditingHandlerBeanDefinitionParser(String mappingContextBeanName) {
Assert.hasText(mappingContextBeanName, "MappingContext bean name must not be null!");
@ -70,6 +73,7 @@ public class AuditingHandlerBeanDefinitionParser extends AbstractSingleBeanDefin @@ -70,6 +73,7 @@ public class AuditingHandlerBeanDefinitionParser extends AbstractSingleBeanDefin
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
*/
@Nonnull
@Override
protected Class<?> getBeanClass(Element element) {
return AuditingHandler.class;

5
src/main/java/org/springframework/data/auditing/config/package-info.java

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
/**
* Types to abstract authentication concepts.
*/
@org.springframework.lang.NonNullApi
package org.springframework.data.auditing.config;

3
src/main/java/org/springframework/data/auditing/package-info.java

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/**
* General support for entity auditing.
*/
package org.springframework.data.auditing;
@org.springframework.lang.NonNullApi
package org.springframework.data.auditing;

15
src/main/java/org/springframework/data/authentication/UserCredentials.java

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
*/
package org.springframework.data.authentication;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@ -28,8 +29,7 @@ public class UserCredentials { @@ -28,8 +29,7 @@ public class UserCredentials {
public static final UserCredentials NO_CREDENTIALS = new UserCredentials(null, null);
private final String username;
private final String password;
private final @Nullable String username, password;
/**
* Creates a new {@link UserCredentials} instance from the given username and password. Empty {@link String}s provided
@ -38,7 +38,7 @@ public class UserCredentials { @@ -38,7 +38,7 @@ public class UserCredentials {
* @param username
* @param password
*/
public UserCredentials(String username, String password) {
public UserCredentials(@Nullable String username, @Nullable String password) {
this.username = StringUtils.hasText(username) ? username : null;
this.password = StringUtils.hasText(password) ? password : null;
}
@ -48,6 +48,7 @@ public class UserCredentials { @@ -48,6 +48,7 @@ public class UserCredentials {
*
* @return the username
*/
@Nullable
public String getUsername() {
return username;
}
@ -57,6 +58,7 @@ public class UserCredentials { @@ -57,6 +58,7 @@ public class UserCredentials {
*
* @return the password
*/
@Nullable
public String getPassword() {
return password;
}
@ -85,9 +87,12 @@ public class UserCredentials { @@ -85,9 +87,12 @@ public class UserCredentials {
*
* @return the obfuscated password
*/
@Nullable
public String getObfuscatedPassword() {
if (!hasPassword()) {
String password = this.password;
if (password == null) {
return null;
}
@ -125,7 +130,7 @@ public class UserCredentials { @@ -125,7 +130,7 @@ public class UserCredentials {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;

3
src/main/java/org/springframework/data/authentication/package-info.java

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/**
* Types to abstract authentication concepts.
*/
package org.springframework.data.authentication;
@org.springframework.lang.NonNullApi
package org.springframework.data.authentication;

104
src/main/java/org/springframework/data/config/ConfigurationUtils.java

@ -0,0 +1,104 @@ @@ -0,0 +1,104 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
/**
* Helper class to centralize common functionality that needs to be used in various places of the configuration
* implementation.
*
* @author Oliver Gierke
* @since 2.0
* @soundtrack Richard Spaven - The Self (feat. Jordan Rakei)
*/
public interface ConfigurationUtils {
/**
* Returns the {@link ResourceLoader} from the given {@link XmlReaderContext}.
*
* @param context must not be {@literal null}.
* @return
* @throws IllegalArgumentException if no {@link ResourceLoader} can be obtained from the {@link XmlReaderContext}.
*/
public static ResourceLoader getRequiredResourceLoader(XmlReaderContext context) {
Assert.notNull(context, "XmlReaderContext must not be null!");
ResourceLoader resourceLoader = context.getResourceLoader();
if (resourceLoader == null) {
throw new IllegalArgumentException("Could not obtain ResourceLoader from XmlReaderContext!");
}
return resourceLoader;
}
/**
* Returns the {@link ClassLoader} used by the given {@link XmlReaderContext}.
*
* @param context must not be {@literal null}.
* @return
* @throws IllegalArgumentException if no {@link ClassLoader} can be obtained from the given {@link XmlReaderContext}.
*/
public static ClassLoader getRequiredClassLoader(XmlReaderContext context) {
return getRequiredClassLoader(getRequiredResourceLoader(context));
}
/**
* Returns the {@link ClassLoader} used by the given {@link ResourceLoader}.
*
* @param resourceLoader must not be {@literal null}.
* @return
* @throws IllegalArgumentException if the given {@link ResourceLoader} does not expose a {@link ClassLoader}.
*/
public static ClassLoader getRequiredClassLoader(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
ClassLoader classLoader = resourceLoader.getClassLoader();
if (classLoader == null) {
throw new IllegalArgumentException("Could not obtain ClassLoader from ResourceLoader!");
}
return classLoader;
}
/**
* Returns the bean class name of the given {@link BeanDefinition}.
*
* @param beanDefinition must not be {@literal null}.
* @return
* @throws IllegalArgumentException if the given {@link BeanDefinition} does not contain a bean class name.
*/
public static String getRequiredBeanClassName(BeanDefinition beanDefinition) {
Assert.notNull(beanDefinition, "BeanDefinition must not be null!");
String result = beanDefinition.getBeanClassName();
if (result == null) {
throw new IllegalArgumentException(
String.format("Could not obtain required bean class name from BeanDefinition!", beanDefinition));
}
return result;
}
}

3
src/main/java/org/springframework/data/config/ParsingUtils.java

@ -21,6 +21,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; @@ -21,6 +21,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@ -120,7 +121,7 @@ public abstract class ParsingUtils { @@ -120,7 +121,7 @@ public abstract class ParsingUtils {
* @param source
* @return
*/
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, Object source) {
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, @Nullable Object source) {
Assert.notNull(builder, "Builder must not be null!");

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

@ -30,6 +30,7 @@ import org.springframework.core.type.filter.AspectJTypeFilter; @@ -30,6 +30,7 @@ import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@ -55,7 +56,7 @@ public class TypeFilterParser { @@ -55,7 +56,7 @@ public class TypeFilterParser {
* @param readerContext must not be {@literal null}.
*/
public TypeFilterParser(XmlReaderContext readerContext) {
this(readerContext, readerContext.getResourceLoader().getClassLoader());
this(readerContext, ConfigurationUtils.getRequiredClassLoader(readerContext));
}
/**
@ -92,13 +93,14 @@ public class TypeFilterParser { @@ -92,13 +93,14 @@ public class TypeFilterParser {
Node node = nodeList.item(i);
Element childElement = type.getElement(node);
if (childElement != null) {
if (childElement == null) {
continue;
}
try {
filters.add(createTypeFilter(childElement, classLoader));
} catch (RuntimeException e) {
readerContext.error(e.getMessage(), readerContext.extractSource(element), e.getCause());
}
try {
filters.add(createTypeFilter(childElement, classLoader));
} catch (RuntimeException e) {
readerContext.error(e.getMessage(), readerContext.extractSource(element), e.getCause());
}
}
@ -224,6 +226,7 @@ public class TypeFilterParser { @@ -224,6 +226,7 @@ public class TypeFilterParser {
* @param node
* @return
*/
@Nullable
Element getElement(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {

3
src/main/java/org/springframework/data/config/package-info.java

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/**
* Basic support for creating custom Spring namespaces and JavaConfig.
*/
package org.springframework.data.config;
@org.springframework.lang.NonNullApi
package org.springframework.data.config;

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

@ -38,6 +38,7 @@ import org.springframework.data.mapping.PreferredConstructor.Parameter; @@ -38,6 +38,7 @@ import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.data.mapping.model.MappingInstantiationException;
import org.springframework.data.mapping.model.ParameterValueProvider;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -213,7 +214,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { @@ -213,7 +214,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
* @return
*/
private <P extends PersistentProperty<P>, T> Object[] extractInvocationArguments(
PreferredConstructor<? extends T, P> constructor, ParameterValueProvider<P> provider) {
@Nullable PreferredConstructor<? extends T, P> constructor, ParameterValueProvider<P> provider) {
if (provider == null || constructor == null || !constructor.hasParameters()) {
return EMPTY_ARRAY;
@ -484,7 +485,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { @@ -484,7 +485,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
*/
private class ByteArrayClassLoader extends ClassLoader {
public ByteArrayClassLoader(ClassLoader parent) {
public ByteArrayClassLoader(@Nullable ClassLoader parent) {
super(parent);
}

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

@ -19,6 +19,8 @@ import java.util.HashMap; @@ -19,6 +19,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
@ -77,6 +79,7 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper @@ -77,6 +79,7 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(org.springframework.data.mapping.Alias)
*/
@Nullable
@Override
public TypeInformation<?> resolveTypeFrom(Alias alias) {
return aliasToType.get(alias);

15
src/main/java/org/springframework/data/convert/CustomConversions.java

@ -561,8 +561,11 @@ public class CustomConversions { @@ -561,8 +561,11 @@ public class CustomConversions {
} else if (converter instanceof GenericConverter) {
return Streamable.of(GenericConverter.class.cast(converter).getConvertibleTypes())//
.map(it -> register(it, isReading, isWriting));
Set<ConvertiblePair> convertibleTypes = GenericConverter.class.cast(converter).getConvertibleTypes();
return convertibleTypes == null //
? Streamable.empty() //
: Streamable.of(convertibleTypes).map(it -> register(it, isReading, isWriting));
} else if (converter instanceof ConverterFactory) {
@ -580,7 +583,13 @@ public class CustomConversions { @@ -580,7 +583,13 @@ public class CustomConversions {
private Streamable<ConverterRegistration> getRegistrationFor(Object converter, Class<?> type, boolean isReading,
boolean isWriting) {
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), type);
Class<? extends Object> converterType = converter.getClass();
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converterType, type);
if (arguments == null) {
throw new IllegalStateException(String.format("Couldn't resolve type arguments for %s!", converterType));
}
return Streamable.of(register(arguments[0], arguments[1], isReading, isWriting));
}

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

@ -27,6 +27,8 @@ import java.util.Set; @@ -27,6 +27,8 @@ import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.GenericConverter;
@ -35,6 +37,7 @@ import org.springframework.data.convert.ConverterBuilder.ConverterAware; @@ -35,6 +37,7 @@ import org.springframework.data.convert.ConverterBuilder.ConverterAware;
import org.springframework.data.convert.ConverterBuilder.ReadingConverterBuilder;
import org.springframework.data.convert.ConverterBuilder.WritingConverterBuilder;
import org.springframework.data.util.Optionals;
import org.springframework.lang.Nullable;
/**
* Builder to easily set up (bi-directional) {@link Converter} instances for Spring Data type mapping using Lambdas. Use
@ -128,9 +131,10 @@ class DefaultConverterBuilder<S, T> @@ -128,9 +131,10 @@ class DefaultConverterBuilder<S, T>
* (non-Javadoc)
* @see org.springframework.core.convert.converter.GenericConverter#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
*/
@Nullable
@Override
@SuppressWarnings("unchecked")
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
return function.apply((S) source);
}
@ -138,6 +142,7 @@ class DefaultConverterBuilder<S, T> @@ -138,6 +142,7 @@ class DefaultConverterBuilder<S, T>
* (non-Javadoc)
* @see org.springframework.core.convert.converter.GenericConverter#getConvertibleTypes()
*/
@Nonnull
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(convertiblePair);

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

@ -28,6 +28,7 @@ import org.springframework.data.mapping.PersistentEntity; @@ -28,6 +28,7 @@ import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -77,7 +78,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -77,7 +78,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* @param additionalMappers must not be {@literal null}.
*/
public DefaultTypeMapper(TypeAliasAccessor<S> accessor,
MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext,
@Nullable MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext,
List<? extends TypeInformationMapper> additionalMappers) {
Assert.notNull(accessor, "Accessor must not be null!");
@ -109,6 +110,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -109,6 +110,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* (non-Javadoc)
* @see org.springframework.data.convert.TypeMapper#readType(java.lang.Object)
*/
@Nullable
public TypeInformation<?> readType(S source) {
Assert.notNull(source, "Source object must not be null!");
@ -123,6 +125,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -123,6 +125,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* @param alias
* @return
*/
@Nullable
private TypeInformation<?> getFromCacheOrCreate(Alias alias) {
return typeCache.computeIfAbsent(alias, getAlias).orElse(null);
}
@ -153,7 +156,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -153,7 +156,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
ClassTypeInformation<?> targetType = ClassTypeInformation.from(documentsTargetType);
return (TypeInformation<? extends T>) (basicType != null ? basicType.specialize(targetType) : targetType);
return (TypeInformation<? extends T>) basicType.specialize(targetType);
}
/**
@ -163,6 +166,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -163,6 +166,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* @param source
* @return
*/
@Nullable
private Class<?> getDefaultedTypeToBeUsed(S source) {
TypeInformation<?> documentsTargetTypeInformation = readType(source);
@ -177,6 +181,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> { @@ -177,6 +181,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S> {
* @param source will never be {@literal null}.
* @return
*/
@Nullable
protected TypeInformation<?> getFallbackTypeFor(S source) {
return null;
}

47
src/main/java/org/springframework/data/convert/JodaTimeConverters.java

@ -22,6 +22,8 @@ import java.util.Collections; @@ -22,6 +22,8 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.annotation.Nonnull;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
@ -72,9 +74,10 @@ public abstract class JodaTimeConverters { @@ -72,9 +74,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
@Nonnull
@Override
public java.time.LocalDateTime convert(LocalDateTime source) {
return source == null ? null : java.time.LocalDateTime.ofInstant(source.toDate().toInstant(), ZoneId.of("UTC"));
return java.time.LocalDateTime.ofInstant(source.toDate().toInstant(), ZoneId.of("UTC"));
}
}
@ -82,8 +85,10 @@ public abstract class JodaTimeConverters { @@ -82,8 +85,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
@Nonnull
@Override
public Date convert(LocalDate source) {
return source == null ? null : source.toDate();
return source.toDate();
}
}
@ -91,8 +96,10 @@ public abstract class JodaTimeConverters { @@ -91,8 +96,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
@Nonnull
@Override
public Date convert(LocalDateTime source) {
return source == null ? null : source.toDate();
return source.toDate();
}
}
@ -100,8 +107,10 @@ public abstract class JodaTimeConverters { @@ -100,8 +107,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
@Nonnull
@Override
public Date convert(DateTime source) {
return source == null ? null : source.toDate();
return source.toDate();
}
}
@ -109,8 +118,10 @@ public abstract class JodaTimeConverters { @@ -109,8 +118,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
@Nonnull
@Override
public LocalDate convert(Date source) {
return source == null ? null : new LocalDate(source.getTime());
return new LocalDate(source.getTime());
}
}
@ -118,8 +129,10 @@ public abstract class JodaTimeConverters { @@ -118,8 +129,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
@Nonnull
@Override
public LocalDateTime convert(Date source) {
return source == null ? null : new LocalDateTime(source.getTime());
return new LocalDateTime(source.getTime());
}
}
@ -127,8 +140,10 @@ public abstract class JodaTimeConverters { @@ -127,8 +140,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
@Nonnull
@Override
public DateTime convert(Date source) {
return source == null ? null : new DateTime(source.getTime());
return new DateTime(source.getTime());
}
}
@ -136,15 +151,10 @@ public abstract class JodaTimeConverters { @@ -136,15 +151,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Nonnull
@Override
public LocalDateTime convert(java.time.LocalDateTime source) {
return source == null ? null
: LocalDateTime.fromDateFields(
org.springframework.data.convert.Jsr310Converters.LocalDateTimeToDateConverter.INSTANCE.convert(source));
return LocalDateTime.fromDateFields(Jsr310Converters.LocalDateTimeToDateConverter.INSTANCE.convert(source));
}
}
@ -152,15 +162,10 @@ public abstract class JodaTimeConverters { @@ -152,15 +162,10 @@ public abstract class JodaTimeConverters {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Nonnull
@Override
public DateTime convert(java.time.LocalDateTime source) {
return source == null ? null
: new DateTime(
org.springframework.data.convert.Jsr310Converters.LocalDateTimeToDateConverter.INSTANCE.convert(source));
return new DateTime(Jsr310Converters.LocalDateTimeToDateConverter.INSTANCE.convert(source));
}
}
}

32
src/main/java/org/springframework/data/convert/Jsr310Converters.java

@ -33,6 +33,8 @@ import java.util.Collections; @@ -33,6 +33,8 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.annotation.Nonnull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.ClassUtils;
@ -92,9 +94,10 @@ public abstract class Jsr310Converters { @@ -92,9 +94,10 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public LocalDateTime convert(Date source) {
return source == null ? null : ofInstant(source.toInstant(), systemDefault());
return ofInstant(source.toInstant(), systemDefault());
}
}
@ -102,9 +105,10 @@ public abstract class Jsr310Converters { @@ -102,9 +105,10 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public Date convert(LocalDateTime source) {
return source == null ? null : Date.from(source.atZone(systemDefault()).toInstant());
return Date.from(source.atZone(systemDefault()).toInstant());
}
}
@ -112,9 +116,10 @@ public abstract class Jsr310Converters { @@ -112,9 +116,10 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public LocalDate convert(Date source) {
return source == null ? null : ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalDate();
return ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalDate();
}
}
@ -122,9 +127,10 @@ public abstract class Jsr310Converters { @@ -122,9 +127,10 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public Date convert(LocalDate source) {
return source == null ? null : Date.from(source.atStartOfDay(systemDefault()).toInstant());
return Date.from(source.atStartOfDay(systemDefault()).toInstant());
}
}
@ -132,9 +138,10 @@ public abstract class Jsr310Converters { @@ -132,9 +138,10 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public LocalTime convert(Date source) {
return source == null ? null : ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalTime();
return ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalTime();
}
}
@ -142,9 +149,10 @@ public abstract class Jsr310Converters { @@ -142,9 +149,10 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public Date convert(LocalTime source) {
return source == null ? null : Date.from(source.atDate(LocalDate.now()).atZone(systemDefault()).toInstant());
return Date.from(source.atDate(LocalDate.now()).atZone(systemDefault()).toInstant());
}
}
@ -152,9 +160,10 @@ public abstract class Jsr310Converters { @@ -152,9 +160,10 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public Instant convert(Date source) {
return source == null ? null : source.toInstant();
return source.toInstant();
}
}
@ -162,9 +171,10 @@ public abstract class Jsr310Converters { @@ -162,9 +171,10 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public Date convert(Instant source) {
return source == null ? null : Date.from(source.atZone(systemDefault()).toInstant());
return Date.from(source.atZone(systemDefault()).toInstant());
}
}
@ -173,6 +183,7 @@ public abstract class Jsr310Converters { @@ -173,6 +183,7 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public String convert(ZoneId source) {
return source.toString();
@ -184,6 +195,7 @@ public abstract class Jsr310Converters { @@ -184,6 +195,7 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public ZoneId convert(String source) {
return ZoneId.of(source);
@ -195,6 +207,7 @@ public abstract class Jsr310Converters { @@ -195,6 +207,7 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public String convert(Duration duration) {
return duration.toString();
@ -206,6 +219,7 @@ public abstract class Jsr310Converters { @@ -206,6 +219,7 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public Duration convert(String s) {
return Duration.parse(s);
@ -217,6 +231,7 @@ public abstract class Jsr310Converters { @@ -217,6 +231,7 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public String convert(Period period) {
return period.toString();
@ -228,6 +243,7 @@ public abstract class Jsr310Converters { @@ -228,6 +243,7 @@ public abstract class Jsr310Converters {
INSTANCE;
@Nonnull
@Override
public Period convert(String s) {
return Period.parse(s);

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

@ -24,6 +24,7 @@ import org.springframework.data.mapping.PersistentEntity; @@ -24,6 +24,7 @@ import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -115,6 +116,7 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe @@ -115,6 +116,7 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.util.Optional)
*/
@Nullable
@Override
public TypeInformation<?> resolveTypeFrom(Alias alias) {

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

@ -22,6 +22,7 @@ import java.util.concurrent.ConcurrentHashMap; @@ -22,6 +22,7 @@ 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.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@ -45,6 +46,7 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper { @@ -45,6 +46,7 @@ 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.
*/
@Nullable
@Override
public TypeInformation<?> resolveTypeFrom(Alias alias) {

32
src/main/java/org/springframework/data/convert/ThreeTenBackPortConverters.java

@ -27,6 +27,8 @@ import java.util.Collections; @@ -27,6 +27,8 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.annotation.Nonnull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.ClassUtils;
import org.threeten.bp.Instant;
@ -95,12 +97,13 @@ public abstract class ThreeTenBackPortConverters { @@ -95,12 +97,13 @@ public abstract class ThreeTenBackPortConverters {
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Nonnull
@Override
public java.time.LocalDateTime convert(LocalDateTime source) {
Date date = toDate(source.atZone(ZoneId.systemDefault()).toInstant());
return source == null ? null : Jsr310Converters.DateToLocalDateTimeConverter.INSTANCE.convert(date);
return Jsr310Converters.DateToLocalDateTimeConverter.INSTANCE.convert(date);
}
}
@ -108,10 +111,10 @@ public abstract class ThreeTenBackPortConverters { @@ -108,10 +111,10 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public LocalDateTime convert(Date source) {
return source == null ? null : ofInstant(toInstant(source), systemDefault());
return ofInstant(toInstant(source), systemDefault());
}
}
@ -119,9 +122,10 @@ public abstract class ThreeTenBackPortConverters { @@ -119,9 +122,10 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public Date convert(LocalDateTime source) {
return source == null ? null : toDate(source.atZone(systemDefault()).toInstant());
return toDate(source.atZone(systemDefault()).toInstant());
}
}
@ -129,9 +133,10 @@ public abstract class ThreeTenBackPortConverters { @@ -129,9 +133,10 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public LocalDate convert(Date source) {
return source == null ? null : ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalDate();
return ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalDate();
}
}
@ -139,9 +144,10 @@ public abstract class ThreeTenBackPortConverters { @@ -139,9 +144,10 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public Date convert(LocalDate source) {
return source == null ? null : toDate(source.atStartOfDay(systemDefault()).toInstant());
return toDate(source.atStartOfDay(systemDefault()).toInstant());
}
}
@ -149,9 +155,10 @@ public abstract class ThreeTenBackPortConverters { @@ -149,9 +155,10 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public LocalTime convert(Date source) {
return source == null ? null : ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalTime();
return ofInstant(ofEpochMilli(source.getTime()), systemDefault()).toLocalTime();
}
}
@ -159,9 +166,10 @@ public abstract class ThreeTenBackPortConverters { @@ -159,9 +166,10 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public Date convert(LocalTime source) {
return source == null ? null : toDate(source.atDate(LocalDate.now()).atZone(systemDefault()).toInstant());
return toDate(source.atDate(LocalDate.now()).atZone(systemDefault()).toInstant());
}
}
@ -169,9 +177,10 @@ public abstract class ThreeTenBackPortConverters { @@ -169,9 +177,10 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public Instant convert(Date source) {
return source == null ? null : toInstant(source);
return toInstant(source);
}
}
@ -179,9 +188,10 @@ public abstract class ThreeTenBackPortConverters { @@ -179,9 +188,10 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public Date convert(Instant source) {
return source == null ? null : toDate(source.atZone(systemDefault()).toInstant());
return toDate(source.atZone(systemDefault()).toInstant());
}
}
@ -190,6 +200,7 @@ public abstract class ThreeTenBackPortConverters { @@ -190,6 +200,7 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public String convert(ZoneId source) {
return source.toString();
@ -201,6 +212,7 @@ public abstract class ThreeTenBackPortConverters { @@ -201,6 +212,7 @@ public abstract class ThreeTenBackPortConverters {
INSTANCE;
@Nonnull
@Override
public ZoneId convert(String source) {
return ZoneId.of(source);

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

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.convert;
import javax.annotation.Nullable;
import org.springframework.data.mapping.Alias;
import org.springframework.data.util.TypeInformation;
@ -28,15 +30,16 @@ public interface TypeInformationMapper { @@ -28,15 +30,16 @@ public interface TypeInformationMapper {
/**
* Returns the actual {@link TypeInformation} to be used for the given alias.
*
* @param alias can be {@literal null}.
* @param alias must not be {@literal null}.
* @return
*/
@Nullable
TypeInformation<?> resolveTypeFrom(Alias alias);
/**
* Returns the alias to be used for the given {@link TypeInformation}.
*
* @param type
* @param type must not be {@literal null}.
* @return
*/
Alias createAliasFor(TypeInformation<?> type);

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

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.convert;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
/**
* Interface to define strategies how to store type information in a store specific sink or source.
@ -30,13 +31,14 @@ public interface TypeMapper<S> { @@ -30,13 +31,14 @@ public interface TypeMapper<S> {
* @param source must not be {@literal null}.
* @return
*/
@Nullable
TypeInformation<?> readType(S source);
/**
* Returns the {@link TypeInformation} from the given source if it is a more concrete type than the given default one.
*
* @param source must not be {@literal null}.
* @param defaultType
* @param defaultType must not be {@literal null}.
* @return
*/
<T> TypeInformation<? extends T> readType(S source, TypeInformation<T> defaultType);

3
src/main/java/org/springframework/data/convert/package-info.java

@ -3,4 +3,5 @@ @@ -3,4 +3,5 @@
*
* @see org.springframework.data.convert.EntityConverter
*/
package org.springframework.data.convert;
@org.springframework.lang.NonNullApi
package org.springframework.data.convert;

4
src/main/java/org/springframework/data/crossstore/ChangeSet.java

@ -17,6 +17,8 @@ package org.springframework.data.crossstore; @@ -17,6 +17,8 @@ package org.springframework.data.crossstore;
import java.util.Map;
import javax.annotation.Nullable;
import org.springframework.core.convert.ConversionService;
/**
@ -27,12 +29,14 @@ import org.springframework.core.convert.ConversionService; @@ -27,12 +29,14 @@ import org.springframework.core.convert.ConversionService;
*/
public interface ChangeSet {
@Nullable
<T> T get(String key, Class<T> requiredClass, ConversionService cs);
void set(String key, Object o);
Map<String, Object> getValues();
@Nullable
Object removeProperty(String k);
}

12
src/main/java/org/springframework/data/crossstore/HashMapChangeSet.java

@ -20,6 +20,7 @@ import java.util.HashMap; @@ -20,6 +20,7 @@ import java.util.HashMap;
import java.util.Map;
import org.springframework.core.convert.ConversionService;
import org.springframework.lang.Nullable;
/**
* Simple ChangeSet implementation backed by a HashMap.
@ -52,12 +53,21 @@ public class HashMapChangeSet implements ChangeSet { @@ -52,12 +53,21 @@ public class HashMapChangeSet implements ChangeSet {
return Collections.unmodifiableMap(values);
}
@Nullable
public Object removeProperty(String k) {
return this.values.remove(k);
}
@Nullable
public <T> T get(String key, Class<T> requiredClass, ConversionService conversionService) {
return conversionService.convert(values.get(key), requiredClass);
Object value = values.get(key);
if (value == null) {
return null;
}
return conversionService.convert(value, requiredClass);
}
}

3
src/main/java/org/springframework/data/crossstore/package-info.java

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/**
* Support for cross-store persistence.
*/
package org.springframework.data.crossstore;
@org.springframework.lang.NonNullApi
package org.springframework.data.crossstore;

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

@ -17,6 +17,8 @@ package org.springframework.data.domain; @@ -17,6 +17,8 @@ package org.springframework.data.domain;
import java.io.Serializable;
import org.springframework.lang.Nullable;
/**
* Abstract Java Bean implementation of {@code Pageable}.
*
@ -131,7 +133,7 @@ public abstract class AbstractPageRequest implements Pageable, Serializable { @@ -131,7 +133,7 @@ public abstract class AbstractPageRequest implements Pageable, Serializable {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

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

@ -25,6 +25,7 @@ import java.util.List; @@ -25,6 +25,7 @@ import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -171,7 +172,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable { @@ -171,7 +172,7 @@ abstract class Chunk<T> implements Slice<T>, Serializable {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

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

@ -32,6 +32,7 @@ import java.util.Optional; @@ -32,6 +32,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -201,9 +202,7 @@ public class ExampleMatcher { @@ -201,9 +202,7 @@ public class ExampleMatcher {
propertySpecifier = propertySpecifier.withStringMatcher(genericPropertyMatcher.stringMatcher);
}
if (genericPropertyMatcher.valueTransformer != null) {
propertySpecifier = propertySpecifier.withValueTransformer(genericPropertyMatcher.valueTransformer);
}
propertySpecifier = propertySpecifier.withValueTransformer(genericPropertyMatcher.valueTransformer);
propertySpecifiers.add(propertySpecifier);
@ -394,8 +393,8 @@ public class ExampleMatcher { @@ -394,8 +393,8 @@ public class ExampleMatcher {
@EqualsAndHashCode
public static class GenericPropertyMatcher {
StringMatcher stringMatcher = null;
Boolean ignoreCase = null;
@Nullable StringMatcher stringMatcher = null;
@Nullable Boolean ignoreCase = null;
PropertyValueTransformer valueTransformer = NoOpPropertyValueTransformer.INSTANCE;
/**
@ -697,6 +696,7 @@ public class ExampleMatcher { @@ -697,6 +696,7 @@ public class ExampleMatcher {
* @see java.util.function.Function#apply(java.lang.Object)
*/
@Override
@SuppressWarnings("null")
public Optional<Object> apply(Optional<Object> source) {
return source;
}
@ -715,8 +715,8 @@ public class ExampleMatcher { @@ -715,8 +715,8 @@ public class ExampleMatcher {
public static class PropertySpecifier {
String path;
StringMatcher stringMatcher;
Boolean ignoreCase;
@Nullable StringMatcher stringMatcher;
@Nullable Boolean ignoreCase;
PropertyValueTransformer valueTransformer;
/**
@ -785,6 +785,7 @@ public class ExampleMatcher { @@ -785,6 +785,7 @@ public class ExampleMatcher {
*
* @return can be {@literal null}.
*/
@Nullable
public StringMatcher getStringMatcher() {
return stringMatcher;
}
@ -792,6 +793,7 @@ public class ExampleMatcher { @@ -792,6 +793,7 @@ public class ExampleMatcher {
/**
* @return {@literal null} if not set.
*/
@Nullable
public Boolean getIgnoreCase() {
return ignoreCase;
}

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

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
*/
package org.springframework.data.domain;
import java.util.Collections;
import java.util.function.Function;
/**
@ -26,6 +27,27 @@ import java.util.function.Function; @@ -26,6 +27,27 @@ import java.util.function.Function;
*/
public interface Page<T> extends Slice<T> {
/**
* Creates a new empty {@link Page}.
*
* @return
* @since 2.0
*/
static <T> Page<T> empty() {
return empty(Pageable.unpaged());
}
/**
* Creates a new empty {@link Page} for the given {@link Pageable}.
*
* @param pageable must not be {@literal null}.
* @return
* @since 2.0
*/
static <T> Page<T> empty(Pageable pageable) {
return new PageImpl<>(Collections.emptyList(), pageable, 0);
}
/**
* Returns the number of total pages.
*

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

@ -18,6 +18,8 @@ package org.springframework.data.domain; @@ -18,6 +18,8 @@ package org.springframework.data.domain;
import java.util.List;
import java.util.function.Function;
import org.springframework.lang.Nullable;
/**
* Basic {@code Page} implementation.
*
@ -127,7 +129,7 @@ public class PageImpl<T> extends Chunk<T> implements Page<T> { @@ -127,7 +129,7 @@ public class PageImpl<T> extends Chunk<T> implements Page<T> {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

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

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.domain;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.lang.Nullable;
/**
* Basic Java Bean implementation of {@code Pageable}.
@ -145,7 +146,7 @@ public class PageRequest extends AbstractPageRequest { @@ -145,7 +146,7 @@ public class PageRequest extends AbstractPageRequest {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

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

@ -18,6 +18,8 @@ package org.springframework.data.domain; @@ -18,6 +18,8 @@ package org.springframework.data.domain;
import java.util.List;
import java.util.function.Function;
import org.springframework.lang.Nullable;
/**
* Default implementation of {@link Slice}.
*
@ -95,7 +97,7 @@ public class SliceImpl<T> extends Chunk<T> { @@ -95,7 +97,7 @@ public class SliceImpl<T> extends Chunk<T> {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

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

@ -26,6 +26,7 @@ import java.util.Optional; @@ -26,6 +26,7 @@ import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.data.util.Streamable;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -212,9 +213,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -212,9 +213,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
*/
public Sort and(Sort sort) {
if (sort == null) {
return this;
}
Assert.notNull(sort, "Sort must not be null!");
ArrayList<Order> these = new ArrayList<>(this.orders);
@ -231,6 +230,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -231,6 +230,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
* @param property
* @return
*/
@Nullable
public Order getOrderFor(String property) {
for (Order order : this) {
@ -255,7 +255,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -255,7 +255,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
@ -400,6 +400,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -400,6 +400,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
private static final long serialVersionUID = 1522511010900108987L;
private static final boolean DEFAULT_IGNORE_CASE = false;
private static final NullHandling DEFAULT_NULL_HANDLING = NullHandling.NATIVE;
private final Direction direction;
private final String property;
@ -414,7 +415,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -414,7 +415,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
* @param property must not be {@literal null} or empty.
*/
public Order(Direction direction, String property) {
this(direction, property, DEFAULT_IGNORE_CASE, null);
this(direction, property, DEFAULT_IGNORE_CASE, DEFAULT_NULL_HANDLING);
}
/**
@ -423,7 +424,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -423,7 +424,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
*
* @param direction can be {@literal null}, will default to {@link Sort#DEFAULT_DIRECTION}
* @param property must not be {@literal null} or empty.
* @param nullHandling can be {@literal null}, will default to {@link NullHandling#NATIVE}.
* @param nullHandling must not be {@literal null}.
*/
public Order(Direction direction, String property, NullHandling nullHandlingHint) {
this(direction, property, DEFAULT_IGNORE_CASE, nullHandlingHint);
@ -460,7 +461,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -460,7 +461,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
* @since 2.0
*/
public static Order asc(String property) {
return new Order(Direction.ASC, property, null);
return new Order(Direction.ASC, property, DEFAULT_NULL_HANDLING);
}
/**
@ -471,7 +472,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -471,7 +472,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
* @since 2.0
*/
public static Order desc(String property) {
return new Order(Direction.DESC, property, null);
return new Order(Direction.DESC, property, DEFAULT_NULL_HANDLING);
}
/**
@ -481,7 +482,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -481,7 +482,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
* @param direction can be {@literal null}, will default to {@link Sort#DEFAULT_DIRECTION}
* @param property must not be {@literal null} or empty.
* @param ignoreCase true if sorting should be case insensitive. false if sorting should be case sensitive.
* @param nullHandling can be {@literal null}, will default to {@link NullHandling#NATIVE}.
* @param nullHandling must not be {@literal null}.
* @since 1.7
*/
private Order(Direction direction, String property, boolean ignoreCase, NullHandling nullHandling) {
@ -493,7 +494,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -493,7 +494,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
this.direction = direction == null ? DEFAULT_DIRECTION : direction;
this.property = property;
this.ignoreCase = ignoreCase;
this.nullHandling = nullHandling == null ? NullHandling.NATIVE : nullHandling;
this.nullHandling = nullHandling;
}
/**
@ -655,7 +656,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -655,7 +656,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

24
src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,8 +17,10 @@ package org.springframework.data.domain.jaxb; @@ -17,8 +17,10 @@ package org.springframework.data.domain.jaxb;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.domain.jaxb.SpringDataJaxb.OrderDto;
import org.springframework.lang.Nullable;
/**
* XmlAdapter to convert {@link Order} instances into {@link OrderDto}s and vice versa.
@ -33,8 +35,9 @@ public class OrderAdapter extends XmlAdapter<OrderDto, Order> { @@ -33,8 +35,9 @@ public class OrderAdapter extends XmlAdapter<OrderDto, Order> {
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Nullable
@Override
public OrderDto marshal(Order order) {
public OrderDto marshal(@Nullable Order order) {
if (order == null) {
return null;
@ -50,8 +53,21 @@ public class OrderAdapter extends XmlAdapter<OrderDto, Order> { @@ -50,8 +53,21 @@ public class OrderAdapter extends XmlAdapter<OrderDto, Order> {
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Nullable
@Override
public Order unmarshal(OrderDto source) {
return source == null ? null : new Order(source.direction, source.property);
public Order unmarshal(@Nullable OrderDto source) {
if (source == null) {
return null;
}
Direction direction = source.direction;
String property = source.property;
if (direction == null || property == null) {
return null;
}
return new Order(direction, property);
}
}

7
src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java

@ -23,6 +23,7 @@ import javax.xml.bind.annotation.adapters.XmlAdapter; @@ -23,6 +23,7 @@ import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.jaxb.SpringDataJaxb.PageDto;
import org.springframework.hateoas.Link;
import org.springframework.lang.Nullable;
/**
* {@link XmlAdapter} to convert {@link Page} instances into {@link PageDto} instances and vice versa.
@ -35,8 +36,9 @@ public class PageAdapter extends XmlAdapter<PageDto, Page<Object>> { @@ -35,8 +36,9 @@ public class PageAdapter extends XmlAdapter<PageDto, Page<Object>> {
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Nullable
@Override
public PageDto marshal(Page<Object> source) {
public PageDto marshal(@Nullable Page<Object> source) {
if (source == null) {
return null;
@ -53,8 +55,9 @@ public class PageAdapter extends XmlAdapter<PageDto, Page<Object>> { @@ -53,8 +55,9 @@ public class PageAdapter extends XmlAdapter<PageDto, Page<Object>> {
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Nullable
@Override
public Page<Object> unmarshal(PageDto v) {
public Page<Object> unmarshal(@Nullable PageDto v) {
return null;
}

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

@ -17,13 +17,14 @@ package org.springframework.data.domain.jaxb; @@ -17,13 +17,14 @@ package org.springframework.data.domain.jaxb;
import java.util.Collections;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.jaxb.SpringDataJaxb.OrderDto;
import org.springframework.data.domain.jaxb.SpringDataJaxb.PageRequestDto;
import org.springframework.data.domain.jaxb.SpringDataJaxb.SortDto;
import org.springframework.lang.Nullable;
/**
* {@link XmlAdapter} to convert {@link Pageable} instances int a {@link PageRequestDto} and vice versa.
@ -37,12 +38,17 @@ class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> { @@ -37,12 +38,17 @@ class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> {
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Nullable
@Override
public PageRequestDto marshal(Pageable request) {
public PageRequestDto marshal(@Nullable Pageable request) {
SortDto sortDto = SortAdapter.INSTANCE.marshal(request.getSort());
if (request == null) {
return null;
}
PageRequestDto dto = new PageRequestDto();
SortDto sortDto = SortAdapter.INSTANCE.marshal(request.getSort());
dto.orders = sortDto == null ? Collections.emptyList() : sortDto.orders;
dto.page = request.getPageNumber();
dto.size = request.getPageSize();
@ -54,8 +60,13 @@ class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> { @@ -54,8 +60,13 @@ class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> {
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Nonnull
@Override
public Pageable unmarshal(PageRequestDto v) {
public Pageable unmarshal(@Nullable PageRequestDto v) {
if (v == null) {
return Pageable.unpaged();
}
if (v.orders.isEmpty()) {
return PageRequest.of(v.page, v.size);

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

@ -15,10 +15,12 @@ @@ -15,10 +15,12 @@
*/
package org.springframework.data.domain.jaxb;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.jaxb.SpringDataJaxb.SortDto;
import org.springframework.lang.Nullable;
/**
* {@link XmlAdapter} to convert {@link Sort} instances into {@link SortDto} instances and vice versa.
@ -33,8 +35,9 @@ public class SortAdapter extends XmlAdapter<SortDto, Sort> { @@ -33,8 +35,9 @@ public class SortAdapter extends XmlAdapter<SortDto, Sort> {
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Nullable
@Override
public SortDto marshal(Sort source) {
public SortDto marshal(@Nullable Sort source) {
if (source == null) {
return null;
@ -50,8 +53,9 @@ public class SortAdapter extends XmlAdapter<SortDto, Sort> { @@ -50,8 +53,9 @@ public class SortAdapter extends XmlAdapter<SortDto, Sort> {
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Nonnull
@Override
public Sort unmarshal(SortDto source) {
public Sort unmarshal(@Nullable SortDto source) {
return source == null ? Sort.unsorted() : Sort.by(SpringDataJaxb.unmarshal(source.orders, OrderAdapter.INSTANCE));
}
}

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

@ -36,6 +36,7 @@ import org.springframework.data.domain.Sort; @@ -36,6 +36,7 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -84,8 +85,8 @@ public abstract class SpringDataJaxb { @@ -84,8 +85,8 @@ public abstract class SpringDataJaxb {
@XmlAccessorType(XmlAccessType.FIELD)
public static class OrderDto {
@XmlAttribute String property;
@XmlAttribute Direction direction;
@Nullable @XmlAttribute String property;
@Nullable @XmlAttribute Direction direction;
}
/**
@ -97,7 +98,7 @@ public abstract class SpringDataJaxb { @@ -97,7 +98,7 @@ public abstract class SpringDataJaxb {
@XmlAccessorType(XmlAccessType.FIELD)
public static class PageDto extends ResourceSupport {
@XmlAnyElement @XmlElementWrapper(name = "content") List<Object> content;
@Nullable @XmlAnyElement @XmlElementWrapper(name = "content") List<Object> content;
}
/**
@ -136,7 +137,7 @@ public abstract class SpringDataJaxb { @@ -136,7 +137,7 @@ public abstract class SpringDataJaxb {
* @return
* @throws Exception
*/
public static <T, S> List<S> marshal(Iterable<T> source, XmlAdapter<S, T> adapter) {
public static <T, S> List<S> marshal(@Nullable Iterable<T> source, XmlAdapter<S, T> adapter) {
Assert.notNull(adapter, "Adapter must not be null!");

8
src/main/java/org/springframework/data/domain/jaxb/package-info.java

@ -1,13 +1,16 @@ @@ -1,13 +1,16 @@
/**
* Central domain abstractions especially to be used in combination with the {@link org.springframework.data.repository.Repository} abstraction.
* Central domain abstractions especially to be used in combination with the
* {@link org.springframework.data.repository.Repository} abstraction.
*
* @see org.springframework.data.repository.Repository
*/
@XmlSchema(xmlns = { @XmlNs(prefix = "sd", namespaceURI = org.springframework.data.domain.jaxb.SpringDataJaxb.NAMESPACE) })
@XmlSchema(
xmlns = { @XmlNs(prefix = "sd", namespaceURI = org.springframework.data.domain.jaxb.SpringDataJaxb.NAMESPACE) })
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.PageableAdapter.class, type = Pageable.class),
@XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.SortAdapter.class, type = Sort.class),
@XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.PageAdapter.class, type = Page.class) })
@org.springframework.lang.NonNullApi
package org.springframework.data.domain.jaxb;
import javax.xml.bind.annotation.XmlNs;
@ -18,4 +21,3 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; @@ -18,4 +21,3 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

5
src/main/java/org/springframework/data/domain/package-info.java

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
/**
* Central domain abstractions especially to be used in combination with the {@link org.springframework.data.repository.Repository} abstraction.
* Central domain abstractions especially to be used in combination with the
* {@link org.springframework.data.repository.Repository} abstraction.
*
* @see org.springframework.data.repository.Repository
*/
@org.springframework.lang.NonNullApi
package org.springframework.data.domain;

3
src/main/java/org/springframework/data/geo/Box.java

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
*/
package org.springframework.data.geo;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -109,7 +110,7 @@ public class Box implements Shape { @@ -109,7 +110,7 @@ public class Box implements Shape {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

38
src/main/java/org/springframework/data/geo/Circle.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.geo;
import lombok.EqualsAndHashCode;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.util.Assert;
@ -26,6 +28,7 @@ import org.springframework.util.Assert; @@ -26,6 +28,7 @@ import org.springframework.util.Assert;
* @author Thomas Darimont
* @since 1.8
*/
@EqualsAndHashCode
public class Circle implements Shape {
private static final long serialVersionUID = 5215611530535947924L;
@ -98,39 +101,4 @@ public class Circle implements Shape { @@ -98,39 +101,4 @@ public class Circle implements Shape {
public String toString() {
return String.format("Circle: [center=%s, radius=%s]", center, radius);
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Circle)) {
return false;
}
Circle that = (Circle) obj;
return this.center.equals(that.center) && this.radius.equals(that.radius);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result += 31 * center.hashCode();
result += 31 * radius.hashCode();
return result;
}
}

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

@ -15,9 +15,13 @@ @@ -15,9 +15,13 @@
*/
package org.springframework.data.geo;
import lombok.Value;
import java.io.Serializable;
import org.springframework.data.domain.Range;
import org.springframework.data.domain.Range.Bound;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -27,11 +31,19 @@ import org.springframework.util.Assert; @@ -27,11 +31,19 @@ import org.springframework.util.Assert;
* @author Thomas Darimont
* @since 1.8
*/
@Value
public class Distance implements Serializable, Comparable<Distance> {
private static final long serialVersionUID = 2460886201934027744L;
/**
* The distance value in the current {@link Metric}.
*/
private final double value;
/**
* The {@link Metric} of the {@link Distance}.
*/
private final Metric metric;
/**
@ -47,12 +59,14 @@ public class Distance implements Serializable, Comparable<Distance> { @@ -47,12 +59,14 @@ public class Distance implements Serializable, Comparable<Distance> {
* Creates a new {@link Distance} with the given {@link Metric}.
*
* @param value
* @param metric can be {@literal null}.
* @param metric must not be {@literal null}.
*/
public Distance(double value, Metric metric) {
Assert.notNull(metric, "Metric must not be null!");
this.value = value;
this.metric = metric == null ? Metrics.NEUTRAL : metric;
this.metric = metric;
}
/**
@ -63,7 +77,7 @@ public class Distance implements Serializable, Comparable<Distance> { @@ -63,7 +77,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<>(min, max);
return Range.from(Bound.inclusive(min)).to(Bound.inclusive(max));
}
/**
@ -79,15 +93,6 @@ public class Distance implements Serializable, Comparable<Distance> { @@ -79,15 +93,6 @@ public class Distance implements Serializable, Comparable<Distance> {
return between(new Distance(minValue, minMetric), new Distance(maxValue, maxMetric));
}
/**
* Returns the distance value in the current {@link Metric}.
*
* @return the value
*/
public double getValue() {
return value;
}
/**
* Returns the normalized value regarding the underlying {@link Metric}.
*
@ -97,15 +102,6 @@ public class Distance implements Serializable, Comparable<Distance> { @@ -97,15 +102,6 @@ public class Distance implements Serializable, Comparable<Distance> {
return value / metric.getMultiplier();
}
/**
* Returns the {@link Metric} of the {@link Distance}.
*
* @return the metric
*/
public Metric getMetric() {
return metric;
}
/**
* Returns a {@link String} representation of the unit the distance is in.
*
@ -160,6 +156,7 @@ public class Distance implements Serializable, Comparable<Distance> { @@ -160,6 +156,7 @@ public class Distance implements Serializable, Comparable<Distance> {
public Distance in(Metric metric) {
Assert.notNull(metric, "Metric must not be null!");
return this.metric.equals(metric) ? this : new Distance(getNormalizedValue() * metric.getMultiplier(), metric);
}
@ -168,49 +165,19 @@ public class Distance implements Serializable, Comparable<Distance> { @@ -168,49 +165,19 @@ public class Distance implements Serializable, Comparable<Distance> {
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(Distance o) {
public int compareTo(@Nullable Distance that) {
double difference = this.getNormalizedValue() - o.getNormalizedValue();
return difference == 0 ? 0 : difference > 0 ? 1 : -1;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
if (that == null) {
return 1;
}
if (!(obj instanceof Distance)) {
return false;
}
double difference = this.getNormalizedValue() - that.getNormalizedValue();
Distance that = (Distance) obj;
return this.value == that.value && this.metric.equals(that.metric);
return difference == 0 ? 0 : difference > 0 ? 1 : -1;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result += 31 * Double.doubleToLongBits(value);
result += 31 * metric.hashCode();
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override

20
src/main/java/org/springframework/data/geo/GeoPage.java

@ -15,9 +15,12 @@ @@ -15,9 +15,12 @@
*/
package org.springframework.data.geo;
import lombok.Getter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@ -31,7 +34,11 @@ import org.springframework.util.ObjectUtils; @@ -31,7 +34,11 @@ import org.springframework.util.ObjectUtils;
public class GeoPage<T> extends PageImpl<GeoResult<T>> {
private static final long serialVersionUID = -5655267379242128600L;
private final Distance averageDistance;
/**
* The average distance of the underlying results.
*/
private final @Getter Distance averageDistance;
/**
* Creates a new {@link GeoPage} from the given {@link GeoResults}.
@ -59,21 +66,12 @@ public class GeoPage<T> extends PageImpl<GeoResult<T>> { @@ -59,21 +66,12 @@ public class GeoPage<T> extends PageImpl<GeoResult<T>> {
this.averageDistance = results.getAverageDistance();
}
/**
* Returns the average distance of the underlying results.
*
* @return the averageDistance
*/
public Distance getAverageDistance() {
return averageDistance;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.PageImpl#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

78
src/main/java/org/springframework/data/geo/GeoResult.java

@ -15,9 +15,10 @@ @@ -15,9 +15,10 @@
*/
package org.springframework.data.geo;
import java.io.Serializable;
import lombok.NonNull;
import lombok.Value;
import org.springframework.util.Assert;
import java.io.Serializable;
/**
* Value object capturing some arbitrary object plus a distance.
@ -26,80 +27,13 @@ import org.springframework.util.Assert; @@ -26,80 +27,13 @@ import org.springframework.util.Assert;
* @author Thomas Darimont
* @since 1.8
*/
@Value
public class GeoResult<T> implements Serializable {
private static final long serialVersionUID = 1637452570977581370L;
private final T content;
private final Distance distance;
/**
* Creates a new {@link GeoResult} for the given content and distance.
*
* @param content must not be {@literal null}.
* @param distance must not be {@literal null}.
*/
public GeoResult(T content, Distance distance) {
Assert.notNull(content, "Content must not be null!");
Assert.notNull(distance, "Distance must not be null!");
this.content = content;
this.distance = distance;
}
/**
* Returns the actual content object.
*
* @return the content
*/
public T getContent() {
return content;
}
/**
* Returns the distance the actual content object has from the origin.
*
* @return the distance
*/
public Distance getDistance() {
return distance;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof GeoResult)) {
return false;
}
GeoResult<?> that = (GeoResult<?>) obj;
return this.content.equals(that.content) && this.distance.equals(that.distance);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result += 31 * distance.hashCode();
result += 31 * content.hashCode();
return result;
}
@NonNull T content;
@NonNull Distance distance;
/*
* (non-Javadoc)

56
src/main/java/org/springframework/data/geo/GeoResults.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.geo;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Collections;
import java.util.Iterator;
@ -31,6 +33,7 @@ import org.springframework.util.StringUtils; @@ -31,6 +33,7 @@ import org.springframework.util.StringUtils;
* @author Thomas Darimont
* @since 1.8
*/
@EqualsAndHashCode
public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
private static final long serialVersionUID = 8347363491300219485L;
@ -45,7 +48,7 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable { @@ -45,7 +48,7 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
* @param results must not be {@literal null}.
*/
public GeoResults(List<? extends GeoResult<T>> results) {
this(results, (Metric) null);
this(results, Metrics.NEUTRAL);
}
/**
@ -63,12 +66,13 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable { @@ -63,12 +66,13 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
* Creates a new {@link GeoResults} instance from the given {@link GeoResult}s and average distance.
*
* @param results must not be {@literal null}.
* @param averageDistance can be {@literal null}.
* @param averageDistance must not be {@literal null}.
*/
@PersistenceConstructor
public GeoResults(List<? extends GeoResult<T>> results, Distance averageDistance) {
Assert.notNull(results, "Results must not be null!");
Assert.notNull(averageDistance, "Average Distance must not be null!");
this.results = results;
this.averageDistance = averageDistance;
@ -101,41 +105,6 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable { @@ -101,41 +105,6 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
return (Iterator<GeoResult<T>>) results.iterator();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof GeoResults)) {
return false;
}
GeoResults<?> that = (GeoResults<?>) obj;
return this.results.equals(that.results) && this.averageDistance.equals(that.averageDistance);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result += 31 * results.hashCode();
result += 31 * averageDistance.hashCode();
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
@ -148,16 +117,17 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable { @@ -148,16 +117,17 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
private static Distance calculateAverageDistance(List<? extends GeoResult<?>> results, Metric metric) {
Assert.notNull(results, "Results must not be null!");
Assert.notNull(metric, "Metric must not be null!");
if (results.isEmpty()) {
return new Distance(0, metric);
}
double averageDistance = 0;
for (GeoResult<?> result : results) {
averageDistance += result.getDistance().getValue();
}
double averageDistance = results.stream()//
.mapToDouble(it -> it.getDistance().getValue())//
.average().orElse(0);
return new Distance(averageDistance / results.size(), metric);
return new Distance(averageDistance, metric);
}
}

3
src/main/java/org/springframework/data/geo/Point.java

@ -19,6 +19,7 @@ import java.io.Serializable; @@ -19,6 +19,7 @@ import java.io.Serializable;
import java.util.Locale;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -102,7 +103,7 @@ public class Point implements Serializable { @@ -102,7 +103,7 @@ public class Point implements Serializable {
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

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

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.geo;
import lombok.EqualsAndHashCode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -32,6 +34,7 @@ import org.springframework.util.StringUtils; @@ -32,6 +34,7 @@ import org.springframework.util.StringUtils;
* @author Thomas Darimont
* @since 1.8
*/
@EqualsAndHashCode
public class Polygon implements Iterable<Point>, Shape {
private static final long serialVersionUID = -2705040068154648988L;
@ -98,35 +101,6 @@ public class Polygon implements Iterable<Point>, Shape { @@ -98,35 +101,6 @@ public class Polygon implements Iterable<Point>, Shape {
return this.points.iterator();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Polygon)) {
return false;
}
Polygon that = (Polygon) obj;
return this.points.equals(that.points);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return points.hashCode();
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()

4
src/main/java/org/springframework/data/geo/format/DistanceFormatter.java

@ -27,6 +27,7 @@ import org.springframework.data.geo.Distance; @@ -27,6 +27,7 @@ import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metric;
import org.springframework.data.geo.Metrics;
import org.springframework.format.Formatter;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
@ -60,6 +61,7 @@ public enum DistanceFormatter implements Converter<String, Distance>, Formatter< @@ -60,6 +61,7 @@ public enum DistanceFormatter implements Converter<String, Distance>, Formatter<
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Nullable
@Override
public final Distance convert(String source) {
return source == null ? null : doConvert(source.trim().toLowerCase(Locale.US));
@ -80,7 +82,7 @@ public enum DistanceFormatter implements Converter<String, Distance>, Formatter< @@ -80,7 +82,7 @@ public enum DistanceFormatter implements Converter<String, Distance>, Formatter<
*/
@Override
public Distance parse(String text, Locale locale) throws ParseException {
return !StringUtils.hasText(text) ? null : doConvert(text.trim().toLowerCase(locale));
return doConvert(text.trim().toLowerCase(locale));
}
/**

6
src/main/java/org/springframework/data/geo/format/PointFormatter.java

@ -18,11 +18,12 @@ package org.springframework.data.geo.format; @@ -18,11 +18,12 @@ package org.springframework.data.geo.format;
import java.text.ParseException;
import java.util.Locale;
import javax.annotation.Nonnull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
import org.springframework.data.geo.Point;
import org.springframework.format.Formatter;
import org.springframework.util.StringUtils;
/**
* Converter to parse two comma-separated doubles into a {@link Point}.
@ -41,6 +42,7 @@ public enum PointFormatter implements Converter<String, Point>, Formatter<Point> @@ -41,6 +42,7 @@ public enum PointFormatter implements Converter<String, Point>, Formatter<Point>
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Nonnull
@Override
public Point convert(String source) {
@ -77,6 +79,6 @@ public enum PointFormatter implements Converter<String, Point>, Formatter<Point> @@ -77,6 +79,6 @@ public enum PointFormatter implements Converter<String, Point>, Formatter<Point>
*/
@Override
public Point parse(String text, Locale locale) throws ParseException {
return !StringUtils.hasText(text) ? null : convert(text);
return convert(text);
}
}

8
src/main/java/org/springframework/data/geo/format/package-info.java

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
/**
* Formatters for geo-spatial types.
*
* @author Oliver Gierke
* @since 1.8
*/
@org.springframework.lang.NonNullApi
package org.springframework.data.geo.format;

3
src/main/java/org/springframework/data/geo/package-info.java

@ -5,4 +5,5 @@ @@ -5,4 +5,5 @@
* @author Oliver Gierke
* @since 1.8
*/
package org.springframework.data.geo;
@org.springframework.lang.NonNullApi
package org.springframework.data.geo;

9
src/main/java/org/springframework/data/history/Revision.java

@ -25,6 +25,8 @@ import lombok.Value; @@ -25,6 +25,8 @@ import lombok.Value;
import java.time.LocalDateTime;
import java.util.Optional;
import org.springframework.lang.Nullable;
/**
* Wrapper to contain {@link RevisionMetadata} as well as the revisioned entity.
*
@ -97,7 +99,12 @@ public final class Revision<N extends Number & Comparable<N>, T> implements Comp @@ -97,7 +99,12 @@ public final class Revision<N extends Number & Comparable<N>, T> implements Comp
* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(Revision<N, ?> that) {
public int compareTo(@Nullable Revision<N, ?> that) {
if (that == null) {
return 1;
}
return mapIfAllPresent(getRevisionNumber(), that.getRevisionNumber(), //
(left, right) -> left.compareTo(right)).orElse(-1);
}

7
src/main/java/org/springframework/data/history/RevisionSort.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.history;
import org.springframework.data.domain.Sort;
import org.springframework.util.Assert;
/**
* A dedicated {@link Sort} implementation that allows the definition of the ordering of revisions independently of the
@ -66,14 +67,12 @@ public class RevisionSort extends Sort { @@ -66,14 +67,12 @@ public class RevisionSort extends Sort {
* Returns in which direction to sort revisions for the given {@link Sort} instance. Defaults to
* {@link Direction#ASC}.
*
* @param sort can be {@literal null}.
* @param sort must not be {@literal null}.
* @return
*/
public static Direction getRevisionDirection(Sort sort) {
if (sort == null) {
return Direction.ASC;
}
Assert.notNull(sort, "Sort must not be null!");
Order order = sort.getOrderFor(PROPERTY);
return order == null ? Direction.ASC : order.getDirection();

4
src/main/java/org/springframework/data/history/package-info.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/**
* Basic interfaces and value objects for historiography API.
* Basic interfaces and value objects for histography API.
*/
@org.springframework.lang.NonNullApi
package org.springframework.data.history;

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

@ -19,6 +19,7 @@ import lombok.AccessLevel; @@ -19,6 +19,7 @@ import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -41,6 +42,7 @@ public class Alias { @@ -41,6 +42,7 @@ public class Alias {
/**
* Common instance for {@code empty()}.
*/
@SuppressWarnings("null") //
public static final Alias NONE = new Alias(null);
private final Object value;
@ -65,7 +67,7 @@ public class Alias { @@ -65,7 +67,7 @@ public class Alias {
* @param alias may be {@literal null}.
* @return the {@link Alias} for {@code alias} or {@link #empty()} if the given alias was {@literal null}.
*/
public static Alias ofNullable(Object alias) {
public static Alias ofNullable(@Nullable Object alias) {
return alias == null ? NONE : new Alias(alias);
}
@ -124,6 +126,7 @@ public class Alias { @@ -124,6 +126,7 @@ public class Alias {
* @param type must not be {@literal null}.
* @return
*/
@Nullable
@SuppressWarnings("unchecked")
public <T> T mapTyped(Class<T> type) {
@ -132,7 +135,8 @@ public class Alias { @@ -132,7 +135,8 @@ public class Alias {
return isPresent() && type.isInstance(value) ? (T) value : null;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override

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

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.mapping;
import org.springframework.lang.Nullable;
/**
* Interface for a component allowing the access of identifier values.
*
@ -29,6 +31,7 @@ public interface IdentifierAccessor { @@ -29,6 +31,7 @@ public interface IdentifierAccessor {
*
* @return the identifier of the underlying instance.
*/
@Nullable
Object getIdentifier();
/**

9
src/main/java/org/springframework/data/mapping/MappingException.java

@ -15,21 +15,20 @@ @@ -15,21 +15,20 @@
*/
package org.springframework.data.mapping;
import org.springframework.lang.Nullable;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MappingException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
public MappingException(String s) {
public MappingException(@Nullable String s) {
super(s);
}
public MappingException(String s, Throwable throwable) {
public MappingException(@Nullable String s, @Nullable Throwable throwable) {
super(s, throwable);
}
}

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

@ -20,6 +20,7 @@ import java.util.Iterator; @@ -20,6 +20,7 @@ import java.util.Iterator;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
/**
* Represents a persistent entity.
@ -47,6 +48,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It @@ -47,6 +48,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It
* indicates that the instantiation of the object of that persistent entity is done through either a customer
* {@link EntityInstantiator} or handled by custom conversion mechanisms entirely.
*/
@Nullable
PreferredConstructor<T, P> getPersistenceConstructor();
/**
@ -81,6 +83,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It @@ -81,6 +83,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It
*
* @return the id property of the {@link PersistentEntity}.
*/
@Nullable
P getIdProperty();
/**
@ -107,6 +110,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It @@ -107,6 +110,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It
*
* @return the version property of the {@link PersistentEntity}.
*/
@Nullable
P getVersionProperty();
/**
@ -134,6 +138,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It @@ -134,6 +138,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It
* @param name The name of the property. Can be {@literal null}.
* @return the {@link PersistentProperty} or {@literal null} if it doesn't exist.
*/
@Nullable
P getPersistentProperty(String name);
/**
@ -161,6 +166,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It @@ -161,6 +166,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It
* @return {@literal null} if no property found with given annotation type.
* @since 1.8
*/
@Nullable
default P getPersistentProperty(Class<? extends Annotation> annotationType) {
Iterator<P> it = getPersistentProperties(annotationType).iterator();
@ -240,6 +246,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It @@ -240,6 +246,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> extends It
* @return {@literal null} if not found.
* @since 1.8
*/
@Nullable
<A extends Annotation> A findAnnotation(Class<A> annotationType);
/**

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

@ -23,6 +23,7 @@ import java.util.Map; @@ -23,6 +23,7 @@ import java.util.Map;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
/**
* @author Graeme Rocher
@ -75,26 +76,64 @@ public interface PersistentProperty<P extends PersistentProperty<P>> { @@ -75,26 +76,64 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
*
* @return the getter method to access the property value if available, otherwise {@literal null}.
*/
@Nullable
Method getGetter();
default Method getRequiredGetter() {
Method getter = getGetter();
if (getter == null) {
throw new IllegalArgumentException("No getter available for this persistent property!");
}
return getter;
}
/**
* Returns the setter method to set a property value. Might return {@literal null} in case there is no setter
* available.
*
* @return the setter method to set a property value if available, otherwise {@literal null}.
*/
@Nullable
Method getSetter();
default Method getRequiredSetter() {
Method setter = getSetter();
if (setter == null) {
throw new IllegalArgumentException("No setter available for this persistent property!");
}
return setter;
}
@Nullable
Field getField();
default Field getRequiredField() {
Field field = getField();
if (field == null) {
throw new IllegalArgumentException("No field backing this persistent property!");
}
return field;
}
/**
* @return {@literal null} if no expression defined.
*/
@Nullable
String getSpelExpression();
/**
* @return {@literal null} if property is not part of an {@link Association}.
*/
@Nullable
Association<P> getAssociation();
/**
@ -193,6 +232,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> { @@ -193,6 +232,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
* @return the component type, the map's key type or {@literal null} if neither {@link java.util.Collection} nor
* {@link java.util.Map}.
*/
@Nullable
Class<?> getComponentType();
/**
@ -207,6 +247,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> { @@ -207,6 +247,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
*
* @return the map's value type or {@literal null} if no {@link java.util.Map}
*/
@Nullable
Class<?> getMapValueType();
/**
@ -225,15 +266,17 @@ public interface PersistentProperty<P extends PersistentProperty<P>> { @@ -225,15 +266,17 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
* @return the annotation of the given type. Can be {@literal null}.
* @see AnnotationUtils#findAnnotation(Method, Class)
*/
@Nullable
<A extends Annotation> A findAnnotation(Class<A> annotationType);
/**
* Looks up the annotation of the given type on the property and the owning type if no annotation can be found on it.
* Usefull to lookup annotations that can be configured on the type but overridden on an individual property.
* Useful to lookup annotations that can be configured on the type but overridden on an individual property.
*
* @param annotationType must not be {@literal null}.
* @return the annotation of the given type. Can be {@literal null}.
*/
@Nullable
<A extends Annotation> A findPropertyOrOwnerAnnotation(Class<A> annotationType);
/**

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

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.data.mapping;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.lang.Nullable;
/**
* Domain service to allow accessing and setting {@link PersistentProperty}s of an entity. Usually obtained through
@ -35,10 +36,9 @@ public interface PersistentPropertyAccessor { @@ -35,10 +36,9 @@ public interface PersistentPropertyAccessor {
*
* @param property must not be {@literal null}.
* @param value can be {@literal null}.
* @throws MappingException in case an exception occurred when setting the
* property value.
* @throws MappingException in case an exception occurred when setting the property value.
*/
void setProperty(PersistentProperty<?> property, Object value);
void setProperty(PersistentProperty<?> property, @Nullable Object value);
/**
* Returns the value of the given {@link PersistentProperty} of the underlying bean instance.
@ -46,6 +46,7 @@ public interface PersistentPropertyAccessor { @@ -46,6 +46,7 @@ public interface PersistentPropertyAccessor {
* @param property must not be {@literal null}.
* @return can be {@literal null}.
*/
@Nullable
Object getProperty(PersistentProperty<?> property);
/**

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

@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Value; @@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
@ -188,17 +189,17 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> { @@ -188,17 +189,17 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
@EqualsAndHashCode(exclude = { "enclosingClassCache", "hasSpelExpression" })
public static class Parameter<T, P extends PersistentProperty<P>> {
private final String name;
private final @Nullable String name;
private final TypeInformation<T> type;
private final String key;
private final PersistentEntity<T, P> entity;
private final @Nullable PersistentEntity<T, P> entity;
private final Lazy<Boolean> enclosingClassCache;
private final Lazy<Boolean> hasSpelExpression;
/**
* Creates a new {@link Parameter} with the given name, {@link TypeInformation} as well as an array of
* {@link Annotation}s. Will insprect the annotations for an {@link Value} annotation to lookup a key or an SpEL
* {@link Annotation}s. Will inspect the annotations for an {@link Value} annotation to lookup a key or an SpEL
* expression to be evaluated.
*
* @param name the name of the parameter, can be {@literal null}
@ -206,7 +207,8 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> { @@ -206,7 +207,8 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
* @param annotations must not be {@literal null} but can be empty
* @param entity must not be {@literal null}.
*/
public Parameter(String name, TypeInformation<T> type, Annotation[] annotations, PersistentEntity<T, P> entity) {
public Parameter(@Nullable String name, TypeInformation<T> type, Annotation[] annotations,
@Nullable PersistentEntity<T, P> entity) {
Assert.notNull(type, "Type must not be null!");
Assert.notNull(annotations, "Annotations must not be null!");
@ -242,6 +244,7 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> { @@ -242,6 +244,7 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
*
* @return
*/
@Nullable
public String getName() {
return name;
}
@ -290,7 +293,11 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> { @@ -290,7 +293,11 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
*/
boolean maps(PersistentProperty<?> property) {
P referencedProperty = entity == null ? null : entity.getPersistentProperty(name);
PersistentEntity<T, P> entity = this.entity;
String name = this.name;
P referencedProperty = entity == null ? null : name == null ? null : entity.getPersistentProperty(name);
return property != null && property.equals(referencedProperty);
}

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

@ -31,6 +31,7 @@ import java.util.regex.Pattern; @@ -31,6 +31,7 @@ import java.util.regex.Pattern;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.StringUtils;
@ -57,7 +58,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -57,7 +58,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
private final TypeInformation<?> actualTypeInformation;
private final boolean isCollection;
private PropertyPath next;
private @Nullable PropertyPath next;
/**
* Creates a leaf {@link PropertyPath} (no nested ones) with the given name inside the given owning type.
@ -92,8 +93,9 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -92,8 +93,9 @@ public class PropertyPath implements Streamable<PropertyPath> {
this.owningType = owningType;
this.typeInformation = propertyType;
this.isCollection = propertyType.isCollectionLike();
this.actualTypeInformation = propertyType.getActualType();
this.name = propertyName;
this.actualTypeInformation = propertyType.getActualType() == null ? propertyType
: propertyType.getRequiredActualType();
}
/**
@ -124,7 +126,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -124,7 +126,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
PropertyPath result = this;
while (result.hasNext()) {
result = result.next();
result = result.requiredNext();
}
return result;
@ -146,6 +148,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -146,6 +148,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
* @return the next nested {@link PropertyPath} or {@literal null} if no nested {@link PropertyPath} available.
* @see #hasNext()
*/
@Nullable
public PropertyPath next() {
return next;
}
@ -168,7 +171,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -168,7 +171,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
public String toDotPath() {
if (hasNext()) {
return getSegment() + "." + next().toDotPath();
return getSegment() + "." + requiredNext().toDotPath();
}
return getSegment();
@ -188,17 +191,25 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -188,17 +191,25 @@ public class PropertyPath implements Streamable<PropertyPath> {
* @see java.lang.Iterable#iterator()
*/
public Iterator<PropertyPath> iterator() {
return new Iterator<PropertyPath>() {
private PropertyPath current = PropertyPath.this;
private @Nullable PropertyPath current = PropertyPath.this;
public boolean hasNext() {
return current != null;
}
@Nullable
public PropertyPath next() {
PropertyPath result = current;
this.current = current.next();
if (result == null) {
return null;
}
this.current = result.next();
return result;
}
@ -208,6 +219,24 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -208,6 +219,24 @@ public class PropertyPath implements Streamable<PropertyPath> {
};
}
/**
* Returns the next {@link PropertyPath}.
*
* @return
* @throws IllegalStateException it there's no next one.
*/
private PropertyPath requiredNext() {
PropertyPath result = next;
if (result == null) {
throw new IllegalStateException(
"No next path available! Clients should call hasNext() before invoking this method!");
}
return result;
}
/**
* Extracts the {@link PropertyPath} chain from the given source {@link String} and type.
*
@ -258,6 +287,11 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -258,6 +287,11 @@ public class PropertyPath implements Streamable<PropertyPath> {
}
}
if (result == null) {
throw new IllegalStateException(
String.format("Expected parsing to yield a PropertyPath from %s but got null!", source));
}
return result;
});
}
@ -277,7 +311,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -277,7 +311,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
PropertyPath previous = base.peek();
PropertyPath propertyPath = create(source, previous.typeInformation.getActualType(), base);
PropertyPath propertyPath = create(source, previous.typeInformation.getRequiredActualType(), base);
previous.next = propertyPath;
return propertyPath;
}
@ -297,7 +331,7 @@ public class PropertyPath implements Streamable<PropertyPath> { @@ -297,7 +331,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
}
/**
* Tries to look up a chain of {@link PropertyPath}s by trying the givne source first. If that fails it will split the
* Tries to look up a chain of {@link PropertyPath}s by trying the given source first. If that fails it will split the
* source apart at camel case borders (starting from the right side) and try to look up a {@link PropertyPath} from
* the calculated head and recombined new tail and additional tail.
*

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

@ -23,6 +23,7 @@ import java.util.Set; @@ -23,6 +23,7 @@ import java.util.Set;
import org.springframework.beans.PropertyMatches;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -118,6 +119,7 @@ public class PropertyReferenceException extends RuntimeException { @@ -118,6 +119,7 @@ public class PropertyReferenceException extends RuntimeException {
*
* @return
*/
@Nullable
public PropertyPath getBaseProperty() {
return alreadyResolvedPath.isEmpty() ? null : alreadyResolvedPath.get(alreadyResolvedPath.size() - 1);
}

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

@ -56,6 +56,7 @@ import org.springframework.data.util.Optionals; @@ -56,6 +56,7 @@ import org.springframework.data.util.Optionals;
import org.springframework.data.util.Pair;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
@ -89,7 +90,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -89,7 +90,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
private final Map<TypeAndProperties, PersistentPropertyPath<P>> propertyPaths = new ConcurrentReferenceHashMap<>();
private final PersistentPropertyAccessorFactory persistentPropertyAccessorFactory = new ClassGeneratingPropertyAccessorFactory();
private ApplicationEventPublisher applicationEventPublisher;
private @Nullable ApplicationEventPublisher applicationEventPublisher;
private Set<? extends Class<?>> initialEntitySet = new HashSet<>();
private boolean strict = false;
@ -131,7 +132,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -131,7 +132,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
/**
* Configures the {@link SimpleTypeHolder} to be used by the {@link MappingContext}. Allows customization of what
* types will be regarded as simple types and thus not recursively analysed.
* types will be regarded as simple types and thus not recursively analyzed.
*
* @param simpleTypes must not be {@literal null}.
*/
@ -166,6 +167,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -166,6 +167,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContext#getPersistentEntity(java.lang.Class)
*/
@Nullable
public E getPersistentEntity(Class<?> type) {
return getPersistentEntity(ClassTypeInformation.from(type));
}
@ -186,6 +188,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -186,6 +188,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContext#getPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Nullable
@Override
public E getPersistentEntity(TypeInformation<?> type) {
@ -228,13 +231,14 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -228,13 +231,14 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getPersistentEntity(org.springframework.data.mapping.PersistentProperty)
*/
@Nullable
@Override
public E getPersistentEntity(P persistentProperty) {
Assert.notNull(persistentProperty, "PersistentProperty must not be null!");
TypeInformation<?> typeInfo = persistentProperty.getTypeInformation();
return getPersistentEntity(typeInfo.getActualType());
return getPersistentEntity(typeInfo.getRequiredActualType());
}
/*
@ -315,6 +319,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -315,6 +319,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
return path;
}
@Nullable
private Pair<DefaultPersistentPropertyPath<P>, E> getPair(DefaultPersistentPropertyPath<P> path,
Iterator<String> iterator, String segment, E entity) {
@ -324,7 +329,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -324,7 +329,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
return null;
}
TypeInformation<?> type = property.getTypeInformation().getActualType();
TypeInformation<?> type = property.getTypeInformation().getRequiredActualType();
return Pair.of(path.append(property), iterator.hasNext() ? getRequiredPersistentEntity(type) : entity);
}
@ -520,9 +525,10 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -520,9 +525,10 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
*/
public void addPropertiesForRemainingDescriptors() {
remainingDescriptors.values().stream()//
.map(Property::of)//
.filter(PersistentPropertyFilter.INSTANCE::matches)//
remainingDescriptors.values().stream() //
.filter(Property::supportsStandalone) //
.map(Property::of) //
.filter(PersistentPropertyFilter.INSTANCE::matches) //
.forEach(this::createAndRegisterProperty);
}
@ -541,7 +547,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -541,7 +547,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
entity.addPersistentProperty(property);
if (property.isAssociation()) {
entity.addAssociation(property.getAssociation());
entity.addAssociation(property.getRequiredAssociation());
}
if (entity.getType().equals(property.getRawType())) {
@ -621,19 +627,18 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -621,19 +627,18 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
*/
static class PropertyMatch {
private final String namePattern;
private final String typeName;
private final @Nullable String namePattern, typeName;
/**
* Creates a new {@link PropertyMatch} for the given name pattern and type name. At least one of the paramters
* Creates a new {@link PropertyMatch} for the given name pattern and type name. At least one of the parameters
* must not be {@literal null}.
*
* @param namePattern a regex pattern to match field names, can be {@literal null}.
* @param typeName the name of the type to exclude, can be {@literal null}.
*/
public PropertyMatch(String namePattern, String typeName) {
public PropertyMatch(@Nullable String namePattern, @Nullable String typeName) {
Assert.isTrue(!(namePattern == null && typeName == null), "Either name patter or type name must be given!");
Assert.isTrue(!(namePattern == null && typeName == null), "Either name pattern or type name must be given!");
this.namePattern = namePattern;
this.typeName = typeName;
@ -643,10 +648,14 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -643,10 +648,14 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* Returns whether the given {@link Field} matches the defined {@link PropertyMatch}.
*
* @param name must not be {@literal null}.
* @param type must not be {@literal null}.
* @return
*/
public boolean matches(String name, Class<?> type) {
Assert.notNull(name, "Name must not be null!");
Assert.notNull(type, "Type must not be null!");
if (namePattern != null && !name.matches(namePattern)) {
return false;
}

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

@ -16,13 +16,13 @@ @@ -16,13 +16,13 @@
package org.springframework.data.mapping.context;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -32,25 +32,19 @@ import org.springframework.util.StringUtils; @@ -32,25 +32,19 @@ import org.springframework.util.StringUtils;
* @author Oliver Gierke
* @author Christoph Strobl
*/
class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements PersistentPropertyPath<T> {
class DefaultPersistentPropertyPath<P extends PersistentProperty<P>> implements PersistentPropertyPath<P> {
private enum PropertyNameConverter implements Converter<PersistentProperty<?>, String> {
private static final Converter<PersistentProperty<?>, String> DEFAULT_CONVERTER = (source) -> source.getName();
private static final String DEFAULT_DELIMITER = ".";
INSTANCE;
public String convert(PersistentProperty<?> source) {
return source.getName();
}
}
private final List<T> properties;
private final List<P> properties;
/**
* Creates a new {@link DefaultPersistentPropertyPath} for the given {@link PersistentProperty}s.
*
* @param properties must not be {@literal null}.
*/
public DefaultPersistentPropertyPath(List<T> properties) {
public DefaultPersistentPropertyPath(List<P> properties) {
Assert.notNull(properties, "Properties must not be null!");
@ -63,7 +57,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -63,7 +57,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* @return
*/
public static <T extends PersistentProperty<T>> DefaultPersistentPropertyPath<T> empty() {
return new DefaultPersistentPropertyPath<>(Collections.<T> emptyList());
return new DefaultPersistentPropertyPath<T>(Collections.emptyList());
}
/**
@ -73,7 +67,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -73,7 +67,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* @return a new {@link DefaultPersistentPropertyPath} with the given property appended to the current one.
* @throws IllegalArgumentException in case the property is not a property of the type of the current leaf property.
*/
public DefaultPersistentPropertyPath<T> append(T property) {
public DefaultPersistentPropertyPath<P> append(P property) {
Assert.notNull(property, "Property must not be null!");
@ -81,11 +75,13 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -81,11 +75,13 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
return new DefaultPersistentPropertyPath<>(Collections.singletonList(property));
}
@SuppressWarnings("null")
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<>(this.properties);
List<P> properties = new ArrayList<>(this.properties);
properties.add(property);
return new DefaultPersistentPropertyPath<>(properties);
@ -95,56 +91,59 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -95,56 +91,59 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#toDotPath()
*/
@Nullable
public String toDotPath() {
return toPath(null, null);
return toPath(DEFAULT_DELIMITER, DEFAULT_CONVERTER);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#toDotPath(org.springframework.core.convert.converter.Converter)
*/
public String toDotPath(Converter<? super T, String> converter) {
return toPath(null, converter);
@Nullable
public String toDotPath(Converter<? super P, String> converter) {
return toPath(DEFAULT_DELIMITER, converter);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#toPath(java.lang.String)
*/
@Nullable
public String toPath(String delimiter) {
return toPath(delimiter, null);
return toPath(delimiter, DEFAULT_CONVERTER);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#toPath(java.lang.String, org.springframework.core.convert.converter.Converter)
*/
public String toPath(String delimiter, Converter<? super T, String> converter) {
@Nullable
public String toPath(String delimiter, Converter<? super P, String> converter) {
@SuppressWarnings("unchecked")
Converter<? super T, String> converterToUse = converter == null
? PropertyNameConverter.INSTANCE : converter;
String delimiterToUse = delimiter == null ? "." : delimiter;
Assert.hasText(delimiter, "Delimiter must not be null or empty!");
Assert.notNull(converter, "Converter must not be null!");
List<String> result = new ArrayList<>();
for (T property : properties) {
for (P property : properties) {
String convert = converterToUse.convert(property);
String convert = converter.convert(property);
if (StringUtils.hasText(convert)) {
result.add(convert);
}
}
return result.isEmpty() ? null : StringUtils.collectionToDelimitedString(result, delimiterToUse);
return result.isEmpty() ? null : StringUtils.collectionToDelimitedString(result, delimiter);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#getLeafProperty()
*/
public T getLeafProperty() {
@Nullable
public P getLeafProperty() {
return properties.get(properties.size() - 1);
}
@ -152,7 +151,8 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -152,7 +151,8 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#getBaseProperty()
*/
public T getBaseProperty() {
@Nullable
public P getBaseProperty() {
return properties.get(0);
}
@ -160,21 +160,19 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -160,21 +160,19 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#isBasePathOf(org.springframework.data.mapping.context.PersistentPropertyPath)
*/
public boolean isBasePathOf(PersistentPropertyPath<T> path) {
public boolean isBasePathOf(PersistentPropertyPath<P> path) {
if (path == null) {
return false;
}
Assert.notNull(path, "PersistentPropertyPath must not be null!");
Iterator<T> iterator = path.iterator();
Iterator<P> iterator = path.iterator();
for (T property : this) {
for (P property : this) {
if (!iterator.hasNext()) {
return false;
}
T reference = iterator.next();
P reference = iterator.next();
if (!property.equals(reference)) {
return false;
@ -188,14 +186,14 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -188,14 +186,14 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#getExtensionForBaseOf(org.springframework.data.mapping.context.PersistentPropertyPath)
*/
public PersistentPropertyPath<T> getExtensionForBaseOf(PersistentPropertyPath<T> base) {
public PersistentPropertyPath<P> getExtensionForBaseOf(PersistentPropertyPath<P> base) {
if (!base.isBasePathOf(this)) {
return this;
}
List<T> result = new ArrayList<>();
Iterator<T> iterator = iterator();
List<P> result = new ArrayList<>();
Iterator<P> iterator = iterator();
for (int i = 0; i < base.getLength(); i++) {
iterator.next();
@ -212,11 +210,14 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -212,11 +210,14 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* (non-Javadoc)
* @see org.springframework.data.mapping.context.PersistentPropertyPath#getParentPath()
*/
public PersistentPropertyPath<T> getParentPath() {
public PersistentPropertyPath<P> getParentPath() {
int size = properties.size();
if (size <= 1) {
return this;
}
return new DefaultPersistentPropertyPath<>(properties.subList(0, size - 1));
}
@ -232,7 +233,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -232,7 +233,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
public Iterator<T> iterator() {
public Iterator<P> iterator() {
return properties.iterator();
}
@ -249,7 +250,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -249,7 +250,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
@ -278,6 +279,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements @@ -278,6 +279,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* @see java.lang.Object#toString()
*/
@Override
@Nullable
public String toString() {
return toDotPath();
}

5
src/main/java/org/springframework/data/mapping/context/InvalidPersistentPropertyPath.java

@ -17,6 +17,7 @@ package org.springframework.data.mapping.context; @@ -17,6 +17,7 @@ package org.springframework.data.mapping.context;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -40,8 +41,8 @@ public class InvalidPersistentPropertyPath extends MappingException { @@ -40,8 +41,8 @@ public class InvalidPersistentPropertyPath extends MappingException {
* @param resolvedPath
* @param message must not be {@literal null} or empty.
*/
InvalidPersistentPropertyPath(String source, TypeInformation<?> type, String unresolvableSegment, String resolvedPath,
String message) {
InvalidPersistentPropertyPath(String source, TypeInformation<?> type, String unresolvableSegment,
@Nullable String resolvedPath, String message) {
super(message);

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

@ -22,6 +22,7 @@ import org.springframework.data.mapping.PersistentEntity; @@ -22,6 +22,7 @@ import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
/**
* This interface defines the overall context including all known PersistentEntity instances and methods to obtain
@ -51,6 +52,7 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers @@ -51,6 +52,7 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
* @param type must not be {@literal null}.
* @return {@literal null} if no {@link PersistentEntity} found for {@literal type}.
*/
@Nullable
E getPersistentEntity(Class<?> type);
/**
@ -91,6 +93,7 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers @@ -91,6 +93,7 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
* @param type must not be {@literal null}.
* @return {@literal null} if no {@link PersistentEntity} found for {@link TypeInformation}.
*/
@Nullable
E getPersistentEntity(TypeInformation<?> type);
/**
@ -117,11 +120,12 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers @@ -117,11 +120,12 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
* Returns the {@link PersistentEntity} mapped by the given {@link PersistentProperty}.
*
* @param persistentProperty must not be {@literal null}.
* @return the {@link PersistentEntity} mapped by the given {@link PersistentProperty} or null if no
* @return the {@link PersistentEntity} mapped by the given {@link PersistentProperty} or {@literal 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)}).
*/
@Nullable
E getPersistentEntity(P persistentProperty);
/**

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

@ -26,6 +26,7 @@ import org.springframework.data.mapping.PersistentProperty; @@ -26,6 +26,7 @@ import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.support.IsNewStrategy;
import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.data.support.IsNewStrategyFactorySupport;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -68,12 +69,11 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp @@ -68,12 +69,11 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
* (non-Javadoc)
* @see org.springframework.data.support.IsNewStrategyFactorySupport#getFallBackStrategy(java.lang.Class)
*/
@Nullable
@Override
protected IsNewStrategy doGetIsNewStrategy(Class<?> type) {
return MappingContextIsNewStrategyFactory.getIsNewStrategy(context.getRequiredPersistentEntity(type));
}
private static IsNewStrategy getIsNewStrategy(PersistentEntity<?, ?> entity) {
PersistentEntity<?, ? extends PersistentProperty<?>> entity = context.getRequiredPersistentEntity(type);
if (entity.hasVersionProperty()) {

19
src/main/java/org/springframework/data/mapping/context/PersistentPropertyPath.java

@ -17,6 +17,7 @@ package org.springframework.data.mapping.context; @@ -17,6 +17,7 @@ package org.springframework.data.mapping.context;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.lang.Nullable;
/**
* Abstraction of a path of {@link PersistentProperty}s.
@ -30,33 +31,37 @@ public interface PersistentPropertyPath<T extends PersistentProperty<T>> extends @@ -30,33 +31,37 @@ public interface PersistentPropertyPath<T extends PersistentProperty<T>> extends
*
* @return
*/
@Nullable
String toDotPath();
/**
* Returns the dot based path notation using the given {@link Converter} to translate individual
* {@link PersistentProperty}s to path segments.
*
* @param converter
* @param converter must not be {@literal null}.
* @return
*/
@Nullable
String toDotPath(Converter<? super T, String> converter);
/**
* Returns a {@link String} path with the given delimiter based on the {@link PersistentProperty#getName()}.
*
* @param delimiter will default to {@code .} if {@literal null} is given.
* @param delimiter must not be {@literal null}.
* @return
*/
@Nullable
String toPath(String delimiter);
/**
* Returns a {@link String} path with the given delimiter using the given {@link Converter} for
* {@link PersistentProperty} to String conversion.
*
* @param delimiter will default to {@code .} if {@literal null} is given.
* @param converter will default to use {@link PersistentProperty#getName()}.
* @param delimiter must not be {@literal null}.
* @param converter must not be {@literal null}.
* @return
*/
@Nullable
String toPath(String delimiter, Converter<? super T, String> converter);
/**
@ -66,6 +71,7 @@ public interface PersistentPropertyPath<T extends PersistentProperty<T>> extends @@ -66,6 +71,7 @@ public interface PersistentPropertyPath<T extends PersistentProperty<T>> extends
*
* @return
*/
@Nullable
T getLeafProperty();
/**
@ -75,13 +81,14 @@ public interface PersistentPropertyPath<T extends PersistentProperty<T>> extends @@ -75,13 +81,14 @@ public interface PersistentPropertyPath<T extends PersistentProperty<T>> extends
*
* @return
*/
@Nullable
T getBaseProperty();
/**
* Returns whether the given {@link PersistentPropertyPath} is a base path of the current one. This means that the
* current {@link PersistentPropertyPath} is basically an extension of the given one.
*
* @param path
* @param path must not be {@literal null}.
* @return
*/
boolean isBasePathOf(PersistentPropertyPath<T> path);
@ -91,7 +98,7 @@ public interface PersistentPropertyPath<T extends PersistentProperty<T>> extends @@ -91,7 +98,7 @@ public interface PersistentPropertyPath<T extends PersistentProperty<T>> extends
* {@code foo.bar} and a given base {@code foo} it would return {@code bar}. If the given path is not a base of the
* the current one the current {@link PersistentPropertyPath} will be returned as is.
*
* @param base
* @param base must not be {@literal null}.
* @return
*/
PersistentPropertyPath<T> getExtensionForBaseOf(PersistentPropertyPath<T> base);

3
src/main/java/org/springframework/data/mapping/context/package-info.java

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/**
* Mapping context API and implementation base classes.
*/
package org.springframework.data.mapping.context;
@org.springframework.lang.NonNullApi
package org.springframework.data.mapping.context;

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

@ -31,9 +31,10 @@ import org.springframework.data.mapping.PersistentEntity; @@ -31,9 +31,10 @@ 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.ReflectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Simple implementation of {@link PersistentProperty}.
@ -48,7 +49,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -48,7 +49,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
private static final Field CAUSE_FIELD;
static {
CAUSE_FIELD = ReflectionUtils.findField(Throwable.class, "cause");
CAUSE_FIELD = ReflectionUtils.findRequiredField(Throwable.class, "cause");
}
private final String name;
@ -56,14 +57,15 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -56,14 +57,15 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
private final Class<?> rawType;
private final Lazy<Association<P>> association;
private final @Getter PersistentEntity<?, P> owner;
private final @Getter(AccessLevel.PROTECTED) Property property;
private final @Getter(value = AccessLevel.PROTECTED, onMethod = @__(@SuppressWarnings("null"))) Property property;
private final Lazy<Integer> hashCode;
private final Lazy<Boolean> usePropertyAccess;
private final Lazy<Optional<? extends TypeInformation<?>>> entityTypeInformation;
private final Method getter;
private final Method setter;
private final Field field;
private final @Getter(onMethod = @__(@Nullable)) Method getter;
private final @Getter(onMethod = @__(@Nullable)) Method setter;
private final @Getter(onMethod = @__(@Nullable)) Field field;
public AbstractPersistentProperty(Property property, PersistentEntity<?, P> owner,
SimpleTypeHolder simpleTypeHolder) {
@ -81,6 +83,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -81,6 +83,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
this.hashCode = Lazy.of(property::hashCode);
this.usePropertyAccess = Lazy.of(() -> owner.getType().isInterface() || CAUSE_FIELD.equals(getField()));
this.entityTypeInformation = Lazy.of(() -> Optional.ofNullable(information.getActualType())//
.filter(it -> !simpleTypeHolder.isSimpleType(it.getType()))//
.filter(it -> !it.isCollectionLike())//
@ -145,38 +148,12 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -145,38 +148,12 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
.orElseGet(Collections::emptySet);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getGetter()
*/
@Override
public Method getGetter() {
return getter;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getSetter()
*/
@Override
public Method getSetter() {
return setter;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getField()
*/
@Override
public Field getField() {
return field;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getSpelExpression()
*/
@Override
@Nullable
public String getSpelExpression() {
return null;
}
@ -212,9 +189,10 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -212,9 +189,10 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getAssociation()
*/
@Nullable
@Override
public Association<P> getAssociation() {
return association.get();
return association.orElse(null);
}
/*
@ -257,6 +235,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -257,6 +235,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getComponentType()
*/
@Nullable
@Override
public Class<?> getComponentType() {
return isMap() || isCollectionLike() ? information.getRequiredComponentType().getType() : null;
@ -266,6 +245,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -266,6 +245,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getMapValueType()
*/
@Nullable
@Override
public Class<?> getMapValueType() {
@ -286,7 +266,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -286,7 +266,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Class<?> getActualType() {
return information.getActualType().getType();
return information.getRequiredActualType().getType();
}
/*
@ -302,7 +282,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -302,7 +282,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;

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

@ -39,6 +39,7 @@ import org.springframework.data.mapping.PersistentEntity; @@ -39,6 +39,7 @@ import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Optionals;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -53,7 +54,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -53,7 +54,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
private static final String SPRING_DATA_PACKAGE = "org.springframework.data";
private final String value;
private final @Nullable String value;
private final Map<Class<? extends Annotation>, Optional<? extends Annotation>> annotationCache = new HashMap<>();
private final Lazy<Boolean> usePropertyAccess = Lazy.of(() -> {
@ -159,6 +160,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -159,6 +160,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
*
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#getSpelExpression()
*/
@Nullable
@Override
public String getSpelExpression() {
return value;
@ -216,6 +218,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -216,6 +218,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
* @param annotationType must not be {@literal null}.
* @return {@literal null} if annotation type not found on property.
*/
@Nullable
public <A extends Annotation> A findAnnotation(Class<A> annotationType) {
Assert.notNull(annotationType, "Annotation type must not be null!");
@ -248,6 +251,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -248,6 +251,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#findPropertyOrOwnerAnnotation(java.lang.Class)
*/
@Nullable
@Override
public <A extends Annotation> A findPropertyOrOwnerAnnotation(Class<A> annotationType) {

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

@ -50,6 +50,7 @@ import org.springframework.data.mapping.SimplePropertyHandler; @@ -50,6 +50,7 @@ import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.mapping.TargetAwareIdentifierAccessor;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@ -69,19 +70,19 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -69,19 +70,19 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
private static final String TYPE_MISMATCH = "Target bean of type %s is not of type of the persistent entity (%s)!";
private final PreferredConstructor<T, P> constructor;
private final @Nullable PreferredConstructor<T, P> constructor;
private final TypeInformation<T> information;
private final List<P> properties;
private final List<P> persistentPropertiesCache;
private final Comparator<P> comparator;
private final @Nullable Comparator<P> comparator;
private final Set<Association<P>> associations;
private final Map<String, P> propertyCache;
private final Map<Class<? extends Annotation>, Optional<Annotation>> annotationCache;
private final MultiValueMap<Class<? extends Annotation>, P> propertyAnnotationCache;
private P idProperty;
private P versionProperty;
private @Nullable P idProperty;
private @Nullable P versionProperty;
private PersistentPropertyAccessorFactory propertyAccessorFactory;
private final Lazy<Alias> typeAlias;
@ -103,7 +104,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -103,7 +104,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* @param information must not be {@literal null}.
* @param comparator can be {@literal null}.
*/
public BasicPersistentEntity(TypeInformation<T> information, Comparator<P> comparator) {
public BasicPersistentEntity(TypeInformation<T> information, @Nullable Comparator<P> comparator) {
Assert.notNull(information, "Information must not be null!");
@ -125,6 +126,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -125,6 +126,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#getPersistenceConstructor()
*/
@Nullable
public PreferredConstructor<T, P> getPersistenceConstructor() {
return constructor;
}
@ -165,6 +167,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -165,6 +167,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#getIdProperty()
*/
@Nullable
public P getIdProperty() {
return idProperty;
}
@ -173,6 +176,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -173,6 +176,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#getVersionProperty()
*/
@Nullable
public P getVersionProperty() {
return versionProperty;
}
@ -223,12 +227,15 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -223,12 +227,15 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
if (property.isVersionProperty()) {
if (this.versionProperty != null) {
P versionProperty = this.versionProperty;
throw new MappingException(String.format(
"Attempt to add version property %s but already have property %s registered "
+ "as version. Check your mapping configuration!",
property.getField(), this.versionProperty.getField()));
if (versionProperty != null) {
throw new MappingException(
String.format(
"Attempt to add version property %s but already have property %s registered "
+ "as version. Check your mapping configuration!",
property.getField(), versionProperty.getField()));
}
this.versionProperty = property;
@ -241,15 +248,18 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -241,15 +248,18 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* @param property the new id property candidate, will never be {@literal null}.
* @return the given id property or {@literal null} if the given property is not an id property.
*/
@Nullable
protected P returnPropertyIfBetterIdPropertyCandidateOrNull(P property) {
if (!property.isIdProperty()) {
return null;
}
if (this.idProperty != null) {
P idProperty = this.idProperty;
if (idProperty != null) {
throw new MappingException(String.format("Attempt to add id property %s but already have property %s registered "
+ "as id. Check your mapping configuration!", property.getField(), this.idProperty.getField()));
+ "as id. Check your mapping configuration!", property.getField(), idProperty.getField()));
}
return property;
@ -273,6 +283,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -273,6 +283,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* @see org.springframework.data.mapping.PersistentEntity#getPersistentProperty(java.lang.String)
*/
@Override
@Nullable
public P getPersistentProperty(String name) {
return propertyCache.get(name);
}
@ -384,8 +395,8 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -384,8 +395,8 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#findAnnotation(java.lang.Class)
*/
@Nullable
@Override
@SuppressWarnings("unchecked")
public <A extends Annotation> A findAnnotation(Class<A> annotationType) {
return doFindAnnotation(annotationType).orElse(null);
}
@ -399,6 +410,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -399,6 +410,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
return doFindAnnotation(annotationType).isPresent();
}
@SuppressWarnings("unchecked")
private <A extends Annotation> Optional<A> doFindAnnotation(Class<A> annotationType) {
return (Optional<A>) annotationCache.computeIfAbsent(annotationType,
@ -492,6 +504,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -492,6 +504,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* @see org.springframework.data.mapping.IdentifierAccessor#getIdentifier()
*/
@Override
@Nullable
public Object getIdentifier() {
return null;
}
@ -513,7 +526,16 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -513,7 +526,16 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* (non-Javadoc)
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Association<P> left, Association<P> right) {
public int compare(@Nullable Association<P> left, @Nullable Association<P> right) {
if (left == null) {
throw new IllegalArgumentException("Left argument must not be null!");
}
if (right == null) {
throw new IllegalArgumentException("Right argument must not be null!");
}
return delegate.compare(left.getInverse(), right.getInverse());
}
}

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

@ -21,6 +21,7 @@ import java.lang.reflect.Method; @@ -21,6 +21,7 @@ import java.lang.reflect.Method;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@ -49,7 +50,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor { @@ -49,7 +50,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentPropertyAccessor#setProperty(org.springframework.data.mapping.PersistentProperty, java.util.Optional)
*/
public void setProperty(PersistentProperty<?> property, Object value) {
public void setProperty(PersistentProperty<?> property, @Nullable Object value) {
Assert.notNull(property, "PersistentProperty must not be null!");
@ -57,20 +58,17 @@ class BeanWrapper<T> implements PersistentPropertyAccessor { @@ -57,20 +58,17 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
if (!property.usePropertyAccess()) {
Field field = property.getField();
Field field = property.getRequiredField();
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, bean, value);
return;
}
Method setter = property.getSetter();
Method setter = property.getRequiredSetter();
if (setter != null) {
ReflectionUtils.makeAccessible(setter);
ReflectionUtils.invokeMethod(setter, bean, value);
}
ReflectionUtils.makeAccessible(setter);
ReflectionUtils.invokeMethod(setter, bean, value);
} catch (IllegalStateException e) {
throw new MappingException("Could not set object property!", e);
@ -81,6 +79,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor { @@ -81,6 +79,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getProperty(org.springframework.data.mapping.PersistentProperty)
*/
@Nullable
public Object getProperty(PersistentProperty<?> property) {
return getProperty(property, property.getType());
}
@ -94,7 +93,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor { @@ -94,7 +93,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
* @return
* @throws MappingException in case an exception occured when accessing the property.
*/
@SuppressWarnings("unchecked")
@Nullable
public <S> Object getProperty(PersistentProperty<?> property, Class<? extends S> type) {
Assert.notNull(property, "PersistentProperty must not be null!");
@ -103,20 +102,16 @@ class BeanWrapper<T> implements PersistentPropertyAccessor { @@ -103,20 +102,16 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
if (!property.usePropertyAccess()) {
Field field = property.getField();
Field field = property.getRequiredField();
ReflectionUtils.makeAccessible(field);
return ReflectionUtils.getField(field, bean);
}
Method getter = property.getGetter();
if (getter != null) {
ReflectionUtils.makeAccessible(getter);
return ReflectionUtils.invokeMethod(getter, bean);
}
Method getter = property.getRequiredGetter();
return null;
ReflectionUtils.makeAccessible(getter);
return ReflectionUtils.invokeMethod(getter, bean);
} catch (IllegalStateException e) {
throw new MappingException(

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

@ -50,8 +50,8 @@ import org.springframework.data.mapping.SimpleAssociationHandler; @@ -50,8 +50,8 @@ import org.springframework.data.mapping.SimpleAssociationHandler;
import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* A factory that can generate byte code to speed-up dynamic property access. Uses the {@link PersistentEntity}'s
@ -530,6 +530,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -530,6 +530,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
* Retrieve all classes which are involved in property/getter/setter declarations as these elements may be
* distributed across the type hierarchy.
*/
@SuppressWarnings("null")
private static List<Class<?>> getPropertyDeclaratingClasses(List<PersistentProperty<?>> persistentProperties) {
return persistentProperties.stream().flatMap(property -> {
@ -854,7 +855,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -854,7 +855,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
}
} else {
Field field = property.getField();
Field field = property.getRequiredField();
if (generateMethodHandle(entity, field)) {
// $fieldGetter.invoke(bean)
mv.visitFieldInsn(GETSTATIC, internalClassName, fieldGetterName(property),
@ -1111,7 +1113,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -1111,7 +1113,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
return !(Modifier.isPrivate(modifiers) || Modifier.isProtected(modifiers) || Modifier.isPublic(modifiers));
}
private static boolean generateSetterMethodHandle(PersistentEntity<?, ?> entity, Field field) {
private static boolean generateSetterMethodHandle(PersistentEntity<?, ?> entity, @Nullable Field field) {
if (field == null) {
return false;
@ -1125,7 +1127,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -1125,7 +1127,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
* its declaring class. Use also {@link java.lang.invoke.MethodHandle} if visibility is protected/package-default
* and packages of the declaring types are different.
*/
private static boolean generateMethodHandle(PersistentEntity<?, ?> entity, Member member) {
private static boolean generateMethodHandle(PersistentEntity<?, ?> entity, @Nullable Member member) {
if (member == null) {
return false;
@ -1143,6 +1145,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -1143,6 +1145,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
return false;
}
}
return true;
}
@ -1358,8 +1361,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -1358,8 +1361,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(PropertyStackAddress o) {
return (hash < o.hash) ? -1 : ((hash == o.hash) ? 0 : 1);
public int compareTo(@SuppressWarnings("null") PropertyStackAddress o) {
return hash < o.hash ? -1 : hash == o.hash ? 0 : 1;
}
}
@ -1398,8 +1401,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -1398,8 +1401,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
ClassLoader classLoader = entity.getType().getClassLoader();
Class<?> classLoaderClass = classLoader.getClass();
Method defineClass = ReflectionUtils.findMethod(classLoaderClass, "defineClass", String.class, byte[].class,
Integer.TYPE, Integer.TYPE, ProtectionDomain.class);
Method defineClass = org.springframework.data.util.ReflectionUtils.findRequiredMethod(classLoaderClass,
"defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE, ProtectionDomain.class);
defineClass.setAccessible(true);

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

@ -18,6 +18,7 @@ package org.springframework.data.mapping.model; @@ -18,6 +18,7 @@ package org.springframework.data.mapping.model;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -55,7 +56,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor { @@ -55,7 +56,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* @see org.springframework.data.mapping.PersistentPropertyAccessor#setProperty(org.springframework.data.mapping.PersistentProperty, java.lang.Object)
*/
@Override
public void setProperty(PersistentProperty<?> property, Object value) {
public void setProperty(PersistentProperty<?> property, @Nullable Object value) {
accessor.setProperty(property, convertIfNecessary(value, property.getType()));
}
@ -63,6 +64,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor { @@ -63,6 +64,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getProperty(org.springframework.data.mapping.PersistentProperty)
*/
@Nullable
@Override
public Object getProperty(PersistentProperty<?> property) {
return accessor.getProperty(property);
@ -75,6 +77,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor { @@ -75,6 +77,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* @param targetType must not be {@literal null}.
* @return
*/
@Nullable
public <T> T getProperty(PersistentProperty<?> property, Class<T> targetType) {
Assert.notNull(property, "PersistentProperty must not be null!");
@ -100,8 +103,9 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor { @@ -100,8 +103,9 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* @param type must not be {@literal null}.
* @return
*/
@Nullable
@SuppressWarnings("unchecked")
private <T> T convertIfNecessary(Object source, Class<T> type) {
private <T> T convertIfNecessary(@Nullable Object source, Class<T> type) {
return (T) (source == null ? null
: type.isAssignableFrom(source.getClass()) ? source : conversionService.convert(source, type));
}

22
src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java

@ -16,10 +16,14 @@ @@ -16,10 +16,14 @@
package org.springframework.data.mapping.model;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;
/**
* {@link ParameterValueProvider} implementation that evaluates the {@link Parameter}s key against
@ -27,23 +31,17 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; @@ -27,23 +31,17 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
public class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator {
private final Object source;
private final SpELContext factory;
/**
* @param source
* @param factory
*/
public DefaultSpELExpressionEvaluator(Object source, SpELContext factory) {
this.source = source;
this.factory = factory;
}
private final @NonNull Object source;
private final @NonNull SpELContext factory;
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.SpELExpressionEvaluator#evaluate(java.lang.String)
*/
@Nullable
@SuppressWarnings("unchecked")
public <T> T evaluate(String expression) {

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

@ -20,6 +20,7 @@ import org.springframework.data.mapping.PersistentEntity; @@ -20,6 +20,7 @@ import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.TargetAwareIdentifierAccessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -57,6 +58,7 @@ public class IdPropertyIdentifierAccessor extends TargetAwareIdentifierAccessor @@ -57,6 +58,7 @@ public class IdPropertyIdentifierAccessor extends TargetAwareIdentifierAccessor
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.IdentifierAccessor#getIdentifier()
*/
@Nullable
public Object getIdentifier() {
return accessor.getProperty(idProperty);
}

9
src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java

@ -22,6 +22,7 @@ import java.util.Optional; @@ -22,6 +22,7 @@ import java.util.Optional;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@ -63,8 +64,8 @@ public class MappingInstantiationException extends RuntimeException { @@ -63,8 +64,8 @@ public class MappingInstantiationException extends RuntimeException {
this(Optional.empty(), arguments, null, cause);
}
private MappingInstantiationException(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments, String message,
Exception cause) {
private MappingInstantiationException(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments,
@Nullable String message, Exception cause) {
super(buildExceptionMessage(entity, arguments, message), cause);
@ -75,13 +76,13 @@ public class MappingInstantiationException extends RuntimeException { @@ -75,13 +76,13 @@ public class MappingInstantiationException extends RuntimeException {
}
private static String buildExceptionMessage(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments,
String defaultMessage) {
@Nullable String defaultMessage) {
return entity.map(it -> {
Optional<? extends PreferredConstructor<?, ?>> constructor = Optional.ofNullable(it.getPersistenceConstructor());
List<String> toStringArgs = new ArrayList<>(arguments.size());
for (Object o : arguments) {
toStringArgs.add(ObjectUtils.nullSafeToString(o));
}

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

@ -17,6 +17,7 @@ package org.springframework.data.mapping.model; @@ -17,6 +17,7 @@ package org.springframework.data.mapping.model;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.lang.Nullable;
/**
* Callback interface to lookup values for a given {@link Parameter}.
@ -31,5 +32,6 @@ public interface ParameterValueProvider<P extends PersistentProperty<P>> { @@ -31,5 +32,6 @@ public interface ParameterValueProvider<P extends PersistentProperty<P>> {
* @param parameter must not be {@literal null}.
* @return
*/
@Nullable
<T> T getParameterValue(Parameter<T, P> parameter);
}

46
src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java

@ -15,12 +15,15 @@ @@ -15,12 +15,15 @@
*/
package org.springframework.data.mapping.model;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.util.Assert;
import org.springframework.lang.Nullable;
/**
* {@link ParameterValueProvider} based on a {@link PersistentEntity} to use a {@link PropertyValueProvider} to lookup
@ -30,50 +33,39 @@ import org.springframework.util.Assert; @@ -30,50 +33,39 @@ import org.springframework.util.Assert;
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
public class PersistentEntityParameterValueProvider<P extends PersistentProperty<P>>
implements ParameterValueProvider<P> {
private final PersistentEntity<?, P> entity;
private final PropertyValueProvider<P> provider;
private final Object parent;
/**
* Creates a new {@link PersistentEntityParameterValueProvider} for the given {@link PersistentEntity} and
* {@link PropertyValueProvider}.
*
* @param entity must not be {@literal null}.
* @param provider must not be {@literal null}.
* @param parent the parent object being created currently, can be {@literal null}.
*/
public PersistentEntityParameterValueProvider(PersistentEntity<?, P> entity, PropertyValueProvider<P> provider,
Object parent) {
Assert.notNull(entity, "Entity must not be null!");
Assert.notNull(provider, "Provider must not be null!");
this.entity = entity;
this.provider = provider;
this.parent = parent;
}
private final @NonNull PersistentEntity<?, P> entity;
private final @NonNull PropertyValueProvider<P> provider;
private final @Nullable Object parent;
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
*/
@Nullable
@SuppressWarnings("unchecked")
public <T> T getParameterValue(Parameter<T, P> parameter) {
PreferredConstructor<?, P> constructor = entity.getPersistenceConstructor();
if (constructor.isEnclosingClassParameter(parameter)) {
if (constructor != null && constructor.isEnclosingClassParameter(parameter)) {
return (T) parent;
}
P property = entity.getPersistentProperty(parameter.getName());
String name = parameter.getName();
if (name == null) {
throw new MappingException(String.format("Parameter %s does not have a name!", parameter));
}
P property = entity.getPersistentProperty(name);
if (property == null) {
throw new MappingException(String.format("No property %s found on entity %s to bind constructor parameter to!",
parameter.getName(), entity.getType()));
throw new MappingException(
String.format("No property %s found on entity %s to bind constructor parameter to!", name, entity.getType()));
}
return provider.getPropertyValue(property);

8
src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java

@ -27,6 +27,7 @@ import org.springframework.data.mapping.PreferredConstructor; @@ -27,6 +27,7 @@ import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
/**
* Helper class to find a {@link PreferredConstructor}.
@ -40,7 +41,7 @@ public class PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>> @@ -40,7 +41,7 @@ public class PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>>
private final ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
private PreferredConstructor<T, P> constructor;
private @Nullable PreferredConstructor<T, P> constructor;
/**
* Creates a new {@link PreferredConstructorDiscoverer} for the given type.
@ -66,7 +67,7 @@ public class PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>> @@ -66,7 +67,7 @@ public class PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>>
* @param type must not be {@literal null}.
* @param entity
*/
protected PreferredConstructorDiscoverer(TypeInformation<T> type, PersistentEntity<T, P> entity) {
protected PreferredConstructorDiscoverer(TypeInformation<T> type, @Nullable PersistentEntity<T, P> entity) {
boolean noArgConstructorFound = false;
int numberOfArgConstructors = 0;
@ -106,7 +107,7 @@ public class PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>> @@ -106,7 +107,7 @@ public class PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>>
@SuppressWarnings({ "unchecked", "rawtypes" })
private PreferredConstructor<T, P> buildPreferredConstructor(Constructor<?> constructor,
TypeInformation<T> typeInformation, PersistentEntity<T, P> entity) {
TypeInformation<T> typeInformation, @Nullable PersistentEntity<T, P> entity) {
List<TypeInformation<?>> parameterTypes = typeInformation.getParameterTypes(constructor);
@ -136,6 +137,7 @@ public class PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>> @@ -136,6 +137,7 @@ public class PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>>
*
* @return
*/
@Nullable
public PreferredConstructor<T, P> getConstructor() {
return constructor;
}

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

@ -22,8 +22,11 @@ import java.beans.PropertyDescriptor; @@ -22,8 +22,11 @@ import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.function.Function;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Optionals;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -43,20 +46,28 @@ public class Property { @@ -43,20 +46,28 @@ public class Property {
private final Optional<Method> getter;
private final Optional<Method> setter;
private final Lazy<String> name;
private final Lazy<String> toString;
private Property(Optional<Field> field, Optional<PropertyDescriptor> descriptor) {
Assert.isTrue(Optionals.isAnyPresent(field, descriptor), "Either field or descriptor has to be given!");
this.field = field;
this.descriptor = descriptor;
this.hashCode = Lazy.of(this::computeHashCode);
this.rawType = field.<Class<?>> map(Field::getType)
.orElseGet(() -> descriptor.map(PropertyDescriptor::getPropertyType)//
.orElse(null));
this.rawType = withFieldOrDescriptor(Field::getType, PropertyDescriptor::getPropertyType);
this.hashCode = Lazy.of(() -> withFieldOrDescriptor(Object::hashCode));
this.name = Lazy.of(() -> withFieldOrDescriptor(Field::getName, FeatureDescriptor::getName));
this.toString = Lazy.of(() -> withFieldOrDescriptor(Object::toString));
this.getter = descriptor.map(PropertyDescriptor::getReadMethod)//
.filter(it -> getType() != null).filter(it -> getType().isAssignableFrom(it.getReturnType()));
.filter(it -> getType() != null)//
.filter(it -> getType().isAssignableFrom(it.getReturnType()));
this.setter = descriptor.map(PropertyDescriptor::getWriteMethod)//
.filter(it -> getType() != null).filter(it -> it.getParameterTypes()[0].isAssignableFrom(getType()));
.filter(it -> getType() != null)//
.filter(it -> it.getParameterTypes()[0].isAssignableFrom(getType()));
}
/**
@ -88,10 +99,12 @@ public class Property { @@ -88,10 +99,12 @@ public class Property {
}
/**
* Creates a new {@link Property} for the given {@link PropertyDescriptor}.
* Creates a new {@link Property} for the given {@link PropertyDescriptor}. The creation might fail if the given
* property is not representing a proper property.
*
* @param descriptor must not be {@literal null}.
* @return
* @see #supportsStandalone(PropertyDescriptor)
*/
public static Property of(PropertyDescriptor descriptor) {
@ -100,6 +113,20 @@ public class Property { @@ -100,6 +113,20 @@ public class Property {
return new Property(Optional.empty(), Optional.of(descriptor));
}
/**
* Returns whether the given {@link PropertyDescriptor} is supported in for standalone creation of a {@link Property}
* instance.
*
* @param descriptor
* @return
*/
public static boolean supportsStandalone(PropertyDescriptor descriptor) {
Assert.notNull(descriptor, "PropertDescriptor must not be null!");
return descriptor.getPropertyType() != null;
}
/**
* Returns whether the property is backed by a field.
*
@ -142,10 +169,7 @@ public class Property { @@ -142,10 +169,7 @@ public class Property {
* @return will never be {@literal null}.
*/
public String getName() {
return field.map(Field::getName)//
.orElseGet(() -> descriptor.map(FeatureDescriptor::getName)//
.orElseThrow(IllegalStateException::new));
return this.name.get();
}
/**
@ -157,27 +181,12 @@ public class Property { @@ -157,27 +181,12 @@ public class Property {
return rawType;
}
private int computeHashCode() {
return this.field.map(Field::hashCode)
.orElseGet(() -> this.descriptor.map(PropertyDescriptor::hashCode).orElseThrow(IllegalStateException::new));
}
/*
* (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) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
@ -192,13 +201,47 @@ public class Property { @@ -192,13 +201,47 @@ public class Property {
return this.field.isPresent() ? this.field.equals(that.field) : this.descriptor.equals(that.descriptor);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return hashCode.get();
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return field.map(Object::toString)
.orElseGet(() -> descriptor.map(Object::toString).orElseThrow(IllegalStateException::new));
return toString.get();
}
/**
* Maps the backing {@link Field} or {@link PropertyDescriptor} using the given {@link Function}.
*
* @param function must not be {@literal null}.
* @return
*/
private <T> T withFieldOrDescriptor(Function<Object, T> function) {
return withFieldOrDescriptor(function, function);
}
/**
* Maps the backing {@link Field} or {@link PropertyDescriptor} using the given functions.
*
* @param field must not be {@literal null}.
* @param descriptor must not be {@literal null}.
* @return
*/
private <T> T withFieldOrDescriptor(Function<? super Field, T> field,
Function<? super PropertyDescriptor, T> descriptor) {
return Optionals.firstNonEmpty(//
() -> this.field.map(field), //
() -> this.descriptor.map(descriptor))//
.orElseThrow(() -> new IllegalStateException("Should not occur! Either field or descriptor has to be given"));
}
}

16
src/main/java/org/springframework/data/mapping/model/SpELContext.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012 the original author or authors.
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,6 +22,8 @@ import org.springframework.expression.ExpressionParser; @@ -22,6 +22,8 @@ import org.springframework.expression.ExpressionParser;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Simple factory to create {@link SpelExpressionParser} and {@link EvaluationContext} instances.
@ -32,7 +34,7 @@ public class SpELContext { @@ -32,7 +34,7 @@ public class SpELContext {
private final SpelExpressionParser parser;
private final PropertyAccessor accessor;
private final BeanFactory factory;
private final @Nullable BeanFactory factory;
/**
* Creates a new {@link SpELContext} with the given {@link PropertyAccessor}. Defaults the
@ -75,7 +77,9 @@ public class SpELContext { @@ -75,7 +77,9 @@ public class SpELContext {
* @param parser
* @param factory
*/
private SpELContext(PropertyAccessor accessor, SpelExpressionParser parser, BeanFactory factory) {
private SpELContext(PropertyAccessor accessor, @Nullable SpelExpressionParser parser, @Nullable BeanFactory factory) {
Assert.notNull(accessor, "PropertyAccessor must not be null!");
this.parser = parser == null ? new SpelExpressionParser() : parser;
this.accessor = accessor;
@ -97,10 +101,7 @@ public class SpELContext { @@ -97,10 +101,7 @@ public class SpELContext {
public EvaluationContext getEvaluationContext(Object source) {
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(source);
if (accessor != null) {
evaluationContext.addPropertyAccessor(accessor);
}
evaluationContext.addPropertyAccessor(accessor);
if (factory != null) {
evaluationContext.setBeanResolver(new BeanFactoryResolver(factory));
@ -108,5 +109,4 @@ public class SpELContext { @@ -108,5 +109,4 @@ public class SpELContext {
return evaluationContext;
}
}

5
src/main/java/org/springframework/data/mapping/model/SpELExpressionEvaluator.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.mapping.model;
import org.springframework.lang.Nullable;
/**
* SPI for components that can evaluate Spring EL expressions.
*
@ -28,5 +30,6 @@ public interface SpELExpressionEvaluator { @@ -28,5 +30,6 @@ public interface SpELExpressionEvaluator {
* @param expression
* @return
*/
@Nullable
<T> T evaluate(String expression);
}
}

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

@ -15,50 +15,34 @@ @@ -15,50 +15,34 @@
*/
package org.springframework.data.mapping.model;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.util.Assert;
import org.springframework.lang.Nullable;
/**
* {@link ParameterValueProvider} that can be used to front a {@link ParameterValueProvider} delegate to prefer a Spel
* {@link ParameterValueProvider} that can be used to front a {@link ParameterValueProvider} delegate to prefer a SpEL
* expression evaluation over directly resolving the parameter value with the delegate.
*
* @author Oliver Gierke
* @author Mark Paluch
*/
@RequiredArgsConstructor
public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P>>
implements ParameterValueProvider<P> {
private final SpELExpressionEvaluator evaluator;
private final ParameterValueProvider<P> delegate;
private final ConversionService conversionService;
/**
* Creates a new {@link SpELExpressionParameterValueProvider} using the given {@link SpELExpressionEvaluator},
* {@link ConversionService} and {@link ParameterValueProvider} delegate to forward calls to, that resolve parameters
* that do not have a Spel expression configured with them.
*
* @param evaluator must not be {@literal null}.
* @param conversionService must not be {@literal null}.
* @param delegate must not be {@literal null}.
*/
public SpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator, ConversionService conversionService,
ParameterValueProvider<P> delegate) {
Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null!");
Assert.notNull(conversionService, "ConversionService must not be null!");
Assert.notNull(delegate, "ParameterValueProvider delegate must not be null!");
this.evaluator = evaluator;
this.conversionService = conversionService;
this.delegate = delegate;
}
private final @NonNull SpELExpressionEvaluator evaluator;
private final @NonNull ConversionService conversionService;
private final @NonNull ParameterValueProvider<P> delegate;
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
*/
@Nullable
public <T> T getParameterValue(Parameter<T, P> parameter) {
if (!parameter.hasSpelExpression()) {
@ -77,6 +61,7 @@ public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P @@ -77,6 +61,7 @@ public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P
* @param parameter the {@link Parameter} we create the value for
* @return
*/
@Nullable
protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, P> parameter) {
return conversionService.convert(object, parameter.getRawType());
}

3
src/main/java/org/springframework/data/mapping/model/package-info.java

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/**
* Core implementation of the mapping subsystem's model.
*/
package org.springframework.data.mapping.model;
@org.springframework.lang.NonNullApi
package org.springframework.data.mapping.model;

3
src/main/java/org/springframework/data/mapping/package-info.java

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/**
* Base package for the mapping subsystem.
*/
package org.springframework.data.mapping;
@org.springframework.lang.NonNullApi
package org.springframework.data.mapping;

10
src/main/java/org/springframework/data/projection/Accessor.java

@ -44,10 +44,14 @@ public final class Accessor { @@ -44,10 +44,14 @@ public final class Accessor {
Assert.notNull(method, "Method must not be null!");
this.descriptor = BeanUtils.findPropertyForMethod(method);
this.method = method;
PropertyDescriptor descriptor = BeanUtils.findPropertyForMethod(method);
if (descriptor == null) {
throw new IllegalArgumentException(String.format("Invoked method %s is no accessor method!", method));
}
Assert.notNull(descriptor, () -> String.format("Invoked method %s is no accessor method!", method));
this.descriptor = descriptor;
this.method = method;
}
/**

5
src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java

@ -25,6 +25,8 @@ import java.util.Arrays; @@ -25,6 +25,8 @@ import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.ProxyMethodInvocation;
@ -48,8 +50,9 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor @@ -48,8 +50,9 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor
* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
@Nullable
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();

7
src/main/java/org/springframework/data/projection/MapAccessingMethodInterceptor.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +21,8 @@ import lombok.RequiredArgsConstructor; @@ -21,6 +21,8 @@ import lombok.RequiredArgsConstructor;
import java.lang.reflect.Method;
import java.util.Map;
import javax.annotation.Nullable;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.util.ReflectionUtils;
@ -40,8 +42,9 @@ class MapAccessingMethodInterceptor implements MethodInterceptor { @@ -40,8 +42,9 @@ class MapAccessingMethodInterceptor implements MethodInterceptor {
* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
@Nullable
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();

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

@ -26,12 +26,15 @@ import java.util.List; @@ -26,12 +26,15 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nonnull;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@ -54,8 +57,9 @@ class ProjectingMethodInterceptor implements MethodInterceptor { @@ -54,8 +57,9 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
@Nullable
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
public Object invoke(@SuppressWarnings("null") @Nonnull MethodInvocation invocation) throws Throwable {
Object result = delegate.invoke(invocation);
@ -121,6 +125,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor { @@ -121,6 +125,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
return result;
}
@Nullable
private Object getProjection(Object result, Class<?> returnType) {
return result == null || ClassUtils.isAssignable(returnType, result.getClass()) ? result
: factory.createProjection(returnType, result);

16
src/main/java/org/springframework/data/projection/ProjectionFactory.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.projection;
import org.springframework.lang.Nullable;
/**
* A factory to create projecting instances for other objects usually used to allow easy creation of representation
* projections to define which properties of a domain objects shall be exported in which way.
@ -29,11 +31,23 @@ public interface ProjectionFactory { @@ -29,11 +31,23 @@ public interface ProjectionFactory {
* the implementations.
*
* @param projectionType the type to create, must not be {@literal null}.
* @param source the object to create a projection for, can be {@literal null}
* @param source the object to create a projection for, must not be {@literal null}.
* @return
*/
<T> T createProjection(Class<T> projectionType, Object source);
/**
* Creates a projection to the given type for the given nullable source.
*
* @param projectionType must not be {@literal null}.
* @param source can be {@literal null}.
* @return
*/
@Nullable
default <T> T createNullableProjection(Class<T> projectionType, @Nullable Object source) {
return source == null ? null : createProjection(projectionType, source);
}
/**
* Creates a projection instance for the given type.
*

4
src/main/java/org/springframework/data/projection/PropertyAccessingMethodInterceptor.java

@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInvocation; @@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@ -52,8 +53,9 @@ class PropertyAccessingMethodInterceptor implements MethodInterceptor { @@ -52,8 +53,9 @@ class PropertyAccessingMethodInterceptor implements MethodInterceptor {
* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
@Nullable
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();

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

Loading…
Cancel
Save