Browse Source

Merge branch 'main' of https://github.com/spring-projects/spring-data-commons into remote-unused-import

Signed-off-by: Tran Ngoc Nhan <ngocnhan.tran1996@gmail.com>

# Conflicts:
#	src/test/java/org/springframework/data/repository/query/ParameterUnitTests.java
pull/3315/head
Tran Ngoc Nhan 2 months ago
parent
commit
1a6fce1e0c
  1. 5
      src/main/antora/modules/ROOT/pages/auditing.adoc
  2. 2
      src/main/java/org/springframework/data/aot/AotMappingContext.java
  3. 2
      src/main/java/org/springframework/data/aot/AuditingBeanRegistrationAotProcessor.java
  4. 10
      src/main/java/org/springframework/data/auditing/AuditingHandler.java
  5. 10
      src/main/java/org/springframework/data/auditing/ReactiveAuditingHandler.java
  6. 13
      src/main/java/org/springframework/data/auditing/config/AuditingBeanDefinitionRegistrarSupport.java
  7. 2
      src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java
  8. 2
      src/main/java/org/springframework/data/convert/CustomConversions.java
  9. 2
      src/main/java/org/springframework/data/convert/DefaultTypeMapper.java
  10. 2
      src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java
  11. 2
      src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java
  12. 2
      src/main/java/org/springframework/data/convert/TypeInformationMapper.java
  13. 2
      src/main/java/org/springframework/data/convert/TypeMapper.java
  14. 2
      src/main/java/org/springframework/data/convert/ValueConversionContext.java
  15. 2
      src/main/java/org/springframework/data/core/ClassTypeInformation.java
  16. 2
      src/main/java/org/springframework/data/core/CustomCollectionRegistrar.java
  17. 2
      src/main/java/org/springframework/data/core/CustomCollections.java
  18. 2
      src/main/java/org/springframework/data/core/NullableWrapper.java
  19. 4
      src/main/java/org/springframework/data/core/NullableWrapperConverters.java
  20. 3
      src/main/java/org/springframework/data/core/PropertyPath.java
  21. 3
      src/main/java/org/springframework/data/core/PropertyReferenceException.java
  22. 3
      src/main/java/org/springframework/data/core/ReactiveWrappers.java
  23. 3
      src/main/java/org/springframework/data/core/SimplePropertyPath.java
  24. 4
      src/main/java/org/springframework/data/core/TypeDiscoverer.java
  25. 3
      src/main/java/org/springframework/data/core/TypeInformation.java
  26. 5
      src/main/java/org/springframework/data/core/package-info.java
  27. 2
      src/main/java/org/springframework/data/mapping/Parameter.java
  28. 2
      src/main/java/org/springframework/data/mapping/PersistentEntity.java
  29. 2
      src/main/java/org/springframework/data/mapping/PersistentProperty.java
  30. 1
      src/main/java/org/springframework/data/mapping/PersistentPropertyPaths.java
  31. 8
      src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java
  32. 2
      src/main/java/org/springframework/data/mapping/context/DefaultPersistentPropertyPath.java
  33. 2
      src/main/java/org/springframework/data/mapping/context/InvalidPersistentPropertyPath.java
  34. 4
      src/main/java/org/springframework/data/mapping/context/MappingContext.java
  35. 2
      src/main/java/org/springframework/data/mapping/context/PersistentEntities.java
  36. 4
      src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java
  37. 2
      src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java
  38. 2
      src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java
  39. 2
      src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java
  40. 2
      src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java
  41. 2
      src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java
  42. 2
      src/main/java/org/springframework/data/mapping/model/InstanceCreatorMetadataDiscoverer.java
  43. 17
      src/main/java/org/springframework/data/mapping/model/KotlinClassGeneratingEntityInstantiator.java
  44. 7
      src/main/java/org/springframework/data/mapping/model/KotlinDefaultMask.java
  45. 228
      src/main/java/org/springframework/data/mapping/model/KotlinInstantiationDelegate.java
  46. 2
      src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java
  47. 2
      src/main/java/org/springframework/data/mapping/model/Property.java
  48. 14
      src/main/java/org/springframework/data/mapping/model/ReflectionEntityInstantiator.java
  49. 4
      src/main/java/org/springframework/data/projection/EntityProjection.java
  50. 8
      src/main/java/org/springframework/data/projection/EntityProjectionIntrospector.java
  51. 6
      src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java
  52. 3
      src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java
  53. 2
      src/main/java/org/springframework/data/querydsl/aot/QuerydslHints.java
  54. 2
      src/main/java/org/springframework/data/querydsl/binding/PathInformation.java
  55. 4
      src/main/java/org/springframework/data/querydsl/binding/PropertyPathInformation.java
  56. 6
      src/main/java/org/springframework/data/querydsl/binding/QuerydslBindings.java
  57. 2
      src/main/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactory.java
  58. 4
      src/main/java/org/springframework/data/querydsl/binding/QuerydslPredicateBuilder.java
  59. 3
      src/main/java/org/springframework/data/repository/aot/generate/MethodMetadata.java
  60. 2
      src/main/java/org/springframework/data/repository/aot/generate/MethodReturn.java
  61. 2
      src/main/java/org/springframework/data/repository/aot/generate/ResolvableGenerics.java
  62. 2
      src/main/java/org/springframework/data/repository/aot/hint/RepositoryRuntimeHints.java
  63. 2
      src/main/java/org/springframework/data/repository/core/RepositoryInformationSupport.java
  64. 2
      src/main/java/org/springframework/data/repository/core/RepositoryMetadata.java
  65. 4
      src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java
  66. 4
      src/main/java/org/springframework/data/repository/core/support/AnnotationRepositoryMetadata.java
  67. 2
      src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryMetadata.java
  68. 2
      src/main/java/org/springframework/data/repository/core/support/MethodLookups.java
  69. 4
      src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java
  70. 2
      src/main/java/org/springframework/data/repository/core/support/ReactiveRepositoryFactorySupport.java
  71. 2
      src/main/java/org/springframework/data/repository/core/support/RepositoryComposition.java
  72. 2
      src/main/java/org/springframework/data/repository/core/support/RepositoryMethodInvoker.java
  73. 2
      src/main/java/org/springframework/data/repository/query/Parameter.java
  74. 2
      src/main/java/org/springframework/data/repository/query/ParametersSource.java
  75. 7
      src/main/java/org/springframework/data/repository/query/QueryMethod.java
  76. 2
      src/main/java/org/springframework/data/repository/query/QueryMethodValueEvaluationContextAccessor.java
  77. 2
      src/main/java/org/springframework/data/repository/query/parser/OrderBySource.java
  78. 2
      src/main/java/org/springframework/data/repository/query/parser/Part.java
  79. 2
      src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java
  80. 11
      src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java
  81. 22
      src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java
  82. 1
      src/main/java/org/springframework/data/spel/spi/Function.java
  83. 369
      src/main/java/org/springframework/data/spel/spi/ParameterTypes.java
  84. 2
      src/main/java/org/springframework/data/util/ParameterTypes.java
  85. 2
      src/main/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactory.java
  86. 6
      src/main/java/org/springframework/data/web/MapDataBinder.java
  87. 2
      src/main/java/org/springframework/data/web/querydsl/QuerydslPredicateArgumentResolverSupport.java
  88. 2
      src/main/kotlin/org/springframework/data/mapping/KPropertyPathExtensions.kt
  89. 6
      src/main/resources/META-INF/spring.factories
  90. 2
      src/test/java/org/springframework/data/aot/AotMappingContextUnitTests.java
  91. 99
      src/test/java/org/springframework/data/auditing/config/AuditingBeanDefinitionRegistrarSupportUnitTests.java
  92. 3
      src/test/java/org/springframework/data/convert/ConfigurableTypeInformationMapperUnitTests.java
  93. 3
      src/test/java/org/springframework/data/convert/DefaultTypeMapperUnitTests.java
  94. 3
      src/test/java/org/springframework/data/convert/MappingContextTypeInformationMapperUnitTests.java
  95. 3
      src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java
  96. 10
      src/test/java/org/springframework/data/core/ClassTypeInformationUnitTests.java
  97. 4
      src/test/java/org/springframework/data/core/CustomCollectionsUnitTests.java
  98. 4
      src/test/java/org/springframework/data/core/DataCmns511Tests.java
  99. 4
      src/test/java/org/springframework/data/core/NullableWrapperConvertersUnitTests.java
  100. 7
      src/test/java/org/springframework/data/core/PropertyPathUnitTests.java
  101. Some files were not shown because too many files have changed in this diff Show More

5
src/main/antora/modules/ROOT/pages/auditing.adoc

@ -3,13 +3,16 @@ @@ -3,13 +3,16 @@
[[auditing.basics]]
== Basics
Spring Data provides sophisticated support to transparently keep track of who created or changed an entity and when the change happened.To benefit from that functionality, you have to equip your entity classes with auditing metadata that can be defined either using annotations or by implementing an interface.
Spring Data provides sophisticated support to transparently keep track of who created or changed an entity and when the change happened.
To benefit from that functionality, you have to equip your entity classes with auditing metadata that can be defined either using annotations or by implementing an interface.
Additionally, auditing has to be enabled either through Annotation configuration or XML configuration to register the required infrastructure components.
Please refer to the store-specific section for configuration samples.
[NOTE]
====
Applications that only track creation and modification dates are not required do make their entities implement <<auditing.auditor-aware,`AuditorAware`>>.
If no `AuditorAware` or `DateTimeProvider` bean is configured, `AuditingHandler` will use Spring's autowiring to detect a matching bean if beans of the corresponding type are available in the application context.
====
[[auditing.annotations]]

2
src/main/java/org/springframework/data/aot/AotMappingContext.java

@ -21,6 +21,7 @@ import java.time.LocalDateTime; @@ -21,6 +21,7 @@ import java.time.LocalDateTime;
import java.util.UUID;
import java.util.function.Predicate;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Page;
import org.springframework.data.geo.Point;
import org.springframework.data.mapping.Association;
@ -34,7 +35,6 @@ import org.springframework.data.mapping.model.EntityInstantiatorSource; @@ -34,7 +35,6 @@ import org.springframework.data.mapping.model.EntityInstantiatorSource;
import org.springframework.data.mapping.model.EntityInstantiators;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
/**
* Simple {@link AbstractMappingContext} for processing of AOT contributions.

2
src/main/java/org/springframework/data/aot/AuditingBeanRegistrationAotProcessor.java

@ -25,9 +25,9 @@ import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; @@ -25,9 +25,9 @@ import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.core.DecoratingProxy;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.domain.ReactiveAuditorAware;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.util.ClassUtils;
/**

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

@ -19,6 +19,8 @@ import java.util.Optional; @@ -19,6 +19,8 @@ import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.mapping.context.MappingContext;
@ -66,12 +68,10 @@ public class AuditingHandler extends AuditingHandlerSupport implements Initializ @@ -66,12 +68,10 @@ public class AuditingHandler extends AuditingHandlerSupport implements Initializ
/**
* Setter to inject a {@code AuditorAware} component to retrieve the current auditor.
*
* @param auditorAware must not be {@literal null}.
* @param auditorAware can be {@literal null} if no auditor-aware is available.
*/
public void setAuditorAware(AuditorAware<?> auditorAware) {
Assert.notNull(auditorAware, "AuditorAware must not be null");
this.auditorAware = Optional.of(auditorAware);
public void setAuditorAware(@Nullable AuditorAware<?> auditorAware) {
this.auditorAware = Optional.ofNullable(auditorAware);
}
/**

10
src/main/java/org/springframework/data/auditing/ReactiveAuditingHandler.java

@ -17,6 +17,8 @@ package org.springframework.data.auditing; @@ -17,6 +17,8 @@ package org.springframework.data.auditing;
import reactor.core.publisher.Mono;
import org.jspecify.annotations.Nullable;
import org.springframework.data.domain.ReactiveAuditorAware;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentEntities;
@ -56,12 +58,10 @@ public class ReactiveAuditingHandler extends AuditingHandlerSupport { @@ -56,12 +58,10 @@ public class ReactiveAuditingHandler extends AuditingHandlerSupport {
/**
* Setter to inject a {@link ReactiveAuditorAware} component to retrieve the current auditor.
*
* @param auditorAware must not be {@literal null}.
* @param auditorAware can be {@literal null}.
*/
public void setAuditorAware(ReactiveAuditorAware<?> auditorAware) {
Assert.notNull(auditorAware, "AuditorAware must not be null");
this.auditorAware = auditorAware;
public void setAuditorAware(@Nullable ReactiveAuditorAware<?> auditorAware) {
this.auditorAware = auditorAware == null ? Mono::empty : auditorAware;
}
/**

13
src/main/java/org/springframework/data/auditing/config/AuditingBeanDefinitionRegistrarSupport.java

@ -21,7 +21,6 @@ import java.lang.annotation.Annotation; @@ -21,7 +21,6 @@ import java.lang.annotation.Annotation;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.target.LazyInitTargetSource;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@ -29,7 +28,6 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry; @@ -29,7 +28,6 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.auditing.AuditingHandler;
import org.springframework.data.auditing.CurrentDateTimeProvider;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -42,6 +40,7 @@ import org.springframework.util.StringUtils; @@ -42,6 +40,7 @@ import org.springframework.util.StringUtils;
* @author Thomas Darimont
* @author Oliver Gierke
* @author Francisco Soler
* @author Jaeyeon Kim
*/
public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar {
@ -120,8 +119,9 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe @@ -120,8 +119,9 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe
if (StringUtils.hasText(configuration.getAuditorAwareRef())) {
builder.addPropertyValue(AUDITOR_AWARE,
createLazyInitTargetSourceBeanDefinition(configuration.getAuditorAwareRef()));
} else {
builder.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);
}
else {
builder.addAutowiredProperty(AUDITOR_AWARE);
}
builder.addPropertyValue(SET_DATES, configuration.isSetDates());
@ -129,8 +129,9 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe @@ -129,8 +129,9 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe
if (StringUtils.hasText(configuration.getDateTimeProviderRef())) {
builder.addPropertyReference(DATE_TIME_PROVIDER, configuration.getDateTimeProviderRef());
} else {
builder.addPropertyValue(DATE_TIME_PROVIDER, CurrentDateTimeProvider.INSTANCE);
}
else {
builder.addAutowiredProperty(DATE_TIME_PROVIDER);
}
builder.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);

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

@ -21,10 +21,10 @@ import java.util.Map.Entry; @@ -21,10 +21,10 @@ import java.util.Map.Entry;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -34,9 +34,9 @@ import org.springframework.core.convert.converter.GenericConverter; @@ -34,9 +34,9 @@ import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.convert.ConverterBuilder.ConverterAware;
import org.springframework.data.core.CustomCollections;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.CustomCollections;
import org.springframework.data.util.Predicates;
import org.springframework.data.util.Streamable;
import org.springframework.util.Assert;

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

@ -26,10 +26,10 @@ import java.util.function.Function; @@ -26,10 +26,10 @@ import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -20,11 +20,11 @@ import java.util.concurrent.ConcurrentHashMap; @@ -20,11 +20,11 @@ import java.util.concurrent.ConcurrentHashMap;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -22,8 +22,8 @@ import java.util.concurrent.ConcurrentHashMap; @@ -22,8 +22,8 @@ import java.util.concurrent.ConcurrentHashMap;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.ClassUtils;
/**

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

@ -17,8 +17,8 @@ package org.springframework.data.convert; @@ -17,8 +17,8 @@ package org.springframework.data.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.util.TypeInformation;
/**
* Interface to abstract the mapping from a type alias to the actual type.

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

@ -17,7 +17,7 @@ package org.springframework.data.convert; @@ -17,7 +17,7 @@ package org.springframework.data.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.util.TypeInformation;
import org.springframework.data.core.TypeInformation;
/**
* Interface to define strategies how to store type information in a store specific sink or source.

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

@ -17,8 +17,8 @@ package org.springframework.data.convert; @@ -17,8 +17,8 @@ package org.springframework.data.convert;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.TypeInformation;
/**
* The {@link ValueConversionContext} provides access to the store-specific {@link PersistentProperty} and allows to

2
src/main/java/org/springframework/data/util/ClassTypeInformation.java → src/main/java/org/springframework/data/core/ClassTypeInformation.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import java.util.List;
import java.util.Map;

2
src/main/java/org/springframework/data/util/CustomCollectionRegistrar.java → src/main/java/org/springframework/data/core/CustomCollectionRegistrar.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import java.util.Collection;
import java.util.Collections;

2
src/main/java/org/springframework/data/util/CustomCollections.java → src/main/java/org/springframework/data/core/CustomCollections.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import io.vavr.collection.HashMap;
import io.vavr.collection.LinkedHashMap;

2
src/main/java/org/springframework/data/util/NullableWrapper.java → src/main/java/org/springframework/data/core/NullableWrapper.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import org.jspecify.annotations.Nullable;

4
src/main/java/org/springframework/data/util/NullableWrapperConverters.java → src/main/java/org/springframework/data/core/NullableWrapperConverters.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import scala.Function0;
import scala.Option;
@ -31,6 +31,8 @@ import org.springframework.core.convert.TypeDescriptor; @@ -31,6 +31,8 @@ import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.Streamable;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

3
src/main/java/org/springframework/data/mapping/PropertyPath.java → src/main/java/org/springframework/data/core/PropertyPath.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping;
package org.springframework.data.core;
import java.util.Iterator;
import java.util.regex.Pattern;
@ -21,7 +21,6 @@ import java.util.regex.Pattern; @@ -21,7 +21,6 @@ import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

3
src/main/java/org/springframework/data/mapping/PropertyReferenceException.java → src/main/java/org/springframework/data/core/PropertyReferenceException.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping;
package org.springframework.data.core;
import java.io.Serial;
import java.util.Arrays;
@ -26,7 +26,6 @@ import org.jspecify.annotations.Nullable; @@ -26,7 +26,6 @@ import org.jspecify.annotations.Nullable;
import org.springframework.beans.PropertyMatches;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

3
src/main/java/org/springframework/data/util/ReactiveWrappers.java → src/main/java/org/springframework/data/core/ReactiveWrappers.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -28,6 +28,7 @@ import org.jspecify.annotations.Nullable; @@ -28,6 +28,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.ReactiveAdapter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ReactiveTypeDescriptor;
import org.springframework.data.util.ProxyUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;

3
src/main/java/org/springframework/data/mapping/SimplePropertyPath.java → src/main/java/org/springframework/data/core/SimplePropertyPath.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping;
package org.springframework.data.core;
import java.beans.Introspector;
import java.util.ArrayList;
@ -28,7 +28,6 @@ import java.util.regex.Pattern; @@ -28,7 +28,6 @@ import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.StringUtils;

4
src/main/java/org/springframework/data/util/TypeDiscoverer.java → src/main/java/org/springframework/data/core/TypeDiscoverer.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
@ -34,6 +34,8 @@ import org.springframework.beans.BeanUtils; @@ -34,6 +34,8 @@ import org.springframework.beans.BeanUtils;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Streamable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentLruCache;
import org.springframework.util.ObjectUtils;

3
src/main/java/org/springframework/data/util/TypeInformation.java → src/main/java/org/springframework/data/core/TypeInformation.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@ -28,6 +28,7 @@ import org.jspecify.annotations.Nullable; @@ -28,6 +28,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.util.ProxyUtils;
import org.springframework.util.Assert;
/**

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

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
/**
* Provides basic classes for type handling and other core helpers that are not specific to any part of the framework.
*/
@org.jspecify.annotations.NullMarked
package org.springframework.data.core;

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

@ -22,8 +22,8 @@ import org.jspecify.annotations.Nullable; @@ -22,8 +22,8 @@ import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

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

@ -21,7 +21,7 @@ import java.util.Iterator; @@ -21,7 +21,7 @@ import java.util.Iterator;
import org.jspecify.annotations.Nullable;
import org.springframework.data.annotation.Immutable;
import org.springframework.data.util.TypeInformation;
import org.springframework.data.core.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -25,7 +25,7 @@ import org.jspecify.annotations.Nullable; @@ -25,7 +25,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.data.core.TypeInformation;
import org.springframework.util.Assert;
/**

1
src/main/java/org/springframework/data/mapping/PersistentPropertyPaths.java

@ -18,6 +18,7 @@ package org.springframework.data.mapping; @@ -18,6 +18,7 @@ package org.springframework.data.mapping;
import java.util.Optional;
import java.util.function.Predicate;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.util.Streamable;
/**

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

@ -50,13 +50,16 @@ import org.springframework.context.EnvironmentAware; @@ -50,13 +50,16 @@ import org.springframework.context.EnvironmentAware;
import org.springframework.core.KotlinDetector;
import org.springframework.core.NativeDetector;
import org.springframework.core.env.Environment;
import org.springframework.data.core.CustomCollections;
import org.springframework.data.core.NullableWrapperConverters;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.ManagedTypes;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PersistentPropertyPaths;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory;
import org.springframework.data.mapping.model.EntityInstantiators;
import org.springframework.data.mapping.model.InstantiationAwarePropertyAccessorFactory;
@ -66,12 +69,9 @@ import org.springframework.data.mapping.model.Property; @@ -66,12 +69,9 @@ import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.spel.EvaluationContextProvider;
import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider;
import org.springframework.data.util.CustomCollections;
import org.springframework.data.util.KotlinReflectionUtils;
import org.springframework.data.util.NullableWrapperConverters;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;

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

@ -23,9 +23,9 @@ import java.util.List; @@ -23,9 +23,9 @@ import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

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

@ -23,10 +23,10 @@ import java.util.Set; @@ -23,10 +23,10 @@ import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.PropertyMatches;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

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

@ -20,13 +20,13 @@ import java.util.function.Predicate; @@ -20,13 +20,13 @@ import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PersistentPropertyPaths;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.util.TypeInformation;
/**
* This interface defines the overall context including all known PersistentEntity instances and methods to obtain

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

@ -29,12 +29,12 @@ import java.util.stream.StreamSupport; @@ -29,12 +29,12 @@ import java.util.stream.StreamSupport;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

4
src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java

@ -24,16 +24,16 @@ import java.util.stream.Stream; @@ -24,16 +24,16 @@ import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PersistentPropertyPaths;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.util.Pair;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

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

@ -26,6 +26,7 @@ import java.util.stream.Collectors; @@ -26,6 +26,7 @@ import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
@ -33,7 +34,6 @@ import org.springframework.data.util.ClassUtils; @@ -33,7 +34,6 @@ import org.springframework.data.util.ClassUtils;
import org.springframework.data.util.KotlinReflectionUtils;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -35,6 +35,7 @@ import org.springframework.data.annotation.ReadOnlyProperty; @@ -35,6 +35,7 @@ import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Reference;
import org.springframework.data.annotation.Transient;
import org.springframework.data.annotation.Version;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentEntity;
@ -43,7 +44,6 @@ import org.springframework.data.util.ClassUtils; @@ -43,7 +44,6 @@ import org.springframework.data.util.ClassUtils;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -38,6 +38,7 @@ import org.springframework.core.env.EnvironmentCapable; @@ -38,6 +38,7 @@ import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.data.annotation.Immutable;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Persistable;
import org.springframework.data.expression.ValueEvaluationContext;
import org.springframework.data.mapping.*;
@ -46,7 +47,6 @@ import org.springframework.data.spel.ExpressionDependencies; @@ -46,7 +47,6 @@ import org.springframework.data.spel.ExpressionDependencies;
import org.springframework.data.support.IsNewStrategy;
import org.springframework.data.support.PersistableIsNewStrategy;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.EvaluationContext;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

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

@ -37,13 +37,13 @@ import org.springframework.beans.BeanInstantiationException; @@ -37,13 +37,13 @@ import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.core.NativeDetector;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.FactoryMethod;
import org.springframework.data.mapping.InstanceCreatorMetadata;
import org.springframework.data.mapping.Parameter;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

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

@ -49,6 +49,7 @@ import org.springframework.asm.Opcodes; @@ -49,6 +49,7 @@ import org.springframework.asm.Opcodes;
import org.springframework.asm.Type;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.core.KotlinDetector;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
@ -57,7 +58,6 @@ import org.springframework.data.mapping.SimplePropertyHandler; @@ -57,7 +58,6 @@ import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.mapping.model.KotlinCopyMethod.KotlinCopyByProperty;
import org.springframework.data.mapping.model.KotlinValueUtils.ValueBoxing;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentLruCache;

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

@ -35,13 +35,13 @@ import org.springframework.core.KotlinDetector; @@ -35,13 +35,13 @@ import org.springframework.core.KotlinDetector;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.data.annotation.PersistenceCreator;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.FactoryMethod;
import org.springframework.data.mapping.InstanceCreatorMetadata;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.Parameter;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.TypeInformation;
/**
* Discoverer for factory methods and persistence constructors.

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

@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
*/
package org.springframework.data.mapping.model;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import org.springframework.data.mapping.InstanceCreatorMetadata;
@ -43,15 +42,11 @@ class KotlinClassGeneratingEntityInstantiator extends ClassGeneratingEntityInsta @@ -43,15 +42,11 @@ class KotlinClassGeneratingEntityInstantiator extends ClassGeneratingEntityInsta
if (KotlinReflectionUtils.isSupportedKotlinClass(entity.getType())
&& creator instanceof PreferredConstructor<?, ?> constructor) {
PreferredConstructor<?, ? extends PersistentProperty<?>> kotlinJvmConstructor = KotlinInstantiationDelegate
.resolveKotlinJvmConstructor(constructor);
KotlinInstantiationDelegate delegate = KotlinInstantiationDelegate.resolve(constructor);
if (kotlinJvmConstructor != null) {
ObjectInstantiator instantiator = createObjectInstantiator(entity, kotlinJvmConstructor);
return new DefaultingKotlinClassInstantiatorAdapter(instantiator, constructor,
kotlinJvmConstructor.getConstructor());
if (delegate != null) {
ObjectInstantiator instantiator = createObjectInstantiator(entity, delegate.getInstanceCreator());
return new DefaultingKotlinClassInstantiatorAdapter(instantiator, delegate);
}
}
@ -82,10 +77,10 @@ class KotlinClassGeneratingEntityInstantiator extends ClassGeneratingEntityInsta @@ -82,10 +77,10 @@ class KotlinClassGeneratingEntityInstantiator extends ClassGeneratingEntityInsta
private final KotlinInstantiationDelegate delegate;
DefaultingKotlinClassInstantiatorAdapter(ObjectInstantiator instantiator,
PreferredConstructor<?, ?> defaultConstructor, Constructor<?> constructorToInvoke) {
KotlinInstantiationDelegate delegate) {
this.instantiator = instantiator;
this.delegate = new KotlinInstantiationDelegate(defaultConstructor, constructorToInvoke);
this.delegate = delegate;
}
@Override

7
src/main/java/org/springframework/data/mapping/model/KotlinDefaultMask.java

@ -148,7 +148,12 @@ public class KotlinDefaultMask { @@ -148,7 +148,12 @@ public class KotlinDefaultMask {
masks.add(mask);
}
return new KotlinDefaultMask(masks.stream().mapToInt(i -> i).toArray());
int[] defaulting = new int[masks.size()];
for (int i = 0; i < masks.size(); i++) {
defaulting[i] = masks.get(i);
}
return new KotlinDefaultMask(defaulting);
}
public int[] getDefaulting() {

228
src/main/java/org/springframework/data/mapping/model/KotlinInstantiationDelegate.java

@ -20,12 +20,12 @@ import kotlin.reflect.KParameter; @@ -20,12 +20,12 @@ import kotlin.reflect.KParameter;
import kotlin.reflect.jvm.ReflectJvmMapping;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.IntStream;
import org.jspecify.annotations.Nullable;
@ -48,33 +48,27 @@ import org.springframework.data.util.ReflectionUtils; @@ -48,33 +48,27 @@ import org.springframework.data.util.ReflectionUtils;
*/
class KotlinInstantiationDelegate {
private final KFunction<?> constructor;
private final PreferredConstructor<?, ?> constructor;
private final KFunction<?> constructorFunction;
private final List<KParameter> kParameters;
private final Map<KParameter, Integer> indexByKParameter;
private final List<Function<@Nullable Object, @Nullable Object>> wrappers = new ArrayList<>();
private final Constructor<?> constructorToInvoke;
private final List<Function<@Nullable Object, @Nullable Object>> wrappers;
private final boolean hasDefaultConstructorMarker;
public KotlinInstantiationDelegate(PreferredConstructor<?, ?> preferredConstructor,
Constructor<?> constructorToInvoke) {
private KotlinInstantiationDelegate(PreferredConstructor<?, ?> constructor, KFunction<?> constructorFunction) {
KFunction<?> kotlinConstructor = ReflectJvmMapping.getKotlinFunction(preferredConstructor.getConstructor());
this.constructor = constructor;
this.hasDefaultConstructorMarker = hasDefaultConstructorMarker(getConstructor().getParameters());
if (kotlinConstructor == null) {
throw new IllegalArgumentException(
"No corresponding Kotlin constructor found for " + preferredConstructor.getConstructor());
}
this.constructor = kotlinConstructor;
this.kParameters = kotlinConstructor.getParameters();
this.indexByKParameter = new IdentityHashMap<>();
this.constructorFunction = constructorFunction;
this.kParameters = constructorFunction.getParameters();
this.indexByKParameter = new IdentityHashMap<>(kParameters.size());
for (int i = 0; i < kParameters.size(); i++) {
indexByKParameter.put(kParameters.get(i), i);
}
this.constructorToInvoke = constructorToInvoke;
this.hasDefaultConstructorMarker = hasDefaultConstructorMarker(constructorToInvoke.getParameters());
this.wrappers = new ArrayList<>(kParameters.size());
for (KParameter kParameter : kParameters) {
@ -83,21 +77,32 @@ class KotlinInstantiationDelegate { @@ -83,21 +77,32 @@ class KotlinInstantiationDelegate {
}
}
static boolean hasDefaultConstructorMarker(java.lang.reflect.Parameter[] parameters) {
/**
* @return the constructor to invoke. {@link PreferredConstructor#getParameters() Constructor parameters} describe the
* detected (i.e. user-facing) constructor parameters and not {@link PreferredConstructor#getConstructor()}
* parameters and therefore do not contain any synthetic parameters.
* @since 4.0
*/
public InstanceCreatorMetadata<?> getInstanceCreator() {
return constructor;
}
return parameters.length > 0
&& parameters[parameters.length - 1].getType().getName().equals("kotlin.jvm.internal.DefaultConstructorMarker");
/**
* @return the constructor to invoke. {@link PreferredConstructor#getParameters() Constructor parameters} describe the
* detected (i.e. user-facing) constructor parameters and not {@link PreferredConstructor#getConstructor()}
* parameters and therefore do not contain any synthetic parameters.
* @since 4.0
*/
public Constructor<?> getConstructor() {
return constructor.getConstructor();
}
/**
* @return number of constructor arguments.
* @return number of actual constructor arguments.
* @see #getConstructor()
*/
public int getRequiredParameterCount() {
return hasDefaultConstructorMarker ? constructorToInvoke.getParameterCount()
: (constructorToInvoke.getParameterCount()
+ KotlinDefaultMask.getMaskCount(constructorToInvoke.getParameterCount())
+ /* DefaultConstructorMarker */1);
return getConstructor().getParameterCount();
}
/**
@ -112,7 +117,6 @@ class KotlinInstantiationDelegate { @@ -112,7 +117,6 @@ class KotlinInstantiationDelegate {
}
int userParameterCount = kParameters.size();
List<Parameter<Object, P>> parameters = entityCreator.getParameters();
// Prepare user-space arguments
@ -122,53 +126,83 @@ class KotlinInstantiationDelegate { @@ -122,53 +126,83 @@ class KotlinInstantiationDelegate {
params[i] = provider.getParameterValue(parameter);
}
KotlinDefaultMask defaultMask = KotlinDefaultMask.forConstructor(constructor, it -> {
// late rewrapping to indicate potential absence of parameters for defaulting
for (int i = 0; i < userParameterCount; i++) {
params[i] = wrappers.get(i).apply(params[i]);
}
if (hasDefaultConstructorMarker) {
int index = indexByKParameter.get(it);
KotlinDefaultMask defaultMask = KotlinDefaultMask.forConstructor(constructorFunction, it -> {
Parameter<Object, P> parameter = parameters.get(index);
Class<Object> type = parameter.getType().getType();
int index = indexByKParameter.get(it);
if (it.isOptional() && (params[index] == null)) {
if (type.isPrimitive()) {
Parameter<Object, P> parameter = parameters.get(index);
Class<Object> type = parameter.getType().getType();
// apply primitive defaulting to prevent NPE on primitive downcast
params[index] = ReflectionUtils.getPrimitiveDefault(type);
if (it.isOptional() && (params[index] == null)) {
if (type.isPrimitive()) {
// apply primitive defaulting to prevent NPE on primitive downcast
params[index] = ReflectionUtils.getPrimitiveDefault(type);
}
return false;
}
return false;
}
return true;
});
return true;
});
// late rewrapping to indicate potential absence of parameters for defaulting
for (int i = 0; i < userParameterCount; i++) {
params[i] = wrappers.get(i).apply(params[i]);
int[] defaulting = defaultMask.getDefaulting();
// append nullability masks to creation arguments
for (int i = 0; i < defaulting.length; i++) {
params[userParameterCount + i] = defaulting[i];
}
}
}
/**
* Try to resolve {@code KotlinInstantiationDelegate} from a {@link PreferredConstructor}. Resolution attempts to find
* a JVM constructor equivalent considering value class mangling, Kotlin defaulting and potentially synthetic
* constructors generated by the Kotlin compile including the lookup of a {@link KFunction} from the given
* {@link PreferredConstructor}.
*
* @return the {@code KotlinInstantiationDelegate} if resolution was successful; {@literal null} otherwise.
* @since 4.0
*/
public static @Nullable KotlinInstantiationDelegate resolve(PreferredConstructor<?, ?> preferredConstructor) {
int[] defaulting = defaultMask.getDefaulting();
// append nullability masks to creation arguments
for (int i = 0; i < defaulting.length; i++) {
params[userParameterCount + i] = defaulting[i];
KFunction<?> constructorFunction = ReflectJvmMapping.getKotlinFunction(preferredConstructor.getConstructor());
if (constructorFunction == null) {
return null;
}
PreferredConstructor<?, ?> resolved = resolveKotlinJvmConstructor(preferredConstructor, constructorFunction);
return resolved != null ? new KotlinInstantiationDelegate(resolved, constructorFunction) : null;
}
/**
* Resolves a {@link PreferredConstructor} to a synthetic Kotlin constructor accepting the same user-space parameters
* suffixed by Kotlin-specifics required for defaulting and the {@code kotlin.jvm.internal.DefaultConstructorMarker}.
* Resolves a {@link PreferredConstructor} to the constructor to be invoked. This can be a synthetic Kotlin
* constructor accepting the same user-space parameters suffixed by Kotlin-specifics required for defaulting and the
* {@code kotlin.jvm.internal.DefaultConstructorMarker} or an actual non-synthetic constructor (i.e. private
* constructor).
* <p>
* Constructor resolution may return {@literal null} indicating that no matching constructor could be found.
* <p>
* The resulting constructor {@link PreferredConstructor#getParameters()} (and parameter count) reflect user-facing
* parameters and do not contain any synthetic parameters.
*
* @return the resolved constructor or {@literal null} if the constructor could not be resolved.
* @since 2.0
* @author Mark Paluch
*/
@SuppressWarnings("unchecked")
@Nullable
public static PreferredConstructor<?, ?> resolveKotlinJvmConstructor(
PreferredConstructor<?, ?> preferredConstructor) {
private static PreferredConstructor<?, ?> resolveKotlinJvmConstructor(PreferredConstructor<?, ?> preferredConstructor,
KFunction<?> constructorFunction) {
Constructor<?> hit = doResolveKotlinConstructor(preferredConstructor.getConstructor());
Constructor<?> hit = findKotlinConstructor(preferredConstructor.getConstructor(), constructorFunction);
if (hit == preferredConstructor.getConstructor()) {
if (preferredConstructor.getConstructor().equals(hit)) {
return preferredConstructor;
}
@ -180,39 +214,48 @@ class KotlinInstantiationDelegate { @@ -180,39 +214,48 @@ class KotlinInstantiationDelegate {
}
@Nullable
private static Constructor<?> doResolveKotlinConstructor(Constructor<?> detectedConstructor) {
private static Constructor<?> findKotlinConstructor(Constructor<?> preferredConstructor,
KFunction<?> constructorFunction) {
Class<?> entityType = detectedConstructor.getDeclaringClass();
Class<?> entityType = preferredConstructor.getDeclaringClass();
Constructor<?> hit = null;
KFunction<?> kotlinFunction = ReflectJvmMapping.getKotlinFunction(detectedConstructor);
Constructor<?> privateFallback = null;
java.lang.reflect.Parameter[] detectedParameters = preferredConstructor.getParameters();
boolean hasDefaultConstructorMarker = KotlinInstantiationDelegate.hasDefaultConstructorMarker(detectedParameters);
for (Constructor<?> candidate : entityType.getDeclaredConstructors()) {
// use only synthetic constructors
java.lang.reflect.Parameter[] candidateParameters = preferredConstructor.equals(candidate)
? detectedParameters
: candidate.getParameters();
if (Modifier.isPrivate(candidate.getModifiers())) {
if (preferredConstructor.equals(candidate)) {
privateFallback = candidate;
}
}
// introspect only synthetic constructors
if (!candidate.isSynthetic()) {
continue;
}
java.lang.reflect.Parameter[] detectedConstructorParameters = detectedConstructor.getParameters();
java.lang.reflect.Parameter[] candidateParameters = candidate.getParameters();
if (!KotlinInstantiationDelegate.hasDefaultConstructorMarker(detectedConstructorParameters)) {
if (!hasDefaultConstructorMarker) {
// candidates must contain at least two additional parameters (int, DefaultConstructorMarker).
// Number of defaulting masks derives from the original constructor arg count
int syntheticParameters = KotlinDefaultMask.getMaskCount(detectedConstructor.getParameterCount())
int syntheticParameters = KotlinDefaultMask.getMaskCount(detectedParameters.length)
+ /* DefaultConstructorMarker */ 1;
if ((detectedConstructor.getParameterCount() + syntheticParameters) != candidate.getParameterCount()) {
if ((detectedParameters.length + syntheticParameters) != candidate.getParameterCount()) {
continue;
}
} else if (kotlinFunction != null) {
} else {
int optionalParameterCount = (int) kotlinFunction.getParameters().stream().filter(KParameter::isOptional)
.count();
int optionalParameterCount = getOptionalParameterCount(constructorFunction);
int syntheticParameters = KotlinDefaultMask.getExactMaskCount(optionalParameterCount);
if ((detectedConstructor.getParameterCount() + syntheticParameters) != candidate.getParameterCount()) {
if ((detectedParameters.length + syntheticParameters) != candidate.getParameterCount()) {
continue;
}
}
@ -221,34 +264,61 @@ class KotlinInstantiationDelegate { @@ -221,34 +264,61 @@ class KotlinInstantiationDelegate {
continue;
}
int userParameterCount = kotlinFunction != null ? kotlinFunction.getParameters().size()
: detectedConstructor.getParameterCount();
if (parametersMatch(detectedConstructorParameters, candidateParameters, userParameterCount)) {
int userParameterCount = constructorFunction.getParameters().size();
if (parametersMatch(detectedParameters, candidateParameters, userParameterCount)) {
hit = candidate;
}
}
if (hit == null) {
return privateFallback;
}
return hit;
}
private static int getOptionalParameterCount(KFunction<?> function) {
int count = 0;
for (KParameter parameter : function.getParameters()) {
if (parameter.isOptional()) {
count++;
}
}
return count;
}
private static boolean parametersMatch(java.lang.reflect.Parameter[] constructorParameters,
java.lang.reflect.Parameter[] candidateParameters, int userParameterCount) {
return IntStream.range(0, userParameterCount)
.allMatch(i -> parametersMatch(constructorParameters[i], candidateParameters[i]));
for (int i = 0; i < userParameterCount; i++) {
if (!parametersMatch(constructorParameters[i].getType(), candidateParameters[i].getType())) {
return false;
}
}
return true;
}
static boolean parametersMatch(java.lang.reflect.Parameter constructorParameter,
java.lang.reflect.Parameter candidateParameter) {
private static boolean parametersMatch(Class<?> constructorParameter, Class<?> candidateParameter) {
if (constructorParameter.getType().equals(candidateParameter.getType())) {
if (constructorParameter.equals(candidateParameter)) {
return true;
}
// candidate can be also a wrapper
Class<?> componentOrWrapperType = KotlinValueUtils.getConstructorValueHierarchy(candidateParameter.getType())
.getActualType();
Class<?> componentOrWrapperType = KotlinValueUtils.getConstructorValueHierarchy(candidateParameter).getActualType();
return constructorParameter.equals(componentOrWrapperType);
}
private static boolean hasDefaultConstructorMarker(java.lang.reflect.Parameter[] parameters) {
return parameters.length > 0 && isDefaultConstructorMarker(parameters[parameters.length - 1].getType());
}
return constructorParameter.getType().equals(componentOrWrapperType);
private static boolean isDefaultConstructorMarker(Class<?> cls) {
return cls.getName().equals("kotlin.jvm.internal.DefaultConstructorMarker");
}
}

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

@ -35,12 +35,12 @@ import org.springframework.core.KotlinDetector; @@ -35,12 +35,12 @@ import org.springframework.core.KotlinDetector;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.annotation.PersistenceCreator;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Parameter;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.util.KotlinReflectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

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

@ -25,9 +25,9 @@ import java.util.function.Function; @@ -25,9 +25,9 @@ import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

14
src/main/java/org/springframework/data/mapping/model/ReflectionEntityInstantiator.java

@ -62,11 +62,10 @@ enum ReflectionEntityInstantiator implements EntityInstantiator { @@ -62,11 +62,10 @@ enum ReflectionEntityInstantiator implements EntityInstantiator {
if (KotlinDetector.isKotlinReflectPresent() && KotlinReflectionUtils.isSupportedKotlinClass(entity.getType())
&& creator instanceof PreferredConstructor<?, ?> constructor) {
PreferredConstructor<?, ? extends PersistentProperty<?>> kotlinJvmConstructor = KotlinInstantiationDelegate
.resolveKotlinJvmConstructor(constructor);
KotlinInstantiationDelegate delegate = KotlinInstantiationDelegate.resolve(constructor);
if (kotlinJvmConstructor != null) {
return instantiateKotlinClass(entity, provider, constructor, kotlinJvmConstructor);
if (delegate != null) {
return instantiateKotlinClass(entity, provider, delegate);
}
}
@ -98,14 +97,11 @@ enum ReflectionEntityInstantiator implements EntityInstantiator { @@ -98,14 +97,11 @@ enum ReflectionEntityInstantiator implements EntityInstantiator {
throw new MappingInstantiationException(entity, new ArrayList<>(Arrays.asList(params)), e);
}
}
@SuppressWarnings("unchecked")
private static <T, E extends PersistentEntity<? extends T, P>, P extends PersistentProperty<P>> T instantiateKotlinClass(
E entity, ParameterValueProvider<P> provider, PreferredConstructor<?, ?> preferredConstructor,
PreferredConstructor<?, ? extends PersistentProperty<?>> kotlinJvmConstructor) {
E entity, ParameterValueProvider<P> provider, KotlinInstantiationDelegate delegate) {
Constructor<?> ctor = kotlinJvmConstructor.getConstructor();
KotlinInstantiationDelegate delegate = new KotlinInstantiationDelegate(preferredConstructor, ctor);
Constructor<?> ctor = delegate.getConstructor();
Object[] params = new Object[delegate.getRequiredParameterCount()];
delegate.extractInvocationArguments(params, entity.getInstanceCreatorMetadata(), provider);

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

@ -25,9 +25,9 @@ import java.util.function.Consumer; @@ -25,9 +25,9 @@ import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
/**
* Descriptor for a top-level mapped type representing a view onto a domain type structure. The view may exactly match

8
src/main/java/org/springframework/data/projection/EntityProjectionIntrospector.java

@ -24,17 +24,17 @@ import java.util.Set; @@ -24,17 +24,17 @@ import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.projection.EntityProjection.ProjectionType;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**
* This class is introspects the returned type in the context of a domain type for all reachable properties (w/o cycles)
* to determine which property paths are subject to projection.
* This class introspects the returned type in the context of a domain type for all reachable properties (w/o cycles) to
* determine which property paths are subject to projection.
*
* @author Gerrit Meier
* @author Mark Paluch

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

@ -31,9 +31,9 @@ import org.jspecify.annotations.Nullable; @@ -31,9 +31,9 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.util.NullableWrapper;
import org.springframework.data.util.NullableWrapperConverters;
import org.springframework.data.util.TypeInformation;
import org.springframework.data.core.NullableWrapper;
import org.springframework.data.core.NullableWrapperConverters;
import org.springframework.data.core.TypeInformation;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

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

@ -24,7 +24,6 @@ import java.util.concurrent.ConcurrentHashMap; @@ -24,7 +24,6 @@ import java.util.concurrent.ConcurrentHashMap;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jspecify.annotations.Nullable;
import org.springframework.aop.framework.Advised;
@ -33,8 +32,8 @@ import org.springframework.beans.factory.BeanClassLoaderAware; @@ -33,8 +32,8 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.convert.Jsr310Converters;
import org.springframework.data.core.NullableWrapperConverters;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.NullableWrapperConverters;
import org.springframework.data.util.NullnessMethodInvocationValidator;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

2
src/main/java/org/springframework/data/querydsl/aot/QuerydslHints.java

@ -23,10 +23,10 @@ import org.springframework.aot.hint.MemberCategory; @@ -23,10 +23,10 @@ import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.QuerydslUtils;
import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor;
import org.springframework.data.util.ReactiveWrappers;
import com.querydsl.core.types.Predicate;

2
src/main/java/org/springframework/data/querydsl/binding/PathInformation.java

@ -19,7 +19,7 @@ import java.beans.PropertyDescriptor; @@ -19,7 +19,7 @@ import java.beans.PropertyDescriptor;
import org.jspecify.annotations.Nullable;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.querydsl.EntityPathResolver;
import com.querydsl.core.types.Path;

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

@ -21,9 +21,9 @@ import java.lang.reflect.Field; @@ -21,9 +21,9 @@ import java.lang.reflect.Field;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.querydsl.EntityPathResolver;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;

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

@ -25,10 +25,10 @@ import java.util.Set; @@ -25,10 +25,10 @@ import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.PropertyReferenceException;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.PropertyReferenceException;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

2
src/main/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactory.java

@ -27,9 +27,9 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -27,9 +27,9 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.querydsl.EntityPathResolver;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import com.querydsl.core.types.EntityPath;

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

@ -30,9 +30,9 @@ import org.springframework.beans.PropertyValues; @@ -30,9 +30,9 @@ import org.springframework.beans.PropertyValues;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.Property;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.querydsl.EntityPathResolver;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.MultiValueMap;

3
src/main/java/org/springframework/data/repository/aot/generate/MethodMetadata.java

@ -26,13 +26,14 @@ import java.util.Map.Entry; @@ -26,13 +26,14 @@ import java.util.Map.Entry;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.ResolvableType;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.javapoet.TypeNames;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.javapoet.ParameterSpec;
import org.springframework.javapoet.TypeName;
import org.springframework.util.Assert;

2
src/main/java/org/springframework/data/repository/aot/generate/MethodReturn.java

@ -19,10 +19,10 @@ import java.util.Optional; @@ -19,10 +19,10 @@ import java.util.Optional;
import java.util.stream.Stream;
import org.springframework.core.ResolvableType;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.javapoet.TypeNames;
import org.springframework.data.repository.query.ReturnedType;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.javapoet.TypeName;
/**

2
src/main/java/org/springframework/data/repository/aot/generate/ResolvableGenerics.java

@ -27,7 +27,7 @@ import java.util.function.Predicate; @@ -27,7 +27,7 @@ import java.util.function.Predicate;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.data.util.TypeInformation;
import org.springframework.data.core.TypeInformation;
/**
* Value object to determine whether generics in a given {@link Method} can be resolved. Resolvable generics are e.g.

2
src/main/java/org/springframework/data/repository/aot/hint/RepositoryRuntimeHints.java

@ -29,6 +29,7 @@ import org.springframework.aot.hint.TypeReference; @@ -29,6 +29,7 @@ import org.springframework.aot.hint.TypeReference;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.DecoratingProxy;
import org.springframework.core.io.InputStreamSource;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.domain.Example;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.core.RepositoryMetadata;
@ -41,7 +42,6 @@ import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuer @@ -41,7 +42,6 @@ import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuer
import org.springframework.data.repository.query.FluentQuery.ReactiveFluentQuery;
import org.springframework.data.repository.query.QueryByExampleExecutor;
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
import org.springframework.data.util.ReactiveWrappers;
/**
* {@link RuntimeHintsRegistrar} holding required hints to bootstrap data repositories. <br />

2
src/main/java/org/springframework/data/repository/core/RepositoryInformationSupport.java

@ -29,9 +29,9 @@ import org.jspecify.annotations.Nullable; @@ -29,9 +29,9 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.data.annotation.QueryAnnotation;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.repository.Repository;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

2
src/main/java/org/springframework/data/repository/core/RepositoryMetadata.java

@ -19,9 +19,9 @@ import java.lang.reflect.Method; @@ -19,9 +19,9 @@ import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Set;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.repository.core.support.RepositoryFragment;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.util.TypeInformation;
/**
* Metadata for repository interfaces.

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

@ -22,6 +22,8 @@ import java.util.List; @@ -22,6 +22,8 @@ import java.util.List;
import java.util.Set;
import org.springframework.core.KotlinDetector;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.CrudMethods;
@ -30,8 +32,6 @@ import org.springframework.data.repository.util.QueryExecutionConverters; @@ -30,8 +32,6 @@ import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.data.repository.util.ReactiveWrapperConverters;
import org.springframework.data.util.KotlinReflectionUtils;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -15,14 +15,14 @@ @@ -15,14 +15,14 @@
*/
package org.springframework.data.repository.core.support;
import java.util.function.Function;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.repository.RepositoryDefinition;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -20,9 +20,9 @@ import java.util.List; @@ -20,9 +20,9 @@ import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -33,12 +33,12 @@ import org.jspecify.annotations.Nullable; @@ -33,12 +33,12 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.MethodLookup.MethodPredicate;
import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.data.repository.util.ReactiveWrapperConverters;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

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

@ -30,10 +30,10 @@ import org.springframework.core.MethodParameter; @@ -30,10 +30,10 @@ import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.core.NullableWrapper;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.data.repository.util.ReactiveWrapperConverters;
import org.springframework.data.util.NullableWrapper;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.data.util.Streamable;
/**

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

@ -23,11 +23,11 @@ import org.jspecify.annotations.Nullable; @@ -23,11 +23,11 @@ import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.ValueExpressionDelegate;
import org.springframework.data.repository.util.ReactiveWrapperConverters;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.util.ClassUtils;
/**

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

@ -31,11 +31,11 @@ import java.util.stream.Stream; @@ -31,11 +31,11 @@ import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.MethodLookup.InvokedMethod;
import org.springframework.data.repository.core.support.RepositoryInvocationMulticaster.NoOpRepositoryInvocationMulticaster;
import org.springframework.data.repository.util.ReactiveWrapperConverters;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.data.util.Streamable;
import org.springframework.lang.CheckReturnValue;
import org.springframework.lang.Contract;

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

@ -31,13 +31,13 @@ import org.reactivestreams.Publisher; @@ -31,13 +31,13 @@ import org.reactivestreams.Publisher;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.KotlinDetector;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.repository.core.support.RepositoryMethodInvocationListener.RepositoryMethodInvocation;
import org.springframework.data.repository.core.support.RepositoryMethodInvocationListener.RepositoryMethodInvocationResult;
import org.springframework.data.repository.core.support.RepositoryMethodInvocationListener.RepositoryMethodInvocationResult.State;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.util.ReactiveWrapperConverters;
import org.springframework.data.util.KotlinReflectionUtils;
import org.springframework.data.util.ReactiveWrappers;
/**
* Invoker for repository methods. Used to invoke query methods and fragment methods. This invoker considers Kotlin

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

@ -26,6 +26,7 @@ import java.util.Optional; @@ -26,6 +26,7 @@ import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.ResolvableType;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Range;
@ -37,7 +38,6 @@ import org.springframework.data.repository.util.QueryExecutionConverters; @@ -37,7 +38,6 @@ import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.data.repository.util.ReactiveWrapperConverters;
import org.springframework.data.util.ClassUtils;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -17,8 +17,8 @@ package org.springframework.data.repository.query; @@ -17,8 +17,8 @@ package org.springframework.data.repository.query;
import java.lang.reflect.Method;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**

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

@ -23,6 +23,10 @@ import java.util.function.Predicate; @@ -23,6 +23,10 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.NullableWrapperConverters;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@ -38,10 +42,7 @@ import org.springframework.data.repository.core.RepositoryMetadata; @@ -38,10 +42,7 @@ import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.data.repository.util.ReactiveWrapperConverters;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.NullableWrapperConverters;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

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

@ -28,6 +28,7 @@ import org.springframework.beans.factory.ListableBeanFactory; @@ -28,6 +28,7 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.expression.ReactiveValueEvaluationContextProvider;
import org.springframework.data.expression.ValueEvaluationContext;
import org.springframework.data.expression.ValueEvaluationContextProvider;
@ -38,7 +39,6 @@ import org.springframework.data.spel.ReactiveEvaluationContextProvider; @@ -38,7 +39,6 @@ import org.springframework.data.spel.ReactiveEvaluationContextProvider;
import org.springframework.data.spel.ReactiveExtensionAwareEvaluationContextProvider;
import org.springframework.data.spel.spi.EvaluationContextExtension;
import org.springframework.data.spel.spi.ExtensionIdAware;
import org.springframework.data.util.ReactiveWrappers;
import org.springframework.expression.EvaluationContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

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

@ -22,10 +22,10 @@ import java.util.Set; @@ -22,10 +22,10 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.util.StringUtils;
/**

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

@ -25,7 +25,7 @@ import java.util.List; @@ -25,7 +25,7 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.core.PropertyPath;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

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

@ -26,13 +26,13 @@ import org.springframework.core.MethodParameter; @@ -26,13 +26,13 @@ import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.core.CrudMethods;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Param;
import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

11
src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java

@ -37,18 +37,19 @@ import org.springframework.core.convert.converter.Converter; @@ -37,18 +37,19 @@ import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.core.CustomCollections;
import org.springframework.data.core.NullableWrapper;
import org.springframework.data.core.NullableWrapperConverters;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.SearchResult;
import org.springframework.data.domain.SearchResults;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Window;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.util.CustomCollections;
import org.springframework.data.util.NullableWrapper;
import org.springframework.data.util.NullableWrapperConverters;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -65,7 +66,7 @@ import org.springframework.util.ObjectUtils; @@ -65,7 +66,7 @@ import org.springframework.util.ObjectUtils;
* via {@link CustomCollections}</li>
* <li>{@code io.vavr.collection.Seq}, {@code io.vavr.collection.Map}, {@code io.vavr.collection.Set} - as of 2.0 via
* {@link CustomCollections}</li>
* <li>Reactive wrappers supported by {@link org.springframework.data.util.ReactiveWrappers} - as of 2.0</li>
* <li>Reactive wrappers supported by {@link ReactiveWrappers} - as of 2.0</li>
* </ul>
*
* @author Oliver Gierke

22
src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java

@ -38,8 +38,9 @@ import org.springframework.core.convert.converter.Converter; @@ -38,8 +38,9 @@ import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.util.ReactiveWrappers.ReactiveLibrary;
import org.springframework.data.util.TypeInformation;
import org.springframework.data.core.ReactiveWrappers;
import org.springframework.data.core.ReactiveWrappers.ReactiveLibrary;
import org.springframework.data.core.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -55,7 +56,7 @@ import org.springframework.util.ClassUtils; @@ -55,7 +56,7 @@ import org.springframework.util.ClassUtils;
* @author Christoph Strobl
* @author Hantsy Bai
* @since 2.0
* @see org.springframework.data.util.ReactiveWrappers
* @see ReactiveWrappers
* @see ReactiveAdapterRegistry
*/
public abstract class ReactiveWrapperConverters {
@ -63,13 +64,13 @@ public abstract class ReactiveWrapperConverters { @@ -63,13 +64,13 @@ public abstract class ReactiveWrapperConverters {
private static final List<ReactiveTypeWrapper<?>> REACTIVE_WRAPPERS = new ArrayList<>();
private static final GenericConversionService GENERIC_CONVERSION_SERVICE = new GenericConversionService();
private static final boolean RXJAVA3_PRESENT = org.springframework.data.util.ReactiveWrappers
private static final boolean RXJAVA3_PRESENT = ReactiveWrappers
.isAvailable(ReactiveLibrary.RXJAVA3);
private static final boolean REACTOR_PRESENT = org.springframework.data.util.ReactiveWrappers
private static final boolean REACTOR_PRESENT = ReactiveWrappers
.isAvailable(ReactiveLibrary.PROJECT_REACTOR);
private static final boolean KOTLIN_COROUTNES_PRESENT = org.springframework.data.util.ReactiveWrappers
private static final boolean KOTLIN_COROUTNES_PRESENT = ReactiveWrappers
.isAvailable(ReactiveLibrary.KOTLIN_COROUTINES);
private static final boolean MUTINY_PRESENT = org.springframework.data.util.ReactiveWrappers
private static final boolean MUTINY_PRESENT = ReactiveWrappers
.isAvailable(ReactiveLibrary.MUTINY);
static {
@ -130,9 +131,8 @@ public abstract class ReactiveWrapperConverters { @@ -130,9 +131,8 @@ public abstract class ReactiveWrapperConverters {
/**
* Returns whether the given type is supported for wrapper type conversion.
* <p>
* NOTE: A reactive wrapper type might be supported in general by
* {@link org.springframework.data.util.ReactiveWrappers#supports(Class)} but not necessarily for conversion using
* this method.
* NOTE: A reactive wrapper type might be supported in general by {@link ReactiveWrappers#supports(Class)} but not
* necessarily for conversion using this method.
* </p>
*
* @param type must not be {@literal null}.
@ -556,7 +556,7 @@ public abstract class ReactiveWrapperConverters { @@ -556,7 +556,7 @@ public abstract class ReactiveWrapperConverters {
static {
if (org.springframework.data.util.ReactiveWrappers.PROJECT_REACTOR_PRESENT) {
if (ReactiveWrappers.PROJECT_REACTOR_PRESENT) {
REACTIVE_ADAPTER_REGISTRY = ReactiveAdapterRegistry.getSharedInstance();
} else {
REACTIVE_ADAPTER_REGISTRY = null;

1
src/main/java/org/springframework/data/spel/spi/Function.java

@ -25,7 +25,6 @@ import java.util.List; @@ -25,7 +25,6 @@ import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.util.ParameterTypes;
import org.springframework.util.Assert;
/**

369
src/main/java/org/springframework/data/spel/spi/ParameterTypes.java

@ -0,0 +1,369 @@ @@ -0,0 +1,369 @@
/*
* Copyright 2025 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
*
* https://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.spel.spi;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.util.Lazy;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.TypeUtils;
/**
* Abstraction over a list of parameter value types. Allows to check whether a list of parameter values with the given
* type setup is a candidate for the invocation of a given {@link Method} (see {@link #areValidFor(Method)}). This is
* necessary to properly match parameter values against methods declaring varargs arguments. The implementation favors
* direct matches and only computes the alternative sets of types to be considered if the primary one doesn't match.
*
* @author Oliver Drotbohm
* @since 2.1.7
* @soundtrack Signs, High Times - Tedeschi Trucks Band (Signs)
*/
class ParameterTypes {
private static final TypeDescriptor OBJECT_DESCRIPTOR = TypeDescriptor.valueOf(Object.class);
private static final ConcurrentMap<List<TypeDescriptor>, ParameterTypes> cache = new ConcurrentReferenceHashMap<>();
private final List<TypeDescriptor> types;
private final Lazy<Collection<ParameterTypes>> alternatives;
/**
* Creates a new {@link ParameterTypes} for the given types.
*
* @param types
*/
private ParameterTypes(List<TypeDescriptor> types) {
this.types = types;
this.alternatives = Lazy.of(this::getAlternatives);
}
public ParameterTypes(List<TypeDescriptor> types, Lazy<Collection<ParameterTypes>> alternatives) {
this.types = types;
this.alternatives = alternatives;
}
/**
* Returns the {@link ParameterTypes} for the given list of {@link TypeDescriptor}s.
*
* @param types must not be {@literal null}.
* @return
*/
public static ParameterTypes of(List<TypeDescriptor> types) {
Assert.notNull(types, "Types must not be null");
return cache.computeIfAbsent(types, ParameterTypes::new);
}
/**
* Returns the {@link ParameterTypes} for the given {@link Class}es.
*
* @param types must not be {@literal null}.
* @return
*/
static ParameterTypes of(Class<?>... types) {
Assert.notNull(types, "Types must not be null");
Assert.noNullElements(types, "Types must not have null elements");
return of(Arrays.stream(types) //
.map(TypeDescriptor::valueOf) //
.collect(Collectors.toList()));
}
/**
* Returns whether the parameter types are valid for the given {@link Method}. That means, a parameter value list with
* the given type arrangement is a valid list to invoke the given method.
*
* @param method must not be {@literal null}.
* @return
*/
public boolean areValidFor(Method method) {
Assert.notNull(method, "Method must not be null");
// Direct matches
if (areValidTypes(method)) {
return true;
}
return hasValidAlternativeFor(method);
}
/**
* Returns whether we have a valid alternative variant (making use of varargs) that will match the given method's
* signature.
*
* @param method
* @return
*/
private boolean hasValidAlternativeFor(Method method) {
if (alternatives.get().stream().anyMatch(it -> it.areValidTypes(method))) {
return true;
}
ParameterTypes parent = getParent();
return parent != null && parent.hasValidAlternativeFor(method);
}
/**
* Returns all suitable alternatives to the current {@link ParameterTypes}.
*
* @return will never be {@literal null}.
*/
List<ParameterTypes> getAllAlternatives() {
List<ParameterTypes> result = new ArrayList<>();
result.addAll(alternatives.get());
ParameterTypes parent = getParent();
if (parent != null) {
result.addAll(parent.getAllAlternatives());
}
return result;
}
/**
* Returns whether the {@link ParameterTypes} consists of the given types.
*
* @param types must not be {@literal null}.
* @return
*/
boolean hasTypes(Class<?>... types) {
Assert.notNull(types, "Types must not be null");
return Arrays.stream(types) //
.map(TypeDescriptor::valueOf) //
.toList()//
.equals(this.types);
}
/**
* Returns whether the current parameter types match the given {@link Method}'s parameters exactly, i.e. they're
* equal, not only assignable.
*
* @param method must not be {@literal null}.
* @return
*/
public boolean exactlyMatchParametersOf(Method method) {
if (method.getParameterCount() != types.size()) {
return false;
}
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
if (parameterTypes[i] != types.get(i).getType()) {
return false;
}
}
return true;
}
@Override
public String toString() {
return types.stream() //
.map(TypeDescriptor::getType) //
.map(Class::getSimpleName) //
.collect(Collectors.joining(", ", "(", ")"));
}
protected @Nullable ParameterTypes getParent() {
return types.isEmpty() ? null : getParent(getTail());
}
protected final @Nullable ParameterTypes getParent(TypeDescriptor tail) {
return types.size() <= 1 //
? null //
: ParentParameterTypes.of(types.subList(0, types.size() - 1), tail);
}
protected @Nullable ParameterTypes withLastVarArgs() {
TypeDescriptor lastDescriptor = types.get(types.size() - 1);
return lastDescriptor.isArray() //
? null //
: withVarArgs(lastDescriptor);
}
@SuppressWarnings("null")
private ParameterTypes withVarArgs(TypeDescriptor descriptor) {
TypeDescriptor lastDescriptor = types.get(types.size() - 1);
if (lastDescriptor.isArray() && descriptor.equals(lastDescriptor.getElementTypeDescriptor())) {
return this;
}
List<TypeDescriptor> result = new ArrayList<>(types.subList(0, types.size() - 1));
result.add(TypeDescriptor.array(descriptor));
return ParameterTypes.of(result);
}
private Collection<ParameterTypes> getAlternatives() {
if (types.isEmpty()) {
return Collections.emptyList();
}
List<ParameterTypes> alternatives = new ArrayList<>();
ParameterTypes parameterTypes = withLastVarArgs();
if (parameterTypes != null) {
alternatives.add(parameterTypes);
}
ParameterTypes objectVarArgs = withVarArgs(OBJECT_DESCRIPTOR);
if (!alternatives.contains(objectVarArgs)) {
alternatives.add(objectVarArgs);
}
return alternatives;
}
/**
* Returns whether the current type list makes up valid arguments for the given method.
*
* @param method must not be {@literal null}.
* @return
*/
private boolean areValidTypes(Method method) {
Assert.notNull(method, "Method must not be null");
if (method.getParameterCount() != types.size()) {
return false;
}
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
if (!TypeUtils.isAssignable(parameterTypes[i], types.get(i).getType())) {
return false;
}
}
return true;
}
private TypeDescriptor getTail() {
return types.get(types.size() - 1);
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ParameterTypes that)) {
return false;
}
return ObjectUtils.nullSafeEquals(types, that.types);
}
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(types);
}
/**
* Extension of {@link ParameterTypes} that remembers the seed tail and only adds typed varargs if the current tail is
* assignable to the seed one.
*
* @author Oliver Drotbohm
*/
static class ParentParameterTypes extends ParameterTypes {
private final TypeDescriptor tail;
private ParentParameterTypes(List<TypeDescriptor> types, TypeDescriptor tail) {
super(types);
this.tail = tail;
}
public static ParentParameterTypes of(List<TypeDescriptor> types, TypeDescriptor tail) {
return new ParentParameterTypes(types, tail);
}
@Override
protected @Nullable ParameterTypes getParent() {
return super.getParent(tail);
}
@Override
protected @Nullable ParameterTypes withLastVarArgs() {
return !tail.isAssignableTo(super.getTail()) //
? null //
: super.withLastVarArgs();
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ParentParameterTypes that)) {
return false;
}
if (!super.equals(o)) {
return false;
}
return ObjectUtils.nullSafeEquals(tail, that.tail);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + ObjectUtils.nullSafeHashCode(tail);
return result;
}
}
}

2
src/main/java/org/springframework/data/util/ParameterTypes.java

@ -41,7 +41,9 @@ import org.springframework.util.TypeUtils; @@ -41,7 +41,9 @@ import org.springframework.util.TypeUtils;
* @author Oliver Drotbohm
* @since 2.1.7
* @soundtrack Signs, High Times - Tedeschi Trucks Band (Signs)
* @deprecated since 4.0, this class is not intended for public use and will be removed in future versions.
*/
@Deprecated(since = "4.0", forRemoval = true)
public class ParameterTypes {
private static final TypeDescriptor OBJECT_DESCRIPTOR = TypeDescriptor.valueOf(Object.class);

2
src/main/java/org/springframework/data/web/JsonProjectingMethodInterceptorFactory.java

@ -33,9 +33,9 @@ import org.jspecify.annotations.Nullable; @@ -33,9 +33,9 @@ import org.jspecify.annotations.Nullable;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.projection.Accessor;
import org.springframework.data.projection.MethodInterceptorFactory;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import com.jayway.jsonpath.Configuration;

6
src/main/java/org/springframework/data/web/MapDataBinder.java

@ -34,9 +34,9 @@ import org.springframework.core.CollectionFactory; @@ -34,9 +34,9 @@ import org.springframework.core.CollectionFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.PropertyReferenceException;
import org.springframework.data.util.TypeInformation;
import org.springframework.data.core.PropertyPath;
import org.springframework.data.core.PropertyReferenceException;
import org.springframework.data.core.TypeInformation;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;

2
src/main/java/org/springframework/data/web/querydsl/QuerydslPredicateArgumentResolverSupport.java

@ -25,12 +25,12 @@ import org.springframework.core.ResolvableType; @@ -25,12 +25,12 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.querydsl.binding.QuerydslBindingsFactory;
import org.springframework.data.querydsl.binding.QuerydslPredicate;
import org.springframework.data.querydsl.binding.QuerydslPredicateBuilder;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;

2
src/main/kotlin/org/springframework/data/mapping/KPropertyPathExtensions.kt

@ -22,6 +22,6 @@ import kotlin.reflect.KProperty @@ -22,6 +22,6 @@ import kotlin.reflect.KProperty
*
* @author Mark Paluch
* @since 2.5
* @see PropertyPath.toDotPath
* @see org.springframework.data.core.PropertyPath.toDotPath
*/
fun KProperty<*>.toDotPath(): String = asString(this)

6
src/main/resources/META-INF/spring.factories

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
org.springframework.beans.BeanInfoFactory=org.springframework.data.util.KotlinBeanInfoFactory
org.springframework.data.core.CustomCollectionRegistrar=org.springframework.data.core.CustomCollections.VavrCollections, \
org.springframework.data.core.CustomCollections.EclipseCollections
org.springframework.data.web.config.SpringDataJacksonModules=org.springframework.data.web.config.SpringDataJacksonConfiguration
org.springframework.data.web.config.SpringDataJackson3Modules=org.springframework.data.web.config.SpringDataJackson3Configuration
org.springframework.data.util.CustomCollectionRegistrar=org.springframework.data.util.CustomCollections.VavrCollections, \
org.springframework.data.util.CustomCollections.EclipseCollections
org.springframework.beans.BeanInfoFactory=org.springframework.data.util.KotlinBeanInfoFactory

2
src/test/java/org/springframework/data/aot/AotMappingContextUnitTests.java

@ -23,7 +23,7 @@ import org.junit.jupiter.api.Test; @@ -23,7 +23,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Reference;
import org.springframework.data.util.TypeInformation;
import org.springframework.data.core.TypeInformation;
/**
* Unit tests for {@link AotMappingContext}.

99
src/test/java/org/springframework/data/auditing/config/AuditingBeanDefinitionRegistrarSupportUnitTests.java

@ -20,16 +20,23 @@ import static org.mockito.ArgumentMatchers.*; @@ -20,16 +20,23 @@ import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.lang.annotation.Annotation;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.config.AutowiredPropertyMarker;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.auditing.AuditingHandler;
import org.springframework.data.auditing.EnableAuditing;
import org.springframework.data.mapping.context.PersistentEntities;
/**
* Unit tests for {@link AuditingBeanDefinitionRegistrarSupport}.
@ -38,6 +45,8 @@ import org.springframework.data.auditing.EnableAuditing; @@ -38,6 +45,8 @@ import org.springframework.data.auditing.EnableAuditing;
* @author Thomas Darimont
* @author Oliver Gierke
* @author Francisco Soler
* @author Jaeyeon Kim
* @author Mark Paluch
*/
@ExtendWith(MockitoExtension.class)
class AuditingBeanDefinitionRegistrarSupportUnitTests {
@ -73,6 +82,96 @@ class AuditingBeanDefinitionRegistrarSupportUnitTests { @@ -73,6 +82,96 @@ class AuditingBeanDefinitionRegistrarSupportUnitTests {
.isThrownBy(() -> registrar.registerBeanDefinitions(metadata, null));
}
@Test // GH-3177
void setsAuditorAwareAndDateTimeProviderIfConfigured() {
AuditingConfiguration configuration = new DummyAuditingBeanDefinitionRegistrarSupport().getConfiguration(null);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(AuditingHandler.class);
DummyAuditingBeanDefinitionRegistrarSupport registrar = new DummyAuditingBeanDefinitionRegistrarSupport();
BeanDefinitionBuilder result = registrar.configureDefaultAuditHandlerAttributes(configuration, builder);
AbstractBeanDefinition beanDefinition = result.getBeanDefinition();
assertThat(beanDefinition.getPropertyValues().contains("auditorAware")).isTrue();
assertThat(beanDefinition.getPropertyValues().contains("dateTimeProvider")).isTrue();
}
@Test // GH-3177
void doesNotSetAuditorAwareAndDateTimeProviderIfNotConfigured() {
AuditingConfiguration configuration = new AuditingConfiguration() {
@Override
public String getAuditorAwareRef() {
return "";
}
@Override
public boolean isSetDates() {
return true;
}
@Override
public String getDateTimeProviderRef() {
return "";
}
@Override
public boolean isModifyOnCreate() {
return true;
}
};
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(AuditingHandler.class);
DummyAuditingBeanDefinitionRegistrarSupport registrar = new DummyAuditingBeanDefinitionRegistrarSupport();
BeanDefinitionBuilder result = registrar.configureDefaultAuditHandlerAttributes(configuration, builder);
AbstractBeanDefinition beanDefinition = result.getBeanDefinition();
assertThat(beanDefinition.getPropertyValues().get("auditorAware")).isEqualTo(AutowiredPropertyMarker.INSTANCE);
assertThat(beanDefinition.getPropertyValues().get("dateTimeProvider")).isEqualTo(AutowiredPropertyMarker.INSTANCE);
}
@Test // GH-3177
void optionalAutowiringShouldConsiderOptionalProperties() {
AuditingConfiguration configuration = new AuditingConfiguration() {
@Override
public String getAuditorAwareRef() {
return "";
}
@Override
public boolean isSetDates() {
return true;
}
@Override
public String getDateTimeProviderRef() {
return "";
}
@Override
public boolean isModifyOnCreate() {
return true;
}
};
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(AuditingHandler.class);
builder.addConstructorArgValue(PersistentEntities.of());
DummyAuditingBeanDefinitionRegistrarSupport registrar = new DummyAuditingBeanDefinitionRegistrarSupport();
BeanDefinitionBuilder result = registrar.configureDefaultAuditHandlerAttributes(configuration, builder);
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("auditingHandler", result.getBeanDefinition());
context.refresh();
AuditingHandler handler = context.getBean(AuditingHandler.class);
assertThat(handler).extracting("auditorAware").isEqualTo(Optional.empty());
}
static class SampleConfig {}
static class DummyAuditingBeanDefinitionRegistrarSupport extends AuditingBeanDefinitionRegistrarSupport {

3
src/test/java/org/springframework/data/convert/ConfigurableTypeInformationMapperUnitTests.java

@ -25,9 +25,10 @@ import org.junit.jupiter.api.BeforeEach; @@ -25,9 +25,10 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.TypeInformation;
/**
* Unit tests for {@link ConfigurableTypeInformationMapper}.

3
src/test/java/org/springframework/data/convert/DefaultTypeMapperUnitTests.java

@ -30,9 +30,10 @@ import org.mockito.Mock; @@ -30,9 +30,10 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.util.TypeInformation;
/**
* Unit tests for {@link DefaultTypeMapper}.

3
src/test/java/org/springframework/data/convert/MappingContextTypeInformationMapperUnitTests.java

@ -21,13 +21,14 @@ import java.util.Collections; @@ -21,13 +21,14 @@ import java.util.Collections;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.SampleMappingContext;
import org.springframework.data.mapping.context.SamplePersistentProperty;
import org.springframework.data.util.AnnotatedTypeScanner;
import org.springframework.data.util.TypeInformation;
/**
* Unit tests for {@link MappingContextTypeInformationMapper}.

3
src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java

@ -18,9 +18,10 @@ package org.springframework.data.convert; @@ -18,9 +18,10 @@ package org.springframework.data.convert;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.springframework.data.classloadersupport.HidingClassLoader;
import org.springframework.data.core.TypeInformation;
import org.springframework.data.mapping.Alias;
import org.springframework.data.util.TypeInformation;
/**
* Unit tests for {@link SimpleTypeInformationMapper}.

10
src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java → src/test/java/org/springframework/data/core/ClassTypeInformationUnitTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2011-2025 the original author or authors.
* Copyright 2025 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.
@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import static org.assertj.core.api.Assertions.*;
@ -27,6 +27,7 @@ import java.util.Set; @@ -27,6 +27,7 @@ import java.util.Set;
import java.util.SortedMap;
import org.aopalliance.aop.Advice;
import org.assertj.core.api.Assertions;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.aop.Advisor;
@ -36,6 +37,7 @@ import org.springframework.aop.framework.Advised; @@ -36,6 +37,7 @@ import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.core.ResolvableType;
import org.springframework.data.mapping.Person;
import org.springframework.data.util.Pair;
/**
* Unit tests for {@link ClassTypeInformation}.
@ -347,7 +349,7 @@ public class ClassTypeInformationUnitTests { @@ -347,7 +349,7 @@ public class ClassTypeInformationUnitTests {
@Test // DATACMNS-446
public void createsToStringRepresentation() {
assertThat(TypeInformation.of(SpecialPerson.class).toString())
.isEqualTo("org.springframework.data.util.ClassTypeInformationUnitTests$SpecialPerson");
.isEqualTo("org.springframework.data.core.ClassTypeInformationUnitTests$SpecialPerson");
}
@Test // DATACMNS-590
@ -396,7 +398,7 @@ public class ClassTypeInformationUnitTests { @@ -396,7 +398,7 @@ public class ClassTypeInformationUnitTests {
var abstractBar = root.getProperty("abstractBar");
assertThat(Pair.of(abstractBar.specialize(TypeInformation.of(Bar.class)),
Assertions.assertThat(Pair.of(abstractBar.specialize(TypeInformation.of(Bar.class)),
abstractBar.specialize(TypeInformation.of(Bar.class)))).satisfies(pair -> {
assertThat(pair.getFirst()).isEqualTo(pair.getSecond());
assertThat(pair.getSecond()).isEqualTo(pair.getFirst());

4
src/test/java/org/springframework/data/util/CustomCollectionsUnitTests.java → src/test/java/org/springframework/data/core/CustomCollectionsUnitTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2022-2025 the original author or authors.
* Copyright 2025 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.
@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import static org.assertj.core.api.Assertions.*;

4
src/test/java/org/springframework/data/util/DataCmns511Tests.java → src/test/java/org/springframework/data/core/DataCmns511Tests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2014-2025 the original author or authors.
* Copyright 2025 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.
@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import static org.assertj.core.api.Assertions.*;

4
src/test/java/org/springframework/data/util/NullableWrapperConvertersUnitTests.java → src/test/java/org/springframework/data/core/NullableWrapperConvertersUnitTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2014-2025 the original author or authors.
* Copyright 2025 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.
@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
package org.springframework.data.core;
import static org.assertj.core.api.Assertions.*;

7
src/test/java/org/springframework/data/mapping/PropertyPathUnitTests.java → src/test/java/org/springframework/data/core/PropertyPathUnitTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2011-2025 the original author or authors.
* Copyright 2025 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.
@ -13,10 +13,10 @@ @@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping;
package org.springframework.data.core;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.mapping.PropertyPath.from;
import static org.springframework.data.core.PropertyPath.from;
import java.util.ArrayList;
import java.util.List;
@ -25,7 +25,6 @@ import java.util.Set; @@ -25,7 +25,6 @@ import java.util.Set;
import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
import org.springframework.data.util.TypeInformation;
/**
* Unit tests for {@link PropertyPath}.

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

Loading…
Cancel
Save