From 7db177e3cdefd07371837d62b3959c32b8175e35 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 18 Nov 2024 08:55:43 +0100 Subject: [PATCH] Remove `@Deprecated` API. Closes #3208 --- .../annotation/PersistenceConstructor.java | 35 -- .../data/mapping/Parameter.java | 12 - .../data/mapping/PersistentEntity.java | 27 - .../data/mapping/PersistentPropertyPath.java | 13 - .../data/mapping/PreferredConstructor.java | 19 +- .../mapping/model/BasicPersistentEntity.java | 7 - .../ClassGeneratingEntityInstantiator.java | 10 +- .../model/DefaultSpELExpressionEvaluator.java | 56 --- .../model/MappingInstantiationException.java | 12 - ...ersistentEntityParameterValueProvider.java | 4 +- .../model/SpELExpressionEvaluator.java | 26 - .../SpELExpressionParameterValueProvider.java | 39 -- ...ValueExpressionParameterValueProvider.java | 17 +- .../SpelEvaluatingMethodInterceptor.java | 3 +- .../data/querydsl/QPageRequest.java | 12 +- .../cdi/CdiRepositoryConfiguration.java | 10 +- ...notationRepositoryConfigurationSource.java | 17 - .../ReactiveRepositoryFactorySupport.java | 28 +- .../support/RepositoryFactoryBeanSupport.java | 31 +- .../support/RepositoryFactorySupport.java | 58 +-- .../core/support/RepositoryFragment.java | 12 - ...eQueryMethodEvaluationContextProvider.java | 121 ----- .../data/repository/query/Parameter.java | 11 - .../data/repository/query/Parameters.java | 14 - .../data/repository/query/QueryMethod.java | 16 +- .../QueryMethodEvaluationContextProvider.java | 63 --- ...yMethodValueEvaluationContextAccessor.java | 2 +- ...eQueryMethodEvaluationContextProvider.java | 99 ---- ...eQueryMethodEvaluationContextProvider.java | 58 --- .../data/repository/query/SpelEvaluator.java | 93 ---- .../repository/query/SpelQueryContext.java | 357 ------------- .../util/QueryExecutionConverters.java | 23 - .../util/ReactiveWrapperConverters.java | 5 +- .../repository/util/ReactiveWrappers.java | 165 ------- .../spel/spi/EvaluationContextExtension.java | 4 +- .../ReactiveEvaluationContextExtension.java | 2 +- .../data/type/MethodsMetadata.java | 57 --- .../classreading/MethodsMetadataReader.java | 38 -- .../MethodsMetadataReaderFactory.java | 194 -------- .../data/type/classreading/package-info.java | 6 - .../data/type/package-info.java | 5 - .../data/util/ClassTypeInformation.java | 31 +- .../data/web/PagedResourcesAssembler.java | 14 - .../data/web/SpringDataAnnotationUtils.java | 27 - ...eferredConstructorDiscovererUnitTests.java | 7 +- ...GeneratingEntityInstantiatorUnitTests.java | 7 - ...ReflectionEntityInstantiatorUnitTests.java | 10 +- ...lExpressionParameterProviderUnitTests.java | 126 ----- .../cdi/CdiRepositoryBeanUnitTests.java | 8 +- ...ositoryConfigurationDelegateUnitTests.java | 5 +- .../DummyReactiveRepositoryFactory.java | 4 +- .../core/support/DummyRepositoryFactory.java | 4 +- .../ReactiveDummyRepositoryFactory.java | 5 +- .../RepositoryFactorySupportUnitTests.java | 9 +- ...areEvaluationContextProviderUnitTests.java | 467 ------------------ .../repository/query/ParameterUnitTests.java | 9 +- .../query/QuotationMapUnitTests.java | 132 ----- .../query/SpelEvaluatorUnitTests.java | 64 --- .../query/SpelExtractorUnitTests.java | 115 ----- .../query/SpelQueryContextUnitTests.java | 82 --- ...DefaultMethodsMetadataReaderUnitTests.java | 115 ----- ...MethodsMetadataReaderFactoryUnitTests.java | 69 --- ...ssGeneratingEntityInstantiatorUnitTests.kt | 14 +- ...PreferredConstructorDiscovererUnitTests.kt | 6 +- .../repository/query/KParameterUnitTests.kt | 3 +- 65 files changed, 73 insertions(+), 3041 deletions(-) delete mode 100644 src/main/java/org/springframework/data/annotation/PersistenceConstructor.java delete mode 100644 src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java delete mode 100644 src/main/java/org/springframework/data/mapping/model/SpELExpressionEvaluator.java delete mode 100644 src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java delete mode 100644 src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java delete mode 100644 src/main/java/org/springframework/data/repository/query/QueryMethodEvaluationContextProvider.java delete mode 100644 src/main/java/org/springframework/data/repository/query/ReactiveExtensionAwareQueryMethodEvaluationContextProvider.java delete mode 100644 src/main/java/org/springframework/data/repository/query/ReactiveQueryMethodEvaluationContextProvider.java delete mode 100644 src/main/java/org/springframework/data/repository/query/SpelEvaluator.java delete mode 100644 src/main/java/org/springframework/data/repository/query/SpelQueryContext.java delete mode 100644 src/main/java/org/springframework/data/repository/util/ReactiveWrappers.java delete mode 100644 src/main/java/org/springframework/data/type/MethodsMetadata.java delete mode 100644 src/main/java/org/springframework/data/type/classreading/MethodsMetadataReader.java delete mode 100644 src/main/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactory.java delete mode 100644 src/main/java/org/springframework/data/type/classreading/package-info.java delete mode 100644 src/main/java/org/springframework/data/type/package-info.java delete mode 100755 src/test/java/org/springframework/data/mapping/model/SpelExpressionParameterProviderUnitTests.java delete mode 100755 src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java delete mode 100644 src/test/java/org/springframework/data/repository/query/QuotationMapUnitTests.java delete mode 100644 src/test/java/org/springframework/data/repository/query/SpelEvaluatorUnitTests.java delete mode 100644 src/test/java/org/springframework/data/repository/query/SpelExtractorUnitTests.java delete mode 100644 src/test/java/org/springframework/data/repository/query/SpelQueryContextUnitTests.java delete mode 100644 src/test/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReaderUnitTests.java delete mode 100644 src/test/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactoryUnitTests.java diff --git a/src/main/java/org/springframework/data/annotation/PersistenceConstructor.java b/src/main/java/org/springframework/data/annotation/PersistenceConstructor.java deleted file mode 100644 index e67b90500..000000000 --- a/src/main/java/org/springframework/data/annotation/PersistenceConstructor.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2011-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.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation to declare a constructor for instantiation. - * - * @author Jon Brisbin - * @author Mark Paluch - * @author Oliver Drotbohm - * @deprecated in favor of {@link PersistenceCreator} since 3.0, to be removed in 3.1 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE }) -@PersistenceCreator -@Deprecated(forRemoval = true) -public @interface PersistenceConstructor {} diff --git a/src/main/java/org/springframework/data/mapping/Parameter.java b/src/main/java/org/springframework/data/mapping/Parameter.java index 50bb28385..e52ea427b 100644 --- a/src/main/java/org/springframework/data/mapping/Parameter.java +++ b/src/main/java/org/springframework/data/mapping/Parameter.java @@ -160,7 +160,6 @@ public class Parameter> { * Returns the expression to be used when looking up a source data structure to populate the actual parameter value. * * @return the expression to be used when looking up a source data structure. - * @deprecated since 3.3, use {@link #getValueExpression()} instead. */ @Nullable public String getSpelExpression() { @@ -194,17 +193,6 @@ public class Parameter> { return getValueExpression(); } - /** - * Returns whether the constructor parameter is equipped with a SpEL expression. - * - * @return {@literal true}} if the parameter is equipped with a SpEL expression. - * @deprecated since 3.3, use {@link #hasValueExpression()} instead. - */ - @Deprecated(since = "3.3") - public boolean hasSpelExpression() { - return hasValueExpression(); - } - /** * Returns whether the constructor parameter is equipped with a value expression. * diff --git a/src/main/java/org/springframework/data/mapping/PersistentEntity.java b/src/main/java/org/springframework/data/mapping/PersistentEntity.java index 556c1b229..2cb8dbd34 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/PersistentEntity.java @@ -43,19 +43,6 @@ public interface PersistentEntity> extends It */ String getName(); - /** - * Returns the {@link PreferredConstructor} to be used to instantiate objects of this {@link PersistentEntity}. - * - * @return {@literal null} in case no suitable constructor for automatic construction can be found. This usually - * indicates that the instantiation of the object of that persistent entity is done through either a - * customer {@link org.springframework.data.mapping.model.EntityInstantiator} or handled by custom - * conversion mechanisms entirely. - * @deprecated since 3.0, use {@link #getInstanceCreatorMetadata()}. - */ - @Nullable - @Deprecated - PreferredConstructor getPersistenceConstructor(); - /** * Returns the {@link InstanceCreatorMetadata} to be used to instantiate objects of this {@link PersistentEntity}. * @@ -68,20 +55,6 @@ public interface PersistentEntity> extends It @Nullable InstanceCreatorMetadata

getInstanceCreatorMetadata(); - /** - * Returns whether the given {@link PersistentProperty} is referred to by a constructor argument of the - * {@link PersistentEntity}. - * - * @param property can be {@literal null}. - * @return true if the given {@link PersistentProperty} is referred to by a constructor argument or {@literal false} - * if not or {@literal null}. - * @deprecated since 3.0, use {@link #isCreatorArgument(PersistentProperty)} instead. - */ - @Deprecated - default boolean isConstructorArgument(PersistentProperty property) { - return isCreatorArgument(property); - } - /** * Returns whether the given {@link PersistentProperty} is referred to by a creator argument of the * {@link PersistentEntity}. diff --git a/src/main/java/org/springframework/data/mapping/PersistentPropertyPath.java b/src/main/java/org/springframework/data/mapping/PersistentPropertyPath.java index b1e8a01ae..c0c20e04a 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentPropertyPath.java +++ b/src/main/java/org/springframework/data/mapping/PersistentPropertyPath.java @@ -70,19 +70,6 @@ public interface PersistentPropertyPath

> extends */ P getLeafProperty(); - /** - * Returns the last property in the {@link PersistentPropertyPath}. So for {@code foo.bar} it will return the - * {@link PersistentProperty} for {@code bar}. For a simple {@code foo} it returns {@link PersistentProperty} for - * {@code foo}. - * - * @return will never be {@literal null}. - * @deprecated use {@link #getLeafProperty()} instead. - */ - @Deprecated(since = "3.1", forRemoval = true) - default P getRequiredLeafProperty() { - return getLeafProperty(); - } - /** * Returns the first property in the {@link PersistentPropertyPath}. So for {@code foo.bar} it will return the * {@link PersistentProperty} for {@code foo}. For a simple {@code foo} it returns {@link PersistentProperty} for diff --git a/src/main/java/org/springframework/data/mapping/PreferredConstructor.java b/src/main/java/org/springframework/data/mapping/PreferredConstructor.java index c45967a8a..e7c28e156 100644 --- a/src/main/java/org/springframework/data/mapping/PreferredConstructor.java +++ b/src/main/java/org/springframework/data/mapping/PreferredConstructor.java @@ -20,7 +20,6 @@ import java.util.Arrays; import java.util.List; import org.springframework.core.annotation.MergedAnnotations; -import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.annotation.PersistenceCreator; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; @@ -36,7 +35,6 @@ import org.springframework.util.ReflectionUtils; * @author Myeonghyeon Lee * @author Xeno Amess */ -@SuppressWarnings("deprecation") public final class PreferredConstructor> extends InstanceCreatorMetadataSupport { @@ -78,26 +76,15 @@ public final class PreferredConstructor> } /** - * Returns whether the constructor was explicitly selected (by {@link PersistenceConstructor}). + * Returns whether the constructor was explicitly selected (by {@link PersistenceCreator}). * - * @return + * @return {@literal true} if the constructor was explicitly selected. */ public boolean isExplicitlyAnnotated() { var annotations = MergedAnnotations.from(getExecutable()); - return annotations.isPresent(PersistenceConstructor.class) - || annotations.isPresent(PersistenceCreator.class); - } - - /** - * @param property - * @return - * @deprecated since 3.0, use {@link #isCreatorParameter(PersistentProperty)} instead. - */ - @Deprecated - public boolean isConstructorParameter(PersistentProperty property) { - return isCreatorParameter(property); + return annotations.isPresent(PersistenceCreator.class); } @Override diff --git a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java index ed51359e0..0f39cd390 100644 --- a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -130,13 +130,6 @@ public class BasicPersistentEntity> implement .anyMatch(it -> !(isCreatorArgument(it) || it.isTransient()))); } - @Nullable - @Override - @SuppressWarnings("unchecked") - public PreferredConstructor getPersistenceConstructor() { - return creator instanceof PreferredConstructor ? (PreferredConstructor) creator : null; - } - @Nullable @Override public InstanceCreatorMetadata

getInstanceCreatorMetadata() { diff --git a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java index a08a00e3b..883f19d08 100644 --- a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java +++ b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java @@ -32,6 +32,7 @@ import org.springframework.asm.MethodVisitor; import org.springframework.asm.Opcodes; import org.springframework.asm.Type; 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.mapping.FactoryMethod; @@ -159,8 +160,7 @@ class ClassGeneratingEntityInstantiator implements EntityInstantiator { * @return */ protected EntityInstantiator doCreateEntityInstantiator(PersistentEntity entity) { - return new EntityInstantiatorAdapter( - createObjectInstantiator(entity, entity.getInstanceCreatorMetadata())); + return new EntityInstantiatorAdapter(createObjectInstantiator(entity, entity.getInstanceCreatorMetadata())); } /** @@ -239,7 +239,8 @@ class ClassGeneratingEntityInstantiator implements EntityInstantiator { @Nullable InstanceCreatorMetadata constructor) { try { - return (ObjectInstantiator) this.generator.generateCustomInstantiatorClass(entity, constructor).newInstance(); + Class instantiatorClass = this.generator.generateCustomInstantiatorClass(entity, constructor); + return (ObjectInstantiator) BeanUtils.instantiateClass(instantiatorClass); } catch (Exception e) { throw new RuntimeException(e); } @@ -482,8 +483,7 @@ class ClassGeneratingEntityInstantiator implements EntityInstantiator { String entityTypeResourcePath = Type.getInternalName(entity.getType()); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, CREATE_METHOD_NAME, - "([" + BytecodeUtil.referenceName(Object.class) + ")" + BytecodeUtil.referenceName(Object.class), - null, null); + "([" + BytecodeUtil.referenceName(Object.class) + ")" + BytecodeUtil.referenceName(Object.class), null, null); mv.visitCode(); mv.visitTypeInsn(NEW, entityTypeResourcePath); mv.visitInsn(DUP); diff --git a/src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java b/src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java deleted file mode 100644 index 871108370..000000000 --- a/src/main/java/org/springframework/data/mapping/model/DefaultSpELExpressionEvaluator.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011-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.mapping.model; - -import org.springframework.data.mapping.Parameter; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * {@link ParameterValueProvider} implementation that evaluates the {@link Parameter}s key against - * {@link SpelExpressionParser} and {@link EvaluationContext}. - * - * @author Oliver Gierke - * @deprecated since 3.3, use {@link CachingValueExpressionEvaluatorFactory} instead. - */ -@Deprecated(since = "3.3") -public class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator { - - private final Object source; - private final SpELContext factory; - - public DefaultSpELExpressionEvaluator(Object source, SpELContext factory) { - - Assert.notNull(source, "Source must not be null"); - Assert.notNull(factory, "SpELContext must not be null"); - - this.source = source; - this.factory = factory; - } - - @Override - @Nullable - @SuppressWarnings("unchecked") - public T evaluate(String expression) { - - Expression parseExpression = factory.getParser().parseExpression(expression); - return (T) parseExpression.getValue(factory.getEvaluationContext(source)); - } -} diff --git a/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java b/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java index 59fd14cf9..5468e1deb 100644 --- a/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java +++ b/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java @@ -155,18 +155,6 @@ public class MappingInstantiationException extends RuntimeException { return Optional.ofNullable(entityType); } - /** - * The constructor used during the instantiation attempt. - * - * @return the constructor - * @deprecated since 3.0, use {@link #getEntityCreator()} instead. - */ - @Deprecated - public Optional> getConstructor() { - return getEntityCreator().filter(PreferredConstructor.class::isInstance).map(PreferredConstructor.class::cast) - .map(PreferredConstructor::getConstructor); - } - /** * The entity creator used during the instantiation attempt. * diff --git a/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java b/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java index 5b39b89d4..31e5a2b5b 100644 --- a/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java +++ b/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java @@ -24,9 +24,7 @@ import org.springframework.lang.Nullable; /** * {@link ParameterValueProvider} based on a {@link PersistentEntity} to use a {@link PropertyValueProvider} to lookup - * the value of the property referenced by the given {@link Parameter}. Additionally a - * {@link DefaultSpELExpressionEvaluator} can be configured to get property value resolution trumped by a SpEL - * expression evaluation. + * the value of the property referenced by the given {@link Parameter}. * * @author Oliver Gierke * @author Johannes Englmeier diff --git a/src/main/java/org/springframework/data/mapping/model/SpELExpressionEvaluator.java b/src/main/java/org/springframework/data/mapping/model/SpELExpressionEvaluator.java deleted file mode 100644 index cb1b414e6..000000000 --- a/src/main/java/org/springframework/data/mapping/model/SpELExpressionEvaluator.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2012-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.mapping.model; - -/** - * SPI for components that can evaluate Spring EL expressions. - * - * @author Oliver Gierke - */ -@Deprecated(since = "3.3") -public interface SpELExpressionEvaluator extends ValueExpressionEvaluator { - -} diff --git a/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java b/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java deleted file mode 100644 index a9b53d4e0..000000000 --- a/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012-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.mapping.model; - -import org.springframework.core.convert.ConversionService; -import org.springframework.data.mapping.PersistentProperty; - -/** - * {@link ParameterValueProvider} that can be used to front a {@link ParameterValueProvider} delegate to prefer a SpEL - * expression evaluation over directly resolving the parameter value with the delegate. - * - * @author Oliver Gierke - * @author Mark Paluch - * @deprecated since 3.3, use {@link ValueExpressionParameterValueProvider} instead. - */ -@Deprecated(since = "3.3") -public class SpELExpressionParameterValueProvider

> - extends ValueExpressionParameterValueProvider

implements ParameterValueProvider

{ - - public SpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator, ConversionService conversionService, - ParameterValueProvider

delegate) { - - super(evaluator, conversionService, delegate); - } - -} diff --git a/src/main/java/org/springframework/data/mapping/model/ValueExpressionParameterValueProvider.java b/src/main/java/org/springframework/data/mapping/model/ValueExpressionParameterValueProvider.java index d45275c0e..43ed677db 100644 --- a/src/main/java/org/springframework/data/mapping/model/ValueExpressionParameterValueProvider.java +++ b/src/main/java/org/springframework/data/mapping/model/ValueExpressionParameterValueProvider.java @@ -66,21 +66,6 @@ public class ValueExpressionParameterValueProvider

T potentiallyConvertSpelValue(Object object, Parameter parameter) { - return conversionService.convert(object, parameter.getRawType()); - } - /** * Hook to allow to massage the value resulting from the Spel expression evaluation. Default implementation will * leverage the configured {@link ConversionService} to massage the value into the parameter type. @@ -92,6 +77,6 @@ public class ValueExpressionParameterValueProvider

T potentiallyConvertExpressionValue(Object object, Parameter parameter) { - return potentiallyConvertSpelValue(object, parameter); + return conversionService.convert(object, parameter.getRawType()); } } diff --git a/src/main/java/org/springframework/data/projection/SpelEvaluatingMethodInterceptor.java b/src/main/java/org/springframework/data/projection/SpelEvaluatingMethodInterceptor.java index 381e4ed8d..e1e1d371e 100644 --- a/src/main/java/org/springframework/data/projection/SpelEvaluatingMethodInterceptor.java +++ b/src/main/java/org/springframework/data/projection/SpelEvaluatingMethodInterceptor.java @@ -16,6 +16,7 @@ package org.springframework.data.projection; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -188,7 +189,7 @@ class SpelEvaluatingMethodInterceptor implements MethodInterceptor { @Override public int hashCode() { int result = ObjectUtils.nullSafeHashCode(target); - result = 31 * result + ObjectUtils.nullSafeHashCode(args); + result = 31 * result + Arrays.hashCode(args); return result; } diff --git a/src/main/java/org/springframework/data/querydsl/QPageRequest.java b/src/main/java/org/springframework/data/querydsl/QPageRequest.java index 359d01601..15e245e58 100644 --- a/src/main/java/org/springframework/data/querydsl/QPageRequest.java +++ b/src/main/java/org/springframework/data/querydsl/QPageRequest.java @@ -43,10 +43,8 @@ public class QPageRequest extends AbstractPageRequest { * * @param pageNumber zero-based page number, must not be negative. * @param pageSize the size of the page to be returned, must be greater than 0. - * @deprecated since 2.1, use {@link #of(int, int)} instead. */ - @Deprecated - public QPageRequest(int pageNumber, int pageSize) { + private QPageRequest(int pageNumber, int pageSize) { this(pageNumber, pageSize, QSort.unsorted()); } @@ -56,10 +54,8 @@ public class QPageRequest extends AbstractPageRequest { * @param pageNumber zero-based page number, must not be negative. * @param pageSize the size of the page to be returned, must be greater than 0. * @param orderSpecifiers must not be {@literal null} or empty; - * @deprecated since 2.1, use {@link #of(int, int, OrderSpecifier...)} instead. */ - @Deprecated - public QPageRequest(int pageNumber, int pageSize, OrderSpecifier... orderSpecifiers) { + private QPageRequest(int pageNumber, int pageSize, OrderSpecifier... orderSpecifiers) { this(pageNumber, pageSize, new QSort(orderSpecifiers)); } @@ -69,10 +65,8 @@ public class QPageRequest extends AbstractPageRequest { * @param pageNumber zero-based page number, must not be negative. * @param pageSize the size of the page to be returned, must be greater than 0. * @param sort must not be {@literal null}. - * @deprecated since 2.1, use {@link #of(int, int, QSort)} instead. */ - @Deprecated - public QPageRequest(int pageNumber, int pageSize, QSort sort) { + private QPageRequest(int pageNumber, int pageSize, QSort sort) { super(pageNumber, pageSize); diff --git a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryConfiguration.java b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryConfiguration.java index cbe56d388..3e4f9e206 100644 --- a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryConfiguration.java +++ b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryConfiguration.java @@ -24,7 +24,7 @@ import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.support.QueryCreationListener; import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor; import org.springframework.data.repository.query.QueryLookupStrategy; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.data.spel.EvaluationContextProvider; /** * Interface containing the configurable options for the Spring Data repository subsystem using CDI. @@ -36,13 +36,13 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextPro public interface CdiRepositoryConfiguration { /** - * Return the {@link QueryMethodEvaluationContextProvider} to use. Can be {@link Optional#empty()} . + * Return the {@link EvaluationContextProvider} to use. Can be {@link Optional#empty()} . * - * @return the optional {@link QueryMethodEvaluationContextProvider} base to use, can be {@link Optional#empty()}, - * must not be {@literal null}. + * @return the optional {@link EvaluationContextProvider} base to use, can be {@link Optional#empty()}, must not be + * {@literal null}. * @since 2.1 */ - default Optional getEvaluationContextProvider() { + default Optional getEvaluationContextProvider() { return Optional.empty(); } diff --git a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java index 4ef488513..753a93ffa 100644 --- a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java @@ -76,23 +76,6 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura private final Function> typeFilterFunction; private final boolean hasExplicitFilters; - /** - * Creates a new {@link AnnotationRepositoryConfigurationSource} from the given {@link AnnotationMetadata} and - * annotation. - * - * @param metadata must not be {@literal null}. - * @param annotation must not be {@literal null}. - * @param resourceLoader must not be {@literal null}. - * @param environment must not be {@literal null}. - * @param registry must not be {@literal null}. - * @deprecated since 2.2. Prefer to use overload taking a {@link BeanNameGenerator} additionally. - */ - @Deprecated(since = "2.2") - public AnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class annotation, - ResourceLoader resourceLoader, Environment environment, BeanDefinitionRegistry registry) { - this(metadata, annotation, resourceLoader, environment, registry, null); - } - /** * Creates a new {@link AnnotationRepositoryConfigurationSource} from the given {@link AnnotationMetadata} and * annotation. diff --git a/src/main/java/org/springframework/data/repository/core/support/ReactiveRepositoryFactorySupport.java b/src/main/java/org/springframework/data/repository/core/support/ReactiveRepositoryFactorySupport.java index 85cc89566..5e6e2dbfd 100644 --- a/src/main/java/org/springframework/data/repository/core/support/ReactiveRepositoryFactorySupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/ReactiveRepositoryFactorySupport.java @@ -24,9 +24,6 @@ import org.reactivestreams.Publisher; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.QueryLookupStrategy; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; -import org.springframework.data.repository.query.ReactiveExtensionAwareQueryMethodEvaluationContextProvider; -import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ValueExpressionDelegate; import org.springframework.data.repository.util.ReactiveWrapperConverters; import org.springframework.data.util.ReactiveWrappers; @@ -61,29 +58,9 @@ public abstract class ReactiveRepositoryFactorySupport extends RepositoryFactory } } - /** - * Sets the {@link QueryMethodEvaluationContextProvider} to be used to evaluate SpEL expressions in manually defined - * queries. - * - * @param evaluationContextProvider can be {@literal null}, defaults to - * {@link ReactiveQueryMethodEvaluationContextProvider#DEFAULT}. - */ - @Override - public void setEvaluationContextProvider(QueryMethodEvaluationContextProvider evaluationContextProvider) { - super.setEvaluationContextProvider( - evaluationContextProvider == null ? ReactiveQueryMethodEvaluationContextProvider.DEFAULT - : evaluationContextProvider); - } - /** * Returns the {@link QueryLookupStrategy} for the given {@link QueryLookupStrategy.Key} and - * {@link ValueExpressionDelegate}. Favor implementing this method over - * {@link #getQueryLookupStrategy(QueryLookupStrategy.Key, QueryMethodEvaluationContextProvider)} for extended - * {@link org.springframework.data.expression.ValueExpression} support. - *

- * This method delegates to - * {@link #getQueryLookupStrategy(QueryLookupStrategy.Key, QueryMethodEvaluationContextProvider)} unless overridden. - *

+ * {@link ValueExpressionDelegate}. * * @param key can be {@literal null}. * @param valueExpressionDelegate will never be {@literal null}. @@ -93,8 +70,7 @@ public abstract class ReactiveRepositoryFactorySupport extends RepositoryFactory @Override protected Optional getQueryLookupStrategy(@Nullable QueryLookupStrategy.Key key, ValueExpressionDelegate valueExpressionDelegate) { - return getQueryLookupStrategy(key, - new ReactiveExtensionAwareQueryMethodEvaluationContextProvider(getEvaluationContextProvider())); + return Optional.empty(); } /** diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java index 9e83cf8f0..5391494f4 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java @@ -38,11 +38,9 @@ import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments; -import org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; import org.springframework.data.repository.query.QueryMethod; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.QueryMethodValueEvaluationContextAccessor; import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.data.util.Lazy; @@ -183,18 +181,6 @@ public abstract class RepositoryFactoryBeanSupport, this.evaluationContextProvider = Optional.of(evaluationContextProvider); } - /** - * Sets the {@link QueryMethodEvaluationContextProvider} to be used to evaluate SpEL expressions in manually defined - * queries. - * - * @param evaluationContextProvider must not be {@literal null}. - * @deprecated since 3.4, use {@link #setEvaluationContextProvider(EvaluationContextProvider)} instead. - */ - @Deprecated(since = "3.4", forRemoval = true) - public void setEvaluationContextProvider(QueryMethodEvaluationContextProvider evaluationContextProvider) { - setEvaluationContextProvider(evaluationContextProvider.getEvaluationContextProvider()); - } - /** * Register a {@link RepositoryFactoryCustomizer} to customize the {@link RepositoryFactorySupport repository factor} * before creating the repository. @@ -246,22 +232,7 @@ public abstract class RepositoryFactoryBeanSupport, */ protected Optional createDefaultEvaluationContextProvider( ListableBeanFactory beanFactory) { - return createDefaultQueryMethodEvaluationContextProvider(beanFactory) - .map(QueryMethodEvaluationContextProvider::getEvaluationContextProvider); - } - - /** - * Create a default {@link QueryMethodEvaluationContextProvider} (or subclass) from {@link ListableBeanFactory}. - * - * @param beanFactory the bean factory to use. - * @return the default instance. May be {@link Optional#empty()}. - * @since 2.4 - * @deprecated since 3.4, use {@link #createDefaultEvaluationContextProvider(ListableBeanFactory)} instead. - */ - @Deprecated(since = "3.4", forRemoval = true) - protected Optional createDefaultQueryMethodEvaluationContextProvider( - ListableBeanFactory beanFactory) { - return Optional.of(new ExtensionAwareQueryMethodEvaluationContextProvider(beanFactory)); + return Optional.of(QueryMethodValueEvaluationContextAccessor.createEvaluationContextProvider(beanFactory)); } @Override diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java index 386eddccf..c485ea79b 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java @@ -31,6 +31,7 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.interceptor.ExposeInvocationInterceptor; import org.springframework.beans.BeanUtils; @@ -62,11 +63,9 @@ import org.springframework.data.repository.core.RepositoryMethodContextHolder; import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments; import org.springframework.data.repository.core.support.RepositoryInvocationMulticaster.DefaultRepositoryInvocationMulticaster; import org.springframework.data.repository.core.support.RepositoryInvocationMulticaster.NoOpRepositoryInvocationMulticaster; -import org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; import org.springframework.data.repository.query.QueryMethod; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.QueryMethodValueEvaluationContextAccessor; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.ValueExpressionDelegate; @@ -211,20 +210,6 @@ public abstract class RepositoryFactorySupport return this.environment; } - /** - * Sets the {@link QueryMethodEvaluationContextProvider} to be used to evaluate SpEL expressions in manually defined - * queries. - * - * @param evaluationContextProvider can be {@literal null}, defaults to - * {@link QueryMethodEvaluationContextProvider#DEFAULT}. - * @deprecated since 3.4, use {@link #setEvaluationContextProvider(EvaluationContextProvider)} instead. - */ - @Deprecated(since = "3.4", forRemoval = true) - public void setEvaluationContextProvider(@Nullable QueryMethodEvaluationContextProvider evaluationContextProvider) { - setEvaluationContextProvider(evaluationContextProvider == null ? EvaluationContextProvider.DEFAULT - : evaluationContextProvider.getEvaluationContextProvider()); - } - /** * Sets the {@link EvaluationContextProvider} to be used to evaluate SpEL expressions in manually defined queries. * @@ -559,28 +544,7 @@ public abstract class RepositoryFactorySupport protected abstract Class getRepositoryBaseClass(RepositoryMetadata metadata); /** - * Returns the {@link QueryLookupStrategy} for the given {@link Key} and {@link QueryMethodEvaluationContextProvider}. - * - * @param key can be {@literal null}. - * @param evaluationContextProvider will never be {@literal null}. - * @return the {@link QueryLookupStrategy} to use or {@literal null} if no queries should be looked up. - * @since 1.9 - * @deprecated since 3.4, use {@link #getQueryLookupStrategy(Key, ValueExpressionDelegate)} instead to support - * {@link org.springframework.data.expression.ValueExpression} in query methods. - */ - @Deprecated(since = "3.4", forRemoval = true) - protected Optional getQueryLookupStrategy(@Nullable Key key, - QueryMethodEvaluationContextProvider evaluationContextProvider) { - return Optional.empty(); - } - - /** - * Returns the {@link QueryLookupStrategy} for the given {@link Key} and {@link ValueExpressionDelegate}. Favor - * implementing this method over {@link #getQueryLookupStrategy(Key, QueryMethodEvaluationContextProvider)} for - * extended {@link org.springframework.data.expression.ValueExpression} support. - *

- * This method delegates to {@link #getQueryLookupStrategy(Key, QueryMethodEvaluationContextProvider)} unless - * overridden. + * Returns the {@link QueryLookupStrategy} for the given {@link Key} and {@link ValueExpressionDelegate}. * * @param key can be {@literal null}. * @param valueExpressionDelegate will never be {@literal null}. @@ -589,8 +553,7 @@ public abstract class RepositoryFactorySupport */ protected Optional getQueryLookupStrategy(@Nullable Key key, ValueExpressionDelegate valueExpressionDelegate) { - return getQueryLookupStrategy(key, - new ExtensionAwareQueryMethodEvaluationContextProvider(evaluationContextProvider)); + return Optional.empty(); } /** @@ -625,21 +588,6 @@ public abstract class RepositoryFactorySupport return instantiateClass(baseClass, constructorArguments); } - /** - * Creates a repository of the repository base class defined in the given {@link RepositoryInformation} using - * reflection. - * - * @param baseClass - * @param constructorArguments - * @return - * @deprecated since 2.6 because it has a misleading name. Use {@link #instantiateClass(Class, Object...)} instead. - */ - @SuppressWarnings("unchecked") - @Deprecated - protected final R getTargetRepositoryViaReflection(Class baseClass, Object... constructorArguments) { - return instantiateClass(baseClass, constructorArguments); - } - /** * Convenience method to instantiate a class using the given {@code constructorArguments} by looking up a matching * constructor. diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFragment.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFragment.java index dfa07468a..48047ae66 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFragment.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFragment.java @@ -169,18 +169,6 @@ public interface RepositoryFragment { private final @Nullable Class interfaceClass; private final T implementation; - /** - * Creates a new {@link ImplementedRepositoryFragment} for the given interface class and implementation. - * - * @param interfaceClass - * @param implementation - * @deprecated since 3.4 - use {@link ImplementedRepositoryFragment(Class, Object)} instead. - */ - @Deprecated(since = "3.4", forRemoval = true) - public ImplementedRepositoryFragment(Optional> interfaceClass, T implementation) { - this(interfaceClass.orElse(null), implementation); - } - /** * Creates a new {@link ImplementedRepositoryFragment} for the given interface class and implementation. * diff --git a/src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java b/src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java deleted file mode 100644 index fdf17c1e6..000000000 --- a/src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2014-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.repository.query; - -import java.util.List; - -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.data.expression.ValueEvaluationContext; -import org.springframework.data.spel.EvaluationContextProvider; -import org.springframework.data.spel.ExpressionDependencies; -import org.springframework.data.spel.spi.EvaluationContextExtension; -import org.springframework.expression.EvaluationContext; -import org.springframework.util.Assert; - -/** - * An {@link QueryMethodEvaluationContextProvider} that assembles an {@link EvaluationContext} from a list of - * {@link EvaluationContextExtension} instances. - * - * @author Thomas Darimont - * @author Oliver Gierke - * @author Christoph Strobl - * @author Jens Schauder - * @author Johannes Englmeier - * @since 1.9 - * @deprecated since 3.4 in favor of {@link QueryMethodValueEvaluationContextAccessor}. - */ -@SuppressWarnings("removal") -@Deprecated(since = "3.4", forRemoval = true) -public class ExtensionAwareQueryMethodEvaluationContextProvider implements QueryMethodEvaluationContextProvider { - - private final QueryMethodValueEvaluationContextAccessor delegate; - - /** - * Creates a new {@link ExtensionAwareQueryMethodEvaluationContextProvider}. - * - * @param evaluationContextProvider to lookup the {@link EvaluationContextExtension}s from, must not be - * {@literal null}. - */ - public ExtensionAwareQueryMethodEvaluationContextProvider(EvaluationContextProvider evaluationContextProvider) { - - Assert.notNull(evaluationContextProvider, "EvaluationContextProvider must not be null"); - - this.delegate = new QueryMethodValueEvaluationContextAccessor(QueryMethodValueEvaluationContextAccessor.ENVIRONMENT, - evaluationContextProvider); - } - - /** - * Creates a new {@link ExtensionAwareQueryMethodEvaluationContextProvider}. - * - * @param beanFactory the {@link ListableBeanFactory} to lookup the {@link EvaluationContextExtension}s from, must not - * be {@literal null}. - */ - public ExtensionAwareQueryMethodEvaluationContextProvider(ListableBeanFactory beanFactory) { - - Assert.notNull(beanFactory, "ListableBeanFactory must not be null"); - - this.delegate = beanFactory instanceof ApplicationContext ctx ? new QueryMethodValueEvaluationContextAccessor(ctx) - : new QueryMethodValueEvaluationContextAccessor(QueryMethodValueEvaluationContextAccessor.ENVIRONMENT, - beanFactory); - } - - /** - * Creates a new {@link ExtensionAwareQueryMethodEvaluationContextProvider} using the given - * {@link EvaluationContextExtension}s. - * - * @param extensions must not be {@literal null}. - */ - public ExtensionAwareQueryMethodEvaluationContextProvider(List extensions) { - - Assert.notNull(extensions, "EvaluationContextExtensions must not be null"); - - this.delegate = new QueryMethodValueEvaluationContextAccessor(QueryMethodValueEvaluationContextAccessor.ENVIRONMENT, - extensions); - } - - ExtensionAwareQueryMethodEvaluationContextProvider(QueryMethodValueEvaluationContextAccessor delegate) { - this.delegate = delegate; - } - - @Override - public EvaluationContextProvider getEvaluationContextProvider() { - return getDelegate().getEvaluationContextProvider(); - } - - public QueryMethodValueEvaluationContextAccessor getDelegate() { - return delegate; - } - - @Override - public > EvaluationContext getEvaluationContext(T parameters, Object[] parameterValues) { - - ValueEvaluationContext evaluationContext = delegate.create(parameters).getEvaluationContext(parameterValues); - - return evaluationContext.getRequiredEvaluationContext(); - } - - @Override - public > EvaluationContext getEvaluationContext(T parameters, Object[] parameterValues, - ExpressionDependencies dependencies) { - - ValueEvaluationContext evaluationContext = delegate.create(parameters).getEvaluationContext(parameterValues, - dependencies); - - return evaluationContext.getRequiredEvaluationContext(); - } - -} diff --git a/src/main/java/org/springframework/data/repository/query/Parameter.java b/src/main/java/org/springframework/data/repository/query/Parameter.java index 03b1a4f97..0907d0f03 100644 --- a/src/main/java/org/springframework/data/repository/query/Parameter.java +++ b/src/main/java/org/springframework/data/repository/query/Parameter.java @@ -71,17 +71,6 @@ public class Parameter { TYPES = Collections.unmodifiableList(types); } - /** - * Creates a new {@link Parameter} for the given {@link MethodParameter}. - * - * @param parameter must not be {@literal null}. - * @deprecated since 3.1, use {@link #Parameter(MethodParameter, TypeInformation)} instead. - */ - @Deprecated(since = "3.1", forRemoval = true) - protected Parameter(MethodParameter parameter) { - this(parameter, TypeInformation.of(Parameter.class)); - } - /** * Creates a new {@link Parameter} for the given {@link MethodParameter} and domain {@link TypeInformation}. * diff --git a/src/main/java/org/springframework/data/repository/query/Parameters.java b/src/main/java/org/springframework/data/repository/query/Parameters.java index 0c5af28e5..9b2bdf991 100644 --- a/src/main/java/org/springframework/data/repository/query/Parameters.java +++ b/src/main/java/org/springframework/data/repository/query/Parameters.java @@ -63,20 +63,6 @@ public abstract class Parameters, T extends Parameter private int dynamicProjectionIndex; - /** - * Creates a new {@link Parameters} instance for the given {@link Method} and {@link Function} to create a - * {@link Parameter} instance from a {@link MethodParameter}. - * - * @param method must not be {@literal null}. - * @param parameterFactory must not be {@literal null}. - * @since 3.0.2 - * @deprecated since 3.2.1, use {@link Parameters(ParametersSource, Function)} instead. - */ - @Deprecated(since = "3.2.1", forRemoval = true) - protected Parameters(Method method, Function parameterFactory) { - this(ParametersSource.of(method), parameterFactory); - } - /** * Creates a new {@link Parameters} instance for the given {@link Method} and {@link Function} to create a * {@link Parameter} instance from a {@link MethodParameter}. diff --git a/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/src/main/java/org/springframework/data/repository/query/QueryMethod.java index 033e543a9..a64b7c56a 100644 --- a/src/main/java/org/springframework/data/repository/query/QueryMethod.java +++ b/src/main/java/org/springframework/data/repository/query/QueryMethod.java @@ -106,7 +106,7 @@ public class QueryMethod { this.method = method; this.unwrappedReturnType = potentiallyUnwrapReturnTypeFor(metadata, method); this.metadata = metadata; - this.parameters = parametersFunction == null ? createParameters(method, metadata.getDomainTypeInformation()) + this.parameters = parametersFunction == null ? createParameters(ParametersSource.of(metadata, method)) : parametersFunction.apply(ParametersSource.of(metadata, method)); this.domainClass = Lazy.of(() -> { @@ -187,20 +187,6 @@ public class QueryMethod { return TypeInformation.of(unwrappedReturnType).isCollectionLike(); } - /** - * Creates a {@link Parameters} instance. - * - * @param method must not be {@literal null}. - * @param domainType must not be {@literal null}. - * @return must not return {@literal null}. - * @deprecated since 3.2.1, use {@link #createParameters(ParametersSource)} instead. - * @since 3.0.2 - */ - @Deprecated(since = "3.2.1", forRemoval = true) - protected Parameters createParameters(Method method, TypeInformation domainType) { - return createParameters(ParametersSource.of(getMetadata(), method)); - } - /** * Creates a {@link Parameters} instance. * diff --git a/src/main/java/org/springframework/data/repository/query/QueryMethodEvaluationContextProvider.java b/src/main/java/org/springframework/data/repository/query/QueryMethodEvaluationContextProvider.java deleted file mode 100644 index 25592003e..000000000 --- a/src/main/java/org/springframework/data/repository/query/QueryMethodEvaluationContextProvider.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2014-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.repository.query; - -import java.util.Collections; - -import org.springframework.data.spel.EvaluationContextProvider; -import org.springframework.data.spel.ExpressionDependencies; -import org.springframework.expression.EvaluationContext; - -/** - * Provides a way to access a centrally defined potentially shared {@link EvaluationContext}. - * - * @author Thomas Darimont - * @author Oliver Gierke - * @author Christoph Strobl - * @since 1.9 - * @deprecated since 3.4 in favor of {@link QueryMethodValueEvaluationContextAccessor}. - */ -@Deprecated(since = "3.4", forRemoval = true) -@SuppressWarnings("removal") -public interface QueryMethodEvaluationContextProvider { - - QueryMethodEvaluationContextProvider DEFAULT = new ExtensionAwareQueryMethodEvaluationContextProvider( - Collections.emptyList()); - - /** - * Returns an {@link EvaluationContext} built using the given {@link Parameters} and parameter values. - * - * @param parameters the {@link Parameters} instance obtained from the query method the context is built for. - * @param parameterValues the values for the parameters. - * @return - */ - > EvaluationContext getEvaluationContext(T parameters, Object[] parameterValues); - - /** - * Returns an {@link EvaluationContext} built using the given {@link Parameters} and parameter values. - * - * @param parameters the {@link Parameters} instance obtained from the query method the context is built for. - * @param parameterValues the values for the parameters. - * @return - */ - > EvaluationContext getEvaluationContext(T parameters, Object[] parameterValues, - ExpressionDependencies dependencies); - - /** - * @return the underlying {@link EvaluationContextProvider}. - */ - EvaluationContextProvider getEvaluationContextProvider(); -} diff --git a/src/main/java/org/springframework/data/repository/query/QueryMethodValueEvaluationContextAccessor.java b/src/main/java/org/springframework/data/repository/query/QueryMethodValueEvaluationContextAccessor.java index 907af0964..168938689 100644 --- a/src/main/java/org/springframework/data/repository/query/QueryMethodValueEvaluationContextAccessor.java +++ b/src/main/java/org/springframework/data/repository/query/QueryMethodValueEvaluationContextAccessor.java @@ -115,7 +115,7 @@ public class QueryMethodValueEvaluationContextAccessor { this.evaluationContextProvider = createEvaluationContextProvider(extensions); } - private static EvaluationContextProvider createEvaluationContextProvider(ListableBeanFactory factory) { + public static EvaluationContextProvider createEvaluationContextProvider(ListableBeanFactory factory) { return ReactiveWrappers.isAvailable(ReactiveWrappers.ReactiveLibrary.PROJECT_REACTOR) ? new ReactiveExtensionAwareEvaluationContextProvider(factory) diff --git a/src/main/java/org/springframework/data/repository/query/ReactiveExtensionAwareQueryMethodEvaluationContextProvider.java b/src/main/java/org/springframework/data/repository/query/ReactiveExtensionAwareQueryMethodEvaluationContextProvider.java deleted file mode 100644 index 5fb0717b8..000000000 --- a/src/main/java/org/springframework/data/repository/query/ReactiveExtensionAwareQueryMethodEvaluationContextProvider.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2014-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.repository.query; - -import reactor.core.publisher.Mono; - -import java.util.List; - -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.data.expression.ReactiveValueEvaluationContextProvider; -import org.springframework.data.expression.ValueEvaluationContext; -import org.springframework.data.spel.EvaluationContextProvider; -import org.springframework.data.spel.ExpressionDependencies; -import org.springframework.data.spel.spi.EvaluationContextExtension; -import org.springframework.data.spel.spi.ExtensionIdAware; -import org.springframework.expression.EvaluationContext; - -/** - * An reactive {@link QueryMethodEvaluationContextProvider} that assembles an {@link EvaluationContext} from a list of - * {@link EvaluationContextExtension} and {@link org.springframework.data.spel.spi.ReactiveEvaluationContextExtension}. - * instances. - * - * @author Mark Paluch - * @since 2.4 - * @deprecated since 3.4 in favor of {@link QueryMethodValueEvaluationContextAccessor}. - */ -@SuppressWarnings("removal") -@Deprecated(since = "3.4", forRemoval = true) -public class ReactiveExtensionAwareQueryMethodEvaluationContextProvider - extends ExtensionAwareQueryMethodEvaluationContextProvider - implements ReactiveQueryMethodEvaluationContextProvider { - - /** - * Create a new {@link ReactiveExtensionAwareQueryMethodEvaluationContextProvider}. - * - * @param beanFactory the {@link ListableBeanFactory} to lookup the {@link EvaluationContextExtension}s from, must not - * be {@literal null}. - */ - public ReactiveExtensionAwareQueryMethodEvaluationContextProvider(ListableBeanFactory beanFactory) { - super(beanFactory); - } - - /** - * Create a new {@link ReactiveExtensionAwareQueryMethodEvaluationContextProvider} using the given - * {@link EvaluationContextExtension}s and - * {@link org.springframework.data.spel.spi.ReactiveEvaluationContextExtension}s. - * - * @param extensions must not be {@literal null}. - */ - public ReactiveExtensionAwareQueryMethodEvaluationContextProvider(List extensions) { - super(new QueryMethodValueEvaluationContextAccessor(QueryMethodValueEvaluationContextAccessor.ENVIRONMENT, - extensions)); - } - - /** - * Creates a new {@link ReactiveExtensionAwareQueryMethodEvaluationContextProvider}. - * - * @param evaluationContextProvider to lookup the {@link EvaluationContextExtension}s from, must not be - * {@literal null}. - */ - public ReactiveExtensionAwareQueryMethodEvaluationContextProvider( - EvaluationContextProvider evaluationContextProvider) { - super(new QueryMethodValueEvaluationContextAccessor(QueryMethodValueEvaluationContextAccessor.ENVIRONMENT, - evaluationContextProvider)); - } - - @Override - public > Mono getEvaluationContextLater(T parameters, - Object[] parameterValues) { - - return createProvider(parameters).getEvaluationContextLater(parameterValues) - .map(ValueEvaluationContext::getRequiredEvaluationContext); - } - - @Override - public > Mono getEvaluationContextLater(T parameters, - Object[] parameterValues, ExpressionDependencies dependencies) { - - return createProvider(parameters).getEvaluationContextLater(parameterValues, dependencies) - .map(ValueEvaluationContext::getRequiredEvaluationContext); - } - - private ReactiveValueEvaluationContextProvider createProvider(Parameters parameters) { - return (ReactiveValueEvaluationContextProvider) getDelegate().create(parameters); - } -} diff --git a/src/main/java/org/springframework/data/repository/query/ReactiveQueryMethodEvaluationContextProvider.java b/src/main/java/org/springframework/data/repository/query/ReactiveQueryMethodEvaluationContextProvider.java deleted file mode 100644 index 730b92d80..000000000 --- a/src/main/java/org/springframework/data/repository/query/ReactiveQueryMethodEvaluationContextProvider.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2014-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.repository.query; - -import reactor.core.publisher.Mono; - -import java.util.Collections; - -import org.springframework.data.spel.ExpressionDependencies; -import org.springframework.expression.EvaluationContext; - -/** - * Provides a way to access a centrally defined potentially shared {@link EvaluationContext} by considering - * {@link org.springframework.data.spel.spi.ReactiveEvaluationContextExtension}. - * - * @author Mark Paluch - * @since 2.4 - * @deprecated since 3.4 in favor of {@link QueryMethodValueEvaluationContextAccessor}. - */ -@Deprecated(since = "3.4", forRemoval = true) -public interface ReactiveQueryMethodEvaluationContextProvider extends QueryMethodEvaluationContextProvider { - - ReactiveQueryMethodEvaluationContextProvider DEFAULT = new ReactiveExtensionAwareQueryMethodEvaluationContextProvider( - Collections.emptyList()); - - /** - * Return a {@link EvaluationContext} built using the given {@link Parameters} and parameter values. - * - * @param parameters the {@link Parameters} instance obtained from the query method the context is built for. - * @param parameterValues the values for the parameters. - * @return a mono that emits exactly one {@link EvaluationContext}. - */ - > Mono getEvaluationContextLater(T parameters, - Object[] parameterValues); - - /** - * Return a {@link EvaluationContext} built using the given {@link Parameters} and parameter values. - * - * @param parameters the {@link Parameters} instance obtained from the query method the context is built for. - * @param parameterValues the values for the parameters. - * @return a mono that emits exactly one {@link EvaluationContext}. - */ - > Mono getEvaluationContextLater(T parameters, Object[] parameterValues, - ExpressionDependencies dependencies); -} diff --git a/src/main/java/org/springframework/data/repository/query/SpelEvaluator.java b/src/main/java/org/springframework/data/repository/query/SpelEvaluator.java deleted file mode 100644 index 17e781247..000000000 --- a/src/main/java/org/springframework/data/repository/query/SpelEvaluator.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2018-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.repository.query; - -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.data.repository.query.SpelQueryContext.SpelExtractor; -import org.springframework.data.spel.ExpressionDependencies; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * Evaluates SpEL expressions as extracted by the {@link SpelExtractor} based on parameter information from a method and - * parameter values from a method call. - * - * @author Jens Schauder - * @author Gerrit Meier - * @author Oliver Gierke - * @since 2.1 - * @see SpelQueryContext#parse(String) - * @deprecated since 3.3, use {@link ValueExpressionQueryRewriter} instead. - */ -@SuppressWarnings("removal") -@Deprecated(since = "3.3", forRemoval = true) -public class SpelEvaluator { - - private static final SpelExpressionParser PARSER = new SpelExpressionParser(); - - private final QueryMethodEvaluationContextProvider evaluationContextProvider; - private final Parameters parameters; - private final SpelExtractor extractor; - - public SpelEvaluator(QueryMethodEvaluationContextProvider evaluationContextProvider, Parameters parameters, - SpelExtractor extractor) { - this.evaluationContextProvider = evaluationContextProvider; - this.parameters = parameters; - this.extractor = extractor; - } - - /** - * Evaluate all the SpEL expressions in {@link SpelExtractor} based on values provided as an argument. - * - * @param values Parameter values. Must not be {@literal null}. - * @return a map from parameter name to evaluated value. Guaranteed to be not {@literal null}. - */ - public Map evaluate(Object[] values) { - - Assert.notNull(values, "Values must not be null."); - - Map parameterMap = extractor.getParameterMap(); - Map results = new LinkedHashMap<>(parameterMap.size()); - - parameterMap.forEach((parameter, expression) -> results.put(parameter, getSpElValue(expression, values))); - - return results; - } - - /** - * Returns the query string produced by the intermediate SpEL expression collection step. - * - * @return - */ - public String getQueryString() { - return extractor.getQueryString(); - } - - @Nullable - private Object getSpElValue(String expressionString, Object[] values) { - - Expression expression = PARSER.parseExpression(expressionString); - EvaluationContext evaluationContext = evaluationContextProvider.getEvaluationContext(parameters, values, - ExpressionDependencies.discover(expression)); - - return expression.getValue(evaluationContext); - } -} diff --git a/src/main/java/org/springframework/data/repository/query/SpelQueryContext.java b/src/main/java/org/springframework/data/repository/query/SpelQueryContext.java deleted file mode 100644 index fa775cbe8..000000000 --- a/src/main/java/org/springframework/data/repository/query/SpelQueryContext.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2018-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.repository.query; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiFunction; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.springframework.data.domain.Range; -import org.springframework.data.domain.Range.Bound; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * A {@literal SpelQueryContext} is able to find SpEL expressions in a query string and to replace them with bind - * variables. - *

- * Result o the parse process is a {@link SpelExtractor} which offers the transformed query string. Alternatively and - * preferred one may provide a {@link QueryMethodEvaluationContextProvider} via - * {@link #withEvaluationContextProvider(QueryMethodEvaluationContextProvider)} which will yield the more powerful - * {@link EvaluatingSpelQueryContext}. - *

- * Typical usage looks like - * - *

- * 
-     SpelQueryContext.EvaluatingSpelQueryContext queryContext = SpelQueryContext
-         .of((counter, expression) -> String.format("__$synthetic$__%d", counter), String::concat)
-         .withEvaluationContextProvider(evaluationContextProvider);
-
-     SpelEvaluator spelEvaluator = queryContext.parse(query, queryMethod.getParameters());
-
-     spelEvaluator.evaluate(objects).forEach(parameterMap::addValue);
- * 
- * 
- * - * @author Jens Schauder - * @author Gerrit Meier - * @author Mark Paluch - * @since 2.1 - * @deprecated since 3.3, use {@link ValueExpressionQueryRewriter} instead. - */ -@SuppressWarnings("removal") -@Deprecated(since = "3.3", forRemoval = true) -public class SpelQueryContext { - - private static final String SPEL_PATTERN_STRING = "([:?])#\\{([^}]+)}"; - private static final Pattern SPEL_PATTERN = Pattern.compile(SPEL_PATTERN_STRING); - - /** - * A function from the index of a SpEL expression in a query and the actual SpEL expression to the parameter name to - * be used in place of the SpEL expression. A typical implementation is expected to look like - * (index, spel) -> "__some_placeholder_" + index - */ - private final BiFunction parameterNameSource; - - /** - * A function from a prefix used to demarcate a SpEL expression in a query and a parameter name as returned from - * {@link #parameterNameSource} to a {@literal String} to be used as a replacement of the SpEL in the query. The - * returned value should normally be interpretable as a bind parameter by the underlying persistence mechanism. A - * typical implementation is expected to look like (prefix, name) -> prefix + name or - * (prefix, name) -> "{" + name + "}" - */ - private final BiFunction replacementSource; - - private SpelQueryContext(BiFunction parameterNameSource, - BiFunction replacementSource) { - - Assert.notNull(parameterNameSource, "Parameter name source must not be null"); - Assert.notNull(replacementSource, "Replacement source must not be null"); - - this.parameterNameSource = parameterNameSource; - this.replacementSource = replacementSource; - } - - public static SpelQueryContext of(BiFunction parameterNameSource, - BiFunction replacementSource) { - return new SpelQueryContext(parameterNameSource, replacementSource); - } - - /** - * Parses the query for SpEL expressions using the pattern: - * - *
-	 * <prefix>#{<spel>}
-	 * 
- *

- * with prefix being the character ':' or '?'. Parsing honors quoted {@literal String}s enclosed in single or double - * quotation marks. - * - * @param query a query containing SpEL expressions in the format described above. Must not be {@literal null}. - * @return A {@link SpelExtractor} which makes the query with SpEL expressions replaced by bind parameters and a map - * from bind parameter to SpEL expression available. Guaranteed to be not {@literal null}. - */ - public SpelExtractor parse(String query) { - return new SpelExtractor(query); - } - - /** - * Createsa {@link EvaluatingSpelQueryContext} from the current one and the given - * {@link QueryMethodEvaluationContextProvider}. - * - * @param provider must not be {@literal null}. - * @return - */ - public EvaluatingSpelQueryContext withEvaluationContextProvider(QueryMethodEvaluationContextProvider provider) { - - Assert.notNull(provider, "QueryMethodEvaluationContextProvider must not be null"); - - return new EvaluatingSpelQueryContext(provider, parameterNameSource, replacementSource); - } - - /** - * An extension of {@link SpelQueryContext} that can create {@link SpelEvaluator} instances as it also knows about a - * {@link QueryMethodEvaluationContextProvider}. - * - * @author Oliver Gierke - * @since 2.1 - */ - public static class EvaluatingSpelQueryContext extends SpelQueryContext { - - private final QueryMethodEvaluationContextProvider evaluationContextProvider; - - /** - * Creates a new {@link EvaluatingSpelQueryContext} for the given {@link QueryMethodEvaluationContextProvider}, - * parameter name source and replacement source. - * - * @param evaluationContextProvider must not be {@literal null}. - * @param parameterNameSource must not be {@literal null}. - * @param replacementSource must not be {@literal null}. - */ - private EvaluatingSpelQueryContext(QueryMethodEvaluationContextProvider evaluationContextProvider, - BiFunction parameterNameSource, BiFunction replacementSource) { - - super(parameterNameSource, replacementSource); - - this.evaluationContextProvider = evaluationContextProvider; - } - - /** - * Parses the query for SpEL expressions using the pattern: - * - *

-		 * <prefix>#{<spel>}
-		 * 
- *

- * with prefix being the character ':' or '?'. Parsing honors quoted {@literal String}s enclosed in single or double - * quotation marks. - * - * @param query a query containing SpEL expressions in the format described above. Must not be {@literal null}. - * @param parameters a {@link Parameters} instance describing query method parameters - * @return A {@link SpelEvaluator} which allows to evaluate the SpEL expressions. Will never be {@literal null}. - */ - public SpelEvaluator parse(String query, Parameters parameters) { - return new SpelEvaluator(evaluationContextProvider, parameters, parse(query)); - } - } - - /** - * Parses a query string, identifies the contained SpEL expressions, replaces them with bind parameters and offers a - * {@link Map} from those bind parameters to the SpEL expression. - *

- * The parser detects quoted parts of the query string and does not detect SpEL expressions inside such quoted parts - * of the query. - * - * @author Jens Schauder - * @author Oliver Gierke - * @author Mark Paluch - * @since 2.1 - */ - public class SpelExtractor { - - private static final int PREFIX_GROUP_INDEX = 1; - private static final int EXPRESSION_GROUP_INDEX = 2; - - private final String query; - private final Map expressions; - private final QuotationMap quotations; - - /** - * Creates a SpelExtractor from a query String. - * - * @param query must not be {@literal null}. - */ - SpelExtractor(String query) { - - Assert.notNull(query, "Query must not be null"); - - Map expressions = new HashMap<>(); - Matcher matcher = SPEL_PATTERN.matcher(query); - StringBuilder resultQuery = new StringBuilder(); - QuotationMap quotedAreas = new QuotationMap(query); - - int expressionCounter = 0; - int matchedUntil = 0; - - while (matcher.find()) { - - if (quotedAreas.isQuoted(matcher.start())) { - - resultQuery.append(query, matchedUntil, matcher.end()); - - } else { - - String spelExpression = matcher.group(EXPRESSION_GROUP_INDEX); - String prefix = matcher.group(PREFIX_GROUP_INDEX); - - String parameterName = parameterNameSource.apply(expressionCounter, spelExpression); - String replacement = replacementSource.apply(prefix, parameterName); - - resultQuery.append(query, matchedUntil, matcher.start()); - resultQuery.append(replacement); - - expressions.put(parameterName, spelExpression); - expressionCounter++; - } - - matchedUntil = matcher.end(); - } - - resultQuery.append(query.substring(matchedUntil)); - - this.expressions = Collections.unmodifiableMap(expressions); - this.query = resultQuery.toString(); - - // recreate quotation map based on rewritten query. - this.quotations = new QuotationMap(this.query); - } - - /** - * The query with all the SpEL expressions replaced with bind parameters. - * - * @return Guaranteed to be not {@literal null}. - */ - public String getQueryString() { - return query; - } - - /** - * Return whether the {@link #getQueryString() query} at {@code index} is quoted. - * - * @param index - * @return {@literal true} if quoted; {@literal false} otherwise. - */ - public boolean isQuoted(int index) { - return quotations.isQuoted(index); - } - - public String getParameter(String name) { - return expressions.get(name); - } - - /** - * Returns the number of expressions in this extractor. - * - * @return the number of expressions in this extractor. - * @since 3.1.3 - */ - public int size() { - return expressions.size(); - } - - /** - * A {@literal Map} from parameter name to SpEL expression. - * - * @return Guaranteed to be not {@literal null}. - */ - Map getParameterMap() { - return expressions; - } - - } - - /** - * Value object to analyze a {@link String} to determine the parts of the {@link String} that are quoted and offers an - * API to query that information. - * - * @author Jens Schauder - * @author Oliver Gierke - * @since 2.1 - */ - static class QuotationMap { - - private static final Collection QUOTING_CHARACTERS = List.of('"', '\''); - - private final List> quotedRanges = new ArrayList<>(); - - /** - * Creates a new {@link QuotationMap} for the query. - * - * @param query can be {@literal null}. - */ - public QuotationMap(@Nullable String query) { - - if (query == null) { - return; - } - - Character inQuotation = null; - int start = 0; - - for (int i = 0; i < query.length(); i++) { - - char currentChar = query.charAt(i); - - if (QUOTING_CHARACTERS.contains(currentChar)) { - - if (inQuotation == null) { - - inQuotation = currentChar; - start = i; - - } else if (currentChar == inQuotation) { - - inQuotation = null; - - quotedRanges.add(Range.from(Bound.inclusive(start)).to(Bound.inclusive(i))); - } - } - } - - if (inQuotation != null) { - throw new IllegalArgumentException( - String.format("The string <%s> starts a quoted range at %d, but never ends it.", query, start)); - } - } - - /** - * Checks if a given index is within a quoted range. - * - * @param index to check if it is part of a quoted range. - * @return whether the query contains a quoted range at {@literal index}. - */ - public boolean isQuoted(int index) { - return quotedRanges.stream().anyMatch(r -> r.contains(index)); - } - } -} diff --git a/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java b/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java index 081b2d35d..f7c223af6 100644 --- a/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java +++ b/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java @@ -205,7 +205,6 @@ public abstract class QueryExecutionConverters { CustomCollections.registerConvertersIn(conversionService); conversionService.addConverter(new NullableWrapperToCompletableFutureConverter()); - conversionService.addConverter(new NullableWrapperToFutureConverter()); conversionService.addConverter(new IterableToStreamableConverter()); } @@ -357,28 +356,6 @@ public abstract class QueryExecutionConverters { protected abstract Object wrap(Object source); } - /** - * A Spring {@link Converter} to support returning {@link Future} instances from repository methods. - * - * @author Oliver Gierke - */ - @Deprecated(since = "3.0", forRemoval = true) - @SuppressWarnings("removal") - private static class NullableWrapperToFutureConverter extends AbstractWrapperTypeConverter { - - /** - * Creates a new {@link NullableWrapperToFutureConverter} using the given {@link ConversionService}. - */ - NullableWrapperToFutureConverter() { - super(new AsyncResult<>(null), List.of(ListenableFuture.class)); - } - - @Override - protected Object wrap(Object source) { - return new AsyncResult<>(source); - } - } - /** * A Spring {@link Converter} to support returning {@link CompletableFuture} instances from repository methods. * diff --git a/src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java b/src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java index c1692be67..eaed2de65 100644 --- a/src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java +++ b/src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java @@ -132,8 +132,9 @@ public abstract class ReactiveWrapperConverters { /** * Returns whether the given type is supported for wrapper type conversion. *

- * NOTE: A reactive wrapper type might be supported in general by {@link ReactiveWrappers#supports(Class)} but not - * necessarily for conversion using this method. + * 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. *

* * @param type must not be {@literal null}. diff --git a/src/main/java/org/springframework/data/repository/util/ReactiveWrappers.java b/src/main/java/org/springframework/data/repository/util/ReactiveWrappers.java deleted file mode 100644 index 9dfef93c4..000000000 --- a/src/main/java/org/springframework/data/repository/util/ReactiveWrappers.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2016-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.repository.util; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.util.Assert; - -/** - * Utility class to expose details about reactive wrapper types. This class exposes whether a reactive wrapper is - * supported in general and whether a particular type is suitable for no-value/single-value/multi-value usage. - *

- * Supported types are discovered by their availability on the class path. This class is typically used to determine - * multiplicity and whether a reactive wrapper type is acceptable for a specific operation. - * - * @author Mark Paluch - * @author Christoph Strobl - * @author Oliver Gierke - * @author Gerrit Meier - * @author Hantsy Bai - * @since 2.0 - * @see org.reactivestreams.Publisher - * @see io.reactivex.rxjava3.core.Single - * @see io.reactivex.rxjava3.core.Maybe - * @see io.reactivex.rxjava3.core.Observable - * @see io.reactivex.rxjava3.core.Completable - * @see io.reactivex.rxjava3.core.Flowable - * @see io.smallrye.mutiny.Multi - * @see io.smallrye.mutiny.Uni - * @see Mono - * @see Flux - * @deprecated since 3.0, use {@link org.springframework.data.util.ReactiveWrappers} instead as the utility was moved - * into the {@code org.springframework.data.util} package. - */ -@Deprecated(since = "3.0", forRemoval = true) -public abstract class ReactiveWrappers { - - private ReactiveWrappers() {} - - /** - * Enumeration of supported reactive libraries. - * - * @author Mark Paluch - * @deprecated use {@link org.springframework.data.util.ReactiveWrappers.ReactiveLibrary} instead. - */ - @Deprecated(since = "3.0", forRemoval = true) - public enum ReactiveLibrary { - - PROJECT_REACTOR, RXJAVA3, KOTLIN_COROUTINES, MUTINY; - } - - /** - * Returns {@literal true} if reactive support is available. More specifically, whether any of the libraries defined - * in {@link ReactiveLibrary} are on the class path. - * - * @return {@literal true} if reactive support is available. - */ - public static boolean isAvailable() { - return org.springframework.data.util.ReactiveWrappers.isAvailable(); - } - - /** - * Returns {@literal true} if the {@link ReactiveLibrary} is available. - * - * @param reactiveLibrary must not be {@literal null}. - * @return {@literal true} if the {@link ReactiveLibrary} is available. - */ - public static boolean isAvailable(ReactiveLibrary reactiveLibrary) { - - Assert.notNull(reactiveLibrary, "Reactive library must not be null"); - - switch (reactiveLibrary) { - case PROJECT_REACTOR: - return org.springframework.data.util.ReactiveWrappers.PROJECT_REACTOR_PRESENT; - case RXJAVA3: - return org.springframework.data.util.ReactiveWrappers.RXJAVA3_PRESENT; - case KOTLIN_COROUTINES: - return org.springframework.data.util.ReactiveWrappers.PROJECT_REACTOR_PRESENT - && org.springframework.data.util.ReactiveWrappers.KOTLIN_COROUTINES_PRESENT; - case MUTINY: - return org.springframework.data.util.ReactiveWrappers.MUTINY_PRESENT; - default: - throw new IllegalArgumentException(String.format("Reactive library %s not supported", reactiveLibrary)); - } - } - - /** - * Returns {@literal true} if the {@code type} is a supported reactive wrapper type. - * - * @param type must not be {@literal null}. - * @return {@literal true} if the {@code type} is a supported reactive wrapper type. - */ - public static boolean supports(Class type) { - return org.springframework.data.util.ReactiveWrappers.supports(type); - } - - /** - * Returns whether the given type uses any reactive wrapper type in its method signatures. - * - * @param type must not be {@literal null}. - * @return - */ - public static boolean usesReactiveType(Class type) { - - Assert.notNull(type, "Type must not be null"); - - return org.springframework.data.util.ReactiveWrappers.usesReactiveType(type); - } - - /** - * Returns {@literal true} if {@code type} is a reactive wrapper type that contains no value. - * - * @param type must not be {@literal null}. - * @return {@literal true} if {@code type} is a reactive wrapper type that contains no value. - */ - public static boolean isNoValueType(Class type) { - - Assert.notNull(type, "Candidate type must not be null"); - - return org.springframework.data.util.ReactiveWrappers.isNoValueType(type); - } - - /** - * Returns {@literal true} if {@code type} is a reactive wrapper type for a single value. - * - * @param type must not be {@literal null}. - * @return {@literal true} if {@code type} is a reactive wrapper type for a single value. - */ - public static boolean isSingleValueType(Class type) { - - Assert.notNull(type, "Candidate type must not be null"); - - return org.springframework.data.util.ReactiveWrappers.isSingleValueType(type); - } - - /** - * Returns {@literal true} if {@code type} is a reactive wrapper type supporting multiple values ({@code 0..N} - * elements). - * - * @param type must not be {@literal null}. - * @return {@literal true} if {@code type} is a reactive wrapper type supporting multiple values ({@code 0..N} - * elements). - */ - public static boolean isMultiValueType(Class type) { - - Assert.notNull(type, "Candidate type must not be null"); - - return org.springframework.data.util.ReactiveWrappers.isMultiValueType(type); - } - -} diff --git a/src/main/java/org/springframework/data/spel/spi/EvaluationContextExtension.java b/src/main/java/org/springframework/data/spel/spi/EvaluationContextExtension.java index 3b18ffc90..3283a8a87 100644 --- a/src/main/java/org/springframework/data/spel/spi/EvaluationContextExtension.java +++ b/src/main/java/org/springframework/data/spel/spi/EvaluationContextExtension.java @@ -18,13 +18,13 @@ package org.springframework.data.spel.spi; import java.util.Collections; import java.util.Map; +import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.expression.EvaluationContext; import org.springframework.lang.Nullable; /** * SPI to allow adding a set of properties and function definitions accessible via the root of an - * {@link EvaluationContext} provided by an - * {@link org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider}. + * {@link EvaluationContext} provided by an {@link ExtensionAwareEvaluationContextProvider}. *

* Extensions can be ordered by following Spring's {@link org.springframework.core.Ordered} conventions. * diff --git a/src/main/java/org/springframework/data/spel/spi/ReactiveEvaluationContextExtension.java b/src/main/java/org/springframework/data/spel/spi/ReactiveEvaluationContextExtension.java index 36b1a9e9e..4cf8dd792 100644 --- a/src/main/java/org/springframework/data/spel/spi/ReactiveEvaluationContextExtension.java +++ b/src/main/java/org/springframework/data/spel/spi/ReactiveEvaluationContextExtension.java @@ -22,7 +22,7 @@ import org.springframework.expression.EvaluationContext; /** * SPI to resolve a {@link EvaluationContextExtension} to make it accessible via the root of an * {@link EvaluationContext} provided by a - * {@link org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider}. + * {@link org.springframework.data.spel.ReactiveExtensionAwareEvaluationContextProvider}. *

* Extensions can be ordered by following Spring's {@link org.springframework.core.Ordered} conventions. * diff --git a/src/main/java/org/springframework/data/type/MethodsMetadata.java b/src/main/java/org/springframework/data/type/MethodsMetadata.java deleted file mode 100644 index 06b5a5d34..000000000 --- a/src/main/java/org/springframework/data/type/MethodsMetadata.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2018-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.type; - -import java.util.Set; - -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.ClassMetadata; -import org.springframework.core.type.MethodMetadata; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.data.type.classreading.MethodsMetadataReader; - -/** - * Interface that defines abstract metadata of a specific class, in a form that does not require that class to be loaded - * yet. - * - * @author Mark Paluch - * @since 2.1 - * @see MethodMetadata - * @see ClassMetadata - * @see MethodsMetadataReader#getMethodsMetadata() - * @deprecated since 3.0, use {@link MetadataReader} directly to obtain {@link AnnotationMetadata#getDeclaredMethods() - * declared methods} directly. - */ -@Deprecated -public interface MethodsMetadata extends ClassMetadata { - - /** - * Return all methods. - * - * @return the methods declared in the class ordered as found in the class file. Order does not necessarily reflect - * the declaration order in the source file. - */ - Set getMethods(); - - /** - * Return all methods matching method {@code name}. - * - * @param name name of the method, must not be {@literal null} or empty. - * @return the methods matching method {@code name } declared in the class ordered as found in the class file. Order - * does not necessarily reflect the declaration order in the source file. - */ - Set getMethods(String name); -} diff --git a/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReader.java b/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReader.java deleted file mode 100644 index 7c422b42d..000000000 --- a/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReader.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2018-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.type.classreading; - -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.data.type.MethodsMetadata; - -/** - * Extension to {@link MetadataReader} for accessing class metadata and method metadata as read by an ASM - * {@link org.springframework.asm.ClassReader}. - * - * @author Mark Paluch - * @since 2.1 - * @deprecated since 3.0, use {@link MetadataReader} to obtain {@link AnnotationMetadata#getDeclaredMethods() declared - * methods} directly. - */ -@Deprecated -public interface MethodsMetadataReader extends MetadataReader { - - /** - * @return the {@link MethodsMetadata} for methods in the class file. - */ - MethodsMetadata getMethodsMetadata(); -} diff --git a/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactory.java b/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactory.java deleted file mode 100644 index ea917df91..000000000 --- a/src/main/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactory.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2018-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.type.classreading; - -import java.io.IOException; -import java.util.Set; -import java.util.stream.Collectors; - -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.ClassMetadata; -import org.springframework.core.type.MethodMetadata; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; -import org.springframework.data.type.MethodsMetadata; -import org.springframework.lang.Nullable; - -/** - * Extension of {@link SimpleMetadataReaderFactory} that reads {@link MethodsMetadata}, creating a new ASM - * {@link MethodsMetadataReader} for every request. - * - * @author Mark Paluch - * @since 2.1 - * @deprecated since 3.0. Use {@link SimpleMetadataReaderFactory} directly. - */ -@Deprecated -public class MethodsMetadataReaderFactory extends SimpleMetadataReaderFactory { - - /** - * Create a new {@link MethodsMetadataReaderFactory} for the default class loader. - */ - public MethodsMetadataReaderFactory() {} - - /** - * Create a new {@link MethodsMetadataReaderFactory} for the given {@link ResourceLoader}. - * - * @param resourceLoader the Spring {@link ResourceLoader} to use (also determines the {@link ClassLoader} to use). - */ - public MethodsMetadataReaderFactory(@Nullable ResourceLoader resourceLoader) { - super(resourceLoader); - } - - /** - * Create a new {@link MethodsMetadataReaderFactory} for the given {@link ClassLoader}. - * - * @param classLoader the class loader to use. - */ - public MethodsMetadataReaderFactory(@Nullable ClassLoader classLoader) { - super(classLoader); - } - - @Override - public MethodsMetadataReader getMetadataReader(String className) throws IOException { - return new MetadataReaderWrapper(super.getMetadataReader(className)); - } - - @Override - public MethodsMetadataReader getMetadataReader(Resource resource) throws IOException { - return new MetadataReaderWrapper(super.getMetadataReader(resource)); - } - - private static class MetadataReaderWrapper implements MethodsMetadataReader { - - private final MetadataReader delegate; - - MetadataReaderWrapper(MetadataReader delegate) { - this.delegate = delegate; - } - - @Override - public MethodsMetadata getMethodsMetadata() { - return new MethodsMetadataWrapper(getAnnotationMetadata(), getClassMetadata()); - } - - @Override - public Resource getResource() { - return delegate.getResource(); - } - - @Override - public ClassMetadata getClassMetadata() { - return delegate.getClassMetadata(); - } - - @Override - public AnnotationMetadata getAnnotationMetadata() { - return delegate.getAnnotationMetadata(); - } - - } - - private static class MethodsMetadataWrapper implements MethodsMetadata, ClassMetadata { - - private final AnnotationMetadata annotationMetadata; - private final ClassMetadata classMetadata; - - MethodsMetadataWrapper(AnnotationMetadata annotationMetadata, ClassMetadata classMetadata) { - this.annotationMetadata = annotationMetadata; - this.classMetadata = classMetadata; - } - - @Override - public Set getMethods() { - return annotationMetadata.getDeclaredMethods(); - } - - @Override - public Set getMethods(String name) { - return annotationMetadata.getDeclaredMethods().stream().filter(it -> it.getMethodName().equals(name)) - .collect(Collectors.toSet()); - } - - @Override - public String getClassName() { - return classMetadata.getClassName(); - } - - @Override - public boolean isInterface() { - return classMetadata.isInterface(); - } - - @Override - public boolean isAnnotation() { - return classMetadata.isAnnotation(); - } - - @Override - public boolean isAbstract() { - return classMetadata.isAbstract(); - } - - @Override - public boolean isConcrete() { - return classMetadata.isConcrete(); - } - - @Override - public boolean isFinal() { - return classMetadata.isFinal(); - } - - @Override - public boolean isIndependent() { - return classMetadata.isIndependent(); - } - - @Override - public boolean hasEnclosingClass() { - return classMetadata.hasEnclosingClass(); - } - - @Override - @Nullable - public String getEnclosingClassName() { - return classMetadata.getEnclosingClassName(); - } - - @Override - public boolean hasSuperClass() { - return classMetadata.hasSuperClass(); - } - - @Override - @Nullable - public String getSuperClassName() { - return classMetadata.getSuperClassName(); - } - - @Override - public String[] getInterfaceNames() { - return classMetadata.getInterfaceNames(); - } - - @Override - public String[] getMemberClassNames() { - return classMetadata.getMemberClassNames(); - } - } -} diff --git a/src/main/java/org/springframework/data/type/classreading/package-info.java b/src/main/java/org/springframework/data/type/classreading/package-info.java deleted file mode 100644 index fe6d22de4..000000000 --- a/src/main/java/org/springframework/data/type/classreading/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Support classes for reading annotation and class-level metadata. - */ -@org.springframework.lang.NonNullApi -@org.springframework.lang.NonNullFields -package org.springframework.data.type.classreading; diff --git a/src/main/java/org/springframework/data/type/package-info.java b/src/main/java/org/springframework/data/type/package-info.java deleted file mode 100644 index b887b66b2..000000000 --- a/src/main/java/org/springframework/data/type/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Core support package for type introspection. - */ -@org.springframework.lang.NonNullApi -package org.springframework.data.type; diff --git a/src/main/java/org/springframework/data/util/ClassTypeInformation.java b/src/main/java/org/springframework/data/util/ClassTypeInformation.java index 9d272f993..21d588df5 100644 --- a/src/main/java/org/springframework/data/util/ClassTypeInformation.java +++ b/src/main/java/org/springframework/data/util/ClassTypeInformation.java @@ -32,11 +32,9 @@ import org.springframework.util.ConcurrentLruCache; * @author Oliver Gierke * @author Christoph Strobl * @author Mark Paluch - * @deprecated since 3.0 to go package protected at some point. Refer to {@link TypeInformation} only. */ -@Deprecated(since = "3.0", forRemoval = true) @SuppressWarnings({ "rawtypes", "unchecked" }) -public class ClassTypeInformation extends TypeDiscoverer { +class ClassTypeInformation extends TypeDiscoverer { private static final ConcurrentLruCache> cache = new ConcurrentLruCache<>(128, ClassTypeInformation::new); @@ -70,9 +68,7 @@ public class ClassTypeInformation extends TypeDiscoverer { * @param * @param type * @return - * @deprecated since 3.0. Use {@link TypeInformation#of} instead. */ - @Deprecated public static ClassTypeInformation from(Class type) { return from(resolvableTypeCache.get(type)); } @@ -84,31 +80,6 @@ public class ClassTypeInformation extends TypeDiscoverer { return (ClassTypeInformation) cache.get(type); } - /** - * Warning: Does not fully resolve generic arguments. - * - * @param method - * @return - * @deprecated since 3.0. Use {@link TypeInformation#fromReturnTypeOf(Method)} instead. - */ - @Deprecated - public static TypeInformation fromReturnTypeOf(Method method) { - return (TypeInformation) TypeInformation.of(ResolvableType.forMethodReturnType(method)); - } - - /** - * @param method - * @param actualType can be {@literal null}. - * @return - */ - static TypeInformation fromReturnTypeOf(Method method, @Nullable Class actualType) { - - var type = actualType == null ? ResolvableType.forMethodReturnType(method) - : ResolvableType.forMethodReturnType(method, actualType); - - return TypeInformation.of(type); - } - @Override public Class getType() { return type; diff --git a/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java b/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java index c4d91ead8..933a62e12 100644 --- a/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java +++ b/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java @@ -290,20 +290,6 @@ public class PagedResourcesAssembler implements RepresentationModelAssembler< return Link.of(UriTemplate.of(builder.build().toString()), relation); } - /** - * Return the {@link MethodParameter} to be used to potentially qualify the paging and sorting request parameters to. - * Default implementations returns {@literal null}, which means the parameters will not be qualified. - * - * @return - * @since 1.7 - * @deprecated since 3.1, rather set up the instance with {@link #withParameter(MethodParameter)}. - */ - @Nullable - @Deprecated(since = "3.1", forRemoval = true) - protected MethodParameter getMethodParameter() { - return null; - } - /** * Creates a new {@link PageMetadata} instance from the given {@link Page}. * diff --git a/src/main/java/org/springframework/data/web/SpringDataAnnotationUtils.java b/src/main/java/org/springframework/data/web/SpringDataAnnotationUtils.java index 9c9caff23..301c7f16b 100644 --- a/src/main/java/org/springframework/data/web/SpringDataAnnotationUtils.java +++ b/src/main/java/org/springframework/data/web/SpringDataAnnotationUtils.java @@ -84,33 +84,6 @@ abstract class SpringDataAnnotationUtils { return false; } - /** - * Returns the value of the given specific property of the given annotation. If the value of that property is the - * properties default, we fall back to the value of the {@code value} attribute. - * - * @param annotation must not be {@literal null}. - * @param property must not be {@literal null} or empty. - * @return - * @deprecated since 3.0 as this method is no longer used within the Framework. - */ - @SuppressWarnings("unchecked") - @Deprecated - public static T getSpecificPropertyOrDefaultFromValue(Annotation annotation, String property) { - - Object propertyDefaultValue = AnnotationUtils.getDefaultValue(annotation, property); - Object propertyValue = AnnotationUtils.getValue(annotation, property); - - Object result = ObjectUtils.nullSafeEquals(propertyDefaultValue, propertyValue) // - ? AnnotationUtils.getValue(annotation) // - : propertyValue; - - if (result == null) { - throw new IllegalStateException("Exepected to be able to look up an annotation property value but failed"); - } - - return (T) result; - } - /** * Determine a qualifier value for a {@link MethodParameter}. * diff --git a/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java b/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java index 3f2aad590..e614fb162 100755 --- a/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java @@ -26,7 +26,6 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.annotation.PersistenceCreator; import org.springframework.data.mapping.PreferredConstructorDiscovererUnitTests.Outer.Inner; import org.springframework.data.mapping.model.BasicPersistentEntity; @@ -114,7 +113,7 @@ class PreferredConstructorDiscovererUnitTests

> { var constructor = PreferredConstructorDiscoverer.discover(entity); assertThat(constructor).isNotNull(); - var annotation = constructor.getConstructor().getAnnotation(PersistenceConstructor.class); + var annotation = constructor.getConstructor().getAnnotation(PersistenceCreator.class); assertThat(annotation).isNotNull(); assertThat(constructor.getConstructor().isSynthetic()).isFalse(); } @@ -184,7 +183,7 @@ class PreferredConstructorDiscovererUnitTests

> { } static class SyntheticConstructor { - @PersistenceConstructor + @PersistenceCreator private SyntheticConstructor(String x) {} class InnerSynthetic { @@ -225,7 +224,7 @@ class PreferredConstructorDiscovererUnitTests

> { public ClassWithMultipleConstructorsAndAnnotation(String value) {} - @PersistenceConstructor + @PersistenceCreator public ClassWithMultipleConstructorsAndAnnotation(Long value) {} } diff --git a/src/test/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiatorUnitTests.java b/src/test/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiatorUnitTests.java index af2a66033..181aa1dc0 100755 --- a/src/test/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiatorUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiatorUnitTests.java @@ -132,7 +132,6 @@ class ClassGeneratingEntityInstantiatorUnitTests

doReturn("FOO").when(provider).getParameterValue(any(Parameter.class)); - Constructor constructor = Sample.class.getConstructor(Long.class, String.class); List parameters = Arrays.asList("FOO", "FOO"); try { @@ -142,12 +141,6 @@ class ClassGeneratingEntityInstantiatorUnitTests

} catch (MappingInstantiationException o_O) { - assertThat(o_O.getEntityCreator() - .map(it -> (PreferredConstructor) it) - .map(PreferredConstructor::getConstructor)) - .isPresent() - .hasValue(constructor); - assertThat(o_O.getConstructorArguments()).isEqualTo(parameters); assertThat(o_O.getEntityType()).hasValue(Sample.class); diff --git a/src/test/java/org/springframework/data/mapping/model/ReflectionEntityInstantiatorUnitTests.java b/src/test/java/org/springframework/data/mapping/model/ReflectionEntityInstantiatorUnitTests.java index c5e5b755b..5128b43e3 100755 --- a/src/test/java/org/springframework/data/mapping/model/ReflectionEntityInstantiatorUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/ReflectionEntityInstantiatorUnitTests.java @@ -113,14 +113,12 @@ class ReflectionEntityInstantiatorUnitTests

> { } @Test // DATACMNS-283 - @SuppressWarnings({ "unchecked", "rawtypes" }) - void capturesContextOnInstantiationException() throws Exception { + void capturesContextOnInstantiationException() { PersistentEntity entity = new BasicPersistentEntity<>(TypeInformation.of(Sample.class)); doReturn("FOO").when(provider).getParameterValue(any(Parameter.class)); - Constructor constructor = Sample.class.getConstructor(Long.class, String.class); List parameters = Arrays.asList("FOO", "FOO"); try { @@ -130,12 +128,6 @@ class ReflectionEntityInstantiatorUnitTests

> { } catch (MappingInstantiationException o_O) { - assertThat(o_O.getEntityCreator() - .map(it -> (PreferredConstructor) it) - .map(PreferredConstructor::getConstructor)) - .isPresent() - .hasValue(constructor); - assertThat(o_O.getConstructorArguments()).isEqualTo(parameters); assertThat(o_O.getEntityType()).hasValue(Sample.class); diff --git a/src/test/java/org/springframework/data/mapping/model/SpelExpressionParameterProviderUnitTests.java b/src/test/java/org/springframework/data/mapping/model/SpelExpressionParameterProviderUnitTests.java deleted file mode 100755 index f340f7e04..000000000 --- a/src/test/java/org/springframework/data/mapping/model/SpelExpressionParameterProviderUnitTests.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2012-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.mapping.model; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import org.junit.jupiter.api.BeforeEach; -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.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; -import org.springframework.core.convert.ConversionService; -import org.springframework.data.mapping.Parameter; -import org.springframework.data.mapping.model.AbstractPersistentPropertyUnitTests.SamplePersistentProperty; - -/** - * Unit tests for {@link SpELExpressionParameterValueProvider}. - * - * @author Oliver Gierke - * @author Mark Paluch - */ -@ExtendWith(MockitoExtension.class) -@MockitoSettings(strictness = Strictness.LENIENT) -class SpelExpressionParameterProviderUnitTests { - - @Mock SpELExpressionEvaluator evaluator; - @Mock ParameterValueProvider delegate; - @Mock ConversionService conversionService; - - private SpELExpressionParameterValueProvider provider; - - private Parameter parameter; - - @BeforeEach - @SuppressWarnings("unchecked") - void setUp() { - provider = new SpELExpressionParameterValueProvider<>(evaluator, conversionService, delegate); - - parameter = mock(Parameter.class); - when(parameter.hasValueExpression()).thenReturn(true); - when(parameter.getRawType()).thenReturn(Object.class); - } - - @Test - @SuppressWarnings("unchecked") - void delegatesIfParameterDoesNotHaveASpELExpression() { - - Parameter parameter = mock(Parameter.class); - when(parameter.hasValueExpression()).thenReturn(false); - - provider.getParameterValue(parameter); - verify(delegate, times(1)).getParameterValue(parameter); - verify(evaluator, times(0)).evaluate("expression"); - } - - @Test - void evaluatesSpELExpression() { - - when(parameter.getRequiredValueExpression()).thenReturn("expression"); - - provider.getParameterValue(parameter); - verify(delegate, times(0)).getParameterValue(parameter); - verify(evaluator, times(1)).evaluate("#{expression}"); - } - - @Test - void handsSpELValueToConversionService() { - - doReturn("source").when(parameter).getRequiredValueExpression(); - doReturn("value").when(evaluator).evaluate(any()); - - provider.getParameterValue(parameter); - - verify(delegate, times(0)).getParameterValue(parameter); - verify(conversionService, times(1)).convert("value", Object.class); - } - - @Test - void doesNotConvertNullValue() { - - doReturn("source").when(parameter).getRequiredValueExpression(); - doReturn(null).when(evaluator).evaluate(any()); - - provider.getParameterValue(parameter); - - verify(delegate, times(0)).getParameterValue(parameter); - verify(conversionService, times(0)).convert("value", Object.class); - } - - @Test - void returnsMassagedObjectOnOverride() { - - provider = new SpELExpressionParameterValueProvider(evaluator, conversionService, - delegate) { - - @Override - @SuppressWarnings("unchecked") - protected T potentiallyConvertSpelValue(Object object, Parameter parameter) { - return (T) "FOO"; - } - }; - - doReturn("source").when(parameter).getRequiredValueExpression(); - doReturn("value").when(evaluator).evaluate(any()); - - assertThat(provider.getParameterValue(parameter)).isEqualTo("FOO"); - - verify(delegate, times(0)).getParameterValue(parameter); - } -} diff --git a/src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java b/src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java index c60ac79ee..c50dac227 100755 --- a/src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java +++ b/src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java @@ -50,8 +50,8 @@ import org.springframework.data.repository.core.support.QueryCreationListener; import org.springframework.data.repository.core.support.RepositoryFactorySupport; import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor; import org.springframework.data.repository.query.QueryLookupStrategy.Key; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.data.spel.EvaluationContextProvider; /** * Unit tests for {@link CdiRepositoryBean}. @@ -182,7 +182,7 @@ class CdiRepositoryBeanUnitTests { bean.applyConfiguration(repositoryFactory); - verify(repositoryFactory).setEvaluationContextProvider(QueryMethodEvaluationContextProvider.DEFAULT); + verify(repositoryFactory).setEvaluationContextProvider(EvaluationContextProvider.DEFAULT); verify(repositoryFactory).setNamedQueries(PropertiesBasedNamedQueries.EMPTY); verify(repositoryFactory).setRepositoryBaseClass(String.class); verify(repositoryFactory).setQueryLookupStrategyKey(Key.CREATE); @@ -217,8 +217,8 @@ class CdiRepositoryBeanUnitTests { INSTANCE; @Override - public Optional getEvaluationContextProvider() { - return Optional.of(QueryMethodEvaluationContextProvider.DEFAULT); + public Optional getEvaluationContextProvider() { + return Optional.of(EvaluationContextProvider.DEFAULT); } @Override diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationDelegateUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationDelegateUnitTests.java index 969a62256..417681d31 100644 --- a/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationDelegateUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationDelegateUnitTests.java @@ -45,7 +45,6 @@ import org.springframework.core.ResolvableType; import org.springframework.core.env.StandardEnvironment; import org.springframework.core.metrics.ApplicationStartup; import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.data.mapping.Person; import org.springframework.data.repository.Repository; import org.springframework.data.repository.config.RepositoryConfigurationDelegate.LazyRepositoryInjectionPointResolver; @@ -81,7 +80,7 @@ class RepositoryConfigurationDelegateUnitTests { var context = new GenericApplicationContext(); RepositoryConfigurationSource configSource = new AnnotationRepositoryConfigurationSource( - new StandardAnnotationMetadata(TestConfig.class, true), EnableRepositories.class, context, environment, + AnnotationMetadata.introspect(TestConfig.class), EnableRepositories.class, context, environment, context.getDefaultListableBeanFactory(), null); var delegate = new RepositoryConfigurationDelegate(configSource, context, environment); @@ -133,7 +132,7 @@ class RepositoryConfigurationDelegateUnitTests { context.setApplicationStartup(startup); RepositoryConfigurationSource configSource = new AnnotationRepositoryConfigurationSource( - new StandardAnnotationMetadata(TestConfig.class, true), EnableRepositories.class, context, environment, + AnnotationMetadata.introspect(TestConfig.class), EnableRepositories.class, context, environment, context.getDefaultListableBeanFactory(), null); var delegate = new RepositoryConfigurationDelegate(configSource, context, environment); diff --git a/src/test/java/org/springframework/data/repository/core/support/DummyReactiveRepositoryFactory.java b/src/test/java/org/springframework/data/repository/core/support/DummyReactiveRepositoryFactory.java index 0bf3d3d99..459914446 100644 --- a/src/test/java/org/springframework/data/repository/core/support/DummyReactiveRepositoryFactory.java +++ b/src/test/java/org/springframework/data/repository/core/support/DummyReactiveRepositoryFactory.java @@ -29,8 +29,8 @@ import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.data.repository.query.ValueExpressionDelegate; /** * @author Mark Paluch @@ -71,7 +71,7 @@ public class DummyReactiveRepositoryFactory extends ReactiveRepositoryFactorySup @Override protected Optional getQueryLookupStrategy(Key key, - QueryMethodEvaluationContextProvider evaluationContextProvider) { + ValueExpressionDelegate evaluationContextProvider) { return Optional.of(strategy); } diff --git a/src/test/java/org/springframework/data/repository/core/support/DummyRepositoryFactory.java b/src/test/java/org/springframework/data/repository/core/support/DummyRepositoryFactory.java index eba849e44..f27e2aa76 100644 --- a/src/test/java/org/springframework/data/repository/core/support/DummyRepositoryFactory.java +++ b/src/test/java/org/springframework/data/repository/core/support/DummyRepositoryFactory.java @@ -36,8 +36,8 @@ import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments; import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.data.repository.query.ValueExpressionDelegate; /** * Dummy implementation for {@link RepositoryFactorySupport} that is equipped with mocks to simulate behavior for test @@ -94,7 +94,7 @@ public class DummyRepositoryFactory extends RepositoryFactorySupport { @Override protected Optional getQueryLookupStrategy(Key key, - QueryMethodEvaluationContextProvider evaluationContextProvider) { + ValueExpressionDelegate valueExpressionDelegate) { return Optional.of(strategy); } diff --git a/src/test/java/org/springframework/data/repository/core/support/ReactiveDummyRepositoryFactory.java b/src/test/java/org/springframework/data/repository/core/support/ReactiveDummyRepositoryFactory.java index 2614f3f38..02ca50c64 100644 --- a/src/test/java/org/springframework/data/repository/core/support/ReactiveDummyRepositoryFactory.java +++ b/src/test/java/org/springframework/data/repository/core/support/ReactiveDummyRepositoryFactory.java @@ -23,6 +23,7 @@ import java.util.function.Supplier; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; + import org.springframework.beans.factory.BeanFactory; import org.springframework.core.metrics.ApplicationStartup; import org.springframework.core.metrics.StartupStep; @@ -35,8 +36,8 @@ import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments; import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.data.repository.query.ValueExpressionDelegate; /** * Dummy implementation for {@link RepositoryFactorySupport} that is equipped with mocks to simulate behavior for test @@ -93,7 +94,7 @@ public class ReactiveDummyRepositoryFactory extends ReactiveRepositoryFactorySup @Override protected Optional getQueryLookupStrategy(Key key, - QueryMethodEvaluationContextProvider evaluationContextProvider) { + ValueExpressionDelegate valueExpressionDelegate) { return Optional.of(strategy); } diff --git a/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java b/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java index e10c2b914..a5072e96d 100755 --- a/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java +++ b/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java @@ -67,9 +67,9 @@ import org.springframework.data.repository.core.support.RepositoryMethodInvocati import org.springframework.data.repository.query.QueryByExampleExecutor; import org.springframework.data.repository.query.QueryCreationException; import org.springframework.data.repository.query.QueryLookupStrategy; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor; import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.data.repository.query.ValueExpressionDelegate; import org.springframework.data.repository.query.parser.PartTree; import org.springframework.data.repository.sample.User; import org.springframework.lang.Nullable; @@ -78,7 +78,6 @@ import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcesso import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.interceptor.TransactionalProxy; import org.springframework.util.ClassUtils; -import org.springframework.util.concurrent.ListenableFuture; /** * Unit tests for {@link RepositoryFactorySupport}. @@ -523,7 +522,7 @@ class RepositoryFactorySupportUnitTests { var factory = new DummyRepositoryFactory(backingRepo) { @Override protected Optional getQueryLookupStrategy(QueryLookupStrategy.Key key, - QueryMethodEvaluationContextProvider evaluationContextProvider) { + ValueExpressionDelegate valueExpressionDelegate) { return Optional.of((method, metadata, factory, namedQueries) -> { new PartTree(method.getName(), method.getReturnType()); return null; @@ -653,11 +652,11 @@ class RepositoryFactorySupportUnitTests { // DATACMNS-714 @Async - ListenableFuture findOneByLastname(String lastname); + CompletableFuture findOneByLastname(String lastname); // DATACMNS-714 @Async - ListenableFuture> readAllByLastname(String lastname); + CompletableFuture> readAllByLastname(String lastname); } static class CustomRepositoryBaseClass { diff --git a/src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java b/src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java deleted file mode 100755 index d2bb7e519..000000000 --- a/src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright 2014-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.repository.query; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; -import org.springframework.data.spel.spi.EvaluationContextExtension; -import org.springframework.data.spel.spi.ExtensionIdAware; -import org.springframework.data.spel.spi.Function; -import org.springframework.expression.spel.standard.SpelExpressionParser; - -/** - * Unit tests {@link ExtensionAwareQueryMethodEvaluationContextProvider}. - * - * @author Oliver Gierke - * @author Thomas Darimont - * @author Jens Schauder - */ -class ExtensionAwareEvaluationContextProviderUnitTests { - - Method method; - QueryMethodEvaluationContextProvider provider; - - @BeforeEach - void setUp() throws Exception { - - this.method = SampleRepo.class.getMethod("findByFirstname", String.class); - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.emptyList()); - } - - @Test // DATACMNS-533 - void usesPropertyDefinedByExtension() { - - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider( - Collections.singletonList(new DummyExtension("_first", "first"))); - - assertThat(evaluateExpression("key")).isEqualTo("first"); - } - - @Test // DATACMNS-533 - void secondExtensionOverridesFirstOne() { - - List extensions = new ArrayList<>(); - extensions.add(new DummyExtension("_first", "first")); - extensions.add(new DummyExtension("_second", "second")); - - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(extensions); - - assertThat(evaluateExpression("key")).isEqualTo("second"); - } - - @Test // DATACMNS-533 - void allowsDirectAccessToExtensionViaKey() { - - List extensions = new ArrayList<>(); - extensions.add(new DummyExtension("_first", "first")); - extensions.add(new DummyExtension("_second", "second")); - - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(extensions); - assertThat(evaluateExpression("_first.key")).isEqualTo("first"); - } - - @Test // DATACMNS-533 - void exposesParametersAsVariables() { - assertThat(evaluateExpression("#firstname")).isEqualTo("parameterValue"); - } - - @Test // DATACMNS-533 - void exposesMethodDefinedByExtension() { - - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider( - Collections.singletonList(new DummyExtension("_first", "first"))); - - assertThat(evaluateExpression("aliasedMethod()")).isEqualTo("methodResult"); - assertThat(evaluateExpression("extensionMethod()")).isEqualTo("methodResult"); - assertThat(evaluateExpression("_first.extensionMethod()")).isEqualTo("methodResult"); - assertThat(evaluateExpression("_first.aliasedMethod()")).isEqualTo("methodResult"); - } - - @Test // DATACMNS-533 - void exposesPropertiesDefinedByExtension() { - - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider( - Collections.singletonList(new DummyExtension("_first", "first"))); - - assertThat(evaluateExpression("DUMMY_KEY")).isEqualTo("dummy"); - assertThat(evaluateExpression("_first.DUMMY_KEY")).isEqualTo("dummy"); - } - - @Test // DATACMNS-533 - void exposesPageableParameter() throws Exception { - - this.method = SampleRepo.class.getMethod("findByFirstname", String.class, Pageable.class); - var pageable = PageRequest.of(2, 3, Sort.by(Direction.DESC, "lastname")); - - assertThat(evaluateExpression("#pageable.offset", new Object[] { "test", pageable })).isEqualTo(6L); - assertThat(evaluateExpression("#pageable.pageSize", new Object[] { "test", pageable })).isEqualTo(3); - assertThat(evaluateExpression("#pageable.sort.toString()", new Object[] { "test", pageable })) - .isEqualTo("lastname: DESC"); - } - - @Test // DATACMNS-533 - void exposesSortParameter() throws Exception { - - this.method = SampleRepo.class.getMethod("findByFirstname", String.class, Sort.class); - var sort = Sort.by(Direction.DESC, "lastname"); - - assertThat(evaluateExpression("#sort.toString()", new Object[] { "test", sort })).isEqualTo("lastname: DESC"); - } - - @Test // DATACMNS-533 - void exposesSpecialParameterEvenIfItsNull() throws Exception { - - this.method = SampleRepo.class.getMethod("findByFirstname", String.class, Sort.class); - - assertThat(evaluateExpression("#sort?.toString()", new Object[] { "test", null })).isNull(); - } - - @Test // DATACMNS-533 - void shouldBeAbleToAccessCustomRootObjectPropertiesAndFunctions() { - - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.singletonList( // - new DummyExtension("_first", "first") { - @Override - public CustomExtensionRootObject1 getRootObject() { - return new CustomExtensionRootObject1(); - } - })); - - assertThat(evaluateExpression("rootObjectInstanceField1")).isEqualTo("rootObjectInstanceF1"); - assertThat(evaluateExpression("rootObjectInstanceMethod1()")).isEqualTo(true); - assertThat(evaluateExpression("getStringProperty()")).isEqualTo("stringProperty"); - assertThat(evaluateExpression("stringProperty")).isEqualTo("stringProperty"); - - assertThat(evaluateExpression("_first.rootObjectInstanceField1")).isEqualTo("rootObjectInstanceF1"); - assertThat(evaluateExpression("_first.rootObjectInstanceMethod1()")).isEqualTo(true); - assertThat(evaluateExpression("_first.getStringProperty()")).isEqualTo("stringProperty"); - assertThat(evaluateExpression("_first.stringProperty")).isEqualTo("stringProperty"); - } - - @Test // DATACMNS-533 - void shouldBeAbleToAccessCustomRootObjectPropertiesAndFunctionsInMultipleExtensions() { - - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(Arrays.asList( // - new DummyExtension("_first", "first") { - @Override - public CustomExtensionRootObject1 getRootObject() { - return new CustomExtensionRootObject1(); - } - }, // - new DummyExtension("_second", "second") { - @Override - public CustomExtensionRootObject2 getRootObject() { - return new CustomExtensionRootObject2(); - } - })); - - assertThat(evaluateExpression("rootObjectInstanceField1")).isEqualTo("rootObjectInstanceF1"); - assertThat(evaluateExpression("rootObjectInstanceMethod1()")).isEqualTo(true); - - assertThat(evaluateExpression("rootObjectInstanceField2")).isEqualTo(42); - assertThat(evaluateExpression("rootObjectInstanceMethod2()")).isEqualTo("rootObjectInstanceMethod2"); - - assertThat(evaluateExpression("[0]")).isEqualTo("parameterValue"); - } - - @Test // DATACMNS-533 - void shouldBeAbleToAccessCustomRootObjectPropertiesAndFunctionsFromDynamicTargetSource() { - - final var counter = new AtomicInteger(); - - this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.singletonList( // - new DummyExtension("_first", "first") { - - @Override - public CustomExtensionRootObject1 getRootObject() { - counter.incrementAndGet(); - return new CustomExtensionRootObject1(); - } - }) // - ); - - // inc counter / property access - assertThat(evaluateExpression("rootObjectInstanceField1")).isEqualTo("rootObjectInstanceF1"); - - // inc counter / function invocation - assertThat(evaluateExpression("rootObjectInstanceMethod1()")).isEqualTo(true); - - assertThat(counter.get()).isEqualTo(2); - } - - @Test // DATACMNS-1026 - void overloadedMethodsGetResolved() throws Exception { - - provider = createContextProviderWithOverloads(); - - // from the root object - assertThat(evaluateExpression("method()")).isEqualTo("zero"); - assertThat(evaluateExpression("method(23)")).isEqualTo("single-int"); - assertThat(evaluateExpression("method('hello')")).isEqualTo("single-string"); - assertThat(evaluateExpression("method('one', 'two')")).isEqualTo("two"); - - // from the extension - assertThat(evaluateExpression("method(1, 2)")).isEqualTo("two-ints"); - assertThat(evaluateExpression("method(1, 'two')")).isEqualTo("int-and-string"); - } - - @Test // DATACMNS-1026 - void methodFromRootObjectOverwritesMethodFromExtension() throws Exception { - - provider = createContextProviderWithOverloads(); - - assertThat(evaluateExpression("ambiguous()")).isEqualTo("from-root"); - } - - @Test // DATACMNS-1026 - void aliasedMethodOverwritesMethodFromRootObject() throws Exception { - - provider = createContextProviderWithOverloads(); - - assertThat(evaluateExpression("aliasedMethod()")).isEqualTo("methodResult"); - } - - @Test // DATACMNS-1026 - void exactMatchIsPreferred() throws Exception { - - provider = createContextProviderWithOverloads(); - - assertThat(evaluateExpression("ambiguousOverloaded('aString')")).isEqualTo("string"); - } - - @Test // DATACMNS-1026 - void throwsExceptionWhenStillAmbiguous() throws Exception { - - provider = createContextProviderWithOverloads(); - - assertThatIllegalStateException() // - .isThrownBy(() -> evaluateExpression("ambiguousOverloaded(23)")) // - .withMessageContaining("ambiguousOverloaded") // - .withMessageContaining("(java.lang.Integer)"); - } - - @Test // DATACMNS-1518 - void invokesMethodWithVarArgs() { - - provider = createContextProviderWithOverloads(); - - assertThat(evaluateExpression("methodWithVarArgs('one', 'two')")).isEqualTo("varargs"); - } - - @Test // DATACMNS-1534 - void contextProviderShouldLazilyLookUpExtensions() { - - var beanFactory = Mockito.mock(ListableBeanFactory.class); - - var contextProvider = new ExtensionAwareEvaluationContextProvider(beanFactory); - - verify(beanFactory, never()).getBeansOfType(eq(EvaluationContextExtension.class), anyBoolean(), anyBoolean()); - - contextProvider.getEvaluationContext(null); - - verify(beanFactory).getBeansOfType(eq(ExtensionIdAware.class), anyBoolean(), anyBoolean()); - } - - @Test // DATACMNS-1534 - void contextProviderShouldLookupExtensionsOnlyOnce() { - - var beanFactory = Mockito.mock(ListableBeanFactory.class); - - var contextProvider = new ExtensionAwareEvaluationContextProvider(beanFactory); - - contextProvider.getEvaluationContext(null); - contextProvider.getEvaluationContext(null); - - verify(beanFactory).getBeansOfType(eq(ExtensionIdAware.class), anyBoolean(), anyBoolean()); - } - - private static ExtensionAwareQueryMethodEvaluationContextProvider createContextProviderWithOverloads() { - - return new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.singletonList( // - new DummyExtension("_first", "first") { - @Override - public Object getRootObject() { - return new RootWithOverloads(); - } - })); - } - - public static class DummyExtension implements org.springframework.data.spel.spi.EvaluationContextExtension { - - public static String DUMMY_KEY = "dummy"; - - private final String key, value; - - public DummyExtension(String key, String value) { - this.key = key; - this.value = value; - } - - @Override - public String getExtensionId() { - return key; - } - - @Override - public Map getProperties() { - - Map properties = new HashMap<>(); - - properties.put("key", value); - - return properties; - } - - @Override - public Map getFunctions() { - - Map functions = new HashMap<>(); - - try { - functions.put("aliasedMethod", new Function(getClass().getMethod("extensionMethod"))); - return functions; - } catch (Exception o_O) { - throw new RuntimeException(o_O); - } - } - - public static String extensionMethod() { - return "methodResult"; - } - - public static String method(int i1, int i2) { - return "two-ints"; - } - - public static String method(int i, String s) { - return "int-and-string"; - } - - public static String ambiguous() { - return "from-extension-type"; - } - - public static String ambiguousToo() { - return "from-extension-type"; - } - } - - private Object evaluateExpression(String expression) { - return evaluateExpression(expression, new Object[] { "parameterValue" }); - } - - private Object evaluateExpression(String expression, Object[] args) { - - var parameters = new DefaultParameters(ParametersSource.of(method)); - var evaluationContext = provider.getEvaluationContext(parameters, args); - return new SpelExpressionParser().parseExpression(expression).getValue(evaluationContext); - } - - interface SampleRepo { - - List findByFirstname(@Param("firstname") String firstname); - - List findByFirstname(@Param("firstname") String firstname, Pageable pageable); - - List findByFirstname(@Param("firstname") String firstname, Sort sort); - } - - public static class CustomExtensionRootObject1 { - - public String rootObjectInstanceField1 = "rootObjectInstanceF1"; - - public boolean rootObjectInstanceMethod1() { - return true; - } - - public String getStringProperty() { - return "stringProperty"; - } - } - - public static class CustomExtensionRootObject2 { - - public Integer rootObjectInstanceField2 = 42; - - public String rootObjectInstanceMethod2() { - return "rootObjectInstanceMethod2"; - } - } - - public static class RootWithOverloads { - - public String method() { - return "zero"; - } - - public String method(String s) { - return "single-string"; - } - - public String method(int i) { - return "single-int"; - } - - public String method(String s1, String s2) { - return "two"; - } - - public String ambiguous() { - return "from-root"; - } - - public String aliasedMethod() { - return "from-root"; - } - - public String ambiguousOverloaded(String s) { - return "string"; - } - - public String ambiguousOverloaded(Object o) { - return "object"; - } - - public String ambiguousOverloaded(Serializable o) { - return "serializable"; - } - - public String methodWithVarArgs(String... args) { - return "varargs"; - } - } -} diff --git a/src/test/java/org/springframework/data/repository/query/ParameterUnitTests.java b/src/test/java/org/springframework/data/repository/query/ParameterUnitTests.java index e1eddb35b..4504ce31e 100644 --- a/src/test/java/org/springframework/data/repository/query/ParameterUnitTests.java +++ b/src/test/java/org/springframework/data/repository/query/ParameterUnitTests.java @@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.springframework.core.MethodParameter; +import org.springframework.data.repository.Repository; import org.springframework.data.repository.query.ParametersUnitTests.User; import org.springframework.data.util.TypeInformation; @@ -42,7 +43,7 @@ class ParameterUnitTests { @Test // DATAJPA-1185 void classParameterWithSameTypeParameterAsReturnedListIsDynamicProjectionParameter() throws Exception { - var parameter = new Parameter(getMethodParameter("dynamicProjectionWithList")); + var parameter = new Parameter(getMethodParameter("dynamicProjectionWithList"), TypeInformation.MAP); assertThat(parameter.isDynamicProjectionParameter()).isTrue(); } @@ -50,7 +51,7 @@ class ParameterUnitTests { @Test // DATAJPA-1185 void classParameterWithSameTypeParameterAsReturnedStreamIsDynamicProjectionParameter() throws Exception { - var parameter = new Parameter(getMethodParameter("dynamicProjectionWithStream")); + var parameter = new Parameter(getMethodParameter("dynamicProjectionWithStream"), TypeInformation.MAP); assertThat(parameter.isDynamicProjectionParameter()).isTrue(); } @@ -58,7 +59,7 @@ class ParameterUnitTests { @Test void classParameterWithSameTypeParameterAsReturnedOptionalIsDynamicProjectionParameter() throws Exception { - var parameter = new Parameter(getMethodParameter("dynamicProjectionWithOptional")); + var parameter = new Parameter(getMethodParameter("dynamicProjectionWithOptional"), TypeInformation.MAP); assertThat(parameter.isDynamicProjectionParameter()).isTrue(); } @@ -80,7 +81,7 @@ class ParameterUnitTests { @Test // #2770 void doesNotConsiderAtParamAnnotatedClassParameterDynamicProjectionOne() throws Exception { - var parameter = new Parameter(getMethodParameter("atParamOnClass")); + var parameter = new Parameter(getMethodParameter("atParamOnClass"), TypeInformation.OBJECT); assertThat(parameter.isDynamicProjectionParameter()).isFalse(); } diff --git a/src/test/java/org/springframework/data/repository/query/QuotationMapUnitTests.java b/src/test/java/org/springframework/data/repository/query/QuotationMapUnitTests.java deleted file mode 100644 index 929dc7508..000000000 --- a/src/test/java/org/springframework/data/repository/query/QuotationMapUnitTests.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2018-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.repository.query; - -import static org.assertj.core.api.Assertions.*; - -import org.assertj.core.api.SoftAssertions; -import org.junit.jupiter.api.Test; -import org.springframework.data.repository.query.SpelQueryContext.QuotationMap; - -/** - * Unit tests for {@link QuotationMap}. - * - * @author Jens Schauder - */ -class QuotationMapUnitTests { - - SoftAssertions softly = new SoftAssertions(); - - @Test // DATAJPA-1235 - void emptyStringDoesNotContainQuotes() { - isNotQuoted("", "empty String", -1, 0, 1); - } - - @Test // DATAJPA-1235 - void nullStringDoesNotContainQuotes() { - isNotQuoted(null, "null String", -1, 0, 1); - } - - @Test // DATAJPA-1235 - void simpleStringDoesNotContainQuotes() { - - var query = "something"; - - isNotQuoted(query, "simple String", -1, 0, query.length() - 1, query.length(), query.length() + 1); - } - - @Test // DATAJPA-1235 - void fullySingleQuotedStringDoesContainQuotes() { - - var query = "'something'"; - - isNotQuoted(query, "quoted String", -1, query.length()); - isQuoted(query, "quoted String", 0, 1, 5, query.length() - 1); - } - - @Test // DATAJPA-1235 - void fullyDoubleQuotedStringDoesContainQuotes() { - - var query = "\"something\""; - - isNotQuoted(query, "double quoted String", -1, query.length()); - isQuoted(query, "double quoted String", 0, 1, 5, query.length() - 1); - } - - @Test // DATAJPA-1235 - void stringWithEmptyQuotes() { - - var query = "abc''def"; - - isNotQuoted(query, "zero length quote", -1, 0, 1, 2, 5, 6, 7); - isQuoted(query, "zero length quote", 3, 4); - } - - @Test // DATAJPA-1235 - void doubleInSingleQuotes() { - - var query = "abc'\"'def"; - - isNotQuoted(query, "double inside single quote", -1, 0, 1, 2, 6, 7, 8); - isQuoted(query, "double inside single quote", 3, 4, 5); - } - - @Test // DATAJPA-1235 - void singleQuotesInDoubleQuotes() { - - var query = "abc\"'\"def"; - - isNotQuoted(query, "single inside double quote", -1, 0, 1, 2, 6, 7, 8); - isQuoted(query, "single inside double quote", 3, 4, 5); - } - - @Test // DATAJPA-1235 - void escapedQuotes() { - - var query = "a'b''cd''e'f"; - isNotQuoted(query, "escaped quote", -1, 0, 11, 12); - isQuoted(query, "escaped quote", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); - } - - @Test // DATAJPA-1235 - void openEndedQuoteThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> new QuotationMap("a'b")); - } - - private static void isNotQuoted(String query, Object label, int... indexes) { - - var quotationMap = new QuotationMap(query); - - for (var index : indexes) { - - assertThat(quotationMap.isQuoted(index)) - .describedAs(String.format("(%s) %s does not contain a quote at %s", label, query, index)) // - .isFalse(); - } - } - - private static void isQuoted(String query, Object label, int... indexes) { - - var quotationMap = new QuotationMap(query); - - for (var index : indexes) { - - assertThat(quotationMap.isQuoted(index)) - .describedAs(String.format("(%s) %s does contain a quote at %s", label, query, index)) // - .isTrue(); - } - } -} diff --git a/src/test/java/org/springframework/data/repository/query/SpelEvaluatorUnitTests.java b/src/test/java/org/springframework/data/repository/query/SpelEvaluatorUnitTests.java deleted file mode 100644 index 3aa97b28b..000000000 --- a/src/test/java/org/springframework/data/repository/query/SpelEvaluatorUnitTests.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2023-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.repository.query; - -import static org.assertj.core.api.Assertions.*; - -import java.lang.reflect.Method; - -import org.junit.jupiter.api.Test; -import org.springframework.data.repository.query.SpelQueryContext.SpelExtractor; - -/** - * Unit tests for {@link SpelEvaluator}. - * - * @author Mark Paluch - */ -class SpelEvaluatorUnitTests { - - final SpelQueryContext context = SpelQueryContext.of((counter, s) -> String.format("__$synthetic$__%d", counter + 1), - String::concat); - - @Test // GH-2904 - void shouldEvaluateExpression() throws Exception { - - SpelExtractor extractor = context.parse("SELECT :#{#value}"); - Method method = MyRepository.class.getDeclaredMethod("simpleExpression", String.class); - SpelEvaluator evaluator = new SpelEvaluator(QueryMethodEvaluationContextProvider.DEFAULT, - new DefaultParameters(ParametersSource.of(method)), extractor); - - assertThat(evaluator.getQueryString()).isEqualTo("SELECT :__$synthetic$__1"); - assertThat(evaluator.evaluate(new Object[] { "hello" })).containsEntry("__$synthetic$__1", "hello"); - } - - @Test // GH-2904 - void shouldAllowNullValues() throws Exception { - - SpelExtractor extractor = context.parse("SELECT :#{#value}"); - Method method = MyRepository.class.getDeclaredMethod("simpleExpression", String.class); - SpelEvaluator evaluator = new SpelEvaluator(QueryMethodEvaluationContextProvider.DEFAULT, - new DefaultParameters(ParametersSource.of(method)), extractor); - - assertThat(evaluator.getQueryString()).isEqualTo("SELECT :__$synthetic$__1"); - assertThat(evaluator.evaluate(new Object[] { null })).containsEntry("__$synthetic$__1", null); - } - - interface MyRepository { - - void simpleExpression(String value); - - } -} diff --git a/src/test/java/org/springframework/data/repository/query/SpelExtractorUnitTests.java b/src/test/java/org/springframework/data/repository/query/SpelExtractorUnitTests.java deleted file mode 100644 index 881906afc..000000000 --- a/src/test/java/org/springframework/data/repository/query/SpelExtractorUnitTests.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2018-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.repository.query; - -import static org.assertj.core.api.Assertions.*; - -import java.util.Arrays; -import java.util.Map; -import java.util.function.BiFunction; - -import org.assertj.core.api.SoftAssertions; -import org.assertj.core.groups.Tuple; -import org.junit.jupiter.api.Test; -import org.springframework.data.repository.query.SpelQueryContext.SpelExtractor; - -/** - * Unit tests for {@link SpelExtractor}. - * - * @author Jens Schauder - * @author Oliver Gierke - */ -class SpelExtractorUnitTests { - - static final BiFunction PARAMETER_NAME_SOURCE = (index, spel) -> "EPP" + index; - static final BiFunction REPLACEMENT_SOURCE = (prefix, name) -> prefix + name; - - final SoftAssertions softly = new SoftAssertions(); - - @Test // DATACMNS-1258 - void nullQueryThrowsException() { - - var context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); - - assertThatIllegalArgumentException().isThrownBy(() -> context.parse(null)); - } - - @Test // DATACMNS-1258 - void emptyStringGetsParsedCorrectly() { - - var context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); - var extractor = context.parse(""); - - softly.assertThat(extractor.getQueryString()).isEqualTo(""); - softly.assertThat(extractor.getParameterMap()).isEmpty(); - - softly.assertAll(); - } - - @Test // DATACMNS-1258 - void findsAndReplacesExpressions() { - - var context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); - var extractor = context.parse(":#{one} ?#{two}"); - - softly.assertThat(extractor.getQueryString()).isEqualTo(":EPP0 ?EPP1"); - softly.assertThat(extractor.getParameterMap().entrySet()) // - .extracting(Map.Entry::getKey, Map.Entry::getValue) // - .containsExactlyInAnyOrder( // - Tuple.tuple("EPP0", "one"), // - Tuple.tuple("EPP1", "two") // - ); - - softly.assertAll(); - } - - @Test // DATACMNS-1258 - void keepsStringWhenNoMatchIsFound() { - - var context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); - var extractor = context.parse("abcdef"); - - softly.assertThat(extractor.getQueryString()).isEqualTo("abcdef"); - softly.assertThat(extractor.getParameterMap()).isEmpty(); - - softly.assertAll(); - } - - @Test // DATACMNS-1258 - void spelsInQuotesGetIgnored() { - - var queries = Arrays.asList(// - "a'b:#{one}cd'ef", // - "a'b:#{o'ne}cdef", // - "ab':#{one}'cdef", // - "ab:'#{one}cd'ef", // - "ab:#'{one}cd'ef", // - "a'b:#{o'ne}cdef"); - - queries.forEach(this::checkNoSpelIsFound); - - softly.assertAll(); - } - - private void checkNoSpelIsFound(String query) { - - var context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); - var extractor = context.parse(query); - - softly.assertThat(extractor.getQueryString()).describedAs(query).isEqualTo(query); - softly.assertThat(extractor.getParameterMap()).describedAs(query).isEmpty(); - } -} diff --git a/src/test/java/org/springframework/data/repository/query/SpelQueryContextUnitTests.java b/src/test/java/org/springframework/data/repository/query/SpelQueryContextUnitTests.java deleted file mode 100644 index ffc77b88d..000000000 --- a/src/test/java/org/springframework/data/repository/query/SpelQueryContextUnitTests.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2018-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.repository.query; - -import static org.assertj.core.api.Assertions.*; - -import java.util.function.BiFunction; - -import org.junit.jupiter.api.Test; - -/** - * Unit tests for {@link SpelQueryContext}. - * - * @author Oliver Gierke - * @author Jens Schauder - * @author Mark Paluch - */ -class SpelQueryContextUnitTests { - - static final QueryMethodEvaluationContextProvider EVALUATION_CONTEXT_PROVIDER = QueryMethodEvaluationContextProvider.DEFAULT; - static final BiFunction PARAMETER_NAME_SOURCE = (index, spel) -> "__$synthetic$__" + index; - static final BiFunction REPLACEMENT_SOURCE = (prefix, name) -> prefix + name; - - @Test // DATACMNS-1258 - void nullParameterNameSourceThrowsException() { - - assertThatIllegalArgumentException() // - .isThrownBy(() -> SpelQueryContext.of(null, REPLACEMENT_SOURCE)); - } - - @Test // DATACMNS-1258 - void nullReplacementSourceThrowsException() { - - assertThatIllegalArgumentException() // - .isThrownBy(() -> SpelQueryContext.of(PARAMETER_NAME_SOURCE, null)); - } - - @Test // DATACMNS-1258 - void rejectsNullEvaluationContextProvider() { - - var context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); - - assertThatIllegalArgumentException() // - .isThrownBy(() -> context.withEvaluationContextProvider(null)); - } - - @Test // DATACMNS-1258 - void createsEvaluatingContextUsingProvider() { - - var context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); - - assertThat(context.withEvaluationContextProvider(EVALUATION_CONTEXT_PROVIDER)).isNotNull(); - } - - @Test // DATACMNS-1683, GH- - void reportsQuotationCorrectly() { - - var context = SpelQueryContext.of(PARAMETER_NAME_SOURCE, REPLACEMENT_SOURCE); - - var extractor = context.parse( - "select n from NetworkServer n where (LOWER(n.name) LIKE LOWER(NULLIF(text(concat('%',:#{#networkRequest.name},'%')), '')) OR :#{#networkRequest.name} IS NULL )"); - - assertThat(extractor.getQueryString()).isEqualTo( - "select n from NetworkServer n where (LOWER(n.name) LIKE LOWER(NULLIF(text(concat('%',:__$synthetic$__0,'%')), '')) OR :__$synthetic$__1 IS NULL )"); - assertThat(extractor.isQuoted(extractor.getQueryString().indexOf(":__$synthetic$__0"))).isFalse(); - assertThat(extractor.isQuoted(extractor.getQueryString().indexOf(":__$synthetic$__1"))).isFalse(); - assertThat(extractor.size()).isEqualTo(2); - } -} diff --git a/src/test/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReaderUnitTests.java b/src/test/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReaderUnitTests.java deleted file mode 100644 index be27ec82a..000000000 --- a/src/test/java/org/springframework/data/type/classreading/DefaultMethodsMetadataReaderUnitTests.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2018-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.type.classreading; - -import static org.assertj.core.api.Assertions.*; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; -import org.springframework.core.type.MethodMetadata; -import org.springframework.data.type.MethodsMetadata; - -/** - * Unit tests for {@link DefaultMethodsMetadataReader}. - * - * @author Mark Paluch - */ -class DefaultMethodsMetadataReaderUnitTests { - - @Test // DATACMNS-1206 - void shouldReadClassMethods() throws IOException { - - var metadata = getMethodsMetadata(Foo.class); - - assertThat(metadata.getMethods()).hasSize(3); - - var iterator = metadata.getMethods().iterator(); - - assertThat(iterator.next().getMethodName()).isEqualTo("one"); - assertThat(iterator.next().getMethodName()).isEqualTo("two"); - assertThat(iterator.next().getMethodName()).isEqualTo("three"); - } - - @Test // DATACMNS-1206 - void shouldReadInterfaceMethods() throws IOException { - - var metadata = getMethodsMetadata(Baz.class); - - assertThat(metadata.getMethods()).hasSize(3); - - var iterator = metadata.getMethods().iterator(); - - assertThat(iterator.next().getMethodName()).isEqualTo("one"); - assertThat(iterator.next().getMethodName()).isEqualTo("two"); - assertThat(iterator.next().getMethodName()).isEqualTo("three"); - } - - @Test // DATACMNS-1206 - void shouldMetadata() throws IOException { - - var factory = new MethodsMetadataReaderFactory(); - var metadataReader = factory.getMetadataReader(getClass().getName()); - - assertThat(metadataReader.getClassMetadata()).isNotNull(); - assertThat(metadataReader.getAnnotationMetadata()).isNotNull(); - } - - @Test // DATACMNS-1206 - void shouldReturnMethodMetadataByName() throws IOException { - - var metadata = getMethodsMetadata(Foo.class); - - assertThat(metadata.getMethods()).hasSize(3); - - assertThat(metadata.getMethods("one")).extracting(MethodMetadata::getMethodName).contains("one"); - assertThat(metadata.getMethods("foo")).isEmpty(); - } - - private static MethodsMetadata getMethodsMetadata(Class classToIntrospect) throws IOException { - - var factory = new MethodsMetadataReaderFactory(); - var metadataReader = factory.getMetadataReader(classToIntrospect.getName()); - return metadataReader.getMethodsMetadata(); - } - - // Create a scenario with a cyclic dependency to mix up methods reported by class.getDeclaredMethods() - // That's not exactly deterministic because it depends on when the compiler sees the classes. - abstract class Foo { - - abstract void one(Foo b); - - abstract void two(Bar b); - - abstract void three(Foo b); - } - - interface Baz { - - void one(Foo b); - - void two(Bar b); - - void three(Baz b); - } - - abstract class Bar { - - abstract void dependOnFoo(Foo f); - - abstract void dependOnBaz(Baz f); - } -} diff --git a/src/test/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactoryUnitTests.java b/src/test/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactoryUnitTests.java deleted file mode 100644 index b4a61ad8c..000000000 --- a/src/test/java/org/springframework/data/type/classreading/MethodsMetadataReaderFactoryUnitTests.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2018-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.type.classreading; - -import static org.assertj.core.api.Assertions.*; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; - -import org.junit.jupiter.api.Test; -import org.springframework.core.io.DefaultResourceLoader; - -/** - * Unit tests for {@link MethodsMetadataReaderFactory}. - * - * @author Mark Paluch - */ -class MethodsMetadataReaderFactoryUnitTests { - - @Test // DATACMNS-1206 - void shouldReadFromDefaultClassLoader() throws IOException { - - var factory = new MethodsMetadataReaderFactory(); - var reader = factory.getMetadataReader(getClass().getName()); - - assertThat(reader).isNotNull(); - } - - @Test // DATACMNS-1206 - void shouldReadFromClassLoader() throws IOException { - - var factory = new MethodsMetadataReaderFactory(getClass().getClassLoader()); - var reader = factory.getMetadataReader(getClass().getName()); - - assertThat(reader).isNotNull(); - } - - @Test // DATACMNS-1206 - void shouldNotFindClass() { - - var factory = new MethodsMetadataReaderFactory(new URLClassLoader(new URL[0], null)); - - assertThatThrownBy(() -> factory.getMetadataReader(getClass().getName())).isInstanceOf(FileNotFoundException.class); - } - - @Test // DATACMNS-1206 - void shouldReadFromResourceLoader() throws IOException { - - var factory = new MethodsMetadataReaderFactory(new DefaultResourceLoader()); - var reader = factory.getMetadataReader(getClass().getName()); - - assertThat(reader).isNotNull(); - } -} diff --git a/src/test/kotlin/org/springframework/data/mapping/model/KotlinClassGeneratingEntityInstantiatorUnitTests.kt b/src/test/kotlin/org/springframework/data/mapping/model/KotlinClassGeneratingEntityInstantiatorUnitTests.kt index 563dabbee..a9c98d57a 100644 --- a/src/test/kotlin/org/springframework/data/mapping/model/KotlinClassGeneratingEntityInstantiatorUnitTests.kt +++ b/src/test/kotlin/org/springframework/data/mapping/model/KotlinClassGeneratingEntityInstantiatorUnitTests.kt @@ -20,12 +20,9 @@ import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.Test -import org.springframework.data.annotation.PersistenceConstructor -import org.springframework.data.annotation.Persistent +import org.springframework.data.annotation.PersistenceCreator import org.springframework.data.mapping.PersistentEntity import org.springframework.data.mapping.context.SamplePersistentProperty -import org.springframework.data.mapping.model.KotlinValueUtils.BoxingRules -import kotlin.jvm.internal.Reflection import kotlin.reflect.KClass /** @@ -297,13 +294,16 @@ class KotlinClassGeneratingEntityInstantiatorUnitTests { ) - data class WithConstructorsHavingSameParameterCount @PersistenceConstructor constructor(val id: Long?, val notes: Map = emptyMap()) { + data class WithConstructorsHavingSameParameterCount @PersistenceCreator constructor( + val id: Long?, + val notes: Map = emptyMap() + ) { constructor(notes: Map, additionalNotes: Map = emptyMap()) : this(null, notes + additionalNotes) } data class ContactWithPersistenceConstructor(val firstname: String, val lastname: String) { - @PersistenceConstructor + @PersistenceCreator constructor(firstname: String) : this(firstname, "") } @@ -312,7 +312,7 @@ class KotlinClassGeneratingEntityInstantiatorUnitTests { var organisations: MutableList = mutableListOf() ) { - @PersistenceConstructor + @PersistenceCreator constructor(id: String?) : this(id, mutableListOf()) } diff --git a/src/test/kotlin/org/springframework/data/mapping/model/PreferredConstructorDiscovererUnitTests.kt b/src/test/kotlin/org/springframework/data/mapping/model/PreferredConstructorDiscovererUnitTests.kt index 005a5a015..6666c93c8 100644 --- a/src/test/kotlin/org/springframework/data/mapping/model/PreferredConstructorDiscovererUnitTests.kt +++ b/src/test/kotlin/org/springframework/data/mapping/model/PreferredConstructorDiscovererUnitTests.kt @@ -17,7 +17,7 @@ package org.springframework.data.mapping.model import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test -import org.springframework.data.annotation.PersistenceConstructor +import org.springframework.data.annotation.PersistenceCreator import org.springframework.data.mapping.model.AbstractPersistentPropertyUnitTests.SamplePersistentProperty /** @@ -129,7 +129,7 @@ class PreferredConstructorDiscovererUnitTests { class AnnotatedConstructors(val firstname: String) { - @PersistenceConstructor + @PersistenceCreator constructor(firstname: String, lastname: String) : this(firstname) } @@ -140,7 +140,7 @@ class PreferredConstructorDiscovererUnitTests { val lastname: String = "bar" ) { - @PersistenceConstructor + @PersistenceCreator constructor(firstname: String = "foo", lastname: String = "bar", age: Int) : this( firstname, lastname diff --git a/src/test/kotlin/org/springframework/data/repository/query/KParameterUnitTests.kt b/src/test/kotlin/org/springframework/data/repository/query/KParameterUnitTests.kt index 1aa1456fa..63afa6943 100644 --- a/src/test/kotlin/org/springframework/data/repository/query/KParameterUnitTests.kt +++ b/src/test/kotlin/org/springframework/data/repository/query/KParameterUnitTests.kt @@ -19,6 +19,7 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.core.DefaultParameterNameDiscoverer import org.springframework.core.MethodParameter +import org.springframework.data.util.TypeInformation import kotlin.reflect.jvm.javaMethod /** @@ -34,7 +35,7 @@ class KParameterUnitTests { val methodParameter = MethodParameter(MyCoroutineRepository::hello.javaMethod!!, 0) methodParameter.initParameterNameDiscovery(DefaultParameterNameDiscoverer()) - val parameter = Parameter(methodParameter) + val parameter = Parameter(methodParameter, TypeInformation.OBJECT) assertThat(parameter.name).isEmpty() assertThat(parameter.isBindable).isFalse()