Browse Source

Replace Optional with Nullable.

issue/less-optional
Mark Paluch 1 year ago
parent
commit
4465eb9193
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 5
      src/main/java/org/springframework/data/convert/ConverterBuilder.java
  2. 65
      src/main/java/org/springframework/data/convert/DefaultConverterBuilder.java
  3. 4
      src/main/java/org/springframework/data/convert/DefaultTypeMapper.java
  4. 2
      src/main/java/org/springframework/data/domain/Sort.java
  5. 2
      src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java
  6. 20
      src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java
  7. 18
      src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java
  8. 2
      src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java
  9. 48
      src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java
  10. 4
      src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java
  11. 86
      src/main/java/org/springframework/data/mapping/model/Property.java
  12. 41
      src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java
  13. 22
      src/main/java/org/springframework/data/querydsl/SimpleEntityPathResolver.java
  14. 6
      src/main/java/org/springframework/data/querydsl/binding/OptionalValueBinding.java
  15. 70
      src/main/java/org/springframework/data/querydsl/binding/QuerydslBindings.java
  16. 72
      src/main/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactory.java
  17. 4
      src/main/java/org/springframework/data/querydsl/binding/QuerydslPredicateBuilder.java
  18. 27
      src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java
  19. 37
      src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java
  20. 34
      src/main/java/org/springframework/data/repository/config/SelectionSet.java
  21. 72
      src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java
  22. 2
      src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java
  23. 30
      src/main/java/org/springframework/data/repository/query/parser/OrderBySource.java
  24. 55
      src/main/java/org/springframework/data/repository/query/parser/PartTree.java
  25. 22
      src/main/java/org/springframework/data/repository/support/AnnotationAttribute.java
  26. 22
      src/main/java/org/springframework/data/repository/support/MethodParameters.java
  27. 2
      src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java
  28. 54
      src/main/java/org/springframework/data/repository/support/Repositories.java
  29. 25
      src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java
  30. 20
      src/main/java/org/springframework/data/util/StreamUtils.java
  31. 11
      src/test/java/org/springframework/data/mapping/model/PropertyUnitTests.java
  32. 4
      src/test/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactoryUnitTests.java
  33. 2
      src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java
  34. 6
      src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java
  35. 13
      src/test/java/org/springframework/data/repository/config/SelectionSetUnitTests.java
  36. 5
      src/test/java/org/springframework/data/repository/query/parser/OrderBySourceUnitTests.java
  37. 7
      src/test/java/org/springframework/data/repository/support/AnnotationAttributeUnitTests.java
  38. 5
      src/test/java/org/springframework/data/repository/support/MethodParametersUnitTests.java

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

@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
*/
package org.springframework.data.convert;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
@ -52,7 +51,7 @@ public interface ConverterBuilder { @@ -52,7 +51,7 @@ public interface ConverterBuilder {
Assert.notNull(target, "Target type must not be null");
Assert.notNull(function, "Conversion function must not be null");
return new DefaultConverterBuilder<>(new ConvertiblePair(source, target), Optional.empty(), Optional.of(function));
return new DefaultConverterBuilder<>(new ConvertiblePair(source, target), null, function);
}
/**
@ -71,7 +70,7 @@ public interface ConverterBuilder { @@ -71,7 +70,7 @@ public interface ConverterBuilder {
Assert.notNull(target, "Target type must not be null");
Assert.notNull(function, "Conversion function must not be null");
return new DefaultConverterBuilder<>(new ConvertiblePair(target, source), Optional.of(function), Optional.empty());
return new DefaultConverterBuilder<>(new ConvertiblePair(target, source), function, null);
}
/**

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

@ -16,10 +16,8 @@ @@ -16,10 +16,8 @@
package org.springframework.data.convert;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
@ -28,12 +26,11 @@ import org.springframework.core.convert.converter.GenericConverter.ConvertiblePa @@ -28,12 +26,11 @@ import org.springframework.core.convert.converter.GenericConverter.ConvertiblePa
import org.springframework.data.convert.ConverterBuilder.ConverterAware;
import org.springframework.data.convert.ConverterBuilder.ReadingConverterBuilder;
import org.springframework.data.convert.ConverterBuilder.WritingConverterBuilder;
import org.springframework.data.util.Optionals;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
* Builder to easily set up (bi-directional) {@link Converter} instances for Spring Data type mapping using Lambdas. Use
* Builder to easily set up (bidirectional) {@link Converter} instances for Spring Data type mapping using Lambdas. Use
* factory methods on {@link ConverterBuilder} to create instances of this class.
*
* @author Oliver Gierke
@ -44,59 +41,85 @@ import org.springframework.util.ObjectUtils; @@ -44,59 +41,85 @@ import org.springframework.util.ObjectUtils;
* @see ConverterBuilder#reading(Class, Class, Function)
* @soundtrack John Mayer - Still Feel Like Your Man (The Search for Everything)
*/
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
record DefaultConverterBuilder<S, T> (ConvertiblePair convertiblePair,
Optional<Function<? super S, ? extends T>> writing, Optional<Function<? super T, ? extends S>> reading)
@Nullable Function<? super S, ? extends T> writing, @Nullable Function<? super T, ? extends S> reading)
implements ConverterAware, ReadingConverterBuilder<T, S>, WritingConverterBuilder<S, T> {
@Override
public ConverterAware andReading(Function<? super T, ? extends S> function) {
return withReading(Optional.of(function));
return withReading(function);
}
@Override
public ConverterAware andWriting(Function<? super S, ? extends T> function) {
return withWriting(Optional.of(function));
return withWriting(function);
}
@Override
public GenericConverter getReadingConverter() {
return getOptionalReadingConverter()
.orElseThrow(() -> new IllegalStateException("No reading converter specified"));
GenericConverter converter = getNullableReadingConverter();
if (converter == null) {
throw new IllegalStateException("No reading converter specified");
}
return converter;
}
@Override
public GenericConverter getWritingConverter() {
return getOptionalWritingConverter()
.orElseThrow(() -> new IllegalStateException("No writing converter specified"));
GenericConverter converter = getNullableWritingConverter();
if (converter == null) {
throw new IllegalStateException("No writing converter specified");
}
return converter;
}
@Override
public Set<GenericConverter> getConverters() {
return Optionals//
.toStream(getOptionalReadingConverter(), getOptionalWritingConverter())//
.collect(Collectors.toSet());
GenericConverter reading = getNullableReadingConverter();
GenericConverter writing = getNullableWritingConverter();
if (reading == null && writing == null) {
return Collections.emptySet();
}
if (reading == null) {
return Set.of(writing);
}
if (writing == null) {
return Set.of(reading);
}
return Set.of(reading, writing);
}
private Optional<GenericConverter> getOptionalReadingConverter() {
return reading.map(it -> new ConfigurableGenericConverter.Reading<>(convertiblePair, it));
@Nullable
private GenericConverter getNullableReadingConverter() {
return reading != null ? new ConfigurableGenericConverter.Reading<>(convertiblePair, reading) : null;
}
private Optional<GenericConverter> getOptionalWritingConverter() {
return writing.map(it -> new ConfigurableGenericConverter.Writing<>(invertedPair(), it));
@Nullable
private GenericConverter getNullableWritingConverter() {
return writing != null ? new ConfigurableGenericConverter.Writing<>(invertedPair(), writing) : null;
}
private ConvertiblePair invertedPair() {
return new ConvertiblePair(convertiblePair.getTargetType(), convertiblePair.getSourceType());
}
DefaultConverterBuilder<S, T> withWriting(Optional<Function<? super S, ? extends T>> writing) {
DefaultConverterBuilder<S, T> withWriting(Function<? super S, ? extends T> writing) {
return this.writing == writing ? this
: new DefaultConverterBuilder<S, T>(this.convertiblePair, writing, this.reading);
}
DefaultConverterBuilder<S, T> withReading(Optional<Function<? super T, ? extends S>> reading) {
DefaultConverterBuilder<S, T> withReading(Function<? super T, ? extends S> reading) {
return this.reading == reading ? this
: new DefaultConverterBuilder<S, T>(this.convertiblePair, this.writing, reading);
}

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

@ -74,7 +74,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S>, BeanClassLoaderAware @@ -74,7 +74,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S>, BeanClassLoaderAware
* given additional mappers.
*
* @param accessor must not be {@literal null}.
* @param mappingContext
* @param mappingContext can be {@literal null} if absent.
* @param additionalMappers must not be {@literal null}.
*/
public DefaultTypeMapper(TypeAliasAccessor<S> accessor,
@ -116,7 +116,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S>, BeanClassLoaderAware @@ -116,7 +116,7 @@ public class DefaultTypeMapper<S> implements TypeMapper<S>, BeanClassLoaderAware
}
/**
* Tries to lookup a {@link TypeInformation} for the given alias from the cache and return it if found. If none is
* Tries to look up a {@link TypeInformation} for the given alias from the cache and return it if found. If none is
* found it'll consult the {@link TypeInformationMapper}s and cache the value found.
*
* @param alias

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

@ -357,7 +357,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord @@ -357,7 +357,7 @@ public class Sort implements Streamable<org.springframework.data.domain.Sort.Ord
* @return Optional holding the {@link Direction} enum value or empty, if {@code value} cannot be parsed into
* {@link Direction}.
*/
public static Optional<Direction> fromOptionalString(String value) {
public static Optional<Direction> fromOptionalString(@Nullable String value) {
if (ObjectUtils.isEmpty(value)) {
return Optional.empty();

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

@ -899,7 +899,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<? @@ -899,7 +899,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
@Override
public boolean matches(Property property) {
Field field = property.getField().orElse(null);
Field field = property.getField();
if (field == null || !KotlinReflectionUtils.isDataClass(field.getDeclaringClass())) {
return false;

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

@ -20,7 +20,6 @@ import java.lang.reflect.Method; @@ -20,7 +20,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@ -93,17 +92,20 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -93,17 +92,20 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
this.isAssociation = Lazy.of(() -> ASSOCIATION_TYPE != null && ASSOCIATION_TYPE.isAssignableFrom(rawType));
this.associationTargetType = ASSOCIATION_TYPE == null //
? Lazy.empty() //
: Lazy.of(() -> Optional.of(getTypeInformation()) //
.map(it -> it.getSuperTypeInformation(ASSOCIATION_TYPE)) //
.map(TypeInformation::getComponentType) //
.orElse(null));
: Lazy.of(() -> {
TypeInformation<?> type = getTypeInformation().getSuperTypeInformation(ASSOCIATION_TYPE);
if (type != null) {
return type.getComponentType();
}
return null;
});
this.entityTypeInformation = Lazy.of(() -> detectEntityTypes(simpleTypeHolder));
this.getter = property.getGetter().orElse(null);
this.setter = property.getSetter().orElse(null);
this.field = property.getField().orElse(null);
this.wither = property.getWither().orElse(null);
this.getter = property.getGetter();
this.setter = property.getSetter();
this.field = property.getField();
this.wither = property.getWither();
this.immutable = setter == null && (field == null || Modifier.isFinal(field.getModifiers()));
this.readable = Lazy.of(() -> {

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

@ -118,12 +118,11 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -118,12 +118,11 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
*/
private void populateAnnotationCache(Property property) {
Optionals.toStream(property.getGetter(), property.getSetter()).forEach(it -> {
StreamUtils.fromNullable(property.getGetter(), property.getSetter(), property.getField()).forEach(it -> {
for (Annotation annotation : it.getAnnotations()) {
Class<? extends Annotation> annotationType = annotation.annotationType();
Annotation mergedAnnotation = AnnotatedElementUtils.getMergedAnnotation(it, annotationType);
validateAnnotation(mergedAnnotation,
@ -134,21 +133,6 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -134,21 +133,6 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
annotationCache.put(annotationType, Optional.of(mergedAnnotation));
}
});
property.getField().ifPresent(it -> {
for (Annotation annotation : it.getAnnotations()) {
Class<? extends Annotation> annotationType = annotation.annotationType();
Annotation mergedAnnotation = AnnotatedElementUtils.getMergedAnnotation(it, annotationType);
validateAnnotation(mergedAnnotation,
"Ambiguous mapping; Annotation %s configured " + "on field %s and one of its accessor methods in class %s",
annotationType.getSimpleName(), it.getName(), getOwner().getType().getSimpleName());
annotationCache.put(annotationType, Optional.of(mergedAnnotation));
}
});
}
/**

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

@ -909,7 +909,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @@ -909,7 +909,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
* Generate the {@link PersistentPropertyAccessor#setProperty(PersistentProperty, Object)} method.
*
* <pre class="code">
* public void setProperty(PersistentProperty<?> property, Optional<? extends Object> value) {
* public void setProperty(PersistentProperty<?> property, Object value) {
* Object bean = this.bean;
* switch (property.getName().hashCode()) {
* case 3355:

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

@ -60,7 +60,7 @@ public class MappingInstantiationException extends RuntimeException { @@ -60,7 +60,7 @@ public class MappingInstantiationException extends RuntimeException {
* @param cause
*/
public MappingInstantiationException(PersistentEntity<?, ?> entity, List<Object> arguments, Exception cause) {
this(Optional.ofNullable(entity), arguments, null, cause);
this(entity, arguments, null, cause);
}
/**
@ -70,39 +70,39 @@ public class MappingInstantiationException extends RuntimeException { @@ -70,39 +70,39 @@ public class MappingInstantiationException extends RuntimeException {
* @param cause
*/
public MappingInstantiationException(List<Object> arguments, Exception cause) {
this(Optional.empty(), arguments, null, cause);
this(null, arguments, null, cause);
}
private MappingInstantiationException(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments,
private MappingInstantiationException(@Nullable PersistentEntity<?, ?> entity, List<Object> arguments,
@Nullable String message, Exception cause) {
super(buildExceptionMessage(entity, arguments, message), cause);
this.entityType = entity.map(PersistentEntity::getType).orElse(null);
this.entityCreator = entity.map(PersistentEntity::getInstanceCreatorMetadata).orElse(null);
this.entityType = entity != null ? entity.getType() : null;
this.entityCreator = entity != null ? entity.getInstanceCreatorMetadata() : null;
this.constructorArguments = arguments;
}
private static String buildExceptionMessage(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments,
@Nullable
private static String buildExceptionMessage(@Nullable PersistentEntity<?, ?> entity, List<Object> arguments,
@Nullable String defaultMessage) {
return entity.map(it -> {
Optional<? extends InstanceCreatorMetadata<?>> constructor = Optional.ofNullable(it.getInstanceCreatorMetadata());
List<String> toStringArgs = new ArrayList<>(arguments.size());
if (entity == null) {
return defaultMessage;
}
for (Object o : arguments) {
toStringArgs.add(ObjectUtils.nullSafeToString(o));
}
InstanceCreatorMetadata<?> constructor = entity.getInstanceCreatorMetadata();
List<String> toStringArgs = new ArrayList<>(arguments.size());
return String.format(TEXT_TEMPLATE, it.getType().getName(),
constructor.map(MappingInstantiationException::toString).orElse("NO_CONSTRUCTOR"), //
String.join(",", toStringArgs));
for (Object o : arguments) {
toStringArgs.add(ObjectUtils.nullSafeToString(o));
}
}).orElse(defaultMessage);
return String.format(TEXT_TEMPLATE, entity.getType().getName(), toString(constructor),
String.join(",", toStringArgs));
}
private static String toString(InstanceCreatorMetadata<?> creator) {
private static String toString(@Nullable InstanceCreatorMetadata<?> creator) {
if (creator instanceof PreferredConstructor<?, ?> c) {
return toString(c);
@ -112,14 +112,19 @@ public class MappingInstantiationException extends RuntimeException { @@ -112,14 +112,19 @@ public class MappingInstantiationException extends RuntimeException {
return toString(m);
}
return creator.toString();
if (creator != null) {
return creator.toString();
}
return "NO_CONSTRUCTOR";
}
private static String toString(PreferredConstructor<?, ?> preferredConstructor) {
Constructor<?> constructor = preferredConstructor.getConstructor();
if (KotlinDetector.isKotlinPresent() && KotlinReflectionUtils.isSupportedKotlinClass(constructor.getDeclaringClass())) {
if (KotlinDetector.isKotlinPresent()
&& KotlinReflectionUtils.isSupportedKotlinClass(constructor.getDeclaringClass())) {
KFunction<?> kotlinFunction = ReflectJvmMapping.getKotlinFunction(constructor);
@ -135,7 +140,8 @@ public class MappingInstantiationException extends RuntimeException { @@ -135,7 +140,8 @@ public class MappingInstantiationException extends RuntimeException {
Method constructor = factoryMethod.getFactoryMethod();
if (KotlinDetector.isKotlinPresent() && KotlinReflectionUtils.isSupportedKotlinClass(constructor.getDeclaringClass())) {
if (KotlinDetector.isKotlinPresent()
&& KotlinReflectionUtils.isSupportedKotlinClass(constructor.getDeclaringClass())) {
KFunction<?> kotlinFunction = ReflectJvmMapping.getKotlinFunction(constructor);

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

@ -186,7 +186,7 @@ public interface PreferredConstructorDiscoverer { @@ -186,7 +186,7 @@ public interface PreferredConstructorDiscoverer {
.filter(it -> it.isSynthetic() && AnnotationUtils.findAnnotation(it, PersistenceCreator.class) != null)
.map(it -> buildPreferredConstructor(it, type, entity)).findFirst();
if(first.isPresent()){
if (first.isPresent()) {
return first.get();
}
@ -222,7 +222,7 @@ public interface PreferredConstructorDiscoverer { @@ -222,7 +222,7 @@ public interface PreferredConstructorDiscoverer {
*/
private static Discoverers findDiscoverer(Class<?> type) {
if(!KotlinDetector.isKotlinPresent()) {
if (!KotlinDetector.isKotlinPresent()) {
return DEFAULT;
}
return KotlinReflectionUtils.isSupportedKotlinClass(type) ? KOTLIN : DEFAULT;

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

@ -19,12 +19,10 @@ import java.beans.FeatureDescriptor; @@ -19,12 +19,10 @@ import java.beans.FeatureDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@ -40,22 +38,25 @@ import org.springframework.util.StringUtils; @@ -40,22 +38,25 @@ import org.springframework.util.StringUtils;
*/
public class Property {
private final Optional<Field> field;
private final Optional<PropertyDescriptor> descriptor;
private final @Nullable Field field;
private final @Nullable PropertyDescriptor descriptor;
private final Class<?> rawType;
private final Lazy<Integer> hashCode;
private final Optional<Method> getter;
private final Optional<Method> setter;
private final @Nullable Method getter;
private final @Nullable Method setter;
private final Lazy<String> name;
private final Lazy<String> toString;
private final Lazy<Optional<Method>> wither;
private final Lazy<Method> wither;
private Property(TypeInformation<?> type, Optional<Field> field, Optional<PropertyDescriptor> descriptor) {
private Property(TypeInformation<?> type, @Nullable Field field, @Nullable PropertyDescriptor descriptor) {
Assert.notNull(type, "Type must not be null");
Assert.isTrue(Optionals.isAnyPresent(field, descriptor), "Either field or descriptor has to be given");
if (field == null && descriptor == null) {
throw new IllegalArgumentException("Either field or descriptor has to be given");
}
this.field = field;
this.descriptor = descriptor;
@ -69,13 +70,23 @@ public class Property { @@ -69,13 +70,23 @@ public class Property {
this.toString = Lazy.of(() -> withFieldOrDescriptor(Object::toString,
it -> String.format("%s.%s", type.getType().getName(), it.getDisplayName())));
this.getter = descriptor.map(PropertyDescriptor::getReadMethod)//
.filter(it -> getType() != null)//
.filter(it -> getType().isAssignableFrom(type.getReturnType(it).getType()));
Method getter = null;
Method setter = null;
if (descriptor != null) {
Method readMethod = descriptor.getReadMethod();
if (readMethod != null && getType().isAssignableFrom(type.getReturnType(readMethod).getType())) {
getter = readMethod;
}
this.setter = descriptor.map(PropertyDescriptor::getWriteMethod)//
.filter(it -> getType() != null)//
.filter(it -> type.getParameterTypes(it).get(0).getType().isAssignableFrom(getType()));
Method writeMethod = descriptor.getWriteMethod();
if (writeMethod != null && type.getParameterTypes(writeMethod).get(0).getType().isAssignableFrom(getType())) {
setter = writeMethod;
}
}
this.getter = getter;
this.setter = setter;
this.wither = Lazy.of(() -> findWither(type, getName(), getType()));
}
@ -91,7 +102,7 @@ public class Property { @@ -91,7 +102,7 @@ public class Property {
Assert.notNull(field, "Field must not be null");
return new Property(type, Optional.of(field), Optional.empty());
return new Property(type, field, null);
}
/**
@ -107,7 +118,7 @@ public class Property { @@ -107,7 +118,7 @@ public class Property {
Assert.notNull(field, "Field must not be null");
Assert.notNull(descriptor, "PropertyDescriptor must not be null");
return new Property(type, Optional.of(field), Optional.of(descriptor));
return new Property(type, field, descriptor);
}
/**
@ -123,7 +134,7 @@ public class Property { @@ -123,7 +134,7 @@ public class Property {
Assert.notNull(descriptor, "PropertyDescriptor must not be null");
return new Property(type, Optional.empty(), Optional.of(descriptor));
return new Property(type, null, descriptor);
}
/**
@ -146,7 +157,7 @@ public class Property { @@ -146,7 +157,7 @@ public class Property {
* @return
*/
public boolean isFieldBacked() {
return field.isPresent();
return field != null;
}
/**
@ -154,7 +165,8 @@ public class Property { @@ -154,7 +165,8 @@ public class Property {
*
* @return will never be {@literal null}.
*/
public Optional<Method> getGetter() {
@Nullable
public Method getGetter() {
return getter;
}
@ -163,7 +175,8 @@ public class Property { @@ -163,7 +175,8 @@ public class Property {
*
* @return will never be {@literal null}.
*/
public Optional<Method> getSetter() {
@Nullable
public Method getSetter() {
return setter;
}
@ -172,8 +185,9 @@ public class Property { @@ -172,8 +185,9 @@ public class Property {
*
* @return will never be {@literal null}.
*/
public Optional<Method> getWither() {
return wither.get();
@Nullable
public Method getWither() {
return wither.getNullable();
}
/**
@ -181,7 +195,8 @@ public class Property { @@ -181,7 +195,8 @@ public class Property {
*
* @return will never be {@literal null}.
*/
public Optional<Field> getField() {
@Nullable
public Field getField() {
return this.field;
}
@ -191,7 +206,7 @@ public class Property { @@ -191,7 +206,7 @@ public class Property {
* @return
*/
public boolean hasAccessor() {
return getGetter().isPresent() || getSetter().isPresent();
return this.getter != null || this.setter != null;
}
/**
@ -223,7 +238,7 @@ public class Property { @@ -223,7 +238,7 @@ public class Property {
return false;
}
return this.field.isPresent() ? this.field.equals(that.field) : this.descriptor.equals(that.descriptor);
return this.field != null ? this.field.equals(that.field) : this.descriptor.equals(that.descriptor);
}
@Override
@ -256,13 +271,19 @@ public class Property { @@ -256,13 +271,19 @@ public class Property {
private <T> T withFieldOrDescriptor(Function<? super Field, T> field,
Function<? super PropertyDescriptor, T> descriptor) {
return Optionals.firstNonEmpty(//
() -> this.field.map(field), //
() -> this.descriptor.map(descriptor))//
.orElseThrow(() -> new IllegalStateException("Should not occur; Either field or descriptor has to be given"));
if (this.field != null) {
return field.apply(this.field);
}
if (this.descriptor != null) {
return descriptor.apply(this.descriptor);
}
throw new IllegalStateException("Should not occur; Either field or descriptor has to be given");
}
private static Optional<Method> findWither(TypeInformation<?> owner, String propertyName, Class<?> rawType) {
@Nullable
private static Method findWither(TypeInformation<?> owner, String propertyName, Class<?> rawType) {
AtomicReference<Method> resultHolder = new AtomicReference<>();
String methodName = String.format("with%s", StringUtils.capitalize(propertyName));
@ -274,8 +295,7 @@ public class Property { @@ -274,8 +295,7 @@ public class Property {
}
}, it -> isMethodWithSingleParameterOfType(it, methodName, rawType));
Method method = resultHolder.get();
return method != null ? Optional.of(method) : Optional.empty();
return resultHolder.get();
}
private static boolean isMethodWithSingleParameterOfType(Method method, String name, Class<?> type) {

41
src/main/java/org/springframework/data/projection/DefaultProjectionInformation.java

@ -22,7 +22,6 @@ import java.util.Arrays; @@ -22,7 +22,6 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
@ -37,6 +36,7 @@ import org.springframework.core.type.MethodMetadata; @@ -37,6 +36,7 @@ import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.data.util.StreamUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -126,7 +126,7 @@ class DefaultProjectionInformation implements ProjectionInformation { @@ -126,7 +126,7 @@ class DefaultProjectionInformation implements ProjectionInformation {
private static final Log logger = LogFactory.getLog(PropertyDescriptorSource.class);
private final Class<?> type;
private final Optional<AnnotationMetadata> metadata;
private final @Nullable AnnotationMetadata metadata;
/**
* Creates a new {@link PropertyDescriptorSource} for the given type.
@ -161,14 +161,19 @@ class DefaultProjectionInformation implements ProjectionInformation { @@ -161,14 +161,19 @@ class DefaultProjectionInformation implements ProjectionInformation {
Stream<PropertyDescriptor> allButDefaultGetters = Arrays.stream(BeanUtils.getPropertyDescriptors(type)) //
.filter(it -> !hasDefaultGetter(it));
Stream<PropertyDescriptor> ownDescriptors = metadata.map(it -> filterAndOrder(allButDefaultGetters, it)) //
.orElse(allButDefaultGetters);
Stream<PropertyDescriptor> ownDescriptors;
Stream<Class<?>> superTypeDescriptors;
Stream<PropertyDescriptor> superTypeDescriptors = metadata.map(this::fromMetadata) //
.orElseGet(this::fromType) //
.flatMap(it -> new PropertyDescriptorSource(it).collectDescriptors());
if (metadata != null) {
ownDescriptors = filterAndOrder(allButDefaultGetters, metadata);
superTypeDescriptors = fromMetadata(metadata);
} else {
ownDescriptors = allButDefaultGetters;
superTypeDescriptors = fromType();
}
return Stream.concat(ownDescriptors, superTypeDescriptors);
return Stream.concat(ownDescriptors,
superTypeDescriptors.flatMap(it -> new PropertyDescriptorSource(it).collectDescriptors()));
}
/**
@ -179,16 +184,14 @@ class DefaultProjectionInformation implements ProjectionInformation { @@ -179,16 +184,14 @@ class DefaultProjectionInformation implements ProjectionInformation {
* @param metadata must not be {@literal null}.
* @return
*/
private Stream<PropertyDescriptor> filterAndOrder(Stream<PropertyDescriptor> source,
AnnotationMetadata metadata) {
private Stream<PropertyDescriptor> filterAndOrder(Stream<PropertyDescriptor> source, AnnotationMetadata metadata) {
Map<String, Integer> orderedMethods = getMethodOrder(metadata);
Stream<PropertyDescriptor> filtered = source.filter(it -> it.getReadMethod() != null)
.filter(it -> it.getReadMethod().getDeclaringClass().equals(type));
return orderedMethods.isEmpty()
? filtered
return orderedMethods.isEmpty() ? filtered
: filtered.sorted(Comparator.comparingInt(left -> orderedMethods.get(left.getReadMethod().getName())));
}
@ -212,26 +215,27 @@ class DefaultProjectionInformation implements ProjectionInformation { @@ -212,26 +215,27 @@ class DefaultProjectionInformation implements ProjectionInformation {
}
/**
* Attempts to obtain {@link AnnotationMetadata} from {@link Class}. Returns {@link Optional} containing
* {@link AnnotationMetadata} if metadata was read successfully, {@link Optional#empty()} otherwise.
* Attempts to obtain {@link AnnotationMetadata} from {@link Class}. Returns {@link AnnotationMetadata} if metadata
* was read successful or {@literal null} if metadata reading failed.
*
* @param type must not be {@literal null}.
* @return the optional {@link AnnotationMetadata}.
*/
private static Optional<AnnotationMetadata> getMetadata(Class<?> type) {
@Nullable
private static AnnotationMetadata getMetadata(Class<?> type) {
try {
SimpleMetadataReaderFactory factory = new SimpleMetadataReaderFactory(type.getClassLoader());
MetadataReader metadataReader = factory.getMetadataReader(ClassUtils.getQualifiedName(type));
return Optional.of(metadataReader.getAnnotationMetadata());
return metadataReader.getAnnotationMetadata();
} catch (IOException e) {
logger.info(
LogMessage.format("Couldn't read class metadata for %s. Input property calculation might fail", type));
return Optional.empty();
return null;
}
}
@ -246,8 +250,7 @@ class DefaultProjectionInformation implements ProjectionInformation { @@ -246,8 +250,7 @@ class DefaultProjectionInformation implements ProjectionInformation {
return Arrays.stream(types) //
.filter(it -> name.equals(it.getName())) //
.findFirst()
.orElseThrow(() -> new IllegalStateException(
.findFirst().orElseThrow(() -> new IllegalStateException(
String.format("Did not find type %s in %s", name, Arrays.toString(types))));
}

22
src/main/java/org/springframework/data/querydsl/SimpleEntityPathResolver.java

@ -17,8 +17,8 @@ package org.springframework.data.querydsl; @@ -17,8 +17,8 @@ package org.springframework.data.querydsl;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Optional;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@ -54,11 +54,11 @@ public class SimpleEntityPathResolver implements EntityPathResolver { @@ -54,11 +54,11 @@ public class SimpleEntityPathResolver implements EntityPathResolver {
}
/**
* Creates an {@link EntityPath} instance for the given domain class. Tries to lookup a class matching the naming
* Creates an {@link EntityPath} instance for the given domain class. Tries to look up a class matching the naming
* convention (prepend Q to the simple name of the class, same package) and find a static field of the same type in
* it.
*
* @param domainClass
* @param domainClass domain class to introspect.
* @return
*/
@Override
@ -70,10 +70,13 @@ public class SimpleEntityPathResolver implements EntityPathResolver { @@ -70,10 +70,13 @@ public class SimpleEntityPathResolver implements EntityPathResolver {
try {
Class<?> pathClass = ClassUtils.forName(pathClassName, domainClass.getClassLoader());
Field field = getStaticFieldOfType(pathClass);
if (field == null) {
throw new IllegalStateException(String.format(NO_FIELD_FOUND_TEMPLATE, pathClass));
}
return getStaticFieldOfType(pathClass)//
.map(it -> (EntityPath<T>) ReflectionUtils.getField(it, null))//
.orElseThrow(() -> new IllegalStateException(String.format(NO_FIELD_FOUND_TEMPLATE, pathClass)));
return (EntityPath<T>) ReflectionUtils.getField(field, null);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(String.format(NO_CLASS_FOUND_TEMPLATE, pathClassName, domainClass.getName()),
@ -87,7 +90,8 @@ public class SimpleEntityPathResolver implements EntityPathResolver { @@ -87,7 +90,8 @@ public class SimpleEntityPathResolver implements EntityPathResolver {
* @param type
* @return
*/
private Optional<Field> getStaticFieldOfType(Class<?> type) {
@Nullable
private Field getStaticFieldOfType(Class<?> type) {
for (Field field : type.getDeclaredFields()) {
@ -95,12 +99,12 @@ public class SimpleEntityPathResolver implements EntityPathResolver { @@ -95,12 +99,12 @@ public class SimpleEntityPathResolver implements EntityPathResolver {
boolean hasSameType = type.equals(field.getType());
if (isStatic && hasSameType) {
return Optional.of(field);
return field;
}
}
Class<?> superclass = type.getSuperclass();
return Object.class.equals(superclass) ? Optional.empty() : getStaticFieldOfType(superclass);
return Object.class.equals(superclass) ? null : getStaticFieldOfType(superclass);
}
/**

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

@ -33,12 +33,12 @@ public interface OptionalValueBinding<T extends Path<? extends S>, S> { @@ -33,12 +33,12 @@ public interface OptionalValueBinding<T extends Path<? extends S>, S> {
/**
* Returns the predicate to be applied to the given {@link Path} for the given value. The given value will be the
* first the first one provided for the given path and converted into the expected type.
* first one provided for the given path and converted into the expected type.
*
* @param path {@link Path} to the property. Will not be {@literal null}.
* @param value the value that should be bound. Will not be {@literal null}.
* @return can be {@literal null}, in which case the binding will not be incorporated in the overall {@link Predicate}
* .
* @return can be {@literal null}, in which case the binding will not be incorporated in the overall
* {@link Predicate}.
*/
Optional<Predicate> bind(T path, Optional<? extends S> value);
}

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

@ -129,7 +129,7 @@ public class QuerydslBindings { @@ -129,7 +129,7 @@ public class QuerydslBindings {
Assert.notEmpty(paths, "At least one path has to be provided");
for (Path<?> path : paths) {
this.denyList.add(toDotPath(Optional.of(path)));
this.denyList.add(toDotPath(path));
}
}
@ -143,7 +143,7 @@ public class QuerydslBindings { @@ -143,7 +143,7 @@ public class QuerydslBindings {
Assert.notEmpty(paths, "At least one path has to be provided");
for (Path<?> path : paths) {
this.allowList.add(toDotPath(Optional.of(path)));
this.allowList.add(toDotPath(path));
}
}
@ -208,16 +208,16 @@ public class QuerydslBindings { @@ -208,16 +208,16 @@ public class QuerydslBindings {
if (pathAndBinding != null) {
Optional<MultiValueBinding<S, T>> binding = pathAndBinding.getBinding();
MultiValueBinding<S, T> binding = pathAndBinding.getBinding();
if (binding.isPresent()) {
return binding;
if (binding != null) {
return Optional.of(binding);
}
}
pathAndBinding = (PathAndBinding<S, T>) typeSpecs.get(path.getLeafType());
return pathAndBinding == null ? Optional.empty() : pathAndBinding.getBinding();
return pathAndBinding == null ? Optional.empty() : Optional.ofNullable(pathAndBinding.getBinding());
}
/**
@ -226,11 +226,12 @@ public class QuerydslBindings { @@ -226,11 +226,12 @@ public class QuerydslBindings {
* @param path must not be {@literal null}.
* @return
*/
Optional<Path<?>> getExistingPath(PathInformation path) {
@Nullable
Path<?> getExistingPath(PathInformation path) {
Assert.notNull(path, "PropertyPath must not be null");
return Optional.ofNullable(pathSpecs.get(createKey(path))).flatMap(PathAndBinding::getPath);
return getPath(createKey(path));
}
/**
@ -253,16 +254,14 @@ public class QuerydslBindings { @@ -253,16 +254,14 @@ public class QuerydslBindings {
// fully-qualified path lookup
String key = createKey(type, path);
if (pathSpecs.containsKey(key)) {
return pathSpecs.get(key).getPath()//
.map(QuerydslPathInformation::of)//
.orElse(null);
Path<?> spec = getPath(key);
return spec != null ? QuerydslPathInformation.of(spec) : null;
}
// alias lookup
if (pathSpecs.containsKey(path)) {
return pathSpecs.get(path).getPath()//
.map(QuerydslPathInformation::of)//
.orElse(null);
Path<?> spec = getPath(path);
return spec != null ? QuerydslPathInformation.of(spec) : null;
}
try {
@ -273,14 +272,21 @@ public class QuerydslBindings { @@ -273,14 +272,21 @@ public class QuerydslBindings {
}
}
@Nullable
private Path<?> getPath(String key) {
PathAndBinding<?, ?> binding = pathSpecs.get(key);
return binding != null ? binding.getPath() : null;
}
/**
* Returns the property path key for the given {@link Path}.
*
* @param path can be {@literal null}.
* @return
*/
private static String createKey(Optional<Path<?>> path) {
return path.map(QuerydslPathInformation::of).map(QuerydslBindings::createKey).orElse("");
private static String createKey(@Nullable Path<?> path) {
return path != null ? QuerydslBindings.createKey(QuerydslPathInformation.of(path)) : "";
}
private static String createKey(PathInformation path) {
@ -348,8 +354,8 @@ public class QuerydslBindings { @@ -348,8 +354,8 @@ public class QuerydslBindings {
* @param path can be {@literal null}.
* @return
*/
private static String toDotPath(Optional<Path<?>> path) {
return path.map(QuerydslBindings::fromRootPath).orElse("");
private static String toDotPath(@Nullable Path<?> path) {
return path != null ? QuerydslBindings.fromRootPath(path) : "";
}
private static String fromRootPath(Path<?> path) {
@ -414,7 +420,7 @@ public class QuerydslBindings { @@ -414,7 +420,7 @@ public class QuerydslBindings {
paths.forEach(path -> registerBinding(PathAndBinding.withPath(path).with(binding)));
}
protected void registerBinding(PathAndBinding<P, T> binding) {
void registerBinding(PathAndBinding<P, T> binding) {
QuerydslBindings.this.pathSpecs.put(createKey(binding.getPath()), binding);
}
}
@ -433,7 +439,7 @@ public class QuerydslBindings { @@ -433,7 +439,7 @@ public class QuerydslBindings {
/**
* Creates a new {@link AliasingPathBinder} for the given {@link Path}.
*
* @param paths must not be {@literal null}.
* @param path must not be {@literal null}.
*/
AliasingPathBinder(P path) {
this(null, path);
@ -477,7 +483,7 @@ public class QuerydslBindings { @@ -477,7 +483,7 @@ public class QuerydslBindings {
}
@Override
protected void registerBinding(PathAndBinding<P, T> binding) {
void registerBinding(PathAndBinding<P, T> binding) {
super.registerBinding(binding);
@ -543,31 +549,33 @@ public class QuerydslBindings { @@ -543,31 +549,33 @@ public class QuerydslBindings {
*/
private static final class PathAndBinding<P extends Path<? extends T>, T> {
private final Optional<Path<?>> path;
private final Optional<MultiValueBinding<P, T>> binding;
private final @Nullable Path<?> path;
private final @Nullable MultiValueBinding<P, T> binding;
PathAndBinding(Optional<Path<?>> path, Optional<MultiValueBinding<P, T>> binding) {
PathAndBinding(@Nullable Path<?> path, @Nullable MultiValueBinding<P, T> binding) {
this.path = path;
this.binding = binding;
}
public static <T, P extends Path<? extends T>> PathAndBinding<P, T> withPath(P path) {
return new PathAndBinding<>(Optional.of(path), Optional.empty());
return new PathAndBinding<>(path, null);
}
public static <T, S extends Path<? extends T>> PathAndBinding<S, T> withoutPath() {
return new PathAndBinding<>(Optional.empty(), Optional.empty());
return new PathAndBinding<>(null, null);
}
public PathAndBinding<P, T> with(MultiValueBinding<P, T> binding) {
return new PathAndBinding<>(path, Optional.of(binding));
return new PathAndBinding<>(path, binding);
}
public Optional<Path<?>> getPath() {
@Nullable
public Path<?> getPath() {
return this.path;
}
public Optional<MultiValueBinding<P, T>> getBinding() {
@Nullable
public MultiValueBinding<P, T> getBinding() {
return this.binding;
}
@ -587,9 +595,7 @@ public class QuerydslBindings { @@ -587,9 +595,7 @@ public class QuerydslBindings {
@Override
public int hashCode() {
int result = ObjectUtils.nullSafeHashCode(path);
result = (31 * result) + ObjectUtils.nullSafeHashCode(binding);
return result;
return ObjectUtils.nullSafeHash(path, binding);
}
@Override

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

@ -17,9 +17,7 @@ package org.springframework.data.querydsl.binding; @@ -17,9 +17,7 @@ package org.springframework.data.querydsl.binding;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
@ -30,6 +28,7 @@ import org.springframework.context.ApplicationContextAware; @@ -30,6 +28,7 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.data.querydsl.EntityPathResolver;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.querydsl.core.types.EntityPath;
@ -49,8 +48,8 @@ public class QuerydslBindingsFactory implements ApplicationContextAware { @@ -49,8 +48,8 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
private final EntityPathResolver entityPathResolver;
private final Map<TypeInformation<?>, EntityPath<?>> entityPaths;
private Optional<AutowireCapableBeanFactory> beanFactory;
private Optional<Repositories> repositories;
private @Nullable AutowireCapableBeanFactory beanFactory;
private @Nullable Repositories repositories;
private QuerydslBinderCustomizer<EntityPath<?>> defaultCustomizer;
/**
@ -64,16 +63,14 @@ public class QuerydslBindingsFactory implements ApplicationContextAware { @@ -64,16 +63,14 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
this.entityPathResolver = entityPathResolver;
this.entityPaths = new ConcurrentHashMap<>();
this.beanFactory = Optional.empty();
this.repositories = Optional.empty();
this.defaultCustomizer = NoOpCustomizer.INSTANCE;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.beanFactory = Optional.of(applicationContext.getAutowireCapableBeanFactory());
this.repositories = Optional.of(new Repositories(applicationContext));
this.beanFactory = applicationContext.getAutowireCapableBeanFactory();
this.repositories = new Repositories(applicationContext);
this.defaultCustomizer = findDefaultCustomizer();
}
@ -94,7 +91,7 @@ public class QuerydslBindingsFactory implements ApplicationContextAware { @@ -94,7 +91,7 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
* @return will never be {@literal null}.
*/
public QuerydslBindings createBindingsFor(TypeInformation<?> domainType) {
return createBindingsFor(domainType, Optional.empty());
return doCreateBindingsFor(domainType, null);
}
/**
@ -107,22 +104,12 @@ public class QuerydslBindingsFactory implements ApplicationContextAware { @@ -107,22 +104,12 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
*/
public QuerydslBindings createBindingsFor(TypeInformation<?> domainType,
Class<? extends QuerydslBinderCustomizer<?>> customizer) {
return createBindingsFor(domainType, Optional.of(customizer));
return doCreateBindingsFor(domainType, customizer);
}
/**
* Creates the {@link QuerydslBindings} to be used using for the given domain type and a pre-defined
* {@link QuerydslBinderCustomizer}. If no customizer is given, auto-detection will be applied.
*
* @param domainType must not be {@literal null}.
* @param customizer the {@link QuerydslBinderCustomizer} to use. If an empty {@link Optional} is given customizer
* detection for the given domain type will be applied.
* @return
*/
private QuerydslBindings createBindingsFor(TypeInformation<?> domainType,
Optional<Class<? extends QuerydslBinderCustomizer<?>>> customizer) {
private QuerydslBindings doCreateBindingsFor(TypeInformation<?> domainType,
@Nullable Class<? extends QuerydslBinderCustomizer<?>> customizer) {
Assert.notNull(customizer, "Customizer must not be null");
Assert.notNull(domainType, "Domain type must not be null");
EntityPath<?> path = verifyEntityPathPresent(domainType);
@ -161,14 +148,14 @@ public class QuerydslBindingsFactory implements ApplicationContextAware { @@ -161,14 +148,14 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
* @return
*/
private QuerydslBinderCustomizer<EntityPath<?>> findDefaultCustomizer() {
return beanFactory.map(this::getDefaultQuerydslBinderCustomizer).orElse(NoOpCustomizer.INSTANCE);
return beanFactory != null ? getDefaultQuerydslBinderCustomizer(beanFactory) : NoOpCustomizer.INSTANCE;
}
private QuerydslBinderCustomizer<EntityPath<?>> getDefaultQuerydslBinderCustomizer(
AutowireCapableBeanFactory beanFactory) {
List<QuerydslBinderCustomizerDefaults> customizers = beanFactory
.getBeanProvider(QuerydslBinderCustomizerDefaults.class).stream().collect(Collectors.toList());
.getBeanProvider(QuerydslBinderCustomizerDefaults.class).stream().toList();
return (bindings, root) -> {
for (QuerydslBinderCustomizerDefaults querydslBinderCustomizerDefaults : customizers) {
@ -187,14 +174,20 @@ public class QuerydslBindingsFactory implements ApplicationContextAware { @@ -187,14 +174,20 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private QuerydslBinderCustomizer<EntityPath<?>> findCustomizerForDomainType(
Optional<? extends Class<? extends QuerydslBinderCustomizer>> customizer, Class<?> domainType) {
return customizer//
.filter(it -> !QuerydslBinderCustomizer.class.equals(it))//
.map(this::createQuerydslBinderCustomizer)
.orElseGet(() -> repositories.flatMap(it -> it.getRepositoryFor(domainType))//
.map(it -> it instanceof QuerydslBinderCustomizer ? (QuerydslBinderCustomizer<EntityPath<?>>) it : null)//
.orElse(NoOpCustomizer.INSTANCE));
@Nullable Class<? extends QuerydslBinderCustomizer> customizer, Class<?> domainType) {
if (customizer == null || QuerydslBinderCustomizer.class.equals(customizer)) {
if (repositories == null) {
return NoOpCustomizer.INSTANCE;
}
return repositories.getRepositoryFor(domainType) //
.map(it -> it instanceof QuerydslBinderCustomizer ? (QuerydslBinderCustomizer<EntityPath<?>>) it : null)
.orElse(NoOpCustomizer.INSTANCE);
}
return createQuerydslBinderCustomizer(customizer);
}
/**
@ -210,14 +203,15 @@ public class QuerydslBindingsFactory implements ApplicationContextAware { @@ -210,14 +203,15 @@ public class QuerydslBindingsFactory implements ApplicationContextAware {
private QuerydslBinderCustomizer<EntityPath<?>> createQuerydslBinderCustomizer(
Class<? extends QuerydslBinderCustomizer> type) {
return beanFactory.map(it -> {
if (beanFactory == null) {
return BeanUtils.instantiateClass(type);
}
try {
return it.getBean(type);
} catch (NoSuchBeanDefinitionException e) {
return it.createBean(type);
}
}).orElseGet(() -> BeanUtils.instantiateClass(type));
try {
return beanFactory.getBean(type);
} catch (NoSuchBeanDefinitionException e) {
return beanFactory.createBean(type);
}
}
private enum NoOpCustomizer implements QuerydslBinderCustomizer<EntityPath<?>> {

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

@ -159,9 +159,9 @@ public class QuerydslPredicateBuilder { @@ -159,9 +159,9 @@ public class QuerydslPredicateBuilder {
*/
private Path<?> getPath(PathInformation path, QuerydslBindings bindings) {
Optional<Path<?>> resolvedPath = bindings.getExistingPath(path);
Path<?> resolvedPath = bindings.getExistingPath(path);
return resolvedPath.orElseGet(() -> paths.computeIfAbsent(path, it -> it.reifyPath(resolver)));
return resolvedPath != null ? resolvedPath : paths.computeIfAbsent(path, it -> it.reifyPath(resolver));
}
/**

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

@ -97,6 +97,7 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl @@ -97,6 +97,7 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
* @param beanManager the CDI {@link BeanManager}, must not be {@literal null}.
* @param detector detector for the custom repository implementations {@link CustomRepositoryImplementationDetector}.
*/
@Deprecated
public CdiRepositoryBean(Set<Annotation> qualifiers, Class<T> repositoryType, BeanManager beanManager,
Optional<CustomRepositoryImplementationDetector> detector) {
@ -113,6 +114,30 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl @@ -113,6 +114,30 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
this.passivationId = createPassivationId(qualifiers, repositoryType);
}
/**
* Creates a new {@link CdiRepositoryBean}.
*
* @param qualifiers must not be {@literal null}.
* @param repositoryType has to be an interface must not be {@literal null}.
* @param beanManager the CDI {@link BeanManager}, must not be {@literal null}.
* @param detector detector for the custom repository implementations {@link CustomRepositoryImplementationDetector}.
*/
public CdiRepositoryBean(Set<Annotation> qualifiers, Class<T> repositoryType, BeanManager beanManager,
CustomRepositoryImplementationDetector detector) {
Assert.notNull(qualifiers, "Qualifiers must not be null");
Assert.notNull(beanManager, "BeanManager must not be null");
Assert.notNull(repositoryType, "Repoitory type must not be null");
Assert.isTrue(repositoryType.isInterface(), "RepositoryType must be an interface");
Assert.notNull(detector, "CustomRepositoryImplementationDetector must not be null");
this.qualifiers = qualifiers;
this.repositoryType = repositoryType;
this.beanManager = beanManager;
this.context = new CdiRepositoryContext(getClass().getClassLoader(), detector);
this.passivationId = createPassivationId(qualifiers, repositoryType);
}
/**
* Creates a new {@link CdiRepositoryBean}.
*
@ -386,7 +411,7 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl @@ -386,7 +411,7 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
}
/**
* Try to lookup a custom implementation for a {@link org.springframework.data.repository.Repository}. Can only be
* Try to look up a custom implementation for a {@link org.springframework.data.repository.Repository}. Can only be
* used when a {@code CustomRepositoryImplementationDetector} is provided.
*
* @param repositoryType

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

@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
*/
package org.springframework.data.repository.config;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@ -27,6 +26,7 @@ import org.springframework.core.env.Environment; @@ -27,6 +26,7 @@ import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.StreamUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -113,15 +113,28 @@ public class CustomRepositoryImplementationDetector { @@ -113,15 +113,28 @@ public class CustomRepositoryImplementationDetector {
private static Optional<AbstractBeanDefinition> selectImplementationCandidate(
ImplementationLookupConfiguration lookup, Set<BeanDefinition> definitions) {
return SelectionSet //
.of(definitions, c -> c.isEmpty() ? firstOrEmptyBeanDefinition(definitions) : throwAmbiguousCustomImplementationException(c)) //
BeanDefinition beanDefinition = SelectionSet //
.of(definitions, c -> {
if (c.isEmpty()) {
return firstOrEmptyBeanDefinition(definitions);
}
String implementationNames = definitions.stream()//
.map(BeanDefinition::getBeanClassName)//
.collect(Collectors.joining(", "));
throw new IllegalStateException(String.format(AMBIGUOUS_CUSTOM_IMPLEMENTATIONS, implementationNames));
}) //
.filterIfNecessary(lookup::hasMatchingBeanName) //
.uniqueResult() //
.map(AbstractBeanDefinition.class::cast);
.uniqueResult();
return Optional.ofNullable((AbstractBeanDefinition) beanDefinition);
}
static Optional<BeanDefinition> firstOrEmptyBeanDefinition(Set<BeanDefinition> definitions) {
return definitions.isEmpty() ? Optional.empty() : Optional.of(definitions.iterator().next());
@Nullable
static BeanDefinition firstOrEmptyBeanDefinition(Set<BeanDefinition> definitions) {
return definitions.isEmpty() ? null : definitions.iterator().next();
}
private Set<BeanDefinition> findCandidateBeanDefinitions(ImplementationDetectionConfiguration config) {
@ -141,14 +154,4 @@ public class CustomRepositoryImplementationDetector { @@ -141,14 +154,4 @@ public class CustomRepositoryImplementationDetector {
.flatMap(it -> provider.findCandidateComponents(it).stream())//
.collect(Collectors.toSet());
}
private static Optional<BeanDefinition> throwAmbiguousCustomImplementationException(
Collection<BeanDefinition> definitions) {
String implementationNames = definitions.stream()//
.map(BeanDefinition::getBeanClassName)//
.collect(Collectors.joining(", "));
throw new IllegalStateException(String.format(AMBIGUOUS_CUSTOM_IMPLEMENTATIONS, implementationNames));
}
}

34
src/main/java/org/springframework/data/repository/config/SelectionSet.java

@ -16,11 +16,12 @@ @@ -16,11 +16,12 @@
package org.springframework.data.repository.config;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.springframework.lang.Nullable;
/**
* Allows filtering of a collection in order to select a unique element. Once a unique element is found all further
* filters are ignored.
@ -33,9 +34,9 @@ import java.util.stream.Collectors; @@ -33,9 +34,9 @@ import java.util.stream.Collectors;
class SelectionSet<T> {
private final Collection<T> collection;
private final Function<Collection<T>, Optional<T>> fallback;
private final Function<Collection<T>, T> fallback;
private SelectionSet(Collection<T> collection, Function<Collection<T>, Optional<T>> fallback) {
private SelectionSet(Collection<T> collection, Function<Collection<T>, T> fallback) {
this.collection = collection;
this.fallback = fallback;
}
@ -48,7 +49,7 @@ class SelectionSet<T> { @@ -48,7 +49,7 @@ class SelectionSet<T> {
return new SelectionSet<>(collection, defaultFallback());
}
public static <T> SelectionSet<T> of(Collection<T> collection, Function<Collection<T>, Optional<T>> fallback) {
public static <T> SelectionSet<T> of(Collection<T> collection, Function<Collection<T>, T> fallback) {
return new SelectionSet<>(collection, fallback);
}
@ -59,11 +60,12 @@ class SelectionSet<T> { @@ -59,11 +60,12 @@ class SelectionSet<T> {
*
* @return a unique result, or the result of the callback provided in the constructor.
*/
Optional<T> uniqueResult() {
@Nullable
T uniqueResult() {
Optional<T> uniqueResult = findUniqueResult();
T uniqueResult = findUniqueResult();
return uniqueResult.isPresent() ? uniqueResult : fallback.apply(collection);
return uniqueResult != null ? uniqueResult : fallback.apply(collection);
}
/**
@ -73,22 +75,28 @@ class SelectionSet<T> { @@ -73,22 +75,28 @@ class SelectionSet<T> {
*/
SelectionSet<T> filterIfNecessary(Predicate<T> predicate) {
return findUniqueResult().map(it -> this).orElseGet(
() -> new SelectionSet<>(collection.stream().filter(predicate).collect(Collectors.toList()), fallback));
T result = findUniqueResult();
if (result != null) {
return this;
}
return new SelectionSet<>(collection.stream().filter(predicate).collect(Collectors.toList()), fallback);
}
private static <S> Function<Collection<S>, Optional<S>> defaultFallback() {
private static <S> Function<Collection<S>, S> defaultFallback() {
return c -> {
if (c.isEmpty()) {
return Optional.empty();
return null;
} else {
throw new IllegalStateException("More than one element in collection");
}
};
}
private Optional<T> findUniqueResult() {
return Optional.ofNullable(collection.size() == 1 ? collection.iterator().next() : null);
@Nullable
private T findUniqueResult() {
return collection.size() == 1 ? collection.iterator().next() : null;
}
}

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

@ -47,6 +47,7 @@ import org.springframework.data.repository.query.QueryMethodValueEvaluationConte @@ -47,6 +47,7 @@ import org.springframework.data.repository.query.QueryMethodValueEvaluationConte
import org.springframework.data.spel.EvaluationContextProvider;
import org.springframework.data.util.Lazy;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -75,17 +76,17 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -75,17 +76,17 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
private RepositoryFactorySupport factory;
private boolean exposeMetadata;
private Key queryLookupStrategyKey;
private Optional<Class<?>> repositoryBaseClass = Optional.empty();
private Optional<Object> customImplementation = Optional.empty();
private Optional<RepositoryFragments> repositoryFragments = Optional.empty();
private @Nullable Class<?> repositoryBaseClass;
private @Nullable Object customImplementation;
private @Nullable RepositoryFragments repositoryFragments;
private NamedQueries namedQueries = PropertiesBasedNamedQueries.EMPTY;
private Optional<MappingContext<?, ?>> mappingContext = Optional.empty();
private @Nullable MappingContext<?, ?> mappingContext;
private ClassLoader classLoader;
private ApplicationEventPublisher publisher;
private BeanFactory beanFactory;
private Environment environment;
private boolean lazyInit = false;
private Optional<EvaluationContextProvider> evaluationContextProvider = Optional.empty();
private @Nullable EvaluationContextProvider evaluationContextProvider;
private final List<RepositoryFactoryCustomizer> repositoryFactoryCustomizers = new ArrayList<>();
private Lazy<T> repository;
@ -110,7 +111,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -110,7 +111,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
* @since 1.11
*/
public void setRepositoryBaseClass(Class<?> repositoryBaseClass) {
this.repositoryBaseClass = Optional.ofNullable(repositoryBaseClass);
this.repositoryBaseClass = repositoryBaseClass;
}
/**
@ -142,7 +143,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -142,7 +143,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
* @param customImplementation
*/
public void setCustomImplementation(Object customImplementation) {
this.customImplementation = Optional.of(customImplementation);
this.customImplementation = customImplementation;
}
/**
@ -151,7 +152,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -151,7 +152,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
* @param repositoryFragments
*/
public void setRepositoryFragments(RepositoryFragments repositoryFragments) {
this.repositoryFragments = Optional.of(repositoryFragments);
this.repositoryFragments = repositoryFragments;
}
/**
@ -170,7 +171,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -170,7 +171,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
* @param mappingContext
*/
protected void setMappingContext(MappingContext<?, ?> mappingContext) {
this.mappingContext = Optional.of(mappingContext);
this.mappingContext = mappingContext;
}
/**
@ -180,7 +181,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -180,7 +181,7 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
* @since 3.4
*/
public void setEvaluationContextProvider(EvaluationContextProvider evaluationContextProvider) {
this.evaluationContextProvider = Optional.of(evaluationContextProvider);
this.evaluationContextProvider = evaluationContextProvider;
}
/**
@ -227,8 +228,8 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -227,8 +228,8 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
this.beanFactory = beanFactory;
if (this.evaluationContextProvider.isEmpty() && beanFactory instanceof ListableBeanFactory lbf) {
this.evaluationContextProvider = createDefaultEvaluationContextProvider(lbf);
if (this.evaluationContextProvider == null && beanFactory instanceof ListableBeanFactory lbf) {
this.evaluationContextProvider = createDefaultEvaluationContextProvider(lbf).orElse(null);
}
}
@ -278,8 +279,8 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -278,8 +279,8 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
@Override
public RepositoryInformation getRepositoryInformation() {
RepositoryFragments fragments = customImplementation.map(RepositoryFragments::just)//
.orElse(RepositoryFragments.empty());
RepositoryFragments fragments = customImplementation != null ? RepositoryFragments.just(customImplementation)
: RepositoryFragments.empty();
return factory.getRepositoryInformation(repositoryMetadata, fragments);
}
@ -287,8 +288,11 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -287,8 +288,11 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
@Override
public PersistentEntity<?, ?> getPersistentEntity() {
return mappingContext.orElseThrow(() -> new IllegalStateException("No MappingContext available"))
.getRequiredPersistentEntity(repositoryMetadata.getDomainType());
if (mappingContext == null) {
throw new IllegalStateException("No MappingContext available");
}
return mappingContext.getRequiredPersistentEntity(repositoryMetadata.getDomainType());
}
@Override
@ -312,40 +316,44 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, @@ -312,40 +316,44 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>,
public void afterPropertiesSet() {
this.factory = createRepositoryFactory();
this.factory.setExposeMetadata(exposeMetadata);
this.factory.setQueryLookupStrategyKey(queryLookupStrategyKey);
this.factory.setNamedQueries(namedQueries);
this.factory.setExposeMetadata(this.exposeMetadata);
this.factory.setQueryLookupStrategyKey(this.queryLookupStrategyKey);
this.factory.setNamedQueries(this.namedQueries);
this.factory.setEvaluationContextProvider(
evaluationContextProvider.orElse(QueryMethodValueEvaluationContextAccessor.DEFAULT_CONTEXT_PROVIDER));
this.factory.setBeanClassLoader(classLoader);
this.factory.setBeanFactory(beanFactory);
this.evaluationContextProvider != null ? this.evaluationContextProvider
: QueryMethodValueEvaluationContextAccessor.DEFAULT_CONTEXT_PROVIDER);
this.factory.setBeanClassLoader(this.classLoader);
this.factory.setBeanFactory(this.beanFactory);
if (this.publisher != null) {
this.factory.addRepositoryProxyPostProcessor(new EventPublishingRepositoryProxyPostProcessor(publisher));
this.factory.addRepositoryProxyPostProcessor(new EventPublishingRepositoryProxyPostProcessor(this.publisher));
}
if (this.environment != null) {
this.factory.setEnvironment(this.environment);
}
repositoryBaseClass.ifPresent(this.factory::setRepositoryBaseClass);
if (repositoryBaseClass != null) {
this.factory.setRepositoryBaseClass(this.repositoryBaseClass);
}
this.repositoryFactoryCustomizers.forEach(customizer -> customizer.customize(this.factory));
RepositoryFragments customImplementationFragment = customImplementation //
.map(RepositoryFragments::just) //
.orElseGet(RepositoryFragments::empty);
RepositoryFragments customImplementationFragment = customImplementation != null
? RepositoryFragments.just(customImplementation)
: RepositoryFragments.empty();
RepositoryFragments repositoryFragmentsToUse = this.repositoryFragments //
.orElseGet(RepositoryFragments::empty) //
.append(customImplementationFragment);
RepositoryFragments repositoryFragmentsToUse = this.repositoryFragments != null
? repositoryFragments.append(customImplementationFragment)
: customImplementationFragment;
this.repositoryMetadata = this.factory.getRepositoryMetadata(repositoryInterface);
this.repository = Lazy.of(() -> this.factory.getRepository(repositoryInterface, repositoryFragmentsToUse));
// Make sure the aggregate root type is present in the MappingContext (e.g. for auditing)
this.mappingContext.ifPresent(it -> it.getPersistentEntity(repositoryMetadata.getDomainType()));
if (this.mappingContext != null) {
this.mappingContext.getPersistentEntity(repositoryMetadata.getDomainType());
}
if (!lazyInit) {
this.repository.get();

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

@ -731,13 +731,11 @@ public abstract class RepositoryFactorySupport @@ -731,13 +731,11 @@ public abstract class RepositoryFactorySupport
*/
static class ImplementationMethodExecutionInterceptor implements MethodInterceptor {
private final RepositoryInformation information;
private final RepositoryComposition composition;
private final RepositoryInvocationMulticaster invocationMulticaster;
public ImplementationMethodExecutionInterceptor(RepositoryInformation information,
RepositoryComposition composition, List<RepositoryMethodInvocationListener> methodInvocationListeners) {
this.information = information;
this.composition = composition;
this.invocationMulticaster = methodInvocationListeners.isEmpty() ? NoOpRepositoryInvocationMulticaster.INSTANCE
: new DefaultRepositoryInvocationMulticaster(methodInvocationListeners);

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

@ -19,7 +19,6 @@ import java.util.ArrayList; @@ -19,7 +19,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -28,6 +27,7 @@ import org.springframework.data.domain.Sort; @@ -28,6 +27,7 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
@ -57,7 +57,7 @@ class OrderBySource { @@ -57,7 +57,7 @@ class OrderBySource {
* @param clause must not be {@literal null}.
*/
OrderBySource(String clause) {
this(clause, Optional.empty());
this(clause, null);
}
/**
@ -67,7 +67,7 @@ class OrderBySource { @@ -67,7 +67,7 @@ class OrderBySource {
* @param clause must not be {@literal null}.
* @param domainClass must not be {@literal null}.
*/
OrderBySource(String clause, Optional<Class<?>> domainClass) {
OrderBySource(String clause, @Nullable Class<?> domainClass) {
this.orders = new ArrayList<>();
@ -91,31 +91,25 @@ class OrderBySource { @@ -91,31 +91,25 @@ class OrderBySource {
throw new IllegalArgumentException(String.format(INVALID_ORDER_SYNTAX, part));
}
this.orders.add(createOrder(propertyString, Direction.fromOptionalString(directionString), domainClass));
this.orders
.add(createOrder(propertyString, Direction.fromOptionalString(directionString).orElse(null), domainClass));
}
}
/**
* Creates an {@link Order} instance from the given property source, direction and domain class. If the domain class
* is given, we will use it for nested property traversal checks.
*
* @param propertySource
* @param direction must not be {@literal null}.
* @param domainClass must not be {@literal null}.
* @return
* @see PropertyPath#from(String, Class)
*/
private Order createOrder(String propertySource, Optional<Direction> direction, Optional<Class<?>> domainClass) {
private Order createOrder(String propertySource, @Nullable Direction direction, @Nullable Class<?> domainClass) {
return domainClass.map(type -> {
String property = propertySource;
PropertyPath propertyPath = PropertyPath.from(propertySource, type);
return direction.map(it -> new Order(it, propertyPath.toDotPath()))
.orElseGet(() -> Order.by(propertyPath.toDotPath()));
if (domainClass != null) {
property = PropertyPath.from(propertySource, domainClass).toDotPath();
}
}).orElseGet(() -> direction//
.map(it -> new Order(it, StringUtils.uncapitalize(propertySource)))
.orElseGet(() -> Order.by(StringUtils.uncapitalize(propertySource))));
return direction != null ? new Order(direction, StringUtils.uncapitalize(property))
: Order.by(StringUtils.uncapitalize(property));
}
/**

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

@ -18,7 +18,6 @@ package org.springframework.data.repository.query.parser; @@ -18,7 +18,6 @@ package org.springframework.data.repository.query.parser;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -96,10 +95,10 @@ public class PartTree implements Streamable<OrPart> { @@ -96,10 +95,10 @@ public class PartTree implements Streamable<OrPart> {
Matcher matcher = PREFIX_TEMPLATE.matcher(source);
if (!matcher.find()) {
this.subject = new Subject(Optional.empty());
this.subject = new Subject();
this.predicate = new Predicate(source, domainClass);
} else {
this.subject = new Subject(Optional.of(matcher.group(0)));
this.subject = new Subject(matcher.group(0));
this.predicate = new Predicate(source.substring(matcher.group().length()), domainClass);
}
}
@ -157,7 +156,7 @@ public class PartTree implements Streamable<OrPart> { @@ -157,7 +156,7 @@ public class PartTree implements Streamable<OrPart> {
}
/**
* Return {@literal true} if the create {@link PartTree} is meant to be used for a query with limited maximal results.
* Return {@literal true} if the {@link PartTree} is meant to be used for a query with limited maximal results.
*
* @return
* @since 1.9
@ -174,7 +173,7 @@ public class PartTree implements Streamable<OrPart> { @@ -174,7 +173,7 @@ public class PartTree implements Streamable<OrPart> {
*/
@Nullable
public Integer getMaxResults() {
return subject.getMaxResults().orElse(null);
return subject.getMaxResults();
}
/**
@ -184,7 +183,9 @@ public class PartTree implements Streamable<OrPart> { @@ -184,7 +183,9 @@ public class PartTree implements Streamable<OrPart> {
* @since 3.2
*/
public Limit getResultLimit() {
return subject.getMaxResults().map(Limit::of).orElse(Limit.unlimited());
Integer maxResults = getMaxResults();
return maxResults != null ? Limit.of(maxResults) : Limit.unlimited();
}
/**
@ -261,6 +262,7 @@ public class PartTree implements Streamable<OrPart> { @@ -261,6 +262,7 @@ public class PartTree implements Streamable<OrPart> {
.collect(Collectors.toList());
}
@Override
public Iterator<Part> iterator() {
return children.iterator();
}
@ -294,11 +296,20 @@ public class PartTree implements Streamable<OrPart> { @@ -294,11 +296,20 @@ public class PartTree implements Streamable<OrPart> {
private final boolean count;
private final boolean exists;
private final boolean delete;
private final Optional<Integer> maxResults;
private final @Nullable Integer maxResults;
public Subject() {
this.distinct = false;
this.count = false;
this.exists = false;
this.delete = false;
this.maxResults = null;
}
public Subject(Optional<String> subject) {
public Subject(String subject) {
this.distinct = subject.map(it -> it.contains(DISTINCT)).orElse(false);
this.distinct = subject.contains(DISTINCT);
this.count = matches(subject, COUNT_BY_TEMPLATE);
this.exists = matches(subject, EXISTS_BY_TEMPLATE);
this.delete = matches(subject, DELETE_BY_TEMPLATE);
@ -310,19 +321,16 @@ public class PartTree implements Streamable<OrPart> { @@ -310,19 +321,16 @@ public class PartTree implements Streamable<OrPart> {
* @return
* @since 1.9
*/
private Optional<Integer> returnMaxResultsIfFirstKSubjectOrNull(Optional<String> subject) {
return subject.map(it -> {
@Nullable
private Integer returnMaxResultsIfFirstKSubjectOrNull(String subject) {
Matcher grp = LIMITED_QUERY_TEMPLATE.matcher(it);
Matcher grp = LIMITED_QUERY_TEMPLATE.matcher(subject);
if (!grp.find()) {
return null;
}
return StringUtils.hasText(grp.group(4)) ? Integer.valueOf(grp.group(4)) : 1;
});
if (!grp.find()) {
return null;
}
return StringUtils.hasText(grp.group(4)) ? Integer.parseInt(grp.group(4)) : 1;
}
/**
@ -353,12 +361,13 @@ public class PartTree implements Streamable<OrPart> { @@ -353,12 +361,13 @@ public class PartTree implements Streamable<OrPart> {
return distinct;
}
public Optional<Integer> getMaxResults() {
@Nullable
public Integer getMaxResults() {
return maxResults;
}
private boolean matches(Optional<String> subject, Pattern pattern) {
return subject.map(it -> pattern.matcher(it).find()).orElse(false);
private boolean matches(String subject, Pattern pattern) {
return pattern.matcher(subject).find();
}
}
@ -390,7 +399,7 @@ public class PartTree implements Streamable<OrPart> { @@ -390,7 +399,7 @@ public class PartTree implements Streamable<OrPart> {
.map(part -> new OrPart(part, domainClass, alwaysIgnoreCase)) //
.collect(Collectors.toList());
this.orderBySource = parts.length == 2 ? new OrderBySource(parts[1], Optional.of(domainClass))
this.orderBySource = parts.length == 2 ? new OrderBySource(parts[1], domainClass)
: OrderBySource.EMPTY;
}

22
src/main/java/org/springframework/data/repository/support/AnnotationAttribute.java

@ -17,7 +17,6 @@ package org.springframework.data.repository.support; @@ -17,7 +17,6 @@ package org.springframework.data.repository.support;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
@ -34,7 +33,7 @@ import org.springframework.util.Assert; @@ -34,7 +33,7 @@ import org.springframework.util.Assert;
class AnnotationAttribute {
private final Class<? extends Annotation> annotationType;
private final Optional<String> attributeName;
private final @Nullable String attributeName;
/**
* Creates a new {@link AnnotationAttribute} to the {@code value} attribute of the given {@link Annotation} type.
@ -42,13 +41,12 @@ class AnnotationAttribute { @@ -42,13 +41,12 @@ class AnnotationAttribute {
* @param annotationType must not be {@literal null}.
*/
public AnnotationAttribute(Class<? extends Annotation> annotationType) {
this(annotationType, Optional.empty());
this(annotationType, null);
}
public AnnotationAttribute(Class<? extends Annotation> annotationType, Optional<String> attributeName) {
public AnnotationAttribute(Class<? extends Annotation> annotationType, @Nullable String attributeName) {
Assert.notNull(annotationType, "Annotation type must not be null");
Assert.notNull(attributeName, "Attribute name must not be null");
this.annotationType = annotationType;
this.attributeName = attributeName;
@ -69,12 +67,13 @@ class AnnotationAttribute { @@ -69,12 +67,13 @@ class AnnotationAttribute {
* @param parameter must not be {@literal null}.
* @return
*/
public Optional<Object> getValueFrom(MethodParameter parameter) {
@Nullable
public Object getValueFrom(MethodParameter parameter) {
Assert.notNull(parameter, "MethodParameter must not be null");
Annotation annotation = parameter.getParameterAnnotation(annotationType);
return Optional.ofNullable(annotation).map(this::getValueFrom);
return annotation != null ? getValueFrom(annotation) : null;
}
/**
@ -83,12 +82,13 @@ class AnnotationAttribute { @@ -83,12 +82,13 @@ class AnnotationAttribute {
* @param annotatedElement must not be {@literal null}.
* @return
*/
public Optional<Object> getValueFrom(AnnotatedElement annotatedElement) {
@Nullable
public Object getValueFrom(AnnotatedElement annotatedElement) {
Assert.notNull(annotatedElement, "Annotated element must not be null");
Annotation annotation = annotatedElement.getAnnotation(annotationType);
return Optional.ofNullable(annotation).map(it -> getValueFrom(annotation));
return annotation != null ? getValueFrom(annotation) : null;
}
/**
@ -101,7 +101,7 @@ class AnnotationAttribute { @@ -101,7 +101,7 @@ class AnnotationAttribute {
public Object getValueFrom(Annotation annotation) {
Assert.notNull(annotation, "Annotation must not be null");
return attributeName.map(it -> AnnotationUtils.getValue(annotation, it))
.orElseGet(() -> AnnotationUtils.getValue(annotation));
return attributeName != null ? AnnotationUtils.getValue(annotation, attributeName)
: AnnotationUtils.getValue(annotation);
}
}

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

@ -47,7 +47,7 @@ class MethodParameters { @@ -47,7 +47,7 @@ class MethodParameters {
* @param method must not be {@literal null}.
*/
public MethodParameters(Method method) {
this(method, Optional.empty());
this(method, null);
}
/**
@ -57,7 +57,7 @@ class MethodParameters { @@ -57,7 +57,7 @@ class MethodParameters {
* @param method must not be {@literal null}.
* @param namingAnnotation must not be {@literal null}.
*/
public MethodParameters(Method method, Optional<AnnotationAttribute> namingAnnotation) {
public MethodParameters(Method method, @Nullable AnnotationAttribute namingAnnotation) {
Assert.notNull(method, "Method must not be null");
this.parameters = new ArrayList<>();
@ -132,7 +132,6 @@ class MethodParameters { @@ -132,7 +132,6 @@ class MethodParameters {
*/
private static class AnnotationNamingMethodParameter extends MethodParameter {
private final Optional<AnnotationAttribute> attribute;
private final Lazy<String> name;
/**
@ -143,20 +142,25 @@ class MethodParameters { @@ -143,20 +142,25 @@ class MethodParameters {
* @param parameterIndex
* @param attribute can be {@literal null}
*/
public AnnotationNamingMethodParameter(Method method, int parameterIndex, Optional<AnnotationAttribute> attribute) {
public AnnotationNamingMethodParameter(Method method, int parameterIndex, @Nullable AnnotationAttribute attribute) {
super(method, parameterIndex);
this.attribute = attribute;
this.name = Lazy.of(() -> this.attribute.//
flatMap(it -> it.getValueFrom(this).map(Object::toString)).//
orElseGet(super::getParameterName));
this.name = Lazy.of(() -> {
if (attribute == null) {
return super.getParameterName();
}
Object value = attribute.getValueFrom(this);
return value != null ? value.toString() : super.getParameterName();
});
}
@Nullable
@Override
public String getParameterName() {
return name.orElse(null);
return name.getNullable();
}
}
}

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

@ -159,7 +159,7 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker { @@ -159,7 +159,7 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker {
private Object[] prepareParameters(Method method, MultiValueMap<String, ?> rawParameters, Pageable pageable,
Sort sort) {
List<MethodParameter> parameters = new MethodParameters(method, Optional.of(PARAM_ANNOTATION)).getParameters();
List<MethodParameter> parameters = new MethodParameters(method, PARAM_ANNOTATION).getParameters();
if (parameters.isEmpty()) {
return new Object[0];

54
src/main/java/org/springframework/data/repository/support/Repositories.java

@ -37,6 +37,7 @@ import org.springframework.data.repository.core.RepositoryInformation; @@ -37,6 +37,7 @@ import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.support.RepositoryFactoryInformation;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.util.ProxyUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentLruCache;
@ -58,7 +59,7 @@ public class Repositories implements Iterable<Class<?>> { @@ -58,7 +59,7 @@ public class Repositories implements Iterable<Class<?>> {
private static final RepositoryFactoryInformation<Object, Object> EMPTY_REPOSITORY_FACTORY_INFO = EmptyRepositoryFactoryInformation.INSTANCE;
private static final String DOMAIN_TYPE_MUST_NOT_BE_NULL = "Domain type must not be null";
private final Optional<BeanFactory> beanFactory;
private final @Nullable BeanFactory beanFactory;
private final Map<Class<?>, String> repositoryBeanNames;
private final Map<Class<?>, RepositoryFactoryInformation<Object, Object>> repositoryFactoryInfos;
private final ConcurrentLruCache<Class<?>, Class<?>> domainTypeMapping = new ConcurrentLruCache<>(64,
@ -69,7 +70,7 @@ public class Repositories implements Iterable<Class<?>> { @@ -69,7 +70,7 @@ public class Repositories implements Iterable<Class<?>> {
*/
private Repositories() {
this.beanFactory = Optional.empty();
this.beanFactory = null;
this.repositoryBeanNames = Collections.emptyMap();
this.repositoryFactoryInfos = Collections.emptyMap();
}
@ -84,7 +85,7 @@ public class Repositories implements Iterable<Class<?>> { @@ -84,7 +85,7 @@ public class Repositories implements Iterable<Class<?>> {
Assert.notNull(factory, "ListableBeanFactory must not be null");
this.beanFactory = Optional.of(factory);
this.beanFactory = factory;
this.repositoryFactoryInfos = new HashMap<>();
this.repositoryBeanNames = new HashMap<>();
@ -113,22 +114,25 @@ public class Repositories implements Iterable<Class<?>> { @@ -113,22 +114,25 @@ public class Repositories implements Iterable<Class<?>> {
typesToRegister.add(domainType);
typesToRegister.addAll(alternativeDomainTypes);
Optional<ConfigurableListableBeanFactory> beanFactory = Optional.of(factory).map(it -> {
ConfigurableListableBeanFactory beanFactory = getBeanFactory(factory);
if (it instanceof ConfigurableListableBeanFactory) {
return (ConfigurableListableBeanFactory) it;
}
for (Class<?> type : typesToRegister) {
cacheFirstOrPrimary(beanFactory, type, repositoryFactoryInformation, BeanFactoryUtils.transformedBeanName(name));
}
}
if (it instanceof ConfigurableApplicationContext) {
return ((ConfigurableApplicationContext) it).getBeanFactory();
}
@Nullable
private static ConfigurableListableBeanFactory getBeanFactory(ListableBeanFactory beanFactory) {
return null;
});
if (beanFactory instanceof ConfigurableListableBeanFactory clbf) {
return clbf;
}
for (Class<?> type : typesToRegister) {
cacheFirstOrPrimary(beanFactory, type, repositoryFactoryInformation, BeanFactoryUtils.transformedBeanName(name));
if (beanFactory instanceof ConfigurableApplicationContext cac) {
return cac.getBeanFactory();
}
return null;
}
/**
@ -159,9 +163,13 @@ public class Repositories implements Iterable<Class<?>> { @@ -159,9 +163,13 @@ public class Repositories implements Iterable<Class<?>> {
Assert.notNull(domainClass, DOMAIN_TYPE_MUST_NOT_BE_NULL);
Class<?> userClass = domainTypeMapping.get(ProxyUtils.getUserClass(domainClass));
Optional<String> repositoryBeanName = Optional.ofNullable(repositoryBeanNames.get(userClass));
String repositoryBeanName = repositoryBeanNames.get(userClass);
if (beanFactory == null || repositoryBeanName == null) {
return Optional.empty();
}
return beanFactory.flatMap(it -> repositoryBeanName.map(it::getBean));
return Optional.of(beanFactory.getBean(repositoryBeanName));
}
/**
@ -301,16 +309,14 @@ public class Repositories implements Iterable<Class<?>> { @@ -301,16 +309,14 @@ public class Repositories implements Iterable<Class<?>> {
* @param name must not be {@literal null}.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private void cacheFirstOrPrimary(Optional<ConfigurableListableBeanFactory> beanFactory, Class<?> type,
private void cacheFirstOrPrimary(@Nullable ConfigurableListableBeanFactory beanFactory, Class<?> type,
RepositoryFactoryInformation information, String name) {
if (repositoryBeanNames.containsKey(type)) {
if (repositoryBeanNames.containsKey(type) && beanFactory != null) {
Boolean presentAndPrimary = beanFactory.map(it -> it.getMergedBeanDefinition(name)) //
.map(BeanDefinition::isPrimary) //
.orElse(false);
BeanDefinition bd = beanFactory.getMergedBeanDefinition(name);
if (!presentAndPrimary) {
if (!bd.isPrimary()) {
return;
}
}
@ -321,8 +327,8 @@ public class Repositories implements Iterable<Class<?>> { @@ -321,8 +327,8 @@ public class Repositories implements Iterable<Class<?>> {
/**
* Returns the repository domain type for which to look up the repository. The input can either be a repository
* managed type directly. Or it can be a sub-type of a repository managed one, in which case we check the domain types
* we have repositories registered for for assignability.
* managed type directly. Or it can be a subtype of a repository managed one, in which case we check the domain types
* we have repositories registered for assignability.
*
* @param domainType must not be {@literal null}.
* @return

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

@ -23,7 +23,6 @@ import reactor.core.publisher.Mono; @@ -23,7 +23,6 @@ import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import org.reactivestreams.Publisher;
@ -191,15 +190,25 @@ public abstract class ReactiveWrapperConverters { @@ -191,15 +190,25 @@ public abstract class ReactiveWrapperConverters {
Assert.notNull(reactiveObject, "Reactive source object must not be null");
Assert.notNull(converter, "Converter must not be null");
return getFirst(reactiveObject)//
.map(it -> (T) it.map(reactiveObject, converter))//
.orElseThrow(() -> new IllegalStateException(String.format("Cannot apply converter to %s", reactiveObject)));
ReactiveTypeWrapper<?> wrapper = getFirst(reactiveObject);
if (wrapper == null) {
throw new IllegalStateException(String.format("Cannot apply converter to %s", reactiveObject));
}
return (T) wrapper.map(reactiveObject, converter);
}
private static Optional<ReactiveTypeWrapper<?>> getFirst(Object reactiveObject) {
return REACTIVE_WRAPPERS.stream()//
.filter(it -> ClassUtils.isAssignable(it.getWrapperClass(), reactiveObject.getClass()))//
.findFirst();
@Nullable
private static ReactiveTypeWrapper<?> getFirst(Object reactiveObject) {
for (ReactiveTypeWrapper<?> it : REACTIVE_WRAPPERS) {
if (ClassUtils.isAssignable(it.getWrapperClass(), reactiveObject.getClass())) {
return it;
}
}
return null;
}
/**

20
src/main/java/org/springframework/data/util/StreamUtils.java

@ -111,6 +111,26 @@ public interface StreamUtils { @@ -111,6 +111,26 @@ public interface StreamUtils {
return source == null ? Stream.empty() : Stream.of(source);
}
/**
* Creates a new {@link Stream} for the given values by considering non-null values only.
*
* @param source elements to create a {@link Stream} for.
* @return a new {@link Stream} for the given non-null values. Any {@literal null} value are skipped.
* @since 4.0
*/
static <T> Stream<T> fromNullable(@Nullable T... source) {
Stream.Builder<T> builder = Stream.builder();
for (T element : source) {
if (element != null) {
builder.add(element);
}
}
return builder.build();
}
/**
* Zips the given {@link Stream}s using the given {@link BiFunction}. The resulting {@link Stream} will have the
* length of the shorter of the two, abbreviating the zipping when the shorter of the two {@link Stream}s is

11
src/test/java/org/springframework/data/mapping/model/PropertyUnitTests.java

@ -33,10 +33,11 @@ class PropertyUnitTests { @@ -33,10 +33,11 @@ class PropertyUnitTests {
assertThat(Property
.of(TypeInformation.of(ImmutableType.class), ReflectionUtils.findField(ImmutableType.class, "id")).getWither())
.isEmpty();
.isNull();
assertThat(
Property.of(TypeInformation.of(ImmutableType.class), ReflectionUtils.findField(ImmutableType.class, "name"))
.getWither()).isEmpty();
.getWither())
.isNull();
}
@Test // DATACMNS-1322
@ -44,7 +45,7 @@ class PropertyUnitTests { @@ -44,7 +45,7 @@ class PropertyUnitTests {
var property = Property.of(TypeInformation.of(WitherType.class), ReflectionUtils.findField(WitherType.class, "id"));
assertThat(property.getWither()).isPresent().hasValueSatisfying(actual -> {
assertThat(property.getWither()).satisfies(actual -> {
assertThat(actual.getName()).isEqualTo("withId");
assertThat(actual.getReturnType()).isEqualTo(WitherType.class);
});
@ -56,7 +57,7 @@ class PropertyUnitTests { @@ -56,7 +57,7 @@ class PropertyUnitTests {
var property = Property.of(TypeInformation.of(DerivedWitherClass.class),
ReflectionUtils.findField(DerivedWitherClass.class, "id"));
assertThat(property.getWither()).isPresent().hasValueSatisfying(actual -> {
assertThat(property.getWither()).satisfies(actual -> {
assertThat(actual.getName()).isEqualTo("withId");
assertThat(actual.getReturnType()).isEqualTo(DerivedWitherClass.class);
assertThat(actual.getDeclaringClass()).isEqualTo(DerivedWitherClass.class);
@ -69,7 +70,7 @@ class PropertyUnitTests { @@ -69,7 +70,7 @@ class PropertyUnitTests {
var property = Property.of(TypeInformation.of(AnotherLevel.class),
ReflectionUtils.findField(AnotherLevel.class, "id"));
assertThat(property.getWither()).isEmpty();
assertThat(property.getWither()).isNull();
}
static class ImmutableType {

4
src/test/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactoryUnitTests.java

@ -64,7 +64,7 @@ class QuerydslBindingsFactoryUnitTests { @@ -64,7 +64,7 @@ class QuerydslBindingsFactoryUnitTests {
when(repositories.getRepositoryFor(User.class)).thenReturn(Optional.of(new SampleRepo()));
var factory = new QuerydslBindingsFactory(SimpleEntityPathResolver.INSTANCE);
ReflectionTestUtils.setField(factory, "repositories", Optional.of(repositories));
ReflectionTestUtils.setField(factory, "repositories", repositories);
var bindings = factory.createBindingsFor(USER_TYPE);
Optional<MultiValueBinding<Path<Object>, Object>> binding = bindings
@ -84,7 +84,7 @@ class QuerydslBindingsFactoryUnitTests { @@ -84,7 +84,7 @@ class QuerydslBindingsFactoryUnitTests {
when(beanFactory.getBean(SpecificBinding.class)).thenReturn(new SpecificBinding());
var factory = new QuerydslBindingsFactory(SimpleEntityPathResolver.INSTANCE);
ReflectionTestUtils.setField(factory, "beanFactory", Optional.of(beanFactory));
ReflectionTestUtils.setField(factory, "beanFactory", beanFactory);
var bindings = factory.createBindingsFor(USER_TYPE, SpecificBinding.class);
Optional<MultiValueBinding<Path<Object>, Object>> binding = bindings

2
src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java

@ -147,7 +147,7 @@ class CdiRepositoryBeanUnitTests { @@ -147,7 +147,7 @@ class CdiRepositoryBeanUnitTests {
var detector = mock(CustomRepositoryImplementationDetector.class);
var bean = new CdiRepositoryBean<SampleRepository>(SINGLE_ANNOTATION,
SampleRepository.class, beanManager, Optional.of(detector)) {
SampleRepository.class, beanManager, detector) {
@Override
protected SampleRepository create(CreationalContext<SampleRepository> creationalContext,

6
src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java

@ -25,11 +25,11 @@ import java.lang.annotation.Annotation; @@ -25,11 +25,11 @@ import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Optional;
import java.util.Set;
import org.apache.webbeans.context.AbstractContext;
import org.mockito.Mockito;
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
import org.springframework.data.repository.core.support.DummyRepositoryFactory;
@ -50,7 +50,7 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport { @@ -50,7 +50,7 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport {
for (var type : getRepositoryTypes()) {
var bean = new DummyCdiRepositoryBean(type.getValue(), type.getKey(), beanManager,
Optional.of(getCustomImplementationDetector()));
getCustomImplementationDetector());
registerBean(bean);
afterBeanDiscovery.addBean(bean);
}
@ -63,7 +63,7 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport { @@ -63,7 +63,7 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport {
}
DummyCdiRepositoryBean(Set<Annotation> qualifiers, Class<T> repositoryType, BeanManager beanManager,
Optional<CustomRepositoryImplementationDetector> detector) {
CustomRepositoryImplementationDetector detector) {
super(qualifiers, repositoryType, beanManager, detector);
}

13
src/test/java/org/springframework/data/repository/config/SelectionSetUnitTests.java

@ -19,8 +19,6 @@ import static java.util.Arrays.*; @@ -19,8 +19,6 @@ import static java.util.Arrays.*;
import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*;
import java.util.Optional;
import org.junit.jupiter.api.Test;
/**
@ -33,12 +31,12 @@ class SelectionSetUnitTests { @@ -33,12 +31,12 @@ class SelectionSetUnitTests {
@Test // DATACMNS-764
void returnsUniqueResult() {
assertThat(SelectionSet.of(singleton("single value")).uniqueResult()).hasValue("single value");
assertThat(SelectionSet.of(singleton("single value")).uniqueResult()).isEqualTo("single value");
}
@Test // DATACMNS-764
void emptyCollectionReturnsNull() {
assertThat(SelectionSet.of(emptySet()).uniqueResult()).isEmpty();
assertThat(SelectionSet.of(emptySet()).uniqueResult()).isNull();
}
@Test // DATACMNS-764
@ -58,8 +56,7 @@ class SelectionSetUnitTests { @@ -58,8 +56,7 @@ class SelectionSetUnitTests {
@Test // DATACMNS-764
void usesFallbackWhenConfigured() {
assertThat(SelectionSet.of(asList("one", "two"), c -> Optional.of(String.valueOf(c.size()))).uniqueResult())
.hasValue("2");
assertThat(SelectionSet.of(asList("one", "two"), c -> String.valueOf(c.size())).uniqueResult()).isEqualTo("2");
}
@Test // DATACMNS-764
@ -68,7 +65,7 @@ class SelectionSetUnitTests { @@ -68,7 +65,7 @@ class SelectionSetUnitTests {
var selection = SelectionSet.of(asList("one", "two", "three"))
.filterIfNecessary(s -> s.contains("w"));
assertThat(selection.uniqueResult()).hasValue("two");
assertThat(selection.uniqueResult()).isEqualTo("two");
}
@Test // DATACMNS-764
@ -76,6 +73,6 @@ class SelectionSetUnitTests { @@ -76,6 +73,6 @@ class SelectionSetUnitTests {
var selection = SelectionSet.of(asList("one")).filterIfNecessary(s -> s.contains("w"));
assertThat(selection.uniqueResult()).hasValue("one");
assertThat(selection.uniqueResult()).isEqualTo("one");
}
}

5
src/test/java/org/springframework/data/repository/query/parser/OrderBySourceUnitTests.java

@ -17,9 +17,8 @@ package org.springframework.data.repository.query.parser; @@ -17,9 +17,8 @@ package org.springframework.data.repository.query.parser;
import static org.assertj.core.api.Assertions.*;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Sort;
/**
@ -54,7 +53,7 @@ class OrderBySourceUnitTests { @@ -54,7 +53,7 @@ class OrderBySourceUnitTests {
@Test
void usesNestedPropertyCorrectly() throws Exception {
var source = new OrderBySource("BarNameDesc", Optional.of(Foo.class));
var source = new OrderBySource("BarNameDesc", Foo.class);
assertThat(source.toSort()).isEqualTo(Sort.by("bar.name").descending());
}

7
src/test/java/org/springframework/data/repository/support/AnnotationAttributeUnitTests.java

@ -17,9 +17,8 @@ package org.springframework.data.repository.support; @@ -17,9 +17,8 @@ package org.springframework.data.repository.support;
import static org.assertj.core.api.Assertions.*;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Component;
/**
@ -36,14 +35,14 @@ class AnnotationAttributeUnitTests { @@ -36,14 +35,14 @@ class AnnotationAttributeUnitTests {
@Test // DATACMNS-607
void rejectsNullAnnotationTypeForAnnotationAndAttributeName() {
assertThatIllegalArgumentException().isThrownBy(() -> new AnnotationAttribute(null, Optional.of("name")));
assertThatIllegalArgumentException().isThrownBy(() -> new AnnotationAttribute(null, "name"));
}
@Test // DATACMNS-607
void looksUpAttributeFromAnnotatedElement() {
var attribute = new AnnotationAttribute(Component.class);
assertThat(attribute.getValueFrom(Sample.class)).hasValue("foo");
assertThat(attribute.getValueFrom(Sample.class)).isEqualTo("foo");
}
@Component("foo")

5
src/test/java/org/springframework/data/repository/support/MethodParametersUnitTests.java

@ -17,9 +17,8 @@ package org.springframework.data.repository.support; @@ -17,9 +17,8 @@ package org.springframework.data.repository.support;
import static org.assertj.core.api.Assertions.*;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
/**
@ -33,7 +32,7 @@ class MethodParametersUnitTests { @@ -33,7 +32,7 @@ class MethodParametersUnitTests {
void prefersAnnotatedParameterOverDiscovered() throws Exception {
var method = Sample.class.getMethod("method", String.class, String.class, Object.class);
var parameters = new MethodParameters(method, Optional.of(new AnnotationAttribute(Qualifier.class)));
var parameters = new MethodParameters(method, new AnnotationAttribute(Qualifier.class));
assertThat(parameters.getParameter("param")).isPresent();
assertThat(parameters.getParameter("foo")).isPresent();

Loading…
Cancel
Save