diff --git a/pom.xml b/pom.xml index cdd68fe2d4..80cb96801c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-commons - 3.5.0-SNAPSHOT + 3.5.0-GH-3195-SNAPSHOT Spring Data Core Core Spring concepts underpinning every Spring Data module. diff --git a/src/main/java/org/springframework/data/annotation/AccessType.java b/src/main/java/org/springframework/data/annotation/AccessType.java index 53d97b65ee..180ac09ee3 100644 --- a/src/main/java/org/springframework/data/annotation/AccessType.java +++ b/src/main/java/org/springframework/data/annotation/AccessType.java @@ -34,8 +34,6 @@ /** * The access type to be used. - * - * @return */ Type value(); diff --git a/src/main/java/org/springframework/data/annotation/PersistenceCreator.java b/src/main/java/org/springframework/data/annotation/PersistenceCreator.java index 53616aec42..69e64a5ccc 100644 --- a/src/main/java/org/springframework/data/annotation/PersistenceCreator.java +++ b/src/main/java/org/springframework/data/annotation/PersistenceCreator.java @@ -29,4 +29,5 @@ */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) -public @interface PersistenceCreator {} +public @interface PersistenceCreator { +} diff --git a/src/main/java/org/springframework/data/annotation/Reference.java b/src/main/java/org/springframework/data/annotation/Reference.java index d29d86b615..74c43e1117 100644 --- a/src/main/java/org/springframework/data/annotation/Reference.java +++ b/src/main/java/org/springframework/data/annotation/Reference.java @@ -36,8 +36,6 @@ /** * Explicitly define the target type of the reference. Used in case the annotated property is not the target type but * rather an identifier and/or if that identifier type is not uniquely identifying the target entity. - * - * @return */ @AliasFor(attribute = "to") Class value() default Class.class; @@ -45,8 +43,6 @@ /** * Explicitly define the target type of the reference. Used in case the annotated property is not the target type but * rather an identifier and/or if that identifier type is not uniquely identifying the target entity. - * - * @return */ @AliasFor(attribute = "value") Class to() default Class.class; diff --git a/src/main/java/org/springframework/data/annotation/TypeAlias.java b/src/main/java/org/springframework/data/annotation/TypeAlias.java index 782ac9c1e1..186187902f 100644 --- a/src/main/java/org/springframework/data/annotation/TypeAlias.java +++ b/src/main/java/org/springframework/data/annotation/TypeAlias.java @@ -29,6 +29,7 @@ * {@link PersistentEntity}s. * * @author Oliver Gierke + * @see org.springframework.data.mapping.Alias */ @Documented @Inherited @@ -38,9 +39,7 @@ public @interface TypeAlias { /** - * The type alias to be used when persisting - * - * @return + * The type alias to be used when persisting. */ String value(); } diff --git a/src/main/java/org/springframework/data/annotation/Version.java b/src/main/java/org/springframework/data/annotation/Version.java index 45b3fbc485..c66342af18 100644 --- a/src/main/java/org/springframework/data/annotation/Version.java +++ b/src/main/java/org/springframework/data/annotation/Version.java @@ -33,5 +33,4 @@ @Retention(RUNTIME) @Target(value = { FIELD, METHOD, ANNOTATION_TYPE }) public @interface Version { - } diff --git a/src/main/java/org/springframework/data/aot/AotContext.java b/src/main/java/org/springframework/data/aot/AotContext.java index 6e55a3bcdf..4d51343a54 100644 --- a/src/main/java/org/springframework/data/aot/AotContext.java +++ b/src/main/java/org/springframework/data/aot/AotContext.java @@ -140,7 +140,7 @@ default Set> scanPackageForTypes(Collection } /** - * Returns a {@link IntrospectedBeanDefinition} to obtain further detail about the underlying bean definition. A + * Returns a {@link IntrospectedBeanDefinition} to obtain further detail about the underlying bean definition. An * introspected bean definition can also point to an absent bean definition. * * @param reference {@link BeanReference} to the managed bean. @@ -151,7 +151,7 @@ default IntrospectedBeanDefinition introspectBeanDefinition(BeanReference refere } /** - * Returns a {@link IntrospectedBeanDefinition} to obtain further detail about the underlying bean definition. A + * Returns a {@link IntrospectedBeanDefinition} to obtain further detail about the underlying bean definition. An * introspected bean definition can also point to an absent bean definition. * * @param beanName {@link String} containing the {@literal name} of the bean to evaluate; must not be {@literal null}. @@ -251,7 +251,6 @@ interface IntrospectedBeanDefinition { * bean}. * @see BeanDefinition */ - BeanDefinition getBeanDefinition() throws NoSuchBeanDefinitionException; /** diff --git a/src/main/java/org/springframework/data/aot/AuditingBeanRegistrationAotProcessor.java b/src/main/java/org/springframework/data/aot/AuditingBeanRegistrationAotProcessor.java index cfcce1126a..14eb91a08b 100644 --- a/src/main/java/org/springframework/data/aot/AuditingBeanRegistrationAotProcessor.java +++ b/src/main/java/org/springframework/data/aot/AuditingBeanRegistrationAotProcessor.java @@ -39,7 +39,6 @@ */ class AuditingBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor { - @Nullable @Override public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { diff --git a/src/main/java/org/springframework/data/aot/ManagedTypesBeanFactoryInitializationAotProcessor.java b/src/main/java/org/springframework/data/aot/ManagedTypesBeanFactoryInitializationAotProcessor.java index 7e3689c4ac..620b671bd3 100644 --- a/src/main/java/org/springframework/data/aot/ManagedTypesBeanFactoryInitializationAotProcessor.java +++ b/src/main/java/org/springframework/data/aot/ManagedTypesBeanFactoryInitializationAotProcessor.java @@ -29,6 +29,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.data.domain.ManagedTypes; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; @@ -44,10 +45,11 @@ */ public class ManagedTypesBeanFactoryInitializationAotProcessor implements BeanFactoryInitializationAotProcessor { - private static final Log logger = LogFactory.getLog(BeanFactoryInitializationAotProcessor.class); + private static final Log logger = LogFactory.getLog(ManagedTypesBeanFactoryInitializationAotProcessor.class); - @Nullable @Override + @Nullable + @Contract("_ -> null") public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { processManagedTypes(beanFactory); @@ -71,9 +73,9 @@ private void postProcessManagedTypes(ConfigurableListableBeanFactory beanFactory if (hasConstructorArguments(beanDefinition)) { - ValueHolder argumentValue = beanDefinition.getConstructorArgumentValues().getArgumentValue(0, null, null, null); + ValueHolder holder = beanDefinition.getConstructorArgumentValues().getArgumentValue(0, null, null, null); - if (argumentValue.getValue()instanceof Supplier supplier) { + if (holder != null && holder.getValue() instanceof Supplier supplier) { if (logger.isDebugEnabled()) { logger.info(String.format("Replacing ManagedType bean definition %s.", beanName)); diff --git a/src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java b/src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java index 72451b862b..d684545fa5 100644 --- a/src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java +++ b/src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java @@ -78,9 +78,9 @@ private ManagedTypes resolveManagedTypes(RegisteredBean registeredBean) { if (beanDefinition.hasConstructorArgumentValues()) { ValueHolder indexedArgumentValue = beanDefinition.getConstructorArgumentValues().getIndexedArgumentValue(0, null); - Object value = indexedArgumentValue.getValue(); - if (value instanceof Collection values && values.stream().allMatch(it -> it instanceof Class)) { + if (indexedArgumentValue != null && indexedArgumentValue.getValue() instanceof Collection values + && values.stream().allMatch(it -> it instanceof Class)) { return ManagedTypes.fromIterable((Collection>) values); } } @@ -115,7 +115,6 @@ private ManagedTypes resolveManagedTypes(RegisteredBean registeredBean) { * @param managedTypes never {@literal null}. * @return new instance of {@link BeanRegistrationAotContribution} or {@literal null} if nothing to do. */ - @Nullable protected BeanRegistrationAotContribution contribute(AotContext aotContext, ManagedTypes managedTypes, RegisteredBean registeredBean) { return new ManagedTypesRegistrationAotContribution(managedTypes, registeredBean, this::contributeType); diff --git a/src/main/java/org/springframework/data/aot/ManagedTypesRegistrationAotContribution.java b/src/main/java/org/springframework/data/aot/ManagedTypesRegistrationAotContribution.java index 4b800afc51..1c63d73cfe 100644 --- a/src/main/java/org/springframework/data/aot/ManagedTypesRegistrationAotContribution.java +++ b/src/main/java/org/springframework/data/aot/ManagedTypesRegistrationAotContribution.java @@ -15,7 +15,6 @@ */ package org.springframework.data.aot; -import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.util.Collections; import java.util.List; @@ -69,8 +68,8 @@ * @author John Blum * @author Christoph Strobl * @author Mark Paluch - * @see org.springframework.beans.factory.aot.BeanRegistrationAotContribution * @since 3.0 + * @see org.springframework.beans.factory.aot.BeanRegistrationAotContribution */ class ManagedTypesRegistrationAotContribution implements RegisteredBeanAotContribution { @@ -126,7 +125,7 @@ static class ManagedTypesInstanceCodeFragment extends BeanRegistrationCodeFragme public static final ResolvableType MANAGED_TYPES_TYPE = ResolvableType.forType(ManagedTypes.class); private final List> sourceTypes; private final RegisteredBean source; - private final Lazy instanceMethod = Lazy.of(this::findInstanceFactory); + private final Lazy instanceMethod; private static final TypeName WILDCARD = WildcardTypeName.subtypeOf(Object.class); private static final TypeName CLASS_OF_ANY = ParameterizedTypeName.get(ClassName.get(Class.class), WILDCARD); @@ -139,6 +138,7 @@ protected ManagedTypesInstanceCodeFragment(List> sourceTypes, Registere this.sourceTypes = sourceTypes; this.source = source; + this.instanceMethod = Lazy.of(() -> findInstanceFactory(source.getBeanClass())); } @Override @@ -230,15 +230,15 @@ private CodeBlock toCodeBlock(List> values, boolean allPublic) { } @Nullable - private Method findInstanceFactory() { + private static Method findInstanceFactory(Class beanClass) { - for (Method beanMethod : ReflectionUtils.getDeclaredMethods(source.getBeanClass())) { + for (Method beanMethod : ReflectionUtils.getDeclaredMethods(beanClass)) { if (!isInstanceFactory(beanMethod)) { continue; } - ResolvableType parameterType = ResolvableType.forMethodParameter(beanMethod, 0, source.getBeanClass()); + ResolvableType parameterType = ResolvableType.forMethodParameter(beanMethod, 0, beanClass); if (parameterType.isAssignableFrom(LIST_TYPE) || parameterType.isAssignableFrom(MANAGED_TYPES_TYPE)) { return beanMethod; diff --git a/src/main/java/org/springframework/data/aot/PublicMethodReflectiveProcessor.java b/src/main/java/org/springframework/data/aot/PublicMethodReflectiveProcessor.java index d4384f506c..8eb3749209 100644 --- a/src/main/java/org/springframework/data/aot/PublicMethodReflectiveProcessor.java +++ b/src/main/java/org/springframework/data/aot/PublicMethodReflectiveProcessor.java @@ -20,6 +20,8 @@ import org.springframework.aot.hint.annotation.SimpleReflectiveProcessor; /** + * Extension to {@link SimpleReflectiveProcessor} to register reflective hints for invoking public methods. + * * @author Christoph Strobl */ public class PublicMethodReflectiveProcessor extends SimpleReflectiveProcessor { diff --git a/src/main/java/org/springframework/data/aot/RegisteredBeanAotContribution.java b/src/main/java/org/springframework/data/aot/RegisteredBeanAotContribution.java index fb964ee3a8..c8b7015e7e 100644 --- a/src/main/java/org/springframework/data/aot/RegisteredBeanAotContribution.java +++ b/src/main/java/org/springframework/data/aot/RegisteredBeanAotContribution.java @@ -19,7 +19,7 @@ import org.springframework.beans.factory.support.RegisteredBean; /** - * Extension to {@link BeanRegistrationAotContribution} that bases its contribution on a {@link RegisteredBean}. This + * Extension to {@link BeanRegistrationAotContribution} that bases its contribution to a {@link RegisteredBean}. This * interface exposes its {@link #getSource() source}. * * @author Christoph Strobl diff --git a/src/main/java/org/springframework/data/auditing/AuditableBeanWrapper.java b/src/main/java/org/springframework/data/auditing/AuditableBeanWrapper.java index 5be682e9e8..251145674d 100644 --- a/src/main/java/org/springframework/data/auditing/AuditableBeanWrapper.java +++ b/src/main/java/org/springframework/data/auditing/AuditableBeanWrapper.java @@ -18,6 +18,9 @@ import java.time.temporal.TemporalAccessor; import java.util.Optional; +import org.springframework.lang.Contract; +import org.springframework.lang.Nullable; + /** * Interface to abstract the ways setting the auditing information can be implemented. * @@ -31,7 +34,9 @@ public interface AuditableBeanWrapper { * * @param value */ - Object setCreatedBy(Object value); + @Nullable + @Contract("null -> null; !null -> !null") + Object setCreatedBy(@Nullable Object value); /** * Set the date the object was created. @@ -45,7 +50,9 @@ public interface AuditableBeanWrapper { * * @param value */ - Object setLastModifiedBy(Object value); + @Nullable + @Contract("null -> null; !null -> !null") + Object setLastModifiedBy(@Nullable Object value); /** * Returns the date of the last modification date of the backing bean. diff --git a/src/main/java/org/springframework/data/auditing/AuditingHandler.java b/src/main/java/org/springframework/data/auditing/AuditingHandler.java index 91f7fd3ef1..3c553593ea 100644 --- a/src/main/java/org/springframework/data/auditing/AuditingHandler.java +++ b/src/main/java/org/springframework/data/auditing/AuditingHandler.java @@ -104,9 +104,10 @@ Auditor getAuditor() { .orElse(Auditor.none()); } + @Override public void afterPropertiesSet() { - if (!auditorAware.isPresent()) { + if (auditorAware.isEmpty()) { logger.debug("No AuditorAware set; Auditing will not be applied"); } } diff --git a/src/main/java/org/springframework/data/auditing/AuditingHandlerSupport.java b/src/main/java/org/springframework/data/auditing/AuditingHandlerSupport.java index 489a2e6457..3a3fa438d3 100644 --- a/src/main/java/org/springframework/data/auditing/AuditingHandlerSupport.java +++ b/src/main/java/org/springframework/data/auditing/AuditingHandlerSupport.java @@ -151,11 +151,6 @@ private T touch(Auditor auditor, T target, boolean isNew) { /** * Sets modifying and creating auditor. Creating auditor is only set on new auditables. - * - * @param auditor - * @param wrapper - * @param isNew - * @return */ private void touchAuditor(Auditor auditor, AuditableBeanWrapper wrapper, boolean isNew) { @@ -176,10 +171,6 @@ private void touchAuditor(Auditor auditor, AuditableBeanWrapper wrapper, b /** * Touches the auditable regarding modification and creation date. Creation date is only set on new auditables. - * - * @param wrapper - * @param isNew - * @return */ private Optional touchDate(AuditableBeanWrapper wrapper, boolean isNew) { diff --git a/src/main/java/org/springframework/data/auditing/Auditor.java b/src/main/java/org/springframework/data/auditing/Auditor.java index 2c6f775e6d..d9c2427bc4 100644 --- a/src/main/java/org/springframework/data/auditing/Auditor.java +++ b/src/main/java/org/springframework/data/auditing/Auditor.java @@ -28,7 +28,7 @@ */ class Auditor { - private static final Auditor NONE = new Auditor(null) { + private static final Auditor NONE = new Auditor<>(null) { @Override public boolean isPresent() { @@ -59,6 +59,7 @@ public T getValue() { * @param * @return {@link Auditor#none()} if the given {@literal source} is {@literal null}. } */ + @SuppressWarnings({ "unchecked", "rawtypes" }) public static Auditor of(@Nullable T source) { if (source instanceof Auditor) { @@ -77,7 +78,7 @@ public static Auditor of(@Nullable T source) { * @param * @return {@link Auditor#none()} if the given {@literal source} is {@literal null}. } */ - public static Auditor ofOptional(@Nullable Optional source) { + public static Auditor ofOptional(Optional source) { return Auditor.of(source.orElse(null)); } @@ -87,8 +88,9 @@ public static Auditor ofOptional(@Nullable Optional source) { * @param * @return never {@literal null}. */ + @SuppressWarnings("unchecked") public static Auditor none() { - return NONE; + return (Auditor) NONE; } /** diff --git a/src/main/java/org/springframework/data/auditing/DefaultAuditableBeanWrapperFactory.java b/src/main/java/org/springframework/data/auditing/DefaultAuditableBeanWrapperFactory.java index c7e260e78e..0a1d18150b 100644 --- a/src/main/java/org/springframework/data/auditing/DefaultAuditableBeanWrapperFactory.java +++ b/src/main/java/org/springframework/data/auditing/DefaultAuditableBeanWrapperFactory.java @@ -115,7 +115,7 @@ public AuditableInterfaceBeanWrapper(ConversionService conversionService, } @Override - public Object setCreatedBy(Object value) { + public Object setCreatedBy(@Nullable Object value) { auditable.setCreatedBy(value); return value; @@ -267,7 +267,7 @@ public ReflectionAuditingBeanWrapper(ConversionService conversionService, T targ } @Override - public Object setCreatedBy(Object value) { + public Object setCreatedBy(@Nullable Object value) { return setField(metadata.getCreatedByField(), value); } @@ -277,7 +277,7 @@ public TemporalAccessor setCreatedDate(TemporalAccessor value) { } @Override - public Object setLastModifiedBy(Object value) { + public Object setLastModifiedBy(@Nullable Object value) { return setField(metadata.getLastModifiedByField(), value); } @@ -308,7 +308,8 @@ public T getBean() { * @param field * @param value */ - private S setField(Optional field, S value) { + @Nullable + private S setField(Optional field, @Nullable S value) { field.ifPresent(it -> ReflectionUtils.setField(it, target, value)); diff --git a/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java b/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java index b48659ba6e..e63998b63c 100644 --- a/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java +++ b/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java @@ -40,6 +40,8 @@ import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.util.Lazy; +import org.springframework.lang.Contract; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -203,7 +205,7 @@ public TemporalAccessor setCreatedDate(TemporalAccessor value) { } @Override - public Object setLastModifiedBy(Object value) { + public Object setLastModifiedBy(@Nullable Object value) { return setProperty(metadata.lastModifiedByPaths, value); } @@ -226,8 +228,10 @@ public T getBean() { return accessor.getBean(); } + @Nullable + @Contract("_, null -> null; _, !null -> !null") private S setProperty( - PersistentPropertyPaths> paths, S value) { + PersistentPropertyPaths> paths, @Nullable S value) { paths.forEach(it -> this.accessor.setProperty(it, value, OPTIONS)); diff --git a/src/main/java/org/springframework/data/auditing/config/AuditingBeanDefinitionRegistrarSupport.java b/src/main/java/org/springframework/data/auditing/config/AuditingBeanDefinitionRegistrarSupport.java index c5dc3afed7..821a56da54 100644 --- a/src/main/java/org/springframework/data/auditing/config/AuditingBeanDefinitionRegistrarSupport.java +++ b/src/main/java/org/springframework/data/auditing/config/AuditingBeanDefinitionRegistrarSupport.java @@ -65,7 +65,7 @@ public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanD * * @param configuration must not be {@literal null}. * @param registry must not be {@literal null}. - * @return + * @return the {@link AbstractBeanDefinition} for the {@link AuditingConfiguration}. */ protected AbstractBeanDefinition registerAuditHandlerBeanDefinition(AuditingConfiguration configuration, BeanDefinitionRegistry registry) { @@ -96,7 +96,7 @@ protected void postProcess(BeanDefinitionBuilder builder, AuditingConfiguration * implementations. * * @param configuration must not be {@literal null}. - * @return + * @return the {@link BeanDefinitionBuilder} for the {@link AuditingConfiguration}. */ protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AuditingConfiguration configuration) { @@ -142,7 +142,7 @@ protected BeanDefinitionBuilder configureDefaultAuditHandlerAttributes(AuditingC * Retrieve auditing configuration from the given {@link AnnotationMetadata}. * * @param annotationMetadata will never be {@literal null}. - * @return + * @return a new {@link AnnotationAuditingConfiguration}. */ protected AuditingConfiguration getConfiguration(AnnotationMetadata annotationMetadata) { return new AnnotationAuditingConfiguration(annotationMetadata, getAnnotation()); @@ -167,7 +167,7 @@ protected abstract void registerAuditListenerBeanDefinition(BeanDefinition audit /** * Return the name to be used to register the {@link AuditingHandler} under. * - * @return + * @return name of the {@link AuditingHandler} bean. */ protected abstract String getAuditingHandlerBeanName(); diff --git a/src/main/java/org/springframework/data/auditing/config/AuditingHandlerBeanDefinitionParser.java b/src/main/java/org/springframework/data/auditing/config/AuditingHandlerBeanDefinitionParser.java index 7e89666dd2..4043aed64e 100644 --- a/src/main/java/org/springframework/data/auditing/config/AuditingHandlerBeanDefinitionParser.java +++ b/src/main/java/org/springframework/data/auditing/config/AuditingHandlerBeanDefinitionParser.java @@ -29,9 +29,9 @@ import org.springframework.data.config.ParsingUtils; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.repository.config.PersistentEntitiesFactoryBean; -import org.springframework.lang.NonNull; import org.springframework.util.Assert; import org.springframework.util.StringUtils; + import org.w3c.dom.Element; /** @@ -69,7 +69,6 @@ public String getResolvedBeanName() { return resolvedBeanName; } - @NonNull @Override protected Class getBeanClass(Element element) { return AuditingHandler.class; diff --git a/src/main/java/org/springframework/data/config/ConfigurationUtils.java b/src/main/java/org/springframework/data/config/ConfigurationUtils.java index e737894033..873fc58e1f 100644 --- a/src/main/java/org/springframework/data/config/ConfigurationUtils.java +++ b/src/main/java/org/springframework/data/config/ConfigurationUtils.java @@ -38,7 +38,7 @@ public interface ConfigurationUtils { * @return * @throws IllegalArgumentException if no {@link ResourceLoader} can be obtained from the {@link XmlReaderContext}. */ - public static ResourceLoader getRequiredResourceLoader(XmlReaderContext context) { + static ResourceLoader getRequiredResourceLoader(XmlReaderContext context) { Assert.notNull(context, "XmlReaderContext must not be null"); @@ -58,7 +58,7 @@ public static ResourceLoader getRequiredResourceLoader(XmlReaderContext context) * @return * @throws IllegalArgumentException if no {@link ClassLoader} can be obtained from the given {@link XmlReaderContext}. */ - public static ClassLoader getRequiredClassLoader(XmlReaderContext context) { + static ClassLoader getRequiredClassLoader(XmlReaderContext context) { return getRequiredClassLoader(getRequiredResourceLoader(context)); } @@ -69,7 +69,7 @@ public static ClassLoader getRequiredClassLoader(XmlReaderContext context) { * @return * @throws IllegalArgumentException if the given {@link ResourceLoader} does not expose a {@link ClassLoader}. */ - public static ClassLoader getRequiredClassLoader(ResourceLoader resourceLoader) { + static ClassLoader getRequiredClassLoader(ResourceLoader resourceLoader) { Assert.notNull(resourceLoader, "ResourceLoader must not be null"); @@ -89,7 +89,7 @@ public static ClassLoader getRequiredClassLoader(ResourceLoader resourceLoader) * @return * @throws IllegalArgumentException if the given {@link BeanDefinition} does not contain a bean class name. */ - public static String getRequiredBeanClassName(BeanDefinition beanDefinition) { + static String getRequiredBeanClassName(BeanDefinition beanDefinition) { Assert.notNull(beanDefinition, "BeanDefinition must not be null"); diff --git a/src/main/java/org/springframework/data/convert/AnnotatedPropertyValueConverterAccessor.java b/src/main/java/org/springframework/data/convert/AnnotatedPropertyValueConverterAccessor.java index d5460cf021..fd57405b2f 100644 --- a/src/main/java/org/springframework/data/convert/AnnotatedPropertyValueConverterAccessor.java +++ b/src/main/java/org/springframework/data/convert/AnnotatedPropertyValueConverterAccessor.java @@ -27,12 +27,15 @@ */ class AnnotatedPropertyValueConverterAccessor { + private final String name; private final ValueConverter annotation; public AnnotatedPropertyValueConverterAccessor(PersistentProperty property) { Assert.notNull(property, "PersistentProperty must not be null"); - annotation = property.findAnnotation(ValueConverter.class); + + this.name = property.toString(); + this.annotation = property.findAnnotation(ValueConverter.class); } /** @@ -48,6 +51,28 @@ public AnnotatedPropertyValueConverterAccessor(PersistentProperty property) { return annotation != null ? (Class) annotation.value() : null; } + /** + * Obtain the required {@link PropertyValueConverter converter type} to be used for reading and writing property + * values. Uses the {@link ValueConverter} annotation and extracts its {@link ValueConverter#value() value} attribute. + * Throws {@link IllegalStateException} if no converter is defined. + * + * @return {@literal null} if none defined. Check {@link #hasValueConverter()} to check if the annotation is present + * at all. + * @since 4.0 + * @throws IllegalStateException if no converter is defined. + */ + public Class>>> getRequiredValueConverterType() + throws IllegalStateException { + + Class>>> converterType = getValueConverterType(); + + if (converterType == null) { + throw new IllegalStateException("No converter defined for property '" + name + "'"); + } + + return converterType; + } + /** * Return whether a value converter is configured. Uses {@link ValueConverter} as annotation type. * diff --git a/src/main/java/org/springframework/data/convert/CustomConversions.java b/src/main/java/org/springframework/data/convert/CustomConversions.java index f867f647ad..4bef80674e 100644 --- a/src/main/java/org/springframework/data/convert/CustomConversions.java +++ b/src/main/java/org/springframework/data/convert/CustomConversions.java @@ -198,10 +198,6 @@ public boolean hasValueConverter(PersistentProperty property) { * @param type {@link Class} to evaluate as a simple type, such as a primitive type. * @return a boolean value indicating whether the given, required {@link Class type} is simple. */ - // TODO: Technically, an 'isXyz(..)' method (returning a boolean to answer a user's question should not throw an - // Exception). - // Rather, a null Class type argument should simply return false to indicate it is clearly not a "simple type". - // How much data store specific code relies on the existing behavior? public boolean isSimpleType(Class type) { Assert.notNull(type, "Type must not be null"); @@ -229,6 +225,7 @@ public void registerConvertersIn(ConverterRegistry conversionService) { * @param candidate must not be {@literal null}. * @param conversionService must not be {@literal null}. */ + @SuppressWarnings("rawtypes") private void registerConverterIn(Object candidate, ConverterRegistry conversionService) { if (candidate instanceof Converter converter) { @@ -669,7 +666,7 @@ public boolean isDefaultConverter() { return isConverterOfSource(ConverterOrigin.DEFAULT); } - public ConverterRegistration getConverterRegistration() { + ConverterRegistration getConverterRegistration() { return delegate; } @@ -815,7 +812,7 @@ public static StoreConversions of(SimpleTypeHolder storeTypeHolder, Collection getRegistrationsFor(Object converter) { + Streamable getRegistrationsFor(Object converter) { Assert.notNull(converter, "Converter must not be null"); diff --git a/src/main/java/org/springframework/data/convert/DefaultTypeMapper.java b/src/main/java/org/springframework/data/convert/DefaultTypeMapper.java index 35dec3f555..6eba403d0d 100644 --- a/src/main/java/org/springframework/data/convert/DefaultTypeMapper.java +++ b/src/main/java/org/springframework/data/convert/DefaultTypeMapper.java @@ -141,8 +141,8 @@ public TypeInformation readType(S source, TypeInformation ba Class rawType = basicType.getType(); - boolean isMoreConcreteCustomType = (rawType == null) - || (rawType.isAssignableFrom(documentsTargetType) && !rawType.equals(documentsTargetType)); + boolean isMoreConcreteCustomType = (rawType.isAssignableFrom(documentsTargetType) + && !rawType.equals(documentsTargetType)); if (!isMoreConcreteCustomType) { return basicType; @@ -163,10 +163,9 @@ public TypeInformation readType(S source, TypeInformation ba @Nullable private Class getDefaultedTypeToBeUsed(S source) { - TypeInformation documentsTargetTypeInformation = readType(source); - documentsTargetTypeInformation = documentsTargetTypeInformation == null ? getFallbackTypeFor(source) - : documentsTargetTypeInformation; - return documentsTargetTypeInformation == null ? null : documentsTargetTypeInformation.getType(); + TypeInformation type = readType(source); + type = type == null ? getFallbackTypeFor(source) : type; + return type == null ? null : type.getType(); } /** @@ -192,7 +191,7 @@ public void writeType(TypeInformation info, S sink) { Alias alias = getAliasFor(info); if (alias.isPresent()) { - accessor.writeTypeTo(sink, alias.getValue()); + accessor.writeTypeTo(sink, alias.getRequiredValue()); } } diff --git a/src/main/java/org/springframework/data/convert/DtoInstantiatingConverter.java b/src/main/java/org/springframework/data/convert/DtoInstantiatingConverter.java index 103d36c18c..8f697d9973 100644 --- a/src/main/java/org/springframework/data/convert/DtoInstantiatingConverter.java +++ b/src/main/java/org/springframework/data/convert/DtoInstantiatingConverter.java @@ -27,7 +27,7 @@ import org.springframework.data.mapping.model.EntityInstantiator; import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mapping.model.ParameterValueProvider; -import org.springframework.lang.NonNull; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -64,8 +64,8 @@ public DtoInstantiatingConverter(Class dtoType, this.instantiator = instantiators.getInstantiatorFor(context.getRequiredPersistentEntity(dtoType)); } - @NonNull @Override + @Contract("_ -> !null") public Object convert(Object source) { if (targetType.isInterface()) { @@ -82,6 +82,7 @@ public Object convert(Object source) { @Override @Nullable + @SuppressWarnings({ "rawtypes" }) public Object getParameterValue(Parameter parameter) { String name = parameter.getName(); diff --git a/src/main/java/org/springframework/data/convert/EntityReader.java b/src/main/java/org/springframework/data/convert/EntityReader.java index 2b47906623..a5380357cc 100644 --- a/src/main/java/org/springframework/data/convert/EntityReader.java +++ b/src/main/java/org/springframework/data/convert/EntityReader.java @@ -27,7 +27,7 @@ public interface EntityReader { * * @param type they type to convert the given source to. * @param source the source to create an object of the given type from. - * @return + * @return the converted object. */ R read(Class type, S source); } diff --git a/src/main/java/org/springframework/data/convert/EntityWriter.java b/src/main/java/org/springframework/data/convert/EntityWriter.java index b34f77f933..eb26157ddb 100644 --- a/src/main/java/org/springframework/data/convert/EntityWriter.java +++ b/src/main/java/org/springframework/data/convert/EntityWriter.java @@ -24,5 +24,11 @@ */ public interface EntityWriter { + /** + * Writes the given source object into a store specific sink. + * + * @param source the source to create an object of the given type from. + * @param sink the sink to write into. + */ void write(T source, S sink); } diff --git a/src/main/java/org/springframework/data/convert/JMoleculesConverters.java b/src/main/java/org/springframework/data/convert/JMoleculesConverters.java index 88c18391d5..a3d41de6e5 100644 --- a/src/main/java/org/springframework/data/convert/JMoleculesConverters.java +++ b/src/main/java/org/springframework/data/convert/JMoleculesConverters.java @@ -54,8 +54,7 @@ public static Collection getConvertersToRegister() { List converters = new ArrayList<>(); - Supplier conversionService = (Supplier) () -> DefaultConversionService - .getSharedInstance(); + Supplier conversionService = DefaultConversionService::getSharedInstance; IdentifierToPrimitivesConverter toPrimitives = new IdentifierToPrimitivesConverter(conversionService); PrimitivesToIdentifierConverter toIdentifier = new PrimitivesToIdentifierConverter(conversionService); diff --git a/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java b/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java index 7cddcc1ffa..1e05c0b688 100644 --- a/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java @@ -65,7 +65,7 @@ public Alias createAliasFor(TypeInformation type) { PersistentEntity> entity = mappingContext.getPersistentEntity(key); - if (entity == null || entity.getTypeAlias() == null) { + if (entity == null || entity.getTypeAlias().isEmpty()) { return Alias.NONE; } diff --git a/src/main/java/org/springframework/data/convert/PropertyValueConverterFactories.java b/src/main/java/org/springframework/data/convert/PropertyValueConverterFactories.java index 1705cd118a..2f80f0db06 100644 --- a/src/main/java/org/springframework/data/convert/PropertyValueConverterFactories.java +++ b/src/main/java/org/springframework/data/convert/PropertyValueConverterFactories.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.data.mapping.PersistentProperty; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -175,6 +176,7 @@ public > PropertyValueConverter null;_, !null -> !null") > PropertyValueConverter cache(PersistentProperty property, @Nullable PropertyValueConverter converter) { @@ -241,6 +245,8 @@ > PropertyValueConverter cach return converter; } + @Nullable + @Contract("_, null -> null;_, !null -> !null") > PropertyValueConverter cache(Class type, @Nullable PropertyValueConverter converter) { diff --git a/src/main/java/org/springframework/data/convert/PropertyValueConverterFactory.java b/src/main/java/org/springframework/data/convert/PropertyValueConverterFactory.java index 00f5661d70..a464542a7b 100644 --- a/src/main/java/org/springframework/data/convert/PropertyValueConverterFactory.java +++ b/src/main/java/org/springframework/data/convert/PropertyValueConverterFactory.java @@ -60,7 +60,7 @@ default > PropertyValueConverter>) accessor.getValueConverterType()); + return getConverter((Class>) accessor.getRequiredValueConverterType()); } /** diff --git a/src/main/java/org/springframework/data/convert/PropertyValueConverterRegistrar.java b/src/main/java/org/springframework/data/convert/PropertyValueConverterRegistrar.java index a63e455bd1..4f4e5b62e8 100644 --- a/src/main/java/org/springframework/data/convert/PropertyValueConverterRegistrar.java +++ b/src/main/java/org/springframework/data/convert/PropertyValueConverterRegistrar.java @@ -22,6 +22,7 @@ import org.springframework.data.convert.PropertyValueConverter.FunctionPropertyValueConverter; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.util.MethodInvocationRecorder; +import org.springframework.lang.Contract; import org.springframework.util.Assert; /** @@ -87,6 +88,7 @@ public WritingConverterRegistrationBuilder registerConverter(Cla * @param converter the {@link PropertyValueConverter converter} to apply. * @return this. */ + @Contract("_, _, _ -> this") public PropertyValueConverterRegistrar

registerConverter(Class type, String path, PropertyValueConverter> converter) { diff --git a/src/main/java/org/springframework/data/convert/SimplePropertyValueConverterRegistry.java b/src/main/java/org/springframework/data/convert/SimplePropertyValueConverterRegistry.java index 89f56d1b0a..61e8962d8d 100644 --- a/src/main/java/org/springframework/data/convert/SimplePropertyValueConverterRegistry.java +++ b/src/main/java/org/springframework/data/convert/SimplePropertyValueConverterRegistry.java @@ -67,6 +67,7 @@ public boolean containsConverterFor(Class type, String path) { } @Override + @SuppressWarnings("unchecked") public PropertyValueConverter> getConverter(Class type, String path) { diff --git a/src/main/java/org/springframework/data/crossstore/ChangeSetBackedTransactionSynchronization.java b/src/main/java/org/springframework/data/crossstore/ChangeSetBackedTransactionSynchronization.java index 8c5110e6d6..a67b413e83 100644 --- a/src/main/java/org/springframework/data/crossstore/ChangeSetBackedTransactionSynchronization.java +++ b/src/main/java/org/springframework/data/crossstore/ChangeSetBackedTransactionSynchronization.java @@ -35,12 +35,14 @@ public ChangeSetBackedTransactionSynchronization(ChangeSetPersister chan this.entity = entity; } + @Override public void afterCommit() { logger.debug("After Commit called for " + entity); changeSetPersister.persistState(entity, entity.getChangeSet()); changeSetTxStatus = 0; } + @Override public void afterCompletion(int status) { logger.debug("After Completion called with status = " + status); if (changeSetTxStatus == 0) { @@ -54,20 +56,13 @@ public void afterCompletion(int status) { } } - public void beforeCommit(boolean readOnly) { - } - - public void beforeCompletion() { - } - - public void flush() { - } - + @Override public void resume() { throw new IllegalStateException( "ChangedSetBackedTransactionSynchronization does not support transaction suspension currently"); } + @Override public void suspend() { throw new IllegalStateException( "ChangedSetBackedTransactionSynchronization does not support transaction suspension currently"); diff --git a/src/main/java/org/springframework/data/crossstore/ChangeSetPersister.java b/src/main/java/org/springframework/data/crossstore/ChangeSetPersister.java index 10d0a547bb..43899668f7 100644 --- a/src/main/java/org/springframework/data/crossstore/ChangeSetPersister.java +++ b/src/main/java/org/springframework/data/crossstore/ChangeSetPersister.java @@ -15,6 +15,8 @@ */ package org.springframework.data.crossstore; +import java.io.Serial; + import org.springframework.dao.DataAccessException; /** @@ -59,7 +61,7 @@ void getPersistentState(Class entityClass, K key, Cha */ class NotFoundException extends Exception { - private static final long serialVersionUID = -8604207973816331140L; + private static final @Serial long serialVersionUID = -8604207973816331140L; } } diff --git a/src/main/java/org/springframework/data/domain/AbstractAggregateRoot.java b/src/main/java/org/springframework/data/domain/AbstractAggregateRoot.java index 46ddd2545c..22c563b1b2 100644 --- a/src/main/java/org/springframework/data/domain/AbstractAggregateRoot.java +++ b/src/main/java/org/springframework/data/domain/AbstractAggregateRoot.java @@ -21,6 +21,7 @@ import java.util.List; import org.springframework.data.annotation.Transient; +import org.springframework.lang.Contract; import org.springframework.util.Assert; /** @@ -76,6 +77,7 @@ protected Collection domainEvents() { * @return the aggregate */ @SuppressWarnings("unchecked") + @Contract("_ -> this") protected final A andEventsFrom(A aggregate) { Assert.notNull(aggregate, "Aggregate must not be null"); @@ -86,15 +88,16 @@ protected final A andEventsFrom(A aggregate) { } /** - * Adds the given event to the aggregate for later publication - * when calling a Spring Data repository's save or delete method. - * Does the same as {@link #registerEvent(Object)} but returns the aggregate instead of the event. + * Adds the given event to the aggregate for later publication when calling a Spring Data repository's {@code save} or + * {@code delete} method. Does the same as {@link #registerEvent(Object)} but returns the aggregate instead of the + * event. * * @param event must not be {@literal null}. * @return the aggregate * @see #registerEvent(Object) */ @SuppressWarnings("unchecked") + @Contract("_ -> this") protected final A andEvent(Object event) { registerEvent(event); diff --git a/src/main/java/org/springframework/data/domain/AbstractPageRequest.java b/src/main/java/org/springframework/data/domain/AbstractPageRequest.java index 29de4bb355..5dfc9c36d9 100644 --- a/src/main/java/org/springframework/data/domain/AbstractPageRequest.java +++ b/src/main/java/org/springframework/data/domain/AbstractPageRequest.java @@ -15,8 +15,11 @@ */ package org.springframework.data.domain; +import java.io.Serial; import java.io.Serializable; +import org.springframework.util.ObjectUtils; + /** * Abstract Java Bean implementation of {@code Pageable}. * @@ -28,7 +31,7 @@ */ public abstract class AbstractPageRequest implements Pageable, Serializable { - private static final long serialVersionUID = 1232825578694716871L; + private static final @Serial long serialVersionUID = 1232825578694716871L; private final int pageNumber; private final int pageSize; @@ -85,7 +88,7 @@ public Pageable previousOrFirst() { /** * Returns the {@link Pageable} requesting the previous {@link Page}. * - * @return + * @return the previous {@link Pageable} */ public abstract Pageable previous(); @@ -93,29 +96,21 @@ public Pageable previousOrFirst() { public abstract Pageable first(); @Override - public int hashCode() { - - final int prime = 31; - int result = 1; - - result = prime * result + pageNumber; - result = prime * result + pageSize; - - return result; - } - - @Override - public boolean equals(Object obj) { - - if (this == obj) { + public boolean equals(Object o) { + if (this == o) { return true; } - - if (obj == null || getClass() != obj.getClass()) { + if (!(o instanceof AbstractPageRequest that)) { + return false; + } + if (pageNumber != that.pageNumber) { return false; } + return pageSize == that.pageSize; + } - AbstractPageRequest other = (AbstractPageRequest) obj; - return pageNumber == other.pageNumber && pageSize == other.pageSize; + @Override + public int hashCode() { + return ObjectUtils.nullSafeHash(pageNumber, pageSize); } } diff --git a/src/main/java/org/springframework/data/domain/Auditable.java b/src/main/java/org/springframework/data/domain/Auditable.java index c54e811c43..056c9e4aad 100644 --- a/src/main/java/org/springframework/data/domain/Auditable.java +++ b/src/main/java/org/springframework/data/domain/Auditable.java @@ -18,6 +18,8 @@ import java.time.temporal.TemporalAccessor; import java.util.Optional; +import org.springframework.lang.Nullable; + /** * Interface for auditable entities. Allows storing and retrieving creation and modification information. The changing * instance (typically some user) is to be defined by a generics definition. @@ -40,7 +42,7 @@ public interface Auditable extends Persistabl * * @param createdBy the creating entity to set */ - void setCreatedBy(U createdBy); + void setCreatedBy(@Nullable U createdBy); /** * Returns the creation date of the entity. @@ -68,7 +70,7 @@ public interface Auditable extends Persistabl * * @param lastModifiedBy the last modifying entity to set */ - void setLastModifiedBy(U lastModifiedBy); + void setLastModifiedBy(@Nullable U lastModifiedBy); /** * Returns the date of the last modification. diff --git a/src/main/java/org/springframework/data/domain/Chunk.java b/src/main/java/org/springframework/data/domain/Chunk.java index 73f6c637c2..299edcf642 100644 --- a/src/main/java/org/springframework/data/domain/Chunk.java +++ b/src/main/java/org/springframework/data/domain/Chunk.java @@ -15,6 +15,7 @@ */ package org.springframework.data.domain; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -24,6 +25,7 @@ import java.util.stream.Collectors; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * A chunk of data restricted by the configured {@link Pageable}. @@ -34,9 +36,9 @@ */ abstract class Chunk implements Slice, Serializable { - private static final long serialVersionUID = 867755909294344406L; + private static final @Serial long serialVersionUID = 867755909294344406L; - private final List content = new ArrayList<>(); + private final List content; private final Pageable pageable; /** @@ -50,7 +52,7 @@ public Chunk(List content, Pageable pageable) { Assert.notNull(content, "Content must not be null"); Assert.notNull(pageable, "Pageable must not be null"); - this.content.addAll(content); + this.content = new ArrayList<>(content); this.pageable = pageable; } @@ -114,6 +116,7 @@ public Sort getSort() { return pageable.getSort(); } + @Override public Iterator iterator() { return content.iterator(); } @@ -128,34 +131,27 @@ protected List getConvertedContent(Function conve Assert.notNull(converter, "Function must not be null"); - return this.stream().map(converter::apply).collect(Collectors.toList()); + return this.stream().map(converter).collect(Collectors.toList()); } @Override - public boolean equals(Object obj) { + public boolean equals(Object o) { - if (this == obj) { + if (this == o) { return true; } - - if (!(obj instanceof Chunk that)) { + if (!(o instanceof Chunk chunk)) { return false; } - - boolean contentEqual = this.content.equals(that.content); - boolean pageableEqual = this.pageable.equals(that.pageable); - - return contentEqual && pageableEqual; + if (!ObjectUtils.nullSafeEquals(content, chunk.content)) { + return false; + } + return ObjectUtils.nullSafeEquals(pageable, chunk.pageable); } @Override public int hashCode() { - - int result = 17; - - result += 31 * pageable.hashCode(); - result += 31 * content.hashCode(); - - return result; + return ObjectUtils.nullSafeHash(content, pageable); } + } diff --git a/src/main/java/org/springframework/data/domain/DomainEvents.java b/src/main/java/org/springframework/data/domain/DomainEvents.java index ad115975ca..d3a7d7447e 100644 --- a/src/main/java/org/springframework/data/domain/DomainEvents.java +++ b/src/main/java/org/springframework/data/domain/DomainEvents.java @@ -35,4 +35,5 @@ @Reflective @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) -public @interface DomainEvents {} +public @interface DomainEvents { +} diff --git a/src/main/java/org/springframework/data/domain/Example.java b/src/main/java/org/springframework/data/domain/Example.java index 82bc30fa7a..ff5f80aee8 100644 --- a/src/main/java/org/springframework/data/domain/Example.java +++ b/src/main/java/org/springframework/data/domain/Example.java @@ -33,7 +33,7 @@ public interface Example { * Create a new {@link Example} including all non-null properties by default. * * @param probe must not be {@literal null}. - * @return + * @return a new {@link Example} for {@code probe}. */ static Example of(T probe) { return new TypedExample<>(probe, ExampleMatcher.matching()); @@ -44,7 +44,7 @@ static Example of(T probe) { * * @param probe must not be {@literal null}. * @param matcher must not be {@literal null}. - * @return + * @return a new {@link Example} for {@code probe} and {@link ExampleMatcher}. */ static Example of(T probe, ExampleMatcher matcher) { return new TypedExample<>(probe, matcher); @@ -68,7 +68,7 @@ static Example of(T probe, ExampleMatcher matcher) { * Get the actual type for the probe used. This is usually the given class, but the original class in case of a * CGLIB-generated subclass. * - * @return + * @return the underlying probe type, potentially an unwrapped proxy. * @see ProxyUtils#getUserClass(Class) */ @SuppressWarnings("unchecked") diff --git a/src/main/java/org/springframework/data/domain/ExampleMatcher.java b/src/main/java/org/springframework/data/domain/ExampleMatcher.java index 3d716fc11a..5254627c7d 100644 --- a/src/main/java/org/springframework/data/domain/ExampleMatcher.java +++ b/src/main/java/org/springframework/data/domain/ExampleMatcher.java @@ -22,6 +22,8 @@ import java.util.Set; import java.util.function.Function; +import org.springframework.lang.CheckReturnValue; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -81,6 +83,8 @@ static ExampleMatcher matchingAll() { * @param ignoredPaths must not be {@literal null} and not empty. * @return new instance of {@link ExampleMatcher}. */ + @Contract("_ -> new") + @CheckReturnValue ExampleMatcher withIgnorePaths(String... ignoredPaths); /** @@ -90,6 +94,8 @@ static ExampleMatcher matchingAll() { * @param defaultStringMatcher must not be {@literal null}. * @return new instance of {@link ExampleMatcher}. */ + @Contract("_ -> new") + @CheckReturnValue ExampleMatcher withStringMatcher(StringMatcher defaultStringMatcher); /** @@ -98,6 +104,8 @@ static ExampleMatcher matchingAll() { * * @return new instance of {@link ExampleMatcher}. */ + @Contract("-> new") + @CheckReturnValue default ExampleMatcher withIgnoreCase() { return withIgnoreCase(true); } @@ -106,9 +114,11 @@ default ExampleMatcher withIgnoreCase() { * Returns a copy of this {@link ExampleMatcher} with {@code defaultIgnoreCase}. This instance is immutable and * unaffected by this method call. * - * @param defaultIgnoreCase + * @param defaultIgnoreCase {@literal true} to ignore case by default. * @return new instance of {@link ExampleMatcher}. */ + @Contract("_ -> new") + @CheckReturnValue ExampleMatcher withIgnoreCase(boolean defaultIgnoreCase); /** @@ -119,6 +129,8 @@ default ExampleMatcher withIgnoreCase() { * @param matcherConfigurer callback to configure a {@link GenericPropertyMatcher}, must not be {@literal null}. * @return new instance of {@link ExampleMatcher}. */ + @Contract("_, _ -> new") + @CheckReturnValue default ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer matcherConfigurer) { Assert.hasText(propertyPath, "PropertyPath must not be empty"); @@ -138,6 +150,8 @@ default ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer new") + @CheckReturnValue ExampleMatcher withMatcher(String propertyPath, GenericPropertyMatcher genericPropertyMatcher); /** @@ -148,6 +162,8 @@ default ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer new") + @CheckReturnValue ExampleMatcher withTransformer(String propertyPath, PropertyValueTransformer propertyValueTransformer); /** @@ -157,6 +173,8 @@ default ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer new") + @CheckReturnValue ExampleMatcher withIgnoreCase(String... propertyPaths); /** @@ -165,6 +183,8 @@ default ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer new") + @CheckReturnValue default ExampleMatcher withIncludeNullValues() { return withNullHandler(NullHandler.INCLUDE); } @@ -175,6 +195,8 @@ default ExampleMatcher withIncludeNullValues() { * * @return new instance of {@link ExampleMatcher}. */ + @Contract("-> new") + @CheckReturnValue default ExampleMatcher withIgnoreNullValues() { return withNullHandler(NullHandler.IGNORE); } @@ -186,19 +208,21 @@ default ExampleMatcher withIgnoreNullValues() { * @param nullHandler must not be {@literal null}. * @return new instance of {@link ExampleMatcher}. */ + @Contract("_ -> new") + @CheckReturnValue ExampleMatcher withNullHandler(NullHandler nullHandler); /** - * Get defined null handling. + * Get the defined null handling. * - * @return never {@literal null} + * @return the defined null handling. */ NullHandler getNullHandler(); /** - * Get defined {@link ExampleMatcher.StringMatcher}. + * Get the defined {@link ExampleMatcher.StringMatcher}. * - * @return never {@literal null}. + * @return the defined {@link ExampleMatcher.StringMatcher}. */ StringMatcher getDefaultStringMatcher(); @@ -226,10 +250,10 @@ default boolean isIgnoredPath(String path) { PropertySpecifiers getPropertySpecifiers(); /** - * Returns whether all of the predicates of the {@link Example} are supposed to match. If {@literal false} is - * returned, it's sufficient if any of the predicates derived from the {@link Example} match. + * Returns whether all the predicates of the {@link Example} are supposed to match. If {@literal false} is returned, + * it's sufficient if any of the predicates derived from the {@link Example} match. * - * @return whether all of the predicates of the {@link Example} are supposed to match or any of them is sufficient. + * @return whether all the predicates of the {@link Example} are supposed to match or any of them is sufficient. */ default boolean isAllMatching() { return getMatchMode().equals(MatchMode.ALL); @@ -293,8 +317,7 @@ public GenericPropertyMatcher() {} * Creates a new {@link GenericPropertyMatcher} with a {@link StringMatcher} and {@code ignoreCase}. * * @param stringMatcher must not be {@literal null}. - * @param ignoreCase - * @return + * @param ignoreCase {@literal true} to ignore case. */ public static GenericPropertyMatcher of(StringMatcher stringMatcher, boolean ignoreCase) { return new GenericPropertyMatcher().stringMatcher(stringMatcher).ignoreCase(ignoreCase); @@ -304,7 +327,6 @@ public static GenericPropertyMatcher of(StringMatcher stringMatcher, boolean ign * Creates a new {@link GenericPropertyMatcher} with a {@link StringMatcher} and {@code ignoreCase}. * * @param stringMatcher must not be {@literal null}. - * @return */ public static GenericPropertyMatcher of(StringMatcher stringMatcher) { return new GenericPropertyMatcher().stringMatcher(stringMatcher); @@ -312,9 +334,8 @@ public static GenericPropertyMatcher of(StringMatcher stringMatcher) { /** * Sets ignores case to {@literal true}. - * - * @return */ + @Contract(" -> this") public GenericPropertyMatcher ignoreCase() { this.ignoreCase = true; @@ -324,9 +345,9 @@ public GenericPropertyMatcher ignoreCase() { /** * Sets ignores case to {@code ignoreCase}. * - * @param ignoreCase - * @return + * @param ignoreCase {@literal true} to ignore case. */ + @Contract("_ -> this") public GenericPropertyMatcher ignoreCase(boolean ignoreCase) { this.ignoreCase = ignoreCase; @@ -335,9 +356,8 @@ public GenericPropertyMatcher ignoreCase(boolean ignoreCase) { /** * Sets ignores case to {@literal false}. - * - * @return */ + @Contract(" -> this") public GenericPropertyMatcher caseSensitive() { this.ignoreCase = false; @@ -346,9 +366,8 @@ public GenericPropertyMatcher caseSensitive() { /** * Sets string matcher to {@link StringMatcher#CONTAINING}. - * - * @return */ + @Contract(" -> this") public GenericPropertyMatcher contains() { this.stringMatcher = StringMatcher.CONTAINING; @@ -357,9 +376,8 @@ public GenericPropertyMatcher contains() { /** * Sets string matcher to {@link StringMatcher#ENDING}. - * - * @return */ + @Contract(" -> this") public GenericPropertyMatcher endsWith() { this.stringMatcher = StringMatcher.ENDING; @@ -368,9 +386,8 @@ public GenericPropertyMatcher endsWith() { /** * Sets string matcher to {@link StringMatcher#STARTING}. - * - * @return */ + @Contract(" -> this") public GenericPropertyMatcher startsWith() { this.stringMatcher = StringMatcher.STARTING; @@ -379,9 +396,8 @@ public GenericPropertyMatcher startsWith() { /** * Sets string matcher to {@link StringMatcher#EXACT}. - * - * @return */ + @Contract(" -> this") public GenericPropertyMatcher exact() { this.stringMatcher = StringMatcher.EXACT; @@ -390,9 +406,8 @@ public GenericPropertyMatcher exact() { /** * Sets string matcher to {@link StringMatcher#DEFAULT}. - * - * @return */ + @Contract(" -> this") public GenericPropertyMatcher storeDefaultMatching() { this.stringMatcher = StringMatcher.DEFAULT; @@ -401,9 +416,8 @@ public GenericPropertyMatcher storeDefaultMatching() { /** * Sets string matcher to {@link StringMatcher#REGEX}. - * - * @return */ + @Contract(" -> this") public GenericPropertyMatcher regex() { this.stringMatcher = StringMatcher.REGEX; @@ -414,8 +428,8 @@ public GenericPropertyMatcher regex() { * Sets string matcher to {@code stringMatcher}. * * @param stringMatcher must not be {@literal null}. - * @return */ + @Contract("_ -> this") public GenericPropertyMatcher stringMatcher(StringMatcher stringMatcher) { Assert.notNull(stringMatcher, "StringMatcher must not be null"); @@ -427,8 +441,8 @@ public GenericPropertyMatcher stringMatcher(StringMatcher stringMatcher) { * Sets the {@link PropertyValueTransformer} to {@code propertyValueTransformer}. * * @param propertyValueTransformer must not be {@literal null}. - * @return */ + @Contract("_ -> this") public GenericPropertyMatcher transform(PropertyValueTransformer propertyValueTransformer) { Assert.notNull(propertyValueTransformer, "PropertyValueTransformer must not be null"); @@ -463,10 +477,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(stringMatcher); - result = 31 * result + ObjectUtils.nullSafeHashCode(ignoreCase); - result = 31 * result + ObjectUtils.nullSafeHashCode(valueTransformer); - return result; + return ObjectUtils.nullSafeHash(stringMatcher, ignoreCase, valueTransformer); } } @@ -478,9 +489,7 @@ public int hashCode() { class GenericPropertyMatchers { /** - * Creates a {@link GenericPropertyMatcher} that matches string case insensitive. - * - * @return + * Creates a {@link GenericPropertyMatcher} that matches string case-insensitive. */ public static GenericPropertyMatcher ignoreCase() { return new GenericPropertyMatcher().ignoreCase(); @@ -488,8 +497,6 @@ public static GenericPropertyMatcher ignoreCase() { /** * Creates a {@link GenericPropertyMatcher} that matches string case-sensitive. - * - * @return */ public static GenericPropertyMatcher caseSensitive() { return new GenericPropertyMatcher().caseSensitive(); @@ -497,8 +504,6 @@ public static GenericPropertyMatcher caseSensitive() { /** * Creates a {@link GenericPropertyMatcher} that matches string using {@link StringMatcher#CONTAINING}. - * - * @return */ public static GenericPropertyMatcher contains() { return new GenericPropertyMatcher().contains(); @@ -506,8 +511,6 @@ public static GenericPropertyMatcher contains() { /** * Creates a {@link GenericPropertyMatcher} that matches string using {@link StringMatcher#ENDING}. - * - * @return */ public static GenericPropertyMatcher endsWith() { return new GenericPropertyMatcher().endsWith(); @@ -516,8 +519,6 @@ public static GenericPropertyMatcher endsWith() { /** * Creates a {@link GenericPropertyMatcher} that matches string using {@link StringMatcher#STARTING}. - * - * @return */ public static GenericPropertyMatcher startsWith() { return new GenericPropertyMatcher().startsWith(); @@ -525,8 +526,6 @@ public static GenericPropertyMatcher startsWith() { /** * Creates a {@link GenericPropertyMatcher} that matches string using {@link StringMatcher#EXACT}. - * - * @return */ public static GenericPropertyMatcher exact() { return new GenericPropertyMatcher().exact(); @@ -534,8 +533,6 @@ public static GenericPropertyMatcher exact() { /** * Creates a {@link GenericPropertyMatcher} that matches string using {@link StringMatcher#DEFAULT}. - * - * @return */ public static GenericPropertyMatcher storeDefaultMatching() { return new GenericPropertyMatcher().storeDefaultMatching(); @@ -543,8 +540,6 @@ public static GenericPropertyMatcher storeDefaultMatching() { /** * Creates a {@link GenericPropertyMatcher} that matches string using {@link StringMatcher#REGEX}. - * - * @return */ public static GenericPropertyMatcher regex() { return new GenericPropertyMatcher().regex(); @@ -648,8 +643,9 @@ private PropertySpecifier(String path, @Nullable StringMatcher stringMatcher, @N * {@link StringMatcher} in the returned instance. * * @param stringMatcher must not be {@literal null}. - * @return */ + @Contract("_ -> new") + @CheckReturnValue public PropertySpecifier withStringMatcher(StringMatcher stringMatcher) { Assert.notNull(stringMatcher, "StringMatcher must not be null"); @@ -660,9 +656,10 @@ public PropertySpecifier withStringMatcher(StringMatcher stringMatcher) { * Creates a new {@link PropertySpecifier} containing all values from the current instance and sets * {@code ignoreCase}. * - * @param ignoreCase must not be {@literal null}. - * @return + * @param ignoreCase {@literal true} to ignore case. */ + @Contract("_ -> new") + @CheckReturnValue public PropertySpecifier withIgnoreCase(boolean ignoreCase) { return new PropertySpecifier(this.path, this.stringMatcher, ignoreCase, this.valueTransformer); } @@ -672,8 +669,9 @@ public PropertySpecifier withIgnoreCase(boolean ignoreCase) { * {@link PropertyValueTransformer} in the returned instance. * * @param valueTransformer must not be {@literal null}. - * @return */ + @Contract("_ -> new") + @CheckReturnValue public PropertySpecifier withValueTransformer(PropertyValueTransformer valueTransformer) { Assert.notNull(valueTransformer, "PropertyValueTransformer must not be null"); @@ -719,7 +717,7 @@ public PropertyValueTransformer getPropertyValueTransformer() { /** * Transforms a given source using the {@link PropertyValueTransformer}. * - * @param source + * @param source source value to transform. * @return */ public Optional transformValue(Optional source) { @@ -753,11 +751,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(path); - result = 31 * result + ObjectUtils.nullSafeHashCode(stringMatcher); - result = 31 * result + ObjectUtils.nullSafeHashCode(ignoreCase); - result = 31 * result + ObjectUtils.nullSafeHashCode(valueTransformer); - return result; + return ObjectUtils.nullSafeHash(path, stringMatcher, ignoreCase, valueTransformer); } protected boolean canEqual(final Object other) { diff --git a/src/main/java/org/springframework/data/domain/Limit.java b/src/main/java/org/springframework/data/domain/Limit.java index 662c9904b6..f9936aecd5 100644 --- a/src/main/java/org/springframework/data/domain/Limit.java +++ b/src/main/java/org/springframework/data/domain/Limit.java @@ -110,7 +110,7 @@ public boolean equals(@Nullable Object obj) { @Override public int hashCode() { - return max ^ max >>> 32; + return max; } } diff --git a/src/main/java/org/springframework/data/domain/OffsetScrollPosition.java b/src/main/java/org/springframework/data/domain/OffsetScrollPosition.java index 2269f39d3f..4c6163f77f 100644 --- a/src/main/java/org/springframework/data/domain/OffsetScrollPosition.java +++ b/src/main/java/org/springframework/data/domain/OffsetScrollPosition.java @@ -123,6 +123,7 @@ public boolean isInitial() { return offset == -1; } + @Override public boolean equals(@Nullable Object o) { diff --git a/src/main/java/org/springframework/data/domain/Page.java b/src/main/java/org/springframework/data/domain/Page.java index a4f5cf17ec..1ab9fa3c2b 100644 --- a/src/main/java/org/springframework/data/domain/Page.java +++ b/src/main/java/org/springframework/data/domain/Page.java @@ -29,8 +29,6 @@ public interface Page extends Slice { /** * Creates a new empty {@link Page}. - * - * @return * @since 2.0 */ static Page empty() { @@ -41,7 +39,7 @@ static Page empty() { * Creates a new empty {@link Page} for the given {@link Pageable}. * * @param pageable must not be {@literal null}. - * @return + * @return a new, empty {@link Page} wrapping the given {@link Pageable}. * @since 2.0 */ static Page empty(Pageable pageable) { diff --git a/src/main/java/org/springframework/data/domain/PageImpl.java b/src/main/java/org/springframework/data/domain/PageImpl.java index ca3595a28c..21dda4d5c7 100644 --- a/src/main/java/org/springframework/data/domain/PageImpl.java +++ b/src/main/java/org/springframework/data/domain/PageImpl.java @@ -15,10 +15,12 @@ */ package org.springframework.data.domain; +import java.io.Serial; import java.util.List; import java.util.function.Function; import org.springframework.lang.Nullable; +import org.springframework.util.CollectionUtils; /** * Basic {@code Page} implementation. @@ -29,7 +31,7 @@ */ public class PageImpl extends Chunk implements Page { - private static final long serialVersionUID = 867755909294344406L; + private static final @Serial long serialVersionUID = 867755909294344406L; private final long total; @@ -58,7 +60,7 @@ public PageImpl(List content, Pageable pageable, long total) { * @param content must not be {@literal null}. */ public PageImpl(List content) { - this(content, Pageable.unpaged(), null == content ? 0 : content.size()); + this(content, Pageable.unpaged(), CollectionUtils.isEmpty(content) ? 0 : content.size()); } @Override @@ -86,19 +88,6 @@ public Page map(Function converter) { return new PageImpl<>(getConvertedContent(converter), getPageable(), total); } - @Override - public String toString() { - - String contentType = "UNKNOWN"; - List content = getContent(); - - if (!content.isEmpty() && content.get(0) != null) { - contentType = content.get(0).getClass().getName(); - } - - return String.format("Page %s of %d containing %s instances", getNumber() + 1, getTotalPages(), contentType); - } - @Override public boolean equals(@Nullable Object obj) { @@ -115,12 +104,19 @@ public boolean equals(@Nullable Object obj) { @Override public int hashCode() { + return 31 * super.hashCode() + Long.hashCode(total); + } - int result = 17; + @Override + public String toString() { - result += 31 * (int) (total ^ total >>> 32); - result += 31 * super.hashCode(); + String contentType = "UNKNOWN"; + List content = getContent(); - return result; + if (!content.isEmpty() && content.get(0) != null) { + contentType = content.get(0).getClass().getName(); + } + + return String.format("Page %s of %d containing %s instances", getNumber() + 1, getTotalPages(), contentType); } } diff --git a/src/main/java/org/springframework/data/domain/PageRequest.java b/src/main/java/org/springframework/data/domain/PageRequest.java index 23bfbb6131..c60a9fae26 100644 --- a/src/main/java/org/springframework/data/domain/PageRequest.java +++ b/src/main/java/org/springframework/data/domain/PageRequest.java @@ -15,9 +15,14 @@ */ package org.springframework.data.domain; +import java.io.Serial; + import org.springframework.data.domain.Sort.Direction; +import org.springframework.lang.CheckReturnValue; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * Basic Java Bean implementation of {@link Pageable}. @@ -30,7 +35,7 @@ */ public class PageRequest extends AbstractPageRequest { - private static final long serialVersionUID = -4541509938956089562L; + private static final @Serial long serialVersionUID = -4541509938956089562L; private final Sort sort; @@ -103,42 +108,36 @@ public Sort getSort() { } @Override + @Contract("_ -> new") + @CheckReturnValue public PageRequest next() { return new PageRequest(getPageNumber() + 1, getPageSize(), getSort()); } @Override + @Contract("_ -> new") + @CheckReturnValue public PageRequest previous() { return getPageNumber() == 0 ? this : new PageRequest(getPageNumber() - 1, getPageSize(), getSort()); } @Override + @Contract("_ -> new") + @CheckReturnValue public PageRequest first() { return new PageRequest(0, getPageSize(), getSort()); } - @Override - public boolean equals(@Nullable Object obj) { - - if (this == obj) { - return true; - } - - if (!(obj instanceof PageRequest that)) { - return false; - } - - return super.equals(that) && sort.equals(that.sort); - } - /** * Creates a new {@link PageRequest} with {@code pageNumber} applied. * - * @param pageNumber + * @param pageNumber the page number to apply. * @return a new {@link PageRequest}. * @since 2.5 */ @Override + @Contract("_ -> new") + @CheckReturnValue public PageRequest withPage(int pageNumber) { return new PageRequest(pageNumber, getPageSize(), getSort()); } @@ -151,6 +150,8 @@ public PageRequest withPage(int pageNumber) { * @return a new {@link PageRequest}. * @since 2.5 */ + @Contract("_, _ -> new") + @CheckReturnValue public PageRequest withSort(Direction direction, String... properties) { return new PageRequest(getPageNumber(), getPageSize(), Sort.by(direction, properties)); } @@ -162,13 +163,30 @@ public PageRequest withSort(Direction direction, String... properties) { * @return a new {@link PageRequest}. * @since 2.5 */ + @Contract("_ -> new") + @CheckReturnValue public PageRequest withSort(Sort sort) { return new PageRequest(getPageNumber(), getPageSize(), sort); } + @Override + public boolean equals(Object o) { + + if (this == o) { + return true; + } + if (!(o instanceof PageRequest that)) { + return false; + } + if (!super.equals(o)) { + return false; + } + return ObjectUtils.nullSafeEquals(sort, that.sort); + } + @Override public int hashCode() { - return 31 * super.hashCode() + sort.hashCode(); + return super.hashCode() * 31 + ObjectUtils.nullSafeHash(sort); } @Override diff --git a/src/main/java/org/springframework/data/domain/Pageable.java b/src/main/java/org/springframework/data/domain/Pageable.java index f84b7822aa..dde85e49f6 100644 --- a/src/main/java/org/springframework/data/domain/Pageable.java +++ b/src/main/java/org/springframework/data/domain/Pageable.java @@ -17,6 +17,8 @@ import java.util.Optional; +import org.springframework.lang.CheckReturnValue; +import org.springframework.lang.Contract; import org.springframework.util.Assert; /** @@ -30,8 +32,6 @@ public interface Pageable { /** * Returns a {@link Pageable} instance representing no pagination setup. - * - * @return */ static Pageable unpaged() { return unpaged(Sort.unsorted()); @@ -41,7 +41,8 @@ static Pageable unpaged() { * Returns a {@link Pageable} instance representing no pagination setup having a defined result {@link Sort order}. * * @param sort must not be {@literal null}, use {@link Sort#unsorted()} if needed. - * @return never {@literal null}. + * @return an unpaged {@link Pageable} instance representing no pagination setup considering the given {@link Sort} + * order. * @since 3.2 */ static Pageable unpaged(Sort sort) { @@ -62,7 +63,7 @@ static Pageable ofSize(int pageSize) { /** * Returns whether the current {@link Pageable} contains pagination information. * - * @return + * @return {@literal true} if the current {@link Pageable} contains pagination information. */ default boolean isPaged() { return true; @@ -71,7 +72,7 @@ default boolean isPaged() { /** * Returns whether the current {@link Pageable} does not contain pagination information. * - * @return + * @return {@literal true} if the current {@link Pageable} does not contain pagination information. */ default boolean isUnpaged() { return !isPaged(); @@ -107,7 +108,7 @@ default boolean isUnpaged() { /** * Returns the sorting parameters. * - * @return + * @return the sorting order. */ Sort getSort(); @@ -115,7 +116,7 @@ default boolean isUnpaged() { * Returns the current {@link Sort} or the given one if the current one is unsorted. * * @param sort must not be {@literal null}. - * @return + * @return the current {@link Sort} or the {@code sort} one if the current one is unsorted. */ default Sort getSortOr(Sort sort) { @@ -127,47 +128,55 @@ default Sort getSortOr(Sort sort) { /** * Returns the {@link Pageable} requesting the next {@link Page}. * - * @return + * @return the {@link Pageable} requesting the next {@link Page}. */ + @Contract("_ -> new") + @CheckReturnValue Pageable next(); /** * Returns the previous {@link Pageable} or the first {@link Pageable} if the current one already is the first one. * - * @return + * @return the previous {@link Pageable} or the first {@link Pageable} if the current one already is the first one. */ + @Contract("_ -> new") + @CheckReturnValue Pageable previousOrFirst(); /** * Returns the {@link Pageable} requesting the first page. * - * @return + * @return the {@link Pageable} requesting the first page. */ + @Contract("_ -> new") + @CheckReturnValue Pageable first(); /** * Creates a new {@link Pageable} with {@code pageNumber} applied. * - * @param pageNumber + * @param pageNumber the page numbe, zero-based. * @return a new {@link PageRequest} or throws {@link UnsupportedOperationException} if the object is * {@link #isUnpaged()} and the {@code pageNumber} is not zero. * @since 2.5 * @throws UnsupportedOperationException if the object is {@link #isUnpaged()}. */ + @Contract("_ -> new") + @CheckReturnValue Pageable withPage(int pageNumber); /** * Returns whether there's a previous {@link Pageable} we can access from the current one. Will return * {@literal false} in case the current {@link Pageable} already refers to the first page. * - * @return + * @return {@literal true} if there's a previous {@link Pageable} we can access from the current one. */ boolean hasPrevious(); /** * Returns an {@link Optional} so that it can easily be mapped on. * - * @return + * @return an {@link Optional} so that it can easily be mapped on. */ default Optional toOptional() { return isUnpaged() ? Optional.empty() : Optional.of(this); @@ -177,7 +186,7 @@ default Optional toOptional() { * Returns an {@link Limit} from this pageable if the page request {@link #isPaged() is paged} or * {@link Limit#unlimited()} otherwise. * - * @return + * @return a {@link Limit} object based on the current page size. * @since 3.2 */ default Limit toLimit() { @@ -193,7 +202,7 @@ default Limit toLimit() { * Returns an {@link OffsetScrollPosition} from this pageable if the page request {@link #isPaged() is paged}. *

* Given the exclusive nature of scrolling the {@link ScrollPosition} for {@code Page(0, 10)} translates an - * {@link ScrollPosition#isInitial() initial} position, where as {@code Page(1, 10)} will point to the last element of + * {@link ScrollPosition#isInitial() initial} position, whereas {@code Page(1, 10)} will point to the last element of * {@code Page(0,10)} resulting in {@link ScrollPosition#offset(long) ScrollPosition(9)}. * * @return new instance of {@link OffsetScrollPosition}. diff --git a/src/main/java/org/springframework/data/domain/Range.java b/src/main/java/org/springframework/data/domain/Range.java index e34789f5e1..df80a9270d 100644 --- a/src/main/java/org/springframework/data/domain/Range.java +++ b/src/main/java/org/springframework/data/domain/Range.java @@ -19,6 +19,7 @@ import java.util.Optional; import java.util.function.Function; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -55,7 +56,7 @@ private Range(Bound lowerBound, Bound upperBound) { /** * Returns an unbounded {@link Range}. * - * @return + * @return an unbounded {@link Range}. * @since 2.0 */ @SuppressWarnings("unchecked") @@ -66,10 +67,10 @@ public static Range unbounded() { /** * Creates a new {@link Range} with inclusive bounds for both values. * - * @param + * @param the type of the range. * @param from must not be {@literal null}. * @param to must not be {@literal null}. - * @return + * @return a {@link Range} with the lower bound set inclusively and the upper bound inclusively. * @since 2.2 */ public static Range closed(T from, T to) { @@ -79,10 +80,10 @@ public static Range closed(T from, T to) { /** * Creates a new {@link Range} with exclusive bounds for both values. * - * @param + * @param the type of the range. * @param from must not be {@literal null}. * @param to must not be {@literal null}. - * @return + * @return a {@link Range} with the lower bound set exclusively and the upper bound exclusively. * @since 2.2 */ public static Range open(T from, T to) { @@ -92,10 +93,10 @@ public static Range open(T from, T to) { /** * Creates a new left-open {@link Range}, i.e. left exclusive, right inclusive. * - * @param + * @param the type of the range. * @param from must not be {@literal null}. * @param to must not be {@literal null}. - * @return + * @return a {@link Range} with the lower bound set exclusively and the upper bound inclusively. * @since 2.2 */ public static Range leftOpen(T from, T to) { @@ -105,10 +106,10 @@ public static Range leftOpen(T from, T to) { /** * Creates a new right-open {@link Range}, i.e. left inclusive, right exclusive. * - * @param + * @param the type of the range. * @param from must not be {@literal null}. * @param to must not be {@literal null}. - * @return + * @return a {@link Range} with the lower bound set inclusively and the upper bound exclusively. * @since 2.2 */ public static Range rightOpen(T from, T to) { @@ -119,9 +120,9 @@ public static Range rightOpen(T from, T to) { * Creates a left-unbounded {@link Range} (the left bound set to {@link Bound#unbounded()}) with the given right * bound. * - * @param + * @param the type of the range. * @param to the right {@link Bound}, must not be {@literal null}. - * @return + * @return a {@link Range} with the upper bound set to the given value and the lower side unbounded. * @since 2.2 */ public static Range leftUnbounded(Bound to) { @@ -132,9 +133,9 @@ public static Range leftUnbounded(Bound to) { * Creates a right-unbounded {@link Range} (the right bound set to {@link Bound#unbounded()}) with the given left * bound. * - * @param + * @param the type of the range. * @param from the left {@link Bound}, must not be {@literal null}. - * @return + * @return a {@link Range} with the lower bound set to the given value and the upper side unbounded. * @since 2.2 */ public static Range rightUnbounded(Bound from) { @@ -145,7 +146,7 @@ public static Range rightUnbounded(Bound from) { * Create a {@link RangeBuilder} given the lower {@link Bound}. * * @param lower must not be {@literal null}. - * @return + * @return a range builder to continue creating a {@link Range} from the lower bound. * @since 2.0 */ public static RangeBuilder from(Bound lower) { @@ -170,9 +171,9 @@ public static Range of(Bound lowerBound, Bound upperBound) { /** * Creates a new Range with the given value as sole member. * - * @param + * @param the type of the range.> * @param value must not be {@literal null}. - * @return + * @return a range containing the given value. * @see Range#closed(Object, Object) */ public static Range just(T value) { @@ -183,7 +184,7 @@ public static Range just(T value) { * Returns whether the {@link Range} contains the given value. * * @param value must not be {@literal null}. - * @return + * @return {@literal true} if the range contains the value; {@literal false} otherwise. */ @SuppressWarnings({ "unchecked" }) public boolean contains(Comparable value) { @@ -200,7 +201,7 @@ public boolean contains(Comparable value) { * Returns whether the {@link Range} contains the given value. * * @param value must not be {@literal null}. - * @return + * @return {@literal true} if the range contains the value; {@literal false} otherwise. * @since 3.0 */ public boolean contains(T value, Comparator comparator) { @@ -224,7 +225,7 @@ public boolean contains(T value, Comparator comparator) { * @param mapper must not be {@literal null}. If the mapper returns {@code null}, then the corresponding boundary * value represents an {@link Bound#unbounded()} boundary. * @return a new {@link Range} after applying the value to the mapper. - * @param + * @param target type of the mapping function. * @since 3.0 */ public Range map(Function mapper) { @@ -248,7 +249,7 @@ public Range.Bound getUpperBound() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; @@ -267,9 +268,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(lowerBound); - result = 31 * result + ObjectUtils.nullSafeHashCode(upperBound); - return result; + return ObjectUtils.nullSafeHash(lowerBound, upperBound); } /** @@ -313,7 +312,6 @@ public boolean isBounded() { * Creates a boundary including {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound inclusive(T value) { @@ -325,7 +323,6 @@ public static Bound inclusive(T value) { * Creates a boundary including {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound inclusive(int value) { return inclusive((Integer) value); @@ -335,7 +332,6 @@ public static Bound inclusive(int value) { * Creates a boundary including {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound inclusive(long value) { return inclusive((Long) value); @@ -345,7 +341,6 @@ public static Bound inclusive(long value) { * Creates a boundary including {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound inclusive(float value) { return inclusive((Float) value); @@ -355,7 +350,6 @@ public static Bound inclusive(float value) { * Creates a boundary including {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound inclusive(double value) { return inclusive((Double) value); @@ -365,7 +359,6 @@ public static Bound inclusive(double value) { * Creates a boundary excluding {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound exclusive(T value) { @@ -377,7 +370,6 @@ public static Bound exclusive(T value) { * Creates a boundary excluding {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound exclusive(int value) { return exclusive((Integer) value); @@ -387,7 +379,6 @@ public static Bound exclusive(int value) { * Creates a boundary excluding {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound exclusive(long value) { return exclusive((Long) value); @@ -397,7 +388,6 @@ public static Bound exclusive(long value) { * Creates a boundary excluding {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound exclusive(float value) { return exclusive((Float) value); @@ -407,7 +397,6 @@ public static Bound exclusive(float value) { * Creates a boundary excluding {@code value}. * * @param value must not be {@literal null}. - * @return */ public static Bound exclusive(double value) { return exclusive((Double) value); @@ -429,11 +418,6 @@ String toSuffixString() { .orElse("unbounded"); } - @Override - public String toString() { - return value.map(Object::toString).orElse("unbounded"); - } - public Optional getValue() { return this.value; } @@ -442,8 +426,33 @@ public boolean isInclusive() { return this.inclusive; } + /** + * Apply a mapping {@link Function} to the boundary value. + * + * @param mapper must not be {@literal null}. If the mapper returns {@code null}, then the boundary value + * corresponds with {@link Bound#unbounded()}. + * @return a new {@link Bound} after applying the value to the mapper. + * @param + * @since 3.0 + */ + public Bound map(Function mapper) { + + Assert.notNull(mapper, "Mapping function must not be null"); + + return Bound.of(value.map(mapper), inclusive); + } + + private static Bound of(Optional value, boolean inclusive) { + + if (value.isPresent()) { + return new Bound<>(value, inclusive); + } + + return unbounded(); + } + @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; @@ -453,7 +462,7 @@ public boolean equals(Object o) { return false; } - if (!value.isPresent() && !bound.value.isPresent()) { + if (value.isEmpty() && bound.value.isEmpty()) { return true; } @@ -466,7 +475,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - if (!value.isPresent()) { + if (value.isEmpty()) { return ObjectUtils.nullSafeHashCode(value); } @@ -475,29 +484,9 @@ public int hashCode() { return result; } - /** - * Apply a mapping {@link Function} to the boundary value. - * - * @param mapper must not be {@literal null}. If the mapper returns {@code null}, then the boundary value - * corresponds with {@link Bound#unbounded()}. - * @return a new {@link Bound} after applying the value to the mapper. - * @param - * @since 3.0 - */ - public Bound map(Function mapper) { - - Assert.notNull(mapper, "Mapping function must not be null"); - - return Bound.of(value.map(mapper), inclusive); - } - - private static Bound of(Optional value, boolean inclusive) { - - if (value.isPresent()) { - return new Bound<>(value, inclusive); - } - - return unbounded(); + @Override + public String toString() { + return value.map(Object::toString).orElse("unbounded"); } } @@ -521,7 +510,6 @@ public static class RangeBuilder { * Create a {@link Range} given the upper {@link Bound}. * * @param upper must not be {@literal null}. - * @return */ public Range to(Bound upper) { diff --git a/src/main/java/org/springframework/data/domain/ScrollPosition.java b/src/main/java/org/springframework/data/domain/ScrollPosition.java index 6612c71458..5a8d1eba27 100644 --- a/src/main/java/org/springframework/data/domain/ScrollPosition.java +++ b/src/main/java/org/springframework/data/domain/ScrollPosition.java @@ -29,7 +29,7 @@ public interface ScrollPosition { /** * Returns whether the current scroll position is the initial one. * - * @return + * @return {@literal true} if the current scroll position is the initial one. */ boolean isInitial(); @@ -54,7 +54,7 @@ static OffsetScrollPosition offset() { /** * Creates a new {@link ScrollPosition} from an {@code offset}. * - * @param offset + * @param offset the scroll offset. * @return a new {@link OffsetScrollPosition} with the given {@code offset}. */ static OffsetScrollPosition offset(long offset) { @@ -111,4 +111,5 @@ Direction reverse() { return this == FORWARD ? BACKWARD : FORWARD; } } + } diff --git a/src/main/java/org/springframework/data/domain/Slice.java b/src/main/java/org/springframework/data/domain/Slice.java index 624896d61f..8af87889e1 100644 --- a/src/main/java/org/springframework/data/domain/Slice.java +++ b/src/main/java/org/springframework/data/domain/Slice.java @@ -54,35 +54,35 @@ public interface Slice extends Streamable { /** * Returns the page content as {@link List}. * - * @return + * @return the page content as {@link List}. */ List getContent(); /** * Returns whether the {@link Slice} has content at all. * - * @return + * @return {@literal true} if the {@link Slice} has content at all. */ boolean hasContent(); /** * Returns the sorting parameters for the {@link Slice}. * - * @return + * @return the sorting parameters for the {@link Slice}. */ Sort getSort(); /** * Returns whether the current {@link Slice} is the first one. * - * @return + * @return {@literal true} if the current {@link Slice} is the first one. */ boolean isFirst(); /** * Returns whether the current {@link Slice} is the last one. * - * @return + * @return {@literal true} if the current {@link Slice} is the last one. */ boolean isLast(); @@ -103,7 +103,7 @@ public interface Slice extends Streamable { /** * Returns the {@link Pageable} that's been used to request the current {@link Slice}. * - * @return + * @return the {@link Pageable} that's been used to request the current {@link Slice}. * @since 2.0 */ default Pageable getPageable() { @@ -114,7 +114,7 @@ default Pageable getPageable() { * Returns the {@link Pageable} to request the next {@link Slice}. Can be {@link Pageable#unpaged()} in case the * current {@link Slice} is already the last one. Clients should check {@link #hasNext()} before calling this method. * - * @return + * @return the {@link Pageable} to request the next {@link Slice}. * @see #nextOrLastPageable() */ Pageable nextPageable(); @@ -124,26 +124,17 @@ default Pageable getPageable() { * current {@link Slice} is already the first one. Clients should check {@link #hasPrevious()} before calling this * method. * - * @return + * @return the {@link Pageable} to request the previous {@link Slice}. * @see #previousPageable() */ Pageable previousPageable(); - /** - * Returns a new {@link Slice} with the content of the current one mapped by the given {@link Converter}. - * - * @param converter must not be {@literal null}. - * @return a new {@link Slice} with the content of the current one mapped by the given {@link Converter}. - * @since 1.10 - */ - @Override - Slice map(Function converter); - /** * Returns the {@link Pageable} describing the next slice or the one describing the current slice in case it's the * last one. * - * @return + * @return the {@link Pageable} describing the next slice or the one describing the current slice in case it's the + * last one * @since 2.2 */ default Pageable nextOrLastPageable() { @@ -154,10 +145,22 @@ default Pageable nextOrLastPageable() { * Returns the {@link Pageable} describing the previous slice or the one describing the current slice in case it's the * first one. * - * @return + * @return the {@link Pageable} describing the previous slice or the one describing the current slice in case it's the + * first one. * @since 2.2 */ default Pageable previousOrFirstPageable() { return hasPrevious() ? previousPageable() : getPageable(); } + + /** + * Returns a new {@link Slice} with the content of the current one mapped by the given {@link Converter}. + * + * @param converter must not be {@literal null}. + * @return a new {@link Slice} with the content of the current one mapped by the given {@link Converter}. + * @since 1.10 + */ + @Override + Slice map(Function converter); + } diff --git a/src/main/java/org/springframework/data/domain/SliceImpl.java b/src/main/java/org/springframework/data/domain/SliceImpl.java index 018ab6814f..75b4a32916 100644 --- a/src/main/java/org/springframework/data/domain/SliceImpl.java +++ b/src/main/java/org/springframework/data/domain/SliceImpl.java @@ -30,8 +30,7 @@ */ public class SliceImpl extends Chunk { - @Serial - private static final long serialVersionUID = 867755909294344406L; + private static final @Serial long serialVersionUID = 867755909294344406L; private final boolean hasNext; private final Pageable pageable; @@ -71,19 +70,6 @@ public Slice map(Function converter) { return new SliceImpl<>(getConvertedContent(converter), pageable, hasNext); } - @Override - public String toString() { - - String contentType = "UNKNOWN"; - List content = getContent(); - - if (!content.isEmpty()) { - contentType = content.get(0).getClass().getName(); - } - - return String.format("Slice %d containing %s instances", getNumber(), contentType); - } - @Override public boolean equals(@Nullable Object obj) { @@ -100,12 +86,20 @@ public boolean equals(@Nullable Object obj) { @Override public int hashCode() { + return 31 * super.hashCode() + (hasNext ? 1 : 0); + } + + @Override + public String toString() { - int result = 17; + String contentType = "UNKNOWN"; + List content = getContent(); - result += 31 * (hasNext ? 1 : 0); - result += 31 * super.hashCode(); + if (!content.isEmpty()) { + contentType = content.get(0).getClass().getName(); + } - return result; + return String.format("Slice %d containing %s instances", getNumber(), contentType); } + } diff --git a/src/main/java/org/springframework/data/domain/Sort.java b/src/main/java/org/springframework/data/domain/Sort.java index 70bb0d2166..d3dbbb9092 100644 --- a/src/main/java/org/springframework/data/domain/Sort.java +++ b/src/main/java/org/springframework/data/domain/Sort.java @@ -30,6 +30,8 @@ import org.springframework.data.util.MethodInvocationRecorder; import org.springframework.data.util.MethodInvocationRecorder.Recorded; import org.springframework.data.util.Streamable; +import org.springframework.lang.CheckReturnValue; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -160,6 +162,7 @@ public static Sort unsorted() { * * @return a new {@link Sort} with the current setup but descending order direction. */ + @Contract("-> new") public Sort descending() { return withDirection(Direction.DESC); } @@ -169,6 +172,7 @@ public Sort descending() { * * @return a new {@link Sort} with the current setup but ascending order direction. */ + @Contract("-> new") public Sort ascending() { return withDirection(Direction.ASC); } @@ -200,6 +204,8 @@ public boolean isUnsorted() { * @return a new {@link Sort} consisting of the {@link Order}s of the current {@link Sort} combined with the given * ones. */ + @Contract("_ -> new") + @CheckReturnValue public Sort and(Sort sort) { Assert.notNull(sort, "Sort must not be null"); @@ -220,6 +226,7 @@ public Sort and(Sort sort) { * @return a new {@link Sort} object with reversed sort orders applied. * @since 3.1 */ + @Contract("-> new") public Sort reverse() { List reversed = doReverse(); @@ -277,10 +284,7 @@ public boolean equals(@Nullable Object obj) { @Override public int hashCode() { - - int result = 17; - result = 31 * result + orders.hashCode(); - return result; + return orders.hashCode(); } @Override @@ -381,14 +385,14 @@ public enum NullHandling { NATIVE, /** - * A hint to the used data store to order entries with null values before non null entries. + * A hint to the used data store to order entries with null values before non-null entries. */ NULLS_FIRST, /** - * A hint to the used data store to order entries with null values after non null entries. + * A hint to the used data store to order entries with null values after non-null entries. */ - NULLS_LAST; + NULLS_LAST } /** @@ -541,6 +545,8 @@ public boolean isIgnoreCase() { * @param direction the new direction to use. * @return a new {@link Order} with the given {@link Direction} applied. */ + @Contract("_ -> new") + @CheckReturnValue public Order with(Direction direction) { return new Order(direction, this.property, this.ignoreCase, this.nullHandling); } @@ -551,6 +557,7 @@ public Order with(Direction direction) { * @return a reversed {@link Order} with the given {@link Direction} applied. * @since 3.1 */ + @Contract("-> new") public Order reverse() { return with(this.direction == Direction.ASC ? Direction.DESC : Direction.ASC); } @@ -562,6 +569,8 @@ public Order reverse() { * @return a new {@link Order} with the {@code property} name applied. * @since 1.13 */ + @Contract("_ -> new") + @CheckReturnValue public Order withProperty(String property) { return new Order(this.direction, property, this.ignoreCase, this.nullHandling); } @@ -572,6 +581,8 @@ public Order withProperty(String property) { * @param properties properties to sort by. * @return a new {@link Sort} instance for the given properties using {@link #getDirection()}. */ + @Contract("_ -> new") + @CheckReturnValue public Sort withProperties(String... properties) { return Sort.by(this.direction, properties); } @@ -592,6 +603,8 @@ public Order ignoreCase() { * @return a new {@link Order} with the given {@link NullHandling} applied. * @since 1.8 */ + @Contract("_ -> new") + @CheckReturnValue public Order with(NullHandling nullHandling) { return new Order(direction, this.property, ignoreCase, nullHandling); } @@ -602,6 +615,7 @@ public Order with(NullHandling nullHandling) { * @return a new {@link Order} with {@link NullHandling#NULLS_FIRST} as null handling hint applied. * @since 1.8 */ + @Contract("-> new") public Order nullsFirst() { return with(NullHandling.NULLS_FIRST); } @@ -612,6 +626,7 @@ public Order nullsFirst() { * @return a new {@link Order} with {@link NullHandling#NULLS_LAST} as null handling hint applied. * @since 1.7 */ + @Contract("-> new") public Order nullsLast() { return with(NullHandling.NULLS_LAST); } @@ -622,6 +637,7 @@ public Order nullsLast() { * @return a new {@link Order} with {@link NullHandling#NATIVE} as null handling hint applied. * @since 1.7 */ + @Contract("-> new") public Order nullsNative() { return with(NullHandling.NATIVE); } @@ -636,19 +652,6 @@ public NullHandling getNullHandling() { return nullHandling; } - @Override - public int hashCode() { - - int result = 17; - - result = 31 * result + direction.hashCode(); - result = 31 * result + property.hashCode(); - result = 31 * result + (ignoreCase ? 1 : 0); - result = 31 * result + nullHandling.hashCode(); - - return result; - } - @Override public boolean equals(@Nullable Object obj) { @@ -664,6 +667,11 @@ public boolean equals(@Nullable Object obj) { && this.ignoreCase == that.ignoreCase && this.nullHandling.equals(that.nullHandling); } + @Override + public int hashCode() { + return ObjectUtils.nullSafeHash(direction, property, ignoreCase, nullHandling); + } + @Override public String toString() { @@ -679,6 +687,7 @@ public String toString() { return result; } + } /** diff --git a/src/main/java/org/springframework/data/domain/TypedExample.java b/src/main/java/org/springframework/data/domain/TypedExample.java index 99029c0fdf..caeac4eb55 100644 --- a/src/main/java/org/springframework/data/domain/TypedExample.java +++ b/src/main/java/org/springframework/data/domain/TypedExample.java @@ -15,6 +15,7 @@ */ package org.springframework.data.domain; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -49,7 +50,7 @@ public ExampleMatcher getMatcher() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; @@ -68,9 +69,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(probe); - result = 31 * result + ObjectUtils.nullSafeHashCode(matcher); - return result; + return ObjectUtils.nullSafeHash(probe, matcher); } @Override diff --git a/src/main/java/org/springframework/data/domain/TypedExampleMatcher.java b/src/main/java/org/springframework/data/domain/TypedExampleMatcher.java index dbc303fa13..682addac76 100644 --- a/src/main/java/org/springframework/data/domain/TypedExampleMatcher.java +++ b/src/main/java/org/springframework/data/domain/TypedExampleMatcher.java @@ -20,6 +20,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -193,8 +194,9 @@ private PropertySpecifier getOrCreatePropertySpecifier(String propertyPath, Prop return new PropertySpecifier(propertyPath); } + @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; @@ -217,7 +219,6 @@ public boolean equals(Object o) { } if (!ObjectUtils.nullSafeEquals(propertySpecifiers, that.propertySpecifiers)) { - return false; } @@ -230,13 +231,8 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(nullHandler); - result = 31 * result + ObjectUtils.nullSafeHashCode(defaultStringMatcher); - result = 31 * result + ObjectUtils.nullSafeHashCode(propertySpecifiers); - result = 31 * result + ObjectUtils.nullSafeHashCode(ignoredPaths); - result = 31 * result + (defaultIgnoreCase ? 1 : 0); - result = 31 * result + ObjectUtils.nullSafeHashCode(mode); - return result; + return ObjectUtils.nullSafeHash(nullHandler, defaultStringMatcher, propertySpecifiers, ignoredPaths, + defaultIgnoreCase, mode); } @Override diff --git a/src/main/java/org/springframework/data/domain/Unpaged.java b/src/main/java/org/springframework/data/domain/Unpaged.java index 05125b6b90..8e296e6852 100644 --- a/src/main/java/org/springframework/data/domain/Unpaged.java +++ b/src/main/java/org/springframework/data/domain/Unpaged.java @@ -15,6 +15,8 @@ */ package org.springframework.data.domain; +import org.springframework.lang.Nullable; + /** * {@link Pageable} implementation to represent the absence of pagination information. * @@ -91,7 +93,7 @@ public Pageable withPage(int pageNumber) { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; } diff --git a/src/main/java/org/springframework/data/domain/Window.java b/src/main/java/org/springframework/data/domain/Window.java index d5c220b27c..1b2d64192d 100644 --- a/src/main/java/org/springframework/data/domain/Window.java +++ b/src/main/java/org/springframework/data/domain/Window.java @@ -41,7 +41,6 @@ public interface Window extends Streamable { * @param items the list of data. * @param positionFunction the list of data. * @return the {@link Window}. - * @param */ static Window from(List items, IntFunction positionFunction) { return new WindowImpl<>(items, positionFunction, false); @@ -54,7 +53,6 @@ static Window from(List items, IntFunction p * @param positionFunction the list of data. * @param hasNext * @return the {@link Window}. - * @param */ static Window from(List items, IntFunction positionFunction, boolean hasNext) { return new WindowImpl<>(items, positionFunction, hasNext); @@ -78,14 +76,14 @@ static Window from(List items, IntFunction p /** * Returns the windows content as {@link List}. * - * @return + * @return the windows content as {@link List}. */ List getContent(); /** * Returns whether the current window is the last one. * - * @return + * @return {@literal true} if the current window is the last one. */ default boolean isLast() { return !hasNext(); @@ -101,13 +99,14 @@ default boolean isLast() { /** * Returns whether the underlying scroll mechanism can provide a {@link ScrollPosition} at {@code index}. * - * @param index + * @param index the result index to check for a {@link ScrollPosition}. * @return {@code true} if a {@link ScrollPosition} can be created; {@code false} otherwise. * @see #positionAt(int) */ default boolean hasPosition(int index) { try { - return positionAt(index) != null; + positionAt(index); + return true; } catch (IllegalStateException e) { return false; } @@ -116,8 +115,8 @@ default boolean hasPosition(int index) { /** * Returns the {@link ScrollPosition} at {@code index}. * - * @param index - * @return + * @param index index of the window element to determine the scroll position for. + * @return the scroll position for the given object index. * @throws IndexOutOfBoundsException if the index is out of range ({@code index < 0 || index >= size()}). * @throws IllegalStateException if the underlying scroll mechanism cannot provide a scroll position for the given * object. @@ -127,8 +126,8 @@ default boolean hasPosition(int index) { /** * Returns the {@link ScrollPosition} for {@code object}. * - * @param object - * @return + * @param object member of the window to determine the scroll position for. + * @return the scroll position for the given object. * @throws NoSuchElementException if the object is not part of the result. * @throws IllegalStateException if the underlying scroll mechanism cannot provide a scroll position for the given * object. diff --git a/src/main/java/org/springframework/data/domain/WindowImpl.java b/src/main/java/org/springframework/data/domain/WindowImpl.java index cd00006630..ebd9654880 100644 --- a/src/main/java/org/springframework/data/domain/WindowImpl.java +++ b/src/main/java/org/springframework/data/domain/WindowImpl.java @@ -22,6 +22,8 @@ import java.util.stream.Collectors; import org.jetbrains.annotations.NotNull; + +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -86,19 +88,23 @@ public Window map(Function converter) { return new WindowImpl<>(stream().map(converter).collect(Collectors.toList()), positionFunction, hasNext); } - @NotNull @Override public Iterator iterator() { return items.iterator(); } @Override - public boolean equals(Object o) { - if (this == o) + public boolean equals(@Nullable Object o) { + + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; + } + WindowImpl that = (WindowImpl) o; + return ObjectUtils.nullSafeEquals(items, that.items) && ObjectUtils.nullSafeEquals(positionFunction, that.positionFunction) && ObjectUtils.nullSafeEquals(hasNext, that.hasNext); @@ -106,9 +112,11 @@ public boolean equals(Object o) { @Override public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(items); result = 31 * result + ObjectUtils.nullSafeHashCode(positionFunction); result = 31 * result + ObjectUtils.nullSafeHashCode(hasNext); + return result; } diff --git a/src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java b/src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java index e069a5c45c..a86c3d28bd 100644 --- a/src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java +++ b/src/main/java/org/springframework/data/domain/jaxb/OrderAdapter.java @@ -20,6 +20,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Order; import org.springframework.data.domain.jaxb.SpringDataJaxb.OrderDto; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; /** @@ -46,6 +47,7 @@ public OrderDto marshal(@Nullable Order order) { } @Nullable + @Contract("null -> null") @Override public Order unmarshal(@Nullable OrderDto source) { diff --git a/src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java b/src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java index ab213301c2..e0db1a5ba4 100644 --- a/src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java +++ b/src/main/java/org/springframework/data/domain/jaxb/PageAdapter.java @@ -23,6 +23,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.jaxb.SpringDataJaxb.PageDto; import org.springframework.hateoas.Link; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; /** @@ -33,6 +34,7 @@ public class PageAdapter extends XmlAdapter> { @Nullable + @Contract("null -> null; !null -> !null") @Override public PageDto marshal(@Nullable Page source) { @@ -48,6 +50,7 @@ public PageDto marshal(@Nullable Page source) { } @Nullable + @Contract("_ -> null") @Override public Page unmarshal(@Nullable PageDto v) { return null; diff --git a/src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java b/src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java index 5032717374..4202a8ac5b 100644 --- a/src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java +++ b/src/main/java/org/springframework/data/domain/jaxb/SortAdapter.java @@ -19,6 +19,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.domain.jaxb.SpringDataJaxb.SortDto; +import org.springframework.lang.Contract; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @@ -32,6 +33,7 @@ public class SortAdapter extends XmlAdapter { public static final SortAdapter INSTANCE = new SortAdapter(); @Nullable + @Contract("null -> null; !null -> !null") @Override public SortDto marshal(@Nullable Sort source) { diff --git a/src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java b/src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java index 496395e9ca..a34b06bda7 100644 --- a/src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java +++ b/src/main/java/org/springframework/data/domain/jaxb/SpringDataJaxb.java @@ -109,7 +109,7 @@ public static class PageDto extends RepresentationModel { * @param adapter must not be {@literal null}. * @return */ - public static List unmarshal(Collection source, XmlAdapter adapter) { + public static List unmarshal(@Nullable Collection source, XmlAdapter adapter) { Assert.notNull(adapter, "Adapter must not be null"); diff --git a/src/main/java/org/springframework/data/geo/Box.java b/src/main/java/org/springframework/data/geo/Box.java index 424ac930ae..fc44090b98 100644 --- a/src/main/java/org/springframework/data/geo/Box.java +++ b/src/main/java/org/springframework/data/geo/Box.java @@ -15,8 +15,11 @@ */ package org.springframework.data.geo; +import java.io.Serial; + import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * Represents a geospatial box value @@ -28,7 +31,7 @@ */ public class Box implements Shape { - private static final long serialVersionUID = 8198095179084040711L; + private static final @Serial long serialVersionUID = 8198095179084040711L; private final Point first; private final Point second; @@ -66,7 +69,7 @@ public Box(double[] first, double[] second) { /** * Returns the first {@link Point} making up the {@link Box}. * - * @return + * @return the first {@link Point} making up the {@link Box}. */ public Point getFirst() { return first; @@ -75,26 +78,15 @@ public Point getFirst() { /** * Returns the second {@link Point} making up the {@link Box}. * - * @return + * @return the second {@link Point} making up the {@link Box}. */ public Point getSecond() { return second; } - @Override - public String toString() { - return String.format("Box [%s, %s]", first, second); - } - @Override public int hashCode() { - - int result = 31; - - result += 17 * first.hashCode(); - result += 17 * second.hashCode(); - - return result; + return ObjectUtils.nullSafeHash(first, second); } @Override @@ -110,4 +102,9 @@ public boolean equals(@Nullable Object obj) { return this.first.equals(that.first) && this.second.equals(that.second); } + + @Override + public String toString() { + return String.format("Box [%s, %s]", first, second); + } } diff --git a/src/main/java/org/springframework/data/geo/Circle.java b/src/main/java/org/springframework/data/geo/Circle.java index 13bf640dbf..3edaecfec2 100644 --- a/src/main/java/org/springframework/data/geo/Circle.java +++ b/src/main/java/org/springframework/data/geo/Circle.java @@ -15,7 +15,10 @@ */ package org.springframework.data.geo; -import org.springframework.data.annotation.PersistenceConstructor; +import java.io.Serial; + +import org.springframework.data.annotation.PersistenceCreator; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -29,7 +32,7 @@ */ public class Circle implements Shape { - private static final long serialVersionUID = 5215611530535947924L; + private static final @Serial long serialVersionUID = 5215611530535947924L; private final Point center; private final Distance radius; @@ -40,7 +43,7 @@ public class Circle implements Shape { * @param center must not be {@literal null}. * @param radius must not be {@literal null} and it's value greater or equal to zero. */ - @PersistenceConstructor + @PersistenceCreator public Circle(Point center, Distance radius) { Assert.notNull(center, "Center point must not be null"); @@ -65,8 +68,8 @@ public Circle(Point center, double radius) { * Creates a new {@link Circle} from the given coordinates and radius as {@link Distance} with a * {@link Metrics#NEUTRAL}. * - * @param centerX - * @param centerY + * @param centerX X coordinate of the center point. + * @param centerY Y coordinate of the center point. * @param radius must be greater or equal to zero. */ public Circle(double centerX, double centerY, double radius) { @@ -85,14 +88,14 @@ public Point getCenter() { /** * Returns the radius of the {@link Circle}. * - * @return + * @return the radius. */ public Distance getRadius() { return radius; } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; @@ -111,9 +114,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(center); - result = 31 * result + ObjectUtils.nullSafeHashCode(radius); - return result; + return ObjectUtils.nullSafeHash(center, radius); } @Override diff --git a/src/main/java/org/springframework/data/geo/CustomMetric.java b/src/main/java/org/springframework/data/geo/CustomMetric.java index 6e6dd83ab2..d6354447ba 100644 --- a/src/main/java/org/springframework/data/geo/CustomMetric.java +++ b/src/main/java/org/springframework/data/geo/CustomMetric.java @@ -15,6 +15,8 @@ */ package org.springframework.data.geo; +import java.io.Serial; + import org.springframework.util.Assert; /** @@ -26,7 +28,7 @@ */ public class CustomMetric implements Metric { - private static final long serialVersionUID = -2972074177454114228L; + private static final @Serial long serialVersionUID = -2972074177454114228L; private final double multiplier; private final String abbreviation; @@ -34,7 +36,7 @@ public class CustomMetric implements Metric { /** * Creates a custom {@link Metric} using the given multiplier. * - * @param multiplier + * @param multiplier metric multiplier. */ public CustomMetric(double multiplier) { @@ -44,7 +46,7 @@ public CustomMetric(double multiplier) { /** * Creates a custom {@link Metric} using the given multiplier and abbreviation. * - * @param multiplier + * @param multiplier metric multiplier. * @param abbreviation must not be {@literal null}. */ public CustomMetric(double multiplier, String abbreviation) { diff --git a/src/main/java/org/springframework/data/geo/Distance.java b/src/main/java/org/springframework/data/geo/Distance.java index 246ecdd036..efbf71b12c 100644 --- a/src/main/java/org/springframework/data/geo/Distance.java +++ b/src/main/java/org/springframework/data/geo/Distance.java @@ -15,10 +15,13 @@ */ package org.springframework.data.geo; +import java.io.Serial; import java.io.Serializable; import org.springframework.data.domain.Range; import org.springframework.data.domain.Range.Bound; +import org.springframework.lang.CheckReturnValue; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -32,7 +35,7 @@ */ public final class Distance implements Serializable, Comparable { - private static final long serialVersionUID = 2460886201934027744L; + private static final @Serial long serialVersionUID = 2460886201934027744L; /** * The distance value in the current {@link Metric}. @@ -47,7 +50,7 @@ public final class Distance implements Serializable, Comparable { /** * Creates a new {@link Distance} with a neutral metric. This means the provided value needs to be in normalized form. * - * @param value + * @param value distance value. */ public Distance(double value) { this(value, Metrics.NEUTRAL); @@ -81,11 +84,11 @@ public static Range between(Distance min, Distance max) { /** * Creates a new {@link Range} by creating minimum and maximum {@link Distance} from the given values. * - * @param minValue + * @param minValue minimum value. * @param minMetric can be {@literal null}. - * @param maxValue + * @param maxValue maximum value. * @param maxMetric can be {@literal null}. - * @return + * @return the {@link Range} between the given values. */ public static Range between(double minValue, Metric minMetric, double maxValue, Metric maxMetric) { return between(new Distance(minValue, minMetric), new Distance(maxValue, maxMetric)); @@ -94,7 +97,7 @@ public static Range between(double minValue, Metric minMetric, double /** * Returns the normalized value regarding the underlying {@link Metric}. * - * @return + * @return the normalized value. */ public double getNormalizedValue() { return value / metric.getMultiplier(); @@ -115,8 +118,10 @@ public String getUnit() { * current one. * * @param other must not be {@literal null}. - * @return + * @return sum of this and the other distance. */ + @Contract("_ -> new") + @CheckReturnValue public Distance add(Distance other) { Assert.notNull(other, "Distance to add must not be null"); @@ -131,8 +136,9 @@ public Distance add(Distance other) { * * @param other must not be {@literal null}. * @param metric must not be {@literal null}. - * @return + * @return sum of this and the other distance. */ + @Contract("_, _ -> new") public Distance add(Distance other, Metric metric) { Assert.notNull(other, "Distance to must not be null"); @@ -149,8 +155,10 @@ public Distance add(Distance other, Metric metric) { * same normalized value as the original instance. * * @param metric must not be {@literal null}. - * @return + * @return the converted {@link Distance}. */ + @Contract("_ -> new") + @CheckReturnValue public Distance in(Metric metric) { Assert.notNull(metric, "Metric must not be null"); @@ -170,19 +178,6 @@ public int compareTo(@Nullable Distance that) { return difference == 0 ? 0 : difference > 0 ? 1 : -1; } - @Override - public String toString() { - - StringBuilder builder = new StringBuilder(); - builder.append(value); - - if (metric != Metrics.NEUTRAL) { - builder.append(" ").append(metric.toString()); - } - - return builder.toString(); - } - public double getValue() { return this.value; } @@ -192,7 +187,7 @@ public Metric getMetric() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; @@ -205,16 +200,25 @@ public boolean equals(Object o) { if (value != distance.value) { return false; } + return ObjectUtils.nullSafeEquals(metric, distance.metric); } @Override public int hashCode() { - int result; - long temp; - temp = Double.doubleToLongBits(value); - result = (int) (temp ^ (temp >>> 32)); - result = 31 * result + ObjectUtils.nullSafeHashCode(metric); - return result; + return ObjectUtils.nullSafeHash(value, metric); + } + + @Override + public String toString() { + + StringBuilder builder = new StringBuilder(); + builder.append(value); + + if (metric != Metrics.NEUTRAL) { + builder.append(" ").append(metric.toString()); + } + + return builder.toString(); } } diff --git a/src/main/java/org/springframework/data/geo/GeoModule.java b/src/main/java/org/springframework/data/geo/GeoModule.java index 6e903c51ca..9a2f5ac133 100644 --- a/src/main/java/org/springframework/data/geo/GeoModule.java +++ b/src/main/java/org/springframework/data/geo/GeoModule.java @@ -15,6 +15,7 @@ */ package org.springframework.data.geo; +import java.io.Serial; import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -30,9 +31,10 @@ * @author Oliver Gierke * @since 1.8 */ +@SuppressWarnings("unused") public class GeoModule extends SimpleModule { - private static final long serialVersionUID = 1L; + private static final @Serial long serialVersionUID = 1L; /** * Creates a new {@link GeoModule} registering mixins for common geo-spatial types. diff --git a/src/main/java/org/springframework/data/geo/GeoPage.java b/src/main/java/org/springframework/data/geo/GeoPage.java index 7efedb6445..b697089b99 100644 --- a/src/main/java/org/springframework/data/geo/GeoPage.java +++ b/src/main/java/org/springframework/data/geo/GeoPage.java @@ -15,6 +15,8 @@ */ package org.springframework.data.geo; +import java.io.Serial; + import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -31,7 +33,7 @@ */ public class GeoPage extends PageImpl> { - private static final long serialVersionUID = -5655267379242128600L; + private static final @Serial long serialVersionUID = -5655267379242128600L; /** * The average distance of the underlying results. @@ -55,7 +57,7 @@ public GeoPage(GeoResults results) { * * @param results must not be {@literal null}. * @param pageable must not be {@literal null}. - * @param total + * @param total total number of results. */ public GeoPage(GeoResults results, Pageable pageable, long total) { @@ -64,6 +66,10 @@ public GeoPage(GeoResults results, Pageable pageable, long total) { this.averageDistance = results.getAverageDistance(); } + public Distance getAverageDistance() { + return this.averageDistance; + } + @Override public boolean equals(@Nullable Object obj) { @@ -82,8 +88,4 @@ public boolean equals(@Nullable Object obj) { public int hashCode() { return super.hashCode() + ObjectUtils.nullSafeHashCode(this.averageDistance); } - - public Distance getAverageDistance() { - return this.averageDistance; - } } diff --git a/src/main/java/org/springframework/data/geo/GeoResult.java b/src/main/java/org/springframework/data/geo/GeoResult.java index 4ff9fc6a67..7ee7de64d6 100644 --- a/src/main/java/org/springframework/data/geo/GeoResult.java +++ b/src/main/java/org/springframework/data/geo/GeoResult.java @@ -15,8 +15,10 @@ */ package org.springframework.data.geo; +import java.io.Serial; import java.io.Serializable; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -29,7 +31,7 @@ */ public final class GeoResult implements Serializable { - private static final long serialVersionUID = 1637452570977581370L; + private static final @Serial long serialVersionUID = 1637452570977581370L; private final T content; private final Distance distance; @@ -52,7 +54,7 @@ public Distance getDistance() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; @@ -71,9 +73,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(content); - result = 31 * result + ObjectUtils.nullSafeHashCode(distance); - return result; + return ObjectUtils.nullSafeHash(content, distance); } @Override diff --git a/src/main/java/org/springframework/data/geo/GeoResults.java b/src/main/java/org/springframework/data/geo/GeoResults.java index 7913ecbf9b..837032fbf9 100644 --- a/src/main/java/org/springframework/data/geo/GeoResults.java +++ b/src/main/java/org/springframework/data/geo/GeoResults.java @@ -16,12 +16,14 @@ package org.springframework.data.geo; +import java.io.Serial; import java.io.Serializable; import java.util.Collections; import java.util.Iterator; import java.util.List; -import org.springframework.data.annotation.PersistenceConstructor; +import org.springframework.data.annotation.PersistenceCreator; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -35,7 +37,7 @@ */ public class GeoResults implements Iterable>, Serializable { - private static final long serialVersionUID = 8347363491300219485L; + private static final @Serial long serialVersionUID = 8347363491300219485L; private final List> results; private final Distance averageDistance; @@ -67,7 +69,7 @@ public GeoResults(List> results, Metric metric) { * @param results must not be {@literal null}. * @param averageDistance must not be {@literal null}. */ - @PersistenceConstructor + @PersistenceCreator public GeoResults(List> results, Distance averageDistance) { Assert.notNull(results, "Results must not be null"); @@ -89,19 +91,20 @@ public Distance getAverageDistance() { /** * Returns the actual content of the {@link GeoResults}. * - * @return + * @return the actual content. */ public List> getContent() { return Collections.unmodifiableList(results); } + @Override @SuppressWarnings("unchecked") public Iterator> iterator() { return (Iterator>) results.iterator(); } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; @@ -120,9 +123,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(results); - result = 31 * result + ObjectUtils.nullSafeHashCode(averageDistance); - return result; + return ObjectUtils.nullSafeHash(results, averageDistance); } @Override diff --git a/src/main/java/org/springframework/data/geo/Point.java b/src/main/java/org/springframework/data/geo/Point.java index 8a79d509fa..1015426e79 100644 --- a/src/main/java/org/springframework/data/geo/Point.java +++ b/src/main/java/org/springframework/data/geo/Point.java @@ -15,12 +15,14 @@ */ package org.springframework.data.geo; +import java.io.Serial; import java.io.Serializable; import java.util.Locale; -import org.springframework.data.annotation.PersistenceConstructor; +import org.springframework.data.annotation.PersistenceCreator; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * Represents a geospatial point value. @@ -32,7 +34,7 @@ */ public class Point implements Serializable { - private static final long serialVersionUID = 3583151228933783558L; + private static final @Serial long serialVersionUID = 3583151228933783558L; private final double x; private final double y; @@ -40,10 +42,10 @@ public class Point implements Serializable { /** * Creates a {@link Point} from the given {@code x}, {@code y} coordinate. * - * @param x - * @param y + * @param x x coordinate. + * @param y y coordinate. */ - @PersistenceConstructor + @PersistenceCreator public Point(double x, double y) { this.x = x; this.y = y; @@ -65,7 +67,7 @@ public Point(Point point) { /** * Returns the x-coordinate of the {@link Point}. * - * @return + * @return the x-coordinate of the {@link Point}. */ public double getX() { return x; @@ -74,7 +76,7 @@ public double getX() { /** * Returns the y-coordinate of the {@link Point}. * - * @return + * @return the y-coordinate of the {@link Point}. */ public double getY() { return y; @@ -82,16 +84,7 @@ public double getY() { @Override public int hashCode() { - - int result = 1; - - long temp = Double.doubleToLongBits(x); - result = 31 * result + (int) (temp ^ temp >>> 32); - - temp = Double.doubleToLongBits(y); - result = 31 * result + (int) (temp ^ temp >>> 32); - - return result; + return ObjectUtils.nullSafeHash(x, y); } @Override diff --git a/src/main/java/org/springframework/data/geo/Polygon.java b/src/main/java/org/springframework/data/geo/Polygon.java index 9759994a2e..36e0c73b85 100644 --- a/src/main/java/org/springframework/data/geo/Polygon.java +++ b/src/main/java/org/springframework/data/geo/Polygon.java @@ -16,13 +16,15 @@ package org.springframework.data.geo; +import java.io.Serial; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; -import org.springframework.data.annotation.PersistenceConstructor; +import org.springframework.data.annotation.PersistenceCreator; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -36,7 +38,7 @@ */ public class Polygon implements Iterable, Shape { - private static final long serialVersionUID = -2705040068154648988L; + private static final @Serial long serialVersionUID = -2705040068154648988L; private final List points; @@ -46,7 +48,7 @@ public class Polygon implements Iterable, Shape { * @param x must not be {@literal null}. * @param y must not be {@literal null}. * @param z must not be {@literal null}. - * @param others + * @param others other points. */ public Polygon(Point x, Point y, Point z, Point... others) { @@ -67,7 +69,7 @@ public Polygon(Point x, Point y, Point z, Point... others) { * * @param points must not be {@literal null}. */ - @PersistenceConstructor + @PersistenceCreator public Polygon(List points) { Assert.notNull(points, "Points must not be null"); @@ -92,12 +94,13 @@ public List getPoints() { return this.points; } + @Override public Iterator iterator() { return this.points.iterator(); } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; diff --git a/src/main/java/org/springframework/data/geo/format/DistanceFormatter.java b/src/main/java/org/springframework/data/geo/format/DistanceFormatter.java index 90a4648ea2..cb9dca06ec 100644 --- a/src/main/java/org/springframework/data/geo/format/DistanceFormatter.java +++ b/src/main/java/org/springframework/data/geo/format/DistanceFormatter.java @@ -27,6 +27,7 @@ import org.springframework.data.geo.Metric; import org.springframework.data.geo.Metrics; import org.springframework.format.Formatter; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; @@ -57,15 +58,17 @@ public enum DistanceFormatter implements Converter, Formatter< SUPPORTED_METRICS = Collections.unmodifiableMap(metrics); } + @Contract("null -> null; !null -> !null") @Nullable @Override - public final Distance convert(String source) { + public final Distance convert(@Nullable String source) { return source == null ? null : doConvert(source.trim().toLowerCase(Locale.US)); } @Override - public String print(Distance distance, Locale locale) { - return distance == null ? null : String.format("%s%s", distance.getValue(), distance.getUnit().toLowerCase(locale)); + public String print(@Nullable Distance distance, Locale locale) { + return distance == null ? "null" + : String.format("%s%s", distance.getValue(), distance.getUnit().toLowerCase(locale)); } @Override @@ -78,7 +81,6 @@ public Distance parse(String text, Locale locale) throws ParseException { * in the {@link #SUPPORTED_METRICS} map. * * @param source must not be {@literal null}. - * @return */ private static Distance doConvert(String source) { @@ -101,7 +103,6 @@ private static Distance doConvert(String source) { * * @param source the raw source {@link String}, must not be {@literal null} or empty. * @param metric the {@link Metric} detected keyed by the keyword it was detected for, must not be {@literal null}. - * @return */ private static Distance fromString(String source, Entry metric) { diff --git a/src/main/java/org/springframework/data/geo/format/PointFormatter.java b/src/main/java/org/springframework/data/geo/format/PointFormatter.java index fb7b5d9d86..67d0cd2bb7 100644 --- a/src/main/java/org/springframework/data/geo/format/PointFormatter.java +++ b/src/main/java/org/springframework/data/geo/format/PointFormatter.java @@ -23,6 +23,7 @@ import org.springframework.data.geo.Point; import org.springframework.format.Formatter; import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; /** * Converter to parse two comma-separated doubles into a {@link Point}. @@ -60,8 +61,8 @@ public Point convert(String source) { } @Override - public String print(Point point, Locale locale) { - return point == null ? null : String.format("%s,%s", point.getY(), point.getX()); + public String print(@Nullable Point point, Locale locale) { + return point == null ? "null" : String.format("%s,%s", point.getY(), point.getX()); } @Override diff --git a/src/main/java/org/springframework/data/history/RevisionSort.java b/src/main/java/org/springframework/data/history/RevisionSort.java index 5aee862498..973903640e 100644 --- a/src/main/java/org/springframework/data/history/RevisionSort.java +++ b/src/main/java/org/springframework/data/history/RevisionSort.java @@ -15,6 +15,7 @@ */ package org.springframework.data.history; +import java.io.Serial; import java.util.Arrays; import org.springframework.data.domain.Sort; @@ -30,7 +31,7 @@ */ public class RevisionSort extends Sort { - private static final long serialVersionUID = 618238321589063537L; + private static final @Serial long serialVersionUID = 618238321589063537L; private static final String PROPERTY = "__revisionNumber__"; private static final RevisionSort ASC = new RevisionSort(Direction.ASC); diff --git a/src/main/java/org/springframework/data/mapping/Alias.java b/src/main/java/org/springframework/data/mapping/Alias.java index 7d581285b6..a12af2a293 100644 --- a/src/main/java/org/springframework/data/mapping/Alias.java +++ b/src/main/java/org/springframework/data/mapping/Alias.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mapping; +import java.util.NoSuchElementException; import java.util.Objects; import org.springframework.lang.Nullable; @@ -41,9 +42,9 @@ public final class Alias { @SuppressWarnings("null") // public static final Alias NONE = new Alias(null); - private final Object value; + private final @Nullable Object value; - private Alias(Object value) { + private Alias(@Nullable Object value) { this.value = value; } @@ -104,7 +105,7 @@ public boolean hasValue(Object that) { } /** - * Returns whether the the current alias is present and has the same value as the given {@link Alias}. + * Returns whether the current alias is present and has the same value as the given {@link Alias}. * * @param other the other {@link Alias} * @return {@literal true} if there's an alias value present and its equal to the one in the given {@link Alias}. @@ -120,6 +121,14 @@ public boolean isPresent() { return value != null; } + /** + * @return {@literal true} if this {@link Alias} does not contain a value. + * @since 4.0 + */ + public boolean isEmpty() { + return value == null; + } + /** * Return the value typed to {@code type} if the value is present and assignable to {@code type}. * @@ -135,15 +144,27 @@ public T mapTyped(Class type) { return isPresent() && type.isInstance(value) ? (T) value : null; } - @Override - public String toString() { - return isPresent() ? value.toString() : "NONE"; - } - + @Nullable public Object getValue() { return this.value; } + /** + * Retrieve the required value or throw {@link NoSuchElementException} if the value is {@link #isEmpty() absent}. + * + * @return the required value. + */ + public Object getRequiredValue() { + + Object value = getValue(); + + if (value == null) { + throw new NoSuchElementException("No value present"); + } + + return value; + } + @Override public boolean equals(@Nullable Object o) { @@ -162,4 +183,9 @@ public boolean equals(@Nullable Object o) { public int hashCode() { return Objects.hashCode(value); } + + @Override + public String toString() { + return isPresent() ? value.toString() : "NONE"; + } } diff --git a/src/main/java/org/springframework/data/mapping/Association.java b/src/main/java/org/springframework/data/mapping/Association.java index 02533692b1..ca7663b7a7 100644 --- a/src/main/java/org/springframework/data/mapping/Association.java +++ b/src/main/java/org/springframework/data/mapping/Association.java @@ -32,8 +32,8 @@ public class Association

> { /** * Creates a new {@link Association} between the two given {@link PersistentProperty}s. * - * @param inverse - * @param obverse + * @param inverse the inverse {@link PersistentProperty}. + * @param obverse the obverse {@link PersistentProperty}. Can be {@literal null} if absent. */ public Association(P inverse, @Nullable P obverse) { this.inverse = inverse; diff --git a/src/main/java/org/springframework/data/mapping/MappingException.java b/src/main/java/org/springframework/data/mapping/MappingException.java index 7545ce9879..9ccc20b730 100644 --- a/src/main/java/org/springframework/data/mapping/MappingException.java +++ b/src/main/java/org/springframework/data/mapping/MappingException.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mapping; +import java.io.Serial; + import org.springframework.lang.Nullable; /** @@ -22,7 +24,7 @@ */ public class MappingException extends RuntimeException { - private static final long serialVersionUID = 1L; + private static final @Serial long serialVersionUID = 1L; public MappingException(@Nullable String s) { super(s); diff --git a/src/main/java/org/springframework/data/mapping/Parameter.java b/src/main/java/org/springframework/data/mapping/Parameter.java index 1254c2a37d..73e367e256 100644 --- a/src/main/java/org/springframework/data/mapping/Parameter.java +++ b/src/main/java/org/springframework/data/mapping/Parameter.java @@ -156,6 +156,7 @@ public String getValueExpression() { * @return the expression to be used when looking up a source data structure. * @since 3.3 */ + @SuppressWarnings("DataFlowIssue") public String getRequiredValueExpression() { if (!hasValueExpression()) { diff --git a/src/main/java/org/springframework/data/mapping/PropertyReferenceException.java b/src/main/java/org/springframework/data/mapping/PropertyReferenceException.java index 58784115d1..a21c9347c2 100644 --- a/src/main/java/org/springframework/data/mapping/PropertyReferenceException.java +++ b/src/main/java/org/springframework/data/mapping/PropertyReferenceException.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mapping; +import java.io.Serial; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -37,7 +38,7 @@ */ public class PropertyReferenceException extends RuntimeException { - private static final long serialVersionUID = -5254424051438976570L; + private static final @Serial long serialVersionUID = -5254424051438976570L; static final String ERROR_TEMPLATE = "No property '%s' found for type '%s'"; static final String HINTS_TEMPLATE = "Did you mean %s"; diff --git a/src/main/java/org/springframework/data/mapping/callback/DefaultReactiveEntityCallbacks.java b/src/main/java/org/springframework/data/mapping/callback/DefaultReactiveEntityCallbacks.java index e61c5fac27..0d2c5a3afc 100644 --- a/src/main/java/org/springframework/data/mapping/callback/DefaultReactiveEntityCallbacks.java +++ b/src/main/java/org/springframework/data/mapping/callback/DefaultReactiveEntityCallbacks.java @@ -99,6 +99,7 @@ public void addEntityCallback(EntityCallback callback) { static class DefaultReactiveEntityCallbackInvoker implements ReactiveEntityCallbackInvoker { + @SuppressWarnings("unchecked") @Override public Mono invokeCallback(EntityCallback callback, T entity, BiFunction, T, Object> callbackInvokerFunction) { diff --git a/src/main/java/org/springframework/data/mapping/callback/EntityCallbackDiscoverer.java b/src/main/java/org/springframework/data/mapping/callback/EntityCallbackDiscoverer.java index 8df9129766..4f487ea90d 100644 --- a/src/main/java/org/springframework/data/mapping/callback/EntityCallbackDiscoverer.java +++ b/src/main/java/org/springframework/data/mapping/callback/EntityCallbackDiscoverer.java @@ -53,11 +53,8 @@ class EntityCallbackDiscoverer { private final CallbackRetriever defaultRetriever = new CallbackRetriever(); private final Map retrieverCache = new ConcurrentHashMap<>(64); - private final Map, ResolvableType> entityTypeCache = new ConcurrentHashMap<>(64); - @Nullable private ClassLoader beanClassLoader; - - private Object retrievalMutex = this.defaultRetriever; + private @Nullable ClassLoader beanClassLoader; /** * Create a new {@link EntityCallback} instance. @@ -76,7 +73,7 @@ void addEntityCallback(EntityCallback callback) { Assert.notNull(callback, "Callback must not be null"); - synchronized (this.retrievalMutex) { + synchronized (this.defaultRetriever) { // Explicitly remove target for a proxy, if registered already, // in order to avoid double invocations of the same callback. @@ -91,14 +88,6 @@ void addEntityCallback(EntityCallback callback) { } } - void removeEntityCallback(EntityCallback callback) { - - synchronized (this.retrievalMutex) { - this.defaultRetriever.entityCallbacks.remove(callback); - this.retrieverCache.clear(); - } - } - /** * Return a {@link Collection} of all {@link EntityCallback}s matching the given entity type. Non-matching callbacks * get excluded early. @@ -112,8 +101,7 @@ void removeEntityCallback(EntityCallback callback) { @SuppressWarnings({ "unchecked", "rawtypes" }) Collection> getEntityCallbacks(Class entity, ResolvableType callbackType) { - Class sourceType = entity; - CallbackCacheKey cacheKey = new CallbackCacheKey(callbackType, sourceType); + CallbackCacheKey cacheKey = new CallbackCacheKey(callbackType, entity); // Quick check for existing entry on ConcurrentHashMap... CallbackRetriever retriever = this.retrieverCache.get(cacheKey); @@ -122,16 +110,16 @@ Collection> getEntityCallbacks(Class entit } if (this.beanClassLoader == null || ClassUtils.isCacheSafe(entity, this.beanClassLoader) - && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) { + && ClassUtils.isCacheSafe(entity, this.beanClassLoader)) { // Fully synchronized building and caching of a CallbackRetriever - synchronized (this.retrievalMutex) { + synchronized (this.defaultRetriever) { retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return (Collection) retriever.getEntityCallbacks(); } retriever = new CallbackRetriever(); - Collection> callbacks = retrieveEntityCallbacks(ResolvableType.forClass(sourceType), + Collection> callbacks = retrieveEntityCallbacks(ResolvableType.forClass(entity), callbackType, retriever); this.retrieverCache.put(cacheKey, retriever); return (Collection) callbacks; @@ -142,19 +130,6 @@ Collection> getEntityCallbacks(Class entit } } - @Nullable - ResolvableType resolveDeclaredEntityType(Class callbackType) { - - ResolvableType eventType = entityTypeCache.get(callbackType); - - if (eventType == null) { - eventType = ResolvableType.forClass(callbackType).as(EntityCallback.class).getGeneric(); - entityTypeCache.put(callbackType, eventType); - } - - return eventType != ResolvableType.NONE ? eventType : null; - } - /** * Actually retrieve the callbacks for the given entity and callback type. * @@ -169,7 +144,7 @@ private Collection> retrieveEntityCallbacks(ResolvableType ent List> allCallbacks = new ArrayList<>(); Set> callbacks; - synchronized (this.retrievalMutex) { + synchronized (this.defaultRetriever) { callbacks = new LinkedHashSet<>(this.defaultRetriever.entityCallbacks); } @@ -211,15 +186,12 @@ public void setBeanFactory(BeanFactory beanFactory) { if (this.beanClassLoader == null) { this.beanClassLoader = cbf.getBeanClassLoader(); } - - this.retrievalMutex = cbf.getSingletonMutex(); } defaultRetriever.discoverEntityCallbacks(beanFactory); this.retrieverCache.clear(); } - @Nullable static Method lookupCallbackMethod(Class callbackType, Class entityType, Object[] args) { Collection methods = new ArrayList<>(1); @@ -299,6 +271,7 @@ Collection> getEntityCallbacks() { return this.entityCallbacks; } + @SuppressWarnings("rawtypes") void discoverEntityCallbacks(BeanFactory beanFactory) { // We need both a ListableBeanFactory and BeanDefinitionRegistry here for advanced inspection. diff --git a/src/main/java/org/springframework/data/mapping/callback/EntityCallbackInvoker.java b/src/main/java/org/springframework/data/mapping/callback/EntityCallbackInvoker.java index c839693344..b92ac42398 100644 --- a/src/main/java/org/springframework/data/mapping/callback/EntityCallbackInvoker.java +++ b/src/main/java/org/springframework/data/mapping/callback/EntityCallbackInvoker.java @@ -29,7 +29,6 @@ interface EntityCallbackInvoker { * @param callback must not be {@literal null}. * @param entity must not be {@literal null} * @param callbackInvokerFunction must not be {@literal null}. - * @param * @return never {@literal null}. */ Object invokeCallback(EntityCallback callback, T entity, diff --git a/src/main/java/org/springframework/data/mapping/callback/ReactiveEntityCallbackInvoker.java b/src/main/java/org/springframework/data/mapping/callback/ReactiveEntityCallbackInvoker.java index 9301b0cabd..6a4638e060 100644 --- a/src/main/java/org/springframework/data/mapping/callback/ReactiveEntityCallbackInvoker.java +++ b/src/main/java/org/springframework/data/mapping/callback/ReactiveEntityCallbackInvoker.java @@ -19,9 +19,6 @@ import java.util.function.BiFunction; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; - /** * @author Christoph Strobl * @since 2.2 @@ -32,11 +29,9 @@ interface ReactiveEntityCallbackInvoker extends EntityCallbackInvoker { * @param callback must not be {@literal null}. * @param entity can be {@literal null} * @param callbackInvokerFunction must not be {@literal null}. - * @param * @return a {@link Mono} emitting the result of the invocation. */ - @NonNull @Override - Mono invokeCallback(EntityCallback callback, @Nullable T entity, + Mono invokeCallback(EntityCallback callback, T entity, BiFunction, T, Object> callbackInvokerFunction); } diff --git a/src/main/java/org/springframework/data/mapping/callback/ReactiveEntityCallbacks.java b/src/main/java/org/springframework/data/mapping/callback/ReactiveEntityCallbacks.java index 410516adcc..4bcdac64c7 100644 --- a/src/main/java/org/springframework/data/mapping/callback/ReactiveEntityCallbacks.java +++ b/src/main/java/org/springframework/data/mapping/callback/ReactiveEntityCallbacks.java @@ -77,7 +77,7 @@ static ReactiveEntityCallbacks create() { /** * Obtain a new {@link ReactiveEntityCallbacks} instance. *

- * {@link EntityCallback callbacks} are pre loaded from the given {@link BeanFactory}.
+ * {@link EntityCallback callbacks} are pre-loaded from the given {@link BeanFactory}.
* Use {@link #addEntityCallback(EntityCallback)} to register additional callbacks manually. * * @param beanFactory must not be {@literal null}. diff --git a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java index ae632b3b8e..b8e2cb706b 100644 --- a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java +++ b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java @@ -141,7 +141,7 @@ public void setApplicationEventPublisher(ApplicationEventPublisher applicationEv * already set. * * @param applicationContext the ApplicationContext object to be used by this object. - * @throws BeansException + * @throws BeansException in case of initialization errors. */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { @@ -159,7 +159,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws /** * @param beanFactory owning BeanFactory. - * @throws BeansException + * @throws BeansException in case of initialization errors. * @since 3.3 */ @Override @@ -565,9 +565,9 @@ public void initialize() { /** * Returns whether a {@link PersistentEntity} instance should be created for the given {@link TypeInformation}. By - * default this will reject all types considered simple and non-supported Kotlin classes, but it might be necessary to - * tweak that in case you have registered custom converters for top level types (which renders them to be considered - * simple) but still need meta-information about them. + * default, this will reject all types considered simple and non-supported Kotlin classes, but it might be necessary + * to tweak that in case you have registered custom converters for top level types (which renders them to be + * considered simple) but still need meta-information about them. * * @param type will never be {@literal null}. * @return @@ -673,7 +673,7 @@ private void createAndRegisterProperty(Property input) { }); } - protected boolean shouldSkipOverrideProperty(P property) { + private boolean shouldSkipOverrideProperty(P property) { P existingProperty = entity.getPersistentProperty(property.getName()); @@ -758,7 +758,7 @@ private Class getPropertyType(PersistentProperty persistentProperty) { * * @author Oliver Gierke */ - static enum PersistentPropertyFilter implements FieldFilter { + enum PersistentPropertyFilter implements FieldFilter { INSTANCE; diff --git a/src/main/java/org/springframework/data/mapping/context/DefaultPersistentPropertyPath.java b/src/main/java/org/springframework/data/mapping/context/DefaultPersistentPropertyPath.java index aef6139bf5..1f6526e6d6 100644 --- a/src/main/java/org/springframework/data/mapping/context/DefaultPersistentPropertyPath.java +++ b/src/main/java/org/springframework/data/mapping/context/DefaultPersistentPropertyPath.java @@ -24,6 +24,7 @@ import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyPath; import org.springframework.data.util.TypeInformation; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -56,7 +57,7 @@ public DefaultPersistentPropertyPath(List

properties) { /** * Creates an empty {@link DefaultPersistentPropertyPath}. * - * @return + * @return an empty {@link DefaultPersistentPropertyPath}. */ static > DefaultPersistentPropertyPath empty() { return new DefaultPersistentPropertyPath(Collections.emptyList()); @@ -206,6 +207,7 @@ public Iterator

iterator() { * @param type can be {@literal null}. * @return */ + @Contract("null -> false") public boolean containsPropertyOfType(@Nullable TypeInformation type) { if (type == null) { diff --git a/src/main/java/org/springframework/data/mapping/context/InvalidPersistentPropertyPath.java b/src/main/java/org/springframework/data/mapping/context/InvalidPersistentPropertyPath.java index e796941a57..2e09a766f4 100644 --- a/src/main/java/org/springframework/data/mapping/context/InvalidPersistentPropertyPath.java +++ b/src/main/java/org/springframework/data/mapping/context/InvalidPersistentPropertyPath.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mapping.context; +import java.io.Serial; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -36,7 +37,7 @@ */ public class InvalidPersistentPropertyPath extends MappingException { - private static final long serialVersionUID = 2805815643641094488L; + private static final @Serial long serialVersionUID = 2805815643641094488L; private static final String DEFAULT_MESSAGE = "No property '%s' found on %s; Did you mean: %s"; private final String source; @@ -109,9 +110,7 @@ private static String toDotPathOrEmpty(@Nullable PersistentPropertyPath type, String unresolvableSegment) { diff --git a/src/main/java/org/springframework/data/mapping/context/MappingContextEvent.java b/src/main/java/org/springframework/data/mapping/context/MappingContextEvent.java index 7b16709597..0fba3a6def 100644 --- a/src/main/java/org/springframework/data/mapping/context/MappingContextEvent.java +++ b/src/main/java/org/springframework/data/mapping/context/MappingContextEvent.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mapping.context; +import java.io.Serial; + import org.springframework.context.ApplicationEvent; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; @@ -31,7 +33,7 @@ public class MappingContextEvent, P extends PersistentProperty

> extends ApplicationEvent { - private static final long serialVersionUID = 1336466833846092490L; + private static final @Serial long serialVersionUID = 1336466833846092490L; private final MappingContext source; private final E entity; diff --git a/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java b/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java index db7723e832..20d75d99ae 100644 --- a/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java +++ b/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java @@ -53,7 +53,6 @@ public class PersistentEntities implements Streamable> contexts) { Assert.notNull(contexts, "MappingContexts must not be null"); @@ -208,7 +207,7 @@ public Streamable> getManagedTypes() { /** * Returns the type the given {@link PersistentProperty} ultimately refers to. In case it's of a unique identifier - * type of an entity known it'll return the entity type. + * type of entity known it'll return the entity type. * * @param property must not be {@literal null}. * @return diff --git a/src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java b/src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java index 2e0ae920a4..d965d23876 100644 --- a/src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java +++ b/src/main/java/org/springframework/data/mapping/context/PersistentPropertyPathFactory.java @@ -436,8 +436,8 @@ private static class PathResolution { private final PersistentPropertyPath path; private final boolean resolvable; - private @Nullable final String source; + private @Nullable final String source; private @Nullable final String segment; private @Nullable final TypeInformation type; diff --git a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java index 249177bd86..0dde4e5eaf 100644 --- a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -132,7 +132,6 @@ public BasicPersistentEntity(TypeInformation information, @Nullable Comparato @Nullable @Override - @SuppressWarnings("unchecked") public PreferredConstructor getPersistenceConstructor() { return creator instanceof PreferredConstructor ? (PreferredConstructor) creator : null; } @@ -556,15 +555,8 @@ public Object getIdentifier() { * * @author Oliver Gierke */ - private static final class AssociationComparator

> - implements Comparator>, Serializable { - - private static final long serialVersionUID = 4508054194886854513L; - private final Comparator

delegate; - - AssociationComparator(Comparator

delegate) { - this.delegate = delegate; - } + private record AssociationComparator

>( + Comparator

delegate) implements Comparator>, Serializable { @Override public int compare(@Nullable Association

left, @Nullable Association

right) { diff --git a/src/main/java/org/springframework/data/mapping/model/BeanWrapper.java b/src/main/java/org/springframework/data/mapping/model/BeanWrapper.java index b962dd8275..6baa08a93e 100644 --- a/src/main/java/org/springframework/data/mapping/model/BeanWrapper.java +++ b/src/main/java/org/springframework/data/mapping/model/BeanWrapper.java @@ -141,7 +141,7 @@ public Object getProperty(PersistentProperty property, Class } catch (IllegalStateException e) { throw new MappingException( - String.format("Could not read property %s of %s", property.toString(), bean.toString()), e); + String.format("Could not read property %s of %s", property, bean.toString()), e); } } diff --git a/src/main/java/org/springframework/data/mapping/model/BytecodeUtil.java b/src/main/java/org/springframework/data/mapping/model/BytecodeUtil.java index 43fb7d48ef..bfe52a2ef3 100644 --- a/src/main/java/org/springframework/data/mapping/model/BytecodeUtil.java +++ b/src/main/java/org/springframework/data/mapping/model/BytecodeUtil.java @@ -209,7 +209,7 @@ static String referenceName(String internalTypeName) { * Returns the signature type for a {@link Class} including primitives. * * @param type must not be {@literal null} - * @return + * @return bytecode type name in the form of {@literal Ljava/lang/Object;}. */ static String signatureTypeName(Class type) { diff --git a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java index 3ab3e04113..3e482086e6 100644 --- a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java +++ b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java @@ -379,12 +379,10 @@ private static List> getPersistentProperties(PersistentEnt final List> persistentProperties = new ArrayList<>(); entity.doWithAssociations((SimpleAssociationHandler) association -> { - if (association.getInverse() != null) { - persistentProperties.add(association.getInverse()); - } + persistentProperties.add(association.getInverse()); }); - entity.doWithProperties((SimplePropertyHandler) property -> persistentProperties.add(property)); + entity.doWithProperties((SimplePropertyHandler) persistentProperties::add); return persistentProperties; } @@ -583,9 +581,9 @@ private static List> getPropertyDeclaratingClasses(List it.getDeclaringClass()); + .map(Member::getDeclaringClass); - }).collect(Collectors.collectingAndThen(Collectors.toSet(), it -> new ArrayList<>(it))); + }).collect(Collectors.collectingAndThen(Collectors.toSet(), ArrayList::new)); } diff --git a/src/main/java/org/springframework/data/mapping/model/ConvertingPropertyAccessor.java b/src/main/java/org/springframework/data/mapping/model/ConvertingPropertyAccessor.java index 73523671c0..2ad1b66671 100644 --- a/src/main/java/org/springframework/data/mapping/model/ConvertingPropertyAccessor.java +++ b/src/main/java/org/springframework/data/mapping/model/ConvertingPropertyAccessor.java @@ -19,6 +19,7 @@ import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.PersistentPropertyPath; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -99,6 +100,7 @@ protected S getTypedProperty(PersistentProperty property, Class type) * @return */ @Nullable + @Contract("null, _ -> null") @SuppressWarnings("unchecked") private S convertIfNecessary(@Nullable Object source, Class type) { diff --git a/src/main/java/org/springframework/data/mapping/model/KotlinInstantiationDelegate.java b/src/main/java/org/springframework/data/mapping/model/KotlinInstantiationDelegate.java index caa2c0e655..599e9c8cd2 100644 --- a/src/main/java/org/springframework/data/mapping/model/KotlinInstantiationDelegate.java +++ b/src/main/java/org/springframework/data/mapping/model/KotlinInstantiationDelegate.java @@ -101,14 +101,8 @@ public int getRequiredParameterCount() { /** * Extract the actual construction arguments for a direct constructor call. - * - * @param params - * @param entityCreator - * @param provider - * @return - * @param

*/ - public

> Object[] extractInvocationArguments(Object[] params, + public

> void extractInvocationArguments(Object[] params, @Nullable InstanceCreatorMetadata

entityCreator, ParameterValueProvider

provider) { if (entityCreator == null) { @@ -155,8 +149,6 @@ public

> Object[] extractInvocationArguments(Obj for (int i = 0; i < defaulting.length; i++) { params[userParameterCount + i] = defaulting[i]; } - - return params; } /** @@ -214,7 +206,7 @@ private static Constructor doResolveKotlinConstructor(Constructor detected } } else { - int optionalParameterCount = (int) kotlinFunction.getParameters().stream().filter(it -> it.isOptional()) + int optionalParameterCount = (int) kotlinFunction.getParameters().stream().filter(KParameter::isOptional) .count(); int syntheticParameters = KotlinDefaultMask.getExactMaskCount(optionalParameterCount); diff --git a/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java b/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java index 69083639d9..88b7ba59e4 100644 --- a/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java +++ b/src/main/java/org/springframework/data/mapping/model/MappingInstantiationException.java @@ -18,6 +18,7 @@ import kotlin.reflect.KFunction; import kotlin.reflect.jvm.ReflectJvmMapping; +import java.io.Serial; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; @@ -43,7 +44,7 @@ */ public class MappingInstantiationException extends RuntimeException { - private static final long serialVersionUID = 822211065035487628L; + private static final @Serial long serialVersionUID = 822211065035487628L; private static final String TEXT_TEMPLATE = "Failed to instantiate %s using constructor %s with arguments %s"; private final Class entityType; diff --git a/src/main/java/org/springframework/data/mapping/model/ParameterValueProvider.java b/src/main/java/org/springframework/data/mapping/model/ParameterValueProvider.java index b2fbd0e772..2af8017dd1 100644 --- a/src/main/java/org/springframework/data/mapping/model/ParameterValueProvider.java +++ b/src/main/java/org/springframework/data/mapping/model/ParameterValueProvider.java @@ -30,7 +30,7 @@ public interface ParameterValueProvider

> { * Returns the value to be used for the given {@link Parameter} (usually when entity instances are created). * * @param parameter must not be {@literal null}. - * @return + * @return the property value. Can be {@literal null}. */ @Nullable T getParameterValue(Parameter parameter); diff --git a/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java b/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java index 708c91dd6d..2bc3f2831a 100644 --- a/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java +++ b/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java @@ -24,9 +24,7 @@ /** * {@link ParameterValueProvider} based on a {@link PersistentEntity} to use a {@link PropertyValueProvider} to lookup - * the value of the property referenced by the given {@link Parameter}. Additionally a - * {@link DefaultSpELExpressionEvaluator} can be configured to get property value resolution trumped by a SpEL - * expression evaluation. + * the value of the property referenced by the given {@link Parameter}. * * @author Oliver Gierke * @author Johannes Englmeier @@ -39,7 +37,7 @@ public class PersistentEntityParameterValueProvider

entity, PropertyValueProvider

provider, - Object parent) { + @Nullable Object parent) { this.entity = entity; this.provider = provider; this.parent = parent; diff --git a/src/main/java/org/springframework/data/mapping/model/PropertyValueProvider.java b/src/main/java/org/springframework/data/mapping/model/PropertyValueProvider.java index 9c0856aba3..7da5102465 100644 --- a/src/main/java/org/springframework/data/mapping/model/PropertyValueProvider.java +++ b/src/main/java/org/springframework/data/mapping/model/PropertyValueProvider.java @@ -30,7 +30,7 @@ public interface PropertyValueProvider

> { * Returns a value for the given {@link PersistentProperty}. * * @param property will never be {@literal null}. - * @return + * @return the property value. Can be {@literal null}. */ @Nullable T getPropertyValue(P property); diff --git a/src/main/java/org/springframework/data/mapping/model/SimpleTypeHolder.java b/src/main/java/org/springframework/data/mapping/model/SimpleTypeHolder.java index afcbf36d96..a77e4815b2 100644 --- a/src/main/java/org/springframework/data/mapping/model/SimpleTypeHolder.java +++ b/src/main/java/org/springframework/data/mapping/model/SimpleTypeHolder.java @@ -87,8 +87,8 @@ protected SimpleTypeHolder() { * Creates a new {@link SimpleTypeHolder} to carry the given custom simple types. Registration of default simple types * can be deactivated by passing {@literal false} for {@code registerDefaults}. * - * @param customSimpleTypes - * @param registerDefaults + * @param customSimpleTypes set of custom simple types. + * @param registerDefaults whether to register default simple types, see {@link #DEFAULTS}. */ public SimpleTypeHolder(Set> customSimpleTypes, boolean registerDefaults) { @@ -136,7 +136,7 @@ private void registerCachePositives(Map, Boolean> source) { * Returns whether the given type is considered a simple one. * * @param type must not be {@literal null}. - * @return + * @return {@literal true} if the given type is considered simple. */ public boolean isSimpleType(Class type) { diff --git a/src/main/java/org/springframework/data/mapping/model/SpELContext.java b/src/main/java/org/springframework/data/mapping/model/SpELContext.java index 005333c73a..0e912cac55 100644 --- a/src/main/java/org/springframework/data/mapping/model/SpELContext.java +++ b/src/main/java/org/springframework/data/mapping/model/SpELContext.java @@ -92,7 +92,7 @@ public ExpressionParser getParser() { } @Override - public EvaluationContext getEvaluationContext(Object source) { + public EvaluationContext getEvaluationContext(@Nullable Object source) { StandardEvaluationContext evaluationContext = new StandardEvaluationContext(source); evaluationContext.addPropertyAccessor(accessor); diff --git a/src/main/java/org/springframework/data/projection/Accessor.java b/src/main/java/org/springframework/data/projection/Accessor.java index 13410f13a8..643d4cebf7 100644 --- a/src/main/java/org/springframework/data/projection/Accessor.java +++ b/src/main/java/org/springframework/data/projection/Accessor.java @@ -58,7 +58,7 @@ public Accessor(Method method) { /** * Returns whether the accessor is a getter. * - * @return + * @return {@literal true} if the accessor is a getter; {@literal false} otherwise. */ public boolean isGetter() { return method.equals(descriptor.getReadMethod()); @@ -67,7 +67,7 @@ public boolean isGetter() { /** * Returns whether the accessor is a setter. * - * @return + * @return {@literal true} if the accessor is a setter; {@literal false} otherwise. */ public boolean isSetter() { return method.equals(descriptor.getWriteMethod()); diff --git a/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java b/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java index ec73eaf83e..86da0c3740 100644 --- a/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java +++ b/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java @@ -93,7 +93,7 @@ private MethodHandle getMethodHandle(Method method) throws Exception { * * @param method must not be {@literal null}. * @return the method handle. - * @throws ReflectiveOperationException + * @throws ReflectiveOperationException in case of an error during method handle lookup. */ private static MethodHandle lookup(Method method) throws ReflectiveOperationException { diff --git a/src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java b/src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java index fbdb6caf5e..05d019260c 100644 --- a/src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java +++ b/src/main/java/org/springframework/data/projection/ProjectingMethodInterceptor.java @@ -30,6 +30,7 @@ import org.springframework.data.util.NullableWrapper; import org.springframework.data.util.NullableWrapperConverters; import org.springframework.data.util.TypeInformation; +import org.springframework.lang.Contract; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -158,6 +159,7 @@ private Map projectMapValues(Map sources, TypeInformation< } @Nullable + @Contract("null, _ -> null") private Object getProjection(@Nullable Object result, Class returnType) { return (result == null) || ClassUtils.isAssignable(returnType, result.getClass()) ? result : factory.createProjection(returnType, result); diff --git a/src/main/java/org/springframework/data/querydsl/QPageRequest.java b/src/main/java/org/springframework/data/querydsl/QPageRequest.java index 06d822bb5f..2e1b08f643 100644 --- a/src/main/java/org/springframework/data/querydsl/QPageRequest.java +++ b/src/main/java/org/springframework/data/querydsl/QPageRequest.java @@ -15,6 +15,8 @@ */ package org.springframework.data.querydsl; +import java.io.Serial; + import org.springframework.data.domain.AbstractPageRequest; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -33,7 +35,7 @@ */ public class QPageRequest extends AbstractPageRequest { - private static final long serialVersionUID = 7529171950267879273L; + private static final @Serial long serialVersionUID = 7529171950267879273L; private final QSort sort; diff --git a/src/main/java/org/springframework/data/querydsl/QSort.java b/src/main/java/org/springframework/data/querydsl/QSort.java index e59e2f24bb..9384497305 100644 --- a/src/main/java/org/springframework/data/querydsl/QSort.java +++ b/src/main/java/org/springframework/data/querydsl/QSort.java @@ -15,6 +15,7 @@ */ package org.springframework.data.querydsl; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; @@ -37,7 +38,7 @@ */ public class QSort extends Sort implements Serializable { - private static final long serialVersionUID = -6701117396842171930L; + private static final @Serial long serialVersionUID = -6701117396842171930L; private static final QSort UNSORTED = new QSort(); private final List> orderSpecifiers; diff --git a/src/main/java/org/springframework/data/querydsl/aot/package-info.java b/src/main/java/org/springframework/data/querydsl/aot/package-info.java new file mode 100644 index 0000000000..664427e22a --- /dev/null +++ b/src/main/java/org/springframework/data/querydsl/aot/package-info.java @@ -0,0 +1,5 @@ +/** + * Querydsl AOT hints. + */ +@org.springframework.lang.NonNullApi +package org.springframework.data.querydsl.aot; diff --git a/src/main/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactory.java b/src/main/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactory.java index a811a40950..f088e63dc9 100644 --- a/src/main/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactory.java +++ b/src/main/java/org/springframework/data/querydsl/binding/QuerydslBindingsFactory.java @@ -181,7 +181,7 @@ private QuerydslBinderCustomizer> getDefaultQuerydslBinderCustomiz * Obtains the {@link QuerydslBinderCustomizer} for the given domain type. Will inspect the given annotation for a * dedicated configured one or consider the domain type's repository. * - * @param annotation + * @param customizer * @param domainType * @return */ diff --git a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java index 8318ae212a..de1bddf427 100644 --- a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java +++ b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java @@ -156,6 +156,7 @@ private String createPassivationId(Set qualifiers, Class reposito return StringUtils.collectionToDelimitedString(qualifierNames, ":") + ":" + repositoryType.getName(); } + @Override @SuppressWarnings("rawtypes") public Set getTypes() { @@ -201,6 +202,7 @@ public final void initialize() { create(beanManager.createCreationalContext(this)); } + @Override public final T create(@SuppressWarnings("null") CreationalContext creationalContext) { T repoInstance = this.repoInstance; @@ -217,6 +219,7 @@ public final T create(@SuppressWarnings("null") CreationalContext creationalC return repoInstance; } + @Override public void destroy(@SuppressWarnings("null") T instance, @SuppressWarnings("null") CreationalContext creationalContext) { @@ -228,14 +231,17 @@ public void destroy(@SuppressWarnings("null") T instance, creationalContext.release(); } + @Override public Set getQualifiers() { return qualifiers; } + @Override public String getName() { return repositoryType.getName(); } + @Override public Set> getStereotypes() { return Arrays.stream(repositoryType.getAnnotations())// @@ -244,10 +250,12 @@ public Set> getStereotypes() { .collect(Collectors.toSet()); } + @Override public Class getBeanClass() { return repositoryType; } + @Override public boolean isAlternative() { return isAnnotatedWith(repositoryType, Alternative.class); } @@ -256,14 +264,17 @@ public boolean isNullable() { return false; } + @Override public Set getInjectionPoints() { return Collections.emptySet(); } + @Override public Class getScope() { return ApplicationScoped.class; } + @Override public String getId() { return passivationId; } diff --git a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java index 37057144da..29bb4284b0 100644 --- a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java +++ b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java @@ -26,6 +26,7 @@ import jakarta.enterprise.util.AnnotationLiteral; import jakarta.inject.Qualifier; +import java.io.Serial; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.HashSet; @@ -197,14 +198,14 @@ private static boolean isAnnotatedDirectlyWith(Class type, Class implements Default { - private static final long serialVersionUID = 511359421048623933L; + private static final @Serial long serialVersionUID = 511359421048623933L; private static final DefaultAnnotationLiteral INSTANCE = new DefaultAnnotationLiteral(); } @SuppressWarnings("all") static class AnyAnnotationLiteral extends AnnotationLiteral implements Any { - private static final long serialVersionUID = 7261821376671361463L; + private static final @Serial long serialVersionUID = 7261821376671361463L; private static final AnyAnnotationLiteral INSTANCE = new AnyAnnotationLiteral(); } diff --git a/src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java b/src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java index c1c676a968..6e60a9cfad 100644 --- a/src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java +++ b/src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java @@ -18,7 +18,6 @@ import java.util.Collection; import java.util.Optional; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.springframework.beans.factory.config.BeanDefinition; @@ -136,7 +135,7 @@ private Set findCandidateBeanDefinitions(ImplementationDetection provider.setMetadataReaderFactory(config.getMetadataReaderFactory()); provider.addIncludeFilter((reader, factory) -> true); - config.getExcludeFilters().forEach(it -> provider.addExcludeFilter(it)); + config.getExcludeFilters().forEach(provider::addExcludeFilter); return config.getBasePackages().stream()// .flatMap(it -> provider.findCandidateComponents(it).stream())// diff --git a/src/main/java/org/springframework/data/repository/config/DeferredRepositoryInitializationListener.java b/src/main/java/org/springframework/data/repository/config/DeferredRepositoryInitializationListener.java index ece25a7e89..dbd11771a9 100644 --- a/src/main/java/org/springframework/data/repository/config/DeferredRepositoryInitializationListener.java +++ b/src/main/java/org/springframework/data/repository/config/DeferredRepositoryInitializationListener.java @@ -35,6 +35,7 @@ class DeferredRepositoryInitializationListener implements ApplicationListener, Ordered { private static final Log logger = LogFactory.getLog(DeferredRepositoryInitializationListener.class); + private final ListableBeanFactory beanFactory; DeferredRepositoryInitializationListener(ListableBeanFactory beanFactory) { diff --git a/src/main/java/org/springframework/data/repository/config/NamedQueriesBeanDefinitionParser.java b/src/main/java/org/springframework/data/repository/config/NamedQueriesBeanDefinitionParser.java index aefd12d0ed..aab028d44f 100644 --- a/src/main/java/org/springframework/data/repository/config/NamedQueriesBeanDefinitionParser.java +++ b/src/main/java/org/springframework/data/repository/config/NamedQueriesBeanDefinitionParser.java @@ -51,6 +51,7 @@ public NamedQueriesBeanDefinitionParser(String defaultLocation) { this.defaultLocation = defaultLocation; } + @Override @NonNull public BeanDefinition parse(Element element, ParserContext parserContext) { diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java index 622774fd97..a7a2e50f78 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java @@ -54,6 +54,7 @@ public RepositoryBeanDefinitionParser(RepositoryConfigurationExtension extension this.extension = extension; } + @Override @Nullable public BeanDefinition parse(Element element, ParserContext parser) { diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionReader.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionReader.java index ff4c6a001f..c733cbf1bd 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionReader.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionReader.java @@ -45,7 +45,6 @@ static RepositoryInformation readRepositoryInformation(RepositoryConfiguration>> fragments(RepositoryConfiguration metadata, ConfigurableListableBeanFactory beanFactory) { diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java index cb3c320a09..ea3d62640d 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java @@ -27,7 +27,6 @@ import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; -import org.springframework.lang.NonNull; import org.springframework.util.Assert; /** @@ -38,8 +37,8 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware { - private @SuppressWarnings("null") @NonNull ResourceLoader resourceLoader; - private @SuppressWarnings("null") @NonNull Environment environment; + private ResourceLoader resourceLoader; + private Environment environment; @Override public void setResourceLoader(ResourceLoader resourceLoader) { diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java b/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java index 776b57ab38..79f17535a8 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java @@ -46,8 +46,9 @@ */ class RepositoryComponentProvider extends ClassPathScanningCandidateComponentProvider { + private final BeanDefinitionRegistry registry; + private boolean considerNestedRepositoryInterfaces; - private BeanDefinitionRegistry registry; /** * Creates a new {@link RepositoryComponentProvider} using the given {@link TypeFilter} to include components to be diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java index 57de2b2e8f..6e96610359 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java @@ -117,16 +117,8 @@ public ImplementationDetectionConfiguration toImplementationDetectionConfigurati return new SpringImplementationDetectionConfiguration(this, factory); } - private class SpringImplementationDetectionConfiguration implements ImplementationDetectionConfiguration { - - private final RepositoryConfigurationSource source; - private final MetadataReaderFactory metadataReaderFactory; - - SpringImplementationDetectionConfiguration(RepositoryConfigurationSource source, - MetadataReaderFactory metadataReaderFactory) { - this.source = source; - this.metadataReaderFactory = metadataReaderFactory; - } + private record SpringImplementationDetectionConfiguration(RepositoryConfigurationSource source, + MetadataReaderFactory metadataReaderFactory) implements ImplementationDetectionConfiguration { @Override public String getImplementationPostfix() { @@ -145,13 +137,14 @@ public Streamable getExcludeFilters() { } @Override - public String generateBeanName(BeanDefinition definition) { - return source.generateBeanName(definition); + public MetadataReaderFactory getMetadataReaderFactory() { + return metadataReaderFactory; } @Override - public MetadataReaderFactory getMetadataReaderFactory() { - return this.metadataReaderFactory; + public String generateBeanName(BeanDefinition definition) { + return source.generateBeanName(definition); } + } } diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryNameSpaceHandler.java b/src/main/java/org/springframework/data/repository/config/RepositoryNameSpaceHandler.java index 7980f014ab..fe2aecd1a9 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryNameSpaceHandler.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryNameSpaceHandler.java @@ -30,6 +30,7 @@ public class RepositoryNameSpaceHandler extends NamespaceHandlerSupport { private static final BeanDefinitionParser PARSER = new ResourceReaderRepositoryPopulatorBeanDefinitionParser(); + @Override public void init() { registerBeanDefinitionParser("unmarshaller-populator", PARSER); diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotContribution.java b/src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotContribution.java index 59814716f8..9e2532690b 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotContribution.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotContribution.java @@ -44,6 +44,7 @@ import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.support.RepositoryFragment; +import org.springframework.data.util.Predicates; import org.springframework.data.util.QTypeContributor; import org.springframework.data.util.TypeContributor; import org.springframework.data.util.TypeUtils; @@ -151,7 +152,7 @@ public RepositoryRegistrationAotContribution forBean(RegisteredBean repositoryBe return this; } - protected DefaultAotRepositoryContext buildAotRepositoryContext(RegisteredBean bean, + DefaultAotRepositoryContext buildAotRepositoryContext(RegisteredBean bean, RepositoryConfiguration repositoryMetadata) { RepositoryInformation repositoryInformation = resolveRepositoryInformation(repositoryMetadata); @@ -345,6 +346,6 @@ static boolean isJavaOrPrimitiveType(Class type) { // the TypeContributor.contribute(:Class, :Predicate :GenerationContext) method // used in the contributeType(..) method above? public Predicate> typeFilter() { // like only document ones. // TODO: As in MongoDB? - return it -> true; + return Predicates.isTrue(); } } diff --git a/src/main/java/org/springframework/data/repository/core/RepositoryInformationSupport.java b/src/main/java/org/springframework/data/repository/core/RepositoryInformationSupport.java index a2a2341f29..c7e1532359 100644 --- a/src/main/java/org/springframework/data/repository/core/RepositoryInformationSupport.java +++ b/src/main/java/org/springframework/data/repository/core/RepositoryInformationSupport.java @@ -162,7 +162,7 @@ private RepositoryMetadata getMetadata() { return metadata.get(); } - private final DefaultQueryMethods calculateQueryMethods() { + private DefaultQueryMethods calculateQueryMethods() { Class repositoryInterface = getRepositoryInterface(); @@ -172,7 +172,7 @@ private final DefaultQueryMethods calculateQueryMethods() { .toList()), calculateHasCustomMethod(repositoryInterface)); } - private final boolean calculateHasCustomMethod(Class repositoryInterface) { + private boolean calculateHasCustomMethod(Class repositoryInterface) { // No detection required if no typing interface was configured if (isGenericRepositoryInterface(repositoryInterface)) { diff --git a/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java b/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java index 0b8667334f..7c94bbcec6 100644 --- a/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java +++ b/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java @@ -15,8 +15,6 @@ */ package org.springframework.data.repository.core.support; -import static org.springframework.util.ReflectionUtils.*; - import java.lang.reflect.Method; import java.util.Map; import java.util.Set; @@ -25,7 +23,10 @@ import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryInformationSupport; import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.lang.Contract; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; /** * Default implementation of {@link RepositoryInformation}. @@ -78,10 +79,12 @@ public Method getTargetClassMethod(Method method) { return cacheAndReturn(method, baseComposition.findMethod(method).orElse(method)); } - private Method cacheAndReturn(Method key, Method value) { + @Nullable + @Contract("_, null -> null; _, !null -> !null") + private Method cacheAndReturn(Method key, @Nullable Method value) { if (value != null) { - makeAccessible(value); + ReflectionUtils.makeAccessible(value); } methodCache.put(key, value); diff --git a/src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java b/src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java index 02f6184a4a..be7a9e569a 100644 --- a/src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java +++ b/src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java @@ -142,18 +142,19 @@ private static boolean isDeleteMethod(String methodName) { */ static class EventPublishingMethod { - private static Map, EventPublishingMethod> cache = new ConcurrentReferenceHashMap<>(); - private static @SuppressWarnings("null") EventPublishingMethod NONE = new EventPublishingMethod(Object.class, null, + private static final Map, EventPublishingMethod> cache = new ConcurrentReferenceHashMap<>(); + private static final @SuppressWarnings("null") EventPublishingMethod NONE = new EventPublishingMethod(Object.class, + null, null); - private static String ILLEGAL_MODIFCATION = "Aggregate's events were modified during event publication. " + private static final String ILLEGAL_MODIFICATION = "Aggregate's events were modified during event publication. " + "Make sure event listeners obtain a fresh instance of the aggregate before adding further events. " + "Additional events found: %s."; private final Class type; - private final Method publishingMethod; + private final @Nullable Method publishingMethod; private final @Nullable Method clearingMethod; - EventPublishingMethod(Class type, Method publishingMethod, @Nullable Method clearingMethod) { + EventPublishingMethod(Class type, @Nullable Method publishingMethod, @Nullable Method clearingMethod) { this.type = type; this.publishingMethod = publishingMethod; @@ -194,7 +195,7 @@ public static EventPublishingMethod of(Class type) { */ public void publishEventsFrom(@Nullable Iterable aggregates, ApplicationEventPublisher publisher) { - if (aggregates == null) { + if (aggregates == null || publishingMethod == null) { return; } @@ -216,7 +217,7 @@ public void publishEventsFrom(@Nullable Iterable aggregates, ApplicationEvent postPublication.removeAll(events); - throw new IllegalStateException(ILLEGAL_MODIFCATION.formatted(postPublication)); + throw new IllegalStateException(ILLEGAL_MODIFICATION.formatted(postPublication)); } if (clearingMethod != null) { diff --git a/src/main/java/org/springframework/data/repository/core/support/MethodInvocationValidator.java b/src/main/java/org/springframework/data/repository/core/support/MethodInvocationValidator.java index 64fbae3c0c..63726a4363 100644 --- a/src/main/java/org/springframework/data/repository/core/support/MethodInvocationValidator.java +++ b/src/main/java/org/springframework/data/repository/core/support/MethodInvocationValidator.java @@ -17,11 +17,13 @@ import java.lang.annotation.ElementType; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; + import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.KotlinDetector; import org.springframework.core.MethodParameter; @@ -32,8 +34,6 @@ import org.springframework.data.util.ReflectionUtils; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; -import org.springframework.util.ConcurrentReferenceHashMap; -import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType; import org.springframework.util.ObjectUtils; /** @@ -194,9 +194,12 @@ public boolean equals(@Nullable Object o) { @Override public int hashCode() { + int result = (nullableReturn ? 1 : 0); - result = (31 * result) + ObjectUtils.nullSafeHashCode(nullableParameters); - result = (31 * result) + ObjectUtils.nullSafeHashCode(methodParameters); + + result = (31 * result) + Arrays.hashCode(nullableParameters); + result = (31 * result) + Arrays.hashCode(methodParameters); + return result; } diff --git a/src/main/java/org/springframework/data/repository/core/support/MethodLookup.java b/src/main/java/org/springframework/data/repository/core/support/MethodLookup.java index 6b1213e9c9..8303374b09 100644 --- a/src/main/java/org/springframework/data/repository/core/support/MethodLookup.java +++ b/src/main/java/org/springframework/data/repository/core/support/MethodLookup.java @@ -21,6 +21,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.springframework.lang.CheckReturnValue; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -55,6 +57,8 @@ public interface MethodLookup { * @param other must not be {@literal null}. * @return the composed {@link MethodLookup}. */ + @Contract("_ -> new") + @CheckReturnValue default MethodLookup and(MethodLookup other) { Assert.notNull(other, "Other method lookup must not be null"); diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryComposition.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryComposition.java index d26dedf258..b565cbe832 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryComposition.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryComposition.java @@ -35,6 +35,8 @@ import org.springframework.data.repository.util.ReactiveWrapperConverters; import org.springframework.data.util.ReactiveWrappers; import org.springframework.data.util.Streamable; +import org.springframework.lang.CheckReturnValue; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -126,7 +128,7 @@ public static RepositoryComposition empty() { /** * Create an {@link RepositoryComposition} using the provided {@link RepositoryMetadata} to set {@link MethodLookup - * method lookups} depending in the repository type (reactive/imperative). + * method lookups} depending on the repository type (reactive/imperative). * * @return an empty {@link RepositoryComposition}. * @since 2.4 @@ -195,6 +197,8 @@ public static RepositoryComposition of(RepositoryFragments fragments) { * @param fragment must not be {@literal null}. * @return the new {@link RepositoryComposition}. */ + @Contract("_ -> new") + @CheckReturnValue public RepositoryComposition append(RepositoryFragment fragment) { return new RepositoryComposition(metadata, fragments.append(fragment), methodLookup, argumentConverter); } @@ -207,6 +211,8 @@ public RepositoryComposition append(RepositoryFragment fragment) { * @param fragments must not be {@literal null}. * @return the new {@link RepositoryComposition}. */ + @Contract("_ -> new") + @CheckReturnValue public RepositoryComposition append(RepositoryFragments fragments) { return new RepositoryComposition(metadata, this.fragments.append(fragments), methodLookup, argumentConverter); } @@ -217,6 +223,8 @@ public RepositoryComposition append(RepositoryFragments fragments) { * @param argumentConverter must not be {@literal null}. * @return the new {@link RepositoryComposition}. */ + @Contract("_ -> new") + @CheckReturnValue public RepositoryComposition withArgumentConverter(BiFunction argumentConverter) { return new RepositoryComposition(metadata, fragments, methodLookup, argumentConverter); } @@ -227,6 +235,8 @@ public RepositoryComposition withArgumentConverter(BiFunction new") + @CheckReturnValue public RepositoryComposition withMethodLookup(MethodLookup methodLookup) { return new RepositoryComposition(metadata, fragments, methodLookup, argumentConverter); } @@ -238,6 +248,8 @@ public RepositoryComposition withMethodLookup(MethodLookup methodLookup) { * @return new instance of {@link RepositoryComposition}. * @since 2.4 */ + @Contract("_ -> new") + @CheckReturnValue public RepositoryComposition withMetadata(RepositoryMetadata metadata) { return new RepositoryComposition(metadata, fragments, methodLookup, argumentConverter); } @@ -253,24 +265,16 @@ public boolean isEmpty() { /** * Invoke a method on the repository by routing the invocation to the appropriate {@link RepositoryFragment}. - * - * @param method - * @param args - * @return - * @throws Throwable */ + @Nullable public Object invoke(Method method, Object... args) throws Throwable { return invoke(NoOpRepositoryInvocationMulticaster.INSTANCE, method, args); } /** * Invoke a method on the repository by routing the invocation to the appropriate {@link RepositoryFragment}. - * - * @param method - * @param args - * @return - * @throws Throwable */ + @Nullable Object invoke(RepositoryInvocationMulticaster listener, Method method, Object[] args) throws Throwable { Method methodToCall = getMethod(method); @@ -289,7 +293,6 @@ Object invoke(RepositoryInvocationMulticaster listener, Method method, Object[] * Find the implementation method for the given {@link Method} invoked on the composite interface. * * @param method must not be {@literal null}. - * @return */ public Optional findMethod(Method method) { return Optional.ofNullable(getMethod(method)); @@ -299,7 +302,6 @@ public Optional findMethod(Method method) { * Find the implementation method for the given {@link Method} invoked on the composite interface. * * @param method must not be {@literal null}. - * @return * @since 2.2 */ @Nullable @@ -323,6 +325,20 @@ public void validateImplementation() { })); } + public RepositoryFragments getFragments() { + return this.fragments; + } + + public MethodLookup getMethodLookup() { + return this.methodLookup; + } + + /** + * Value object representing an ordered list of {@link RepositoryFragment fragments}. + * + * @author Mark Paluch + * @author Christoph Strobl + */ @Override public boolean equals(Object o) { @@ -342,26 +358,12 @@ public int hashCode() { return ObjectUtils.nullSafeHashCode(fragments); } - public RepositoryFragments getFragments() { - return this.fragments; - } - - public MethodLookup getMethodLookup() { - return this.methodLookup; - } - public BiFunction getArgumentConverter() { return this.argumentConverter; } - - /** - * Value object representing an ordered list of {@link RepositoryFragment fragments}. - * - * @author Mark Paluch - * @author Christoph Strobl - */ public static class RepositoryFragments implements Streamable> { + static final RepositoryFragments EMPTY = new RepositoryFragments(Collections.emptyList()); private final Map> fragmentCache = new ConcurrentHashMap<>(); @@ -431,6 +433,8 @@ public static RepositoryFragments from(List> fragments) { * @return the new {@link RepositoryFragments} containing all existing fragments and the given * {@link RepositoryFragment} as last element. */ + @Contract("_ -> new") + @CheckReturnValue public RepositoryFragments append(RepositoryFragment fragment) { Assert.notNull(fragment, "RepositoryFragment must not be null"); @@ -445,6 +449,8 @@ public RepositoryFragments append(RepositoryFragment fragment) { * @return the new {@link RepositoryFragments} containing all existing fragments and the given * {@link RepositoryFragments} as last elements. */ + @Contract("_ -> new") + @CheckReturnValue public RepositoryFragments append(RepositoryFragments fragments) { Assert.notNull(fragments, "RepositoryFragments must not be null"); @@ -470,11 +476,6 @@ public Stream methods() { /** * Invoke {@link Method} by resolving the fragment that implements a suitable method. - * - * @param invokedMethod invoked method as per invocation on the interface. - * @param methodToCall backend method that is backing the call. - * @return - * @throws Throwable */ @Nullable public Object invoke(Method invokedMethod, Method methodToCall, Object[] args) throws Throwable { @@ -483,14 +484,6 @@ public Object invoke(Method invokedMethod, Method methodToCall, Object[] args) t /** * Invoke {@link Method} by resolving the fragment that implements a suitable method. - * - * @param repositoryInterface - * @param listener - * @param invokedMethod invoked method as per invocation on the interface. - * @param methodToCall backend method that is backing the call. - * @param args - * @return - * @throws Throwable */ @Nullable Object invoke(Class repositoryInterface, RepositoryInvocationMulticaster listener, Method invokedMethod, @@ -499,7 +492,7 @@ Object invoke(Class repositoryInterface, RepositoryInvocationMulticaster list RepositoryFragment fragment = fragmentCache.computeIfAbsent(methodToCall, this::findImplementationFragment); Optional optional = fragment.getImplementation(); - if (!optional.isPresent()) { + if (optional.isEmpty()) { throw new IllegalArgumentException(String.format("No implementation found for method %s", methodToCall)); } @@ -580,10 +573,7 @@ public boolean equals(@Nullable Object o) { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(fragmentCache); - result = (31 * result) + ObjectUtils.nullSafeHashCode(invocationMetadataCache); - result = (31 * result) + ObjectUtils.nullSafeHashCode(fragments); - return result; + return ObjectUtils.nullSafeHash(fragmentCache, invocationMetadataCache, fragmentCache); } } } diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java index 8acd550079..4e7f0ad237 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java @@ -308,11 +308,6 @@ public Class getObjectType() { return repositoryInterface; } - @Override - public boolean isSingleton() { - return true; - } - @Override public void afterPropertiesSet() { diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java index af1c6ad71e..5af625083e 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java @@ -868,7 +868,7 @@ public boolean equals(Object o) { @Override public int hashCode() { int result = ObjectUtils.nullSafeHashCode(repositoryInterfaceName); - result = 31 * result + (int) (compositionHash ^ (compositionHash >>> 32)); + result = 31 * result + Long.hashCode(compositionHash); return result; } diff --git a/src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryProxyPostProcessor.java b/src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryProxyPostProcessor.java index adb451be5e..52b7027896 100644 --- a/src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryProxyPostProcessor.java +++ b/src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryProxyPostProcessor.java @@ -15,6 +15,7 @@ */ package org.springframework.data.repository.core.support; +import java.io.Serial; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -93,14 +94,14 @@ public void postProcess(ProxyFactory factory, RepositoryInformation repositoryIn */ static class RepositoryAnnotationTransactionAttributeSource extends AnnotationTransactionAttributeSource { - private static final long serialVersionUID = 7229616838812819438L; + private static final @Serial long serialVersionUID = 7229616838812819438L; private final RepositoryInformation repositoryInformation; private final boolean enableDefaultTransactions; /** * Create a default CustomAnnotationTransactionAttributeSource, supporting public methods that carry the - * {@code Transactional} annotation or the EJB3 {@link javax.ejb.TransactionAttribute} annotation. + * {@code Transactional} annotation or the EJB3 {@code javax.ejb.TransactionAttribute} annotation. */ public RepositoryAnnotationTransactionAttributeSource(RepositoryInformation repositoryInformation, boolean enableDefaultTransactions) { diff --git a/src/main/java/org/springframework/data/repository/init/AbstractRepositoryPopulatorFactoryBean.java b/src/main/java/org/springframework/data/repository/init/AbstractRepositoryPopulatorFactoryBean.java index 5a63db7ff8..29f8584736 100644 --- a/src/main/java/org/springframework/data/repository/init/AbstractRepositoryPopulatorFactoryBean.java +++ b/src/main/java/org/springframework/data/repository/init/AbstractRepositoryPopulatorFactoryBean.java @@ -54,6 +54,7 @@ public void setResources(Resource[] resources) { this.resources = resources.clone(); } + @Override public void setApplicationContext(ApplicationContext applicationContext) { this.context = applicationContext; } @@ -79,6 +80,7 @@ protected ResourceReaderRepositoryPopulator createInstance() { return initializer; } + @Override public void onApplicationEvent(ContextRefreshedEvent event) { RepositoryPopulator populator = this.populator; diff --git a/src/main/java/org/springframework/data/repository/init/RepositoriesPopulatedEvent.java b/src/main/java/org/springframework/data/repository/init/RepositoriesPopulatedEvent.java index 3474e51e36..c1652df576 100644 --- a/src/main/java/org/springframework/data/repository/init/RepositoriesPopulatedEvent.java +++ b/src/main/java/org/springframework/data/repository/init/RepositoriesPopulatedEvent.java @@ -15,6 +15,8 @@ */ package org.springframework.data.repository.init; +import java.io.Serial; + import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEvent; import org.springframework.data.repository.support.Repositories; @@ -29,7 +31,7 @@ */ public class RepositoriesPopulatedEvent extends ApplicationEvent { - private static final long serialVersionUID = 7449982118828889097L; + private static final @Serial long serialVersionUID = 7449982118828889097L; private final Repositories repositories; diff --git a/src/main/java/org/springframework/data/repository/init/ResourceReaderRepositoryPopulator.java b/src/main/java/org/springframework/data/repository/init/ResourceReaderRepositoryPopulator.java index a78f401c32..0487803eb4 100644 --- a/src/main/java/org/springframework/data/repository/init/ResourceReaderRepositoryPopulator.java +++ b/src/main/java/org/springframework/data/repository/init/ResourceReaderRepositoryPopulator.java @@ -99,6 +99,7 @@ public void setResources(Resource... resources) { this.resources = Arrays.asList(resources); } + @Override public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { this.publisher = publisher; } diff --git a/src/main/java/org/springframework/data/repository/init/UnmarshallingResourceReader.java b/src/main/java/org/springframework/data/repository/init/UnmarshallingResourceReader.java index cb85d41735..bd6f5c65d3 100644 --- a/src/main/java/org/springframework/data/repository/init/UnmarshallingResourceReader.java +++ b/src/main/java/org/springframework/data/repository/init/UnmarshallingResourceReader.java @@ -32,9 +32,6 @@ public class UnmarshallingResourceReader implements ResourceReader { private final Unmarshaller unmarshaller; - /** - * @param unmarshaller - */ public UnmarshallingResourceReader(Unmarshaller unmarshaller) { this.unmarshaller = unmarshaller; } diff --git a/src/main/java/org/springframework/data/repository/query/FluentQuery.java b/src/main/java/org/springframework/data/repository/query/FluentQuery.java index ec26c329f6..3d68c964bd 100644 --- a/src/main/java/org/springframework/data/repository/query/FluentQuery.java +++ b/src/main/java/org/springframework/data/repository/query/FluentQuery.java @@ -15,7 +15,6 @@ */ package org.springframework.data.repository.query; -import org.springframework.data.domain.Window; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -29,6 +28,9 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.ScrollPosition; import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Window; +import org.springframework.lang.CheckReturnValue; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; /** @@ -48,6 +50,8 @@ public interface FluentQuery { * @return a new instance of {@link FluentQuery}. * @throws IllegalArgumentException if {@code sort} is {@code null}. */ + @Contract("_ -> new") + @CheckReturnValue FluentQuery sortBy(Sort sort); /** @@ -59,6 +63,8 @@ public interface FluentQuery { * @throws UnsupportedOperationException if not supported by the underlying implementation. * @since 3.1 */ + @Contract("_ -> new") + @CheckReturnValue default FluentQuery limit(int limit) { throw new UnsupportedOperationException("Limit not supported"); } @@ -72,6 +78,8 @@ default FluentQuery limit(int limit) { * @return a new instance of {@link FluentQuery}. * @throws IllegalArgumentException if {@code resultType} is {@code null}. */ + @Contract("_ -> new") + @CheckReturnValue FluentQuery as(Class resultType); /** @@ -81,6 +89,8 @@ default FluentQuery limit(int limit) { * @return a new instance of {@link FluentQuery}. * @throws IllegalArgumentException if {@code properties} is {@code null}. */ + @Contract("_ -> new") + @CheckReturnValue default FluentQuery project(String... properties) { return project(Arrays.asList(properties)); } @@ -92,6 +102,8 @@ default FluentQuery project(String... properties) { * @return a new instance of {@link FluentQuery}. * @throws IllegalArgumentException if {@code properties} is {@code null}. */ + @Contract("_ -> new") + @CheckReturnValue FluentQuery project(Collection properties); /** @@ -103,22 +115,32 @@ default FluentQuery project(String... properties) { interface FetchableFluentQuery extends FluentQuery { @Override + @Contract("_ -> new") + @CheckReturnValue FetchableFluentQuery sortBy(Sort sort); @Override + @Contract("_ -> new") + @CheckReturnValue default FetchableFluentQuery limit(int limit) { throw new UnsupportedOperationException("Limit not supported"); } @Override + @Contract("_ -> new") + @CheckReturnValue FetchableFluentQuery as(Class resultType); @Override + @Contract("_ -> new") + @CheckReturnValue default FetchableFluentQuery project(String... properties) { return project(Arrays.asList(properties)); } @Override + @Contract("_ -> new") + @CheckReturnValue FetchableFluentQuery project(Collection properties); /** @@ -169,7 +191,6 @@ default Optional first() { * {@code scrollPosition}. * * @param scrollPosition must not be {@literal null}. - * @return * @throws IllegalArgumentException if {@code scrollPosition} is {@literal null}. * @throws UnsupportedOperationException if not supported by the underlying implementation. * @since 3.1 @@ -185,7 +206,6 @@ default Window scroll(ScrollPosition scrollPosition) { * {@literal null}. The given {@link Pageable} will override any previously specified {@link Sort sort} if * the {@link Sort} object is not {@link Sort#isUnsorted()}. Any potentially specified {@link #limit(int)} * will be overridden by {@link Pageable#getPageSize()}. - * @return */ Page page(Pageable pageable); @@ -220,22 +240,32 @@ default Window scroll(ScrollPosition scrollPosition) { interface ReactiveFluentQuery extends FluentQuery { @Override + @Contract("_ -> new") + @CheckReturnValue ReactiveFluentQuery sortBy(Sort sort); @Override + @Contract("_ -> new") + @CheckReturnValue default ReactiveFluentQuery limit(int limit) { throw new UnsupportedOperationException("Limit not supported"); } @Override + @Contract("_ -> new") + @CheckReturnValue ReactiveFluentQuery as(Class resultType); @Override + @Contract("_ -> new") + @CheckReturnValue default ReactiveFluentQuery project(String... properties) { return project(Arrays.asList(properties)); } @Override + @Contract("_ -> new") + @CheckReturnValue ReactiveFluentQuery project(Collection properties); /** @@ -255,8 +285,6 @@ default ReactiveFluentQuery project(String... properties) { /** * Get all matching elements. - * - * @return */ Flux all(); @@ -265,7 +293,6 @@ default ReactiveFluentQuery project(String... properties) { * {@code scrollPosition}. * * @param scrollPosition must not be {@literal null}. - * @return * @throws IllegalArgumentException if {@code scrollPosition} is {@literal null}. * @throws UnsupportedOperationException if not supported by the underlying implementation. * @since 3.1 @@ -281,7 +308,6 @@ default Mono> scroll(ScrollPosition scrollPosition) { * {@literal null}. The given {@link Pageable} will override any previously specified {@link Sort sort} if * the {@link Sort} object is not {@link Sort#isUnsorted()}. Any potentially specified {@link #limit(int)} * will be overridden by {@link Pageable#getPageSize()}. - * @return */ Mono> page(Pageable pageable); diff --git a/src/main/java/org/springframework/data/repository/query/ParameterOutOfBoundsException.java b/src/main/java/org/springframework/data/repository/query/ParameterOutOfBoundsException.java index 38b7693d74..a15476af23 100644 --- a/src/main/java/org/springframework/data/repository/query/ParameterOutOfBoundsException.java +++ b/src/main/java/org/springframework/data/repository/query/ParameterOutOfBoundsException.java @@ -15,6 +15,8 @@ */ package org.springframework.data.repository.query; +import java.io.Serial; + /** * Exception to be thrown when trying to access a {@link Parameter} with an invalid index inside a {@link Parameters} * instance. @@ -23,7 +25,7 @@ */ public class ParameterOutOfBoundsException extends RuntimeException { - private static final long serialVersionUID = 8433209953653278886L; + private static final @Serial long serialVersionUID = 8433209953653278886L; /** * Creates a new {@link ParameterOutOfBoundsException} with the given exception as cause. diff --git a/src/main/java/org/springframework/data/repository/query/Parameters.java b/src/main/java/org/springframework/data/repository/query/Parameters.java index 8967bb7d7d..094e6f1e25 100644 --- a/src/main/java/org/springframework/data/repository/query/Parameters.java +++ b/src/main/java/org/springframework/data/repository/query/Parameters.java @@ -382,7 +382,7 @@ public T getBindableParameter(int bindableIndex) { } /** - * Asserts that either all of the non special parameters ({@link Pageable}, {@link Sort}) are annotated with + * Asserts that either all the non-special parameters ({@link Pageable}, {@link Sort}) are annotated with * {@link Param} or none of them is. */ private void assertEitherAllParamAnnotatedOrNone() { diff --git a/src/main/java/org/springframework/data/repository/query/QueryCreationException.java b/src/main/java/org/springframework/data/repository/query/QueryCreationException.java index d442060fe8..7af7807719 100644 --- a/src/main/java/org/springframework/data/repository/query/QueryCreationException.java +++ b/src/main/java/org/springframework/data/repository/query/QueryCreationException.java @@ -15,6 +15,7 @@ */ package org.springframework.data.repository.query; +import java.io.Serial; import java.lang.reflect.Method; import org.springframework.data.repository.core.RepositoryCreationException; @@ -27,7 +28,7 @@ */ public final class QueryCreationException extends RepositoryCreationException { - private static final long serialVersionUID = -1238456123580L; + private static final @Serial long serialVersionUID = -1238456123580L; private static final String MESSAGE_TEMPLATE = "Could not create query for method %s; Could not find property %s on domain class %s"; private final Method method; diff --git a/src/main/java/org/springframework/data/repository/query/ResultProcessor.java b/src/main/java/org/springframework/data/repository/query/ResultProcessor.java index 6cb08ce3d4..f80e465359 100644 --- a/src/main/java/org/springframework/data/repository/query/ResultProcessor.java +++ b/src/main/java/org/springframework/data/repository/query/ResultProcessor.java @@ -26,10 +26,11 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.data.domain.Window; import org.springframework.data.domain.Slice; +import org.springframework.data.domain.Window; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.repository.util.ReactiveWrapperConverters; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -120,6 +121,7 @@ public ReturnedType getReturnedType() { * @return */ @Nullable + @Contract("null -> null; !null -> !null") public T processResult(@Nullable Object source) { return processResult(source, NoOpConverter.INSTANCE); } @@ -133,6 +135,7 @@ public T processResult(@Nullable Object source) { * @return */ @Nullable + @Contract("null -> null; !null -> !null") @SuppressWarnings("unchecked") public T processResult(@Nullable Object source, Converter preparingConverter) { @@ -247,7 +250,7 @@ public Object convert(Object source) { * @author Oliver Gierke * @since 1.12 */ - private static enum NoOpConverter implements Converter { + private enum NoOpConverter implements Converter { INSTANCE; diff --git a/src/main/java/org/springframework/data/repository/query/ReturnedType.java b/src/main/java/org/springframework/data/repository/query/ReturnedType.java index abe6189dfa..8e2b32fc53 100644 --- a/src/main/java/org/springframework/data/repository/query/ReturnedType.java +++ b/src/main/java/org/springframework/data/repository/query/ReturnedType.java @@ -29,6 +29,7 @@ import org.springframework.data.mapping.model.PreferredConstructorDiscoverer; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.projection.ProjectionInformation; +import org.springframework.lang.Contract; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -93,6 +94,7 @@ public final Class getDomainType() { * @param source can be {@literal null}. * @return */ + @Contract("null -> false") public final boolean isInstance(@Nullable Object source) { return getReturnedType().isInstance(source); } @@ -369,9 +371,11 @@ public boolean equals(Object o) { @Override public int hashCode() { + int result = ObjectUtils.nullSafeHashCode(returnedType); result = 31 * result + ObjectUtils.nullSafeHashCode(domainType); result = 31 * result + projectionFactoryHashCode; + return result; } diff --git a/src/main/java/org/springframework/data/repository/query/parser/Part.java b/src/main/java/org/springframework/data/repository/query/parser/Part.java index 2c71ad391c..d04f0938b2 100644 --- a/src/main/java/org/springframework/data/repository/query/parser/Part.java +++ b/src/main/java/org/springframework/data/repository/query/parser/Part.java @@ -166,26 +166,41 @@ public String toString() { } /** - * The type of a method name part. Used to create query parts in various ways. + * The type of method name part. Used to create query parts in various ways. * * @author Oliver Gierke * @author Thomas Darimont * @author Michael Cramer */ - public static enum Type { - - BETWEEN(2, "IsBetween", "Between"), IS_NOT_NULL(0, "IsNotNull", "NotNull"), IS_NULL(0, "IsNull", "Null"), LESS_THAN( - "IsLessThan", "LessThan"), LESS_THAN_EQUAL("IsLessThanEqual", "LessThanEqual"), GREATER_THAN("IsGreaterThan", - "GreaterThan"), GREATER_THAN_EQUAL("IsGreaterThanEqual", "GreaterThanEqual"), BEFORE("IsBefore", - "Before"), AFTER("IsAfter", "After"), NOT_LIKE("IsNotLike", "NotLike"), LIKE("IsLike", - "Like"), STARTING_WITH("IsStartingWith", "StartingWith", "StartsWith"), ENDING_WITH("IsEndingWith", - "EndingWith", "EndsWith"), IS_NOT_EMPTY(0, "IsNotEmpty", "NotEmpty"), IS_EMPTY(0, "IsEmpty", - "Empty"), NOT_CONTAINING("IsNotContaining", "NotContaining", "NotContains"), CONTAINING( - "IsContaining", "Containing", "Contains"), NOT_IN("IsNotIn", "NotIn"), IN("IsIn", - "In"), NEAR("IsNear", "Near"), WITHIN("IsWithin", "Within"), REGEX("MatchesRegex", - "Matches", "Regex"), EXISTS(0, "Exists"), TRUE(0, "IsTrue", "True"), FALSE(0, - "IsFalse", "False"), NEGATING_SIMPLE_PROPERTY("IsNot", - "Not"), SIMPLE_PROPERTY("Is", "Equals"); + public enum Type { + + BETWEEN(2, "IsBetween", "Between"), // + IS_NOT_NULL(0, "IsNotNull", "NotNull"), // + IS_NULL(0, "IsNull", "Null"), // + LESS_THAN("IsLessThan", "LessThan"), // + LESS_THAN_EQUAL("IsLessThanEqual", "LessThanEqual"), // + GREATER_THAN("IsGreaterThan", "GreaterThan"), // + GREATER_THAN_EQUAL("IsGreaterThanEqual", "GreaterThanEqual"), // + BEFORE("IsBefore", "Before"), // + AFTER("IsAfter", "After"), // + NOT_LIKE("IsNotLike", "NotLike"), // + LIKE("IsLike", "Like"), // + STARTING_WITH("IsStartingWith", "StartingWith", "StartsWith"), // + ENDING_WITH("IsEndingWith", "EndingWith", "EndsWith"), // + IS_NOT_EMPTY(0, "IsNotEmpty", "NotEmpty"), // + IS_EMPTY(0, "IsEmpty", "Empty"), // + NOT_CONTAINING("IsNotContaining", "NotContaining", "NotContains"), // + CONTAINING("IsContaining", "Containing", "Contains"), // + NOT_IN("IsNotIn", "NotIn"), // + IN("IsIn", "In"), // + NEAR("IsNear", "Near"), // + WITHIN("IsWithin", "Within"), // + REGEX("MatchesRegex", "Matches", "Regex"), // + EXISTS(0, "Exists"), // + TRUE(0, "IsTrue", "True"), // + FALSE(0, "IsFalse", "False"), // + NEGATING_SIMPLE_PROPERTY("IsNot", "Not"), // + SIMPLE_PROPERTY("Is", "Equals"); // Need to list them again explicitly as the order is important // (esp. for IS_NULL, IS_NOT_NULL) @@ -253,13 +268,13 @@ public Collection getKeywords() { } /** - * Returns whether the the type supports the given raw property. Default implementation checks whether the property - * ends with the registered keyword. Does not support the keyword if the property is a valid field as is. + * Returns whether the type supports the given raw property. Default implementation checks whether the property ends + * with the registered keyword. Does not support the keyword if the property is a valid field as is. * * @param property * @return */ - protected boolean supports(String property) { + boolean supports(String property) { for (String keyword : keywords) { if (property.endsWith(keyword)) { diff --git a/src/main/java/org/springframework/data/repository/query/parser/PartTree.java b/src/main/java/org/springframework/data/repository/query/parser/PartTree.java index 986f43a7b3..240dd53e8e 100644 --- a/src/main/java/org/springframework/data/repository/query/parser/PartTree.java +++ b/src/main/java/org/springframework/data/repository/query/parser/PartTree.java @@ -104,6 +104,7 @@ public PartTree(String source, Class domainClass) { } } + @Override public Iterator iterator() { return predicate.iterator(); } diff --git a/src/main/java/org/springframework/data/repository/support/AnnotationAttribute.java b/src/main/java/org/springframework/data/repository/support/AnnotationAttribute.java index dda2096348..21200acb06 100644 --- a/src/main/java/org/springframework/data/repository/support/AnnotationAttribute.java +++ b/src/main/java/org/springframework/data/repository/support/AnnotationAttribute.java @@ -21,6 +21,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -96,6 +97,7 @@ public Optional getValueFrom(AnnotatedElement annotatedElement) { * @param annotation must not be {@literal null}. * @return */ + @Nullable public Object getValueFrom(Annotation annotation) { Assert.notNull(annotation, "Annotation must not be null"); diff --git a/src/main/java/org/springframework/data/repository/support/DomainClassConverter.java b/src/main/java/org/springframework/data/repository/support/DomainClassConverter.java index e26c1f3bc9..99691b9b5f 100644 --- a/src/main/java/org/springframework/data/repository/support/DomainClassConverter.java +++ b/src/main/java/org/springframework/data/repository/support/DomainClassConverter.java @@ -29,6 +29,7 @@ import org.springframework.data.repository.core.EntityInformation; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.util.Lazy; +import org.springframework.lang.Contract; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -137,6 +138,7 @@ public Set getConvertibleTypes() { } @Nullable + @Contract("null -> null") @Override public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { @@ -208,6 +210,7 @@ public Set getConvertibleTypes() { } @Nullable + @Contract("null -> null") @Override public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { diff --git a/src/main/java/org/springframework/data/repository/support/MethodParameters.java b/src/main/java/org/springframework/data/repository/support/MethodParameters.java index 0f92a0cb62..bb5c1798d6 100644 --- a/src/main/java/org/springframework/data/repository/support/MethodParameters.java +++ b/src/main/java/org/springframework/data/repository/support/MethodParameters.java @@ -38,7 +38,7 @@ */ class MethodParameters { - private final ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); + private final static ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); private final List parameters; /** diff --git a/src/main/java/org/springframework/data/repository/support/QueryMethodParameterConversionException.java b/src/main/java/org/springframework/data/repository/support/QueryMethodParameterConversionException.java index 5e4287f4d6..0018914d02 100644 --- a/src/main/java/org/springframework/data/repository/support/QueryMethodParameterConversionException.java +++ b/src/main/java/org/springframework/data/repository/support/QueryMethodParameterConversionException.java @@ -15,6 +15,8 @@ */ package org.springframework.data.repository.support; +import java.io.Serial; + import org.springframework.core.MethodParameter; import org.springframework.core.convert.ConversionException; import org.springframework.util.Assert; @@ -29,7 +31,7 @@ */ public class QueryMethodParameterConversionException extends RuntimeException { - private static final long serialVersionUID = -5818002272039533066L; + private static final @Serial long serialVersionUID = -5818002272039533066L; private final Object source; private final MethodParameter parameter; diff --git a/src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java b/src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java index 4d027a24fc..83d7a8f44f 100644 --- a/src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java +++ b/src/main/java/org/springframework/data/repository/support/ReflectionRepositoryInvoker.java @@ -31,6 +31,7 @@ import org.springframework.data.repository.query.Param; import org.springframework.data.repository.util.QueryExecutionConverters; import org.springframework.data.util.TypeInformation; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -194,6 +195,7 @@ private Object[] prepareParameters(Method method, MultiValueMap rawPa } @Nullable + @Contract("null, _ -> null") private Object convert(@Nullable Object value, MethodParameter parameter) { if (value == null) { diff --git a/src/main/java/org/springframework/data/repository/support/Repositories.java b/src/main/java/org/springframework/data/repository/support/Repositories.java index 176b8ca177..4d0fcf116d 100644 --- a/src/main/java/org/springframework/data/repository/support/Repositories.java +++ b/src/main/java/org/springframework/data/repository/support/Repositories.java @@ -351,7 +351,7 @@ private Class getRepositoryDomainTypeFor(Class domainType) { * * @author Thomas Darimont */ - private static enum EmptyRepositoryFactoryInformation implements RepositoryFactoryInformation { + private enum EmptyRepositoryFactoryInformation implements RepositoryFactoryInformation { INSTANCE; diff --git a/src/main/java/org/springframework/data/repository/util/ClassUtils.java b/src/main/java/org/springframework/data/repository/util/ClassUtils.java index a57502ed24..b1bf14f035 100644 --- a/src/main/java/org/springframework/data/repository/util/ClassUtils.java +++ b/src/main/java/org/springframework/data/repository/util/ClassUtils.java @@ -23,7 +23,7 @@ import org.springframework.data.repository.Repository; import org.springframework.data.util.TypeInformation; -import org.springframework.lang.NonNull; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; @@ -77,14 +77,14 @@ public static void ifPresent(String className, @Nullable ClassLoader classLoader } /** - * Returns wthere the given type is the {@link Repository} interface. + * Returns where the given type is the {@link Repository} interface. * - * @param interfaze + * @param ifc * @return */ - public static boolean isGenericRepositoryInterface(Class interfaze) { - - return Repository.class.equals(interfaze); + @Contract("null -> false") + public static boolean isGenericRepositoryInterface(Class ifc) { + return Repository.class.equals(ifc); } /** @@ -93,6 +93,7 @@ public static boolean isGenericRepositoryInterface(Class interfaze) { * @param interfaceName * @return */ + @Contract("null -> false") public static boolean isGenericRepositoryInterface(@Nullable String interfaceName) { return Repository.class.getName().equals(interfaceName); } @@ -114,7 +115,8 @@ public static int getNumberOfOccurences(Method method, Class type) { * {@link Method}. * @see java.lang.reflect.Method#getParameterTypes() */ - public static int getNumberOfOccurrences(@NonNull Method method, @NonNull Class parameterType) { + @Deprecated + public static int getNumberOfOccurrences(Method method, Class parameterType) { return org.springframework.data.util.ReflectionUtils.getParameterCount(method, parameterType::equals); } @@ -145,6 +147,7 @@ public static void assertReturnTypeAssignable(Method method, Class... types) * @param types * @return */ + @Contract("null, _ -> false") public static boolean isOfType(@Nullable Object object, Collection> types) { if (object == null) { diff --git a/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java b/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java index 74aeda8cbf..3c03e716d4 100644 --- a/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java +++ b/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java @@ -45,6 +45,7 @@ import org.springframework.data.util.StreamUtils; import org.springframework.data.util.Streamable; import org.springframework.data.util.TypeInformation; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.util.Assert; @@ -216,6 +217,7 @@ public static void registerConvertersIn(ConfigurableConversionService conversion * @return */ @Nullable + @Contract("null -> null") public static Object unwrap(@Nullable Object source) { source = NullableWrapperConverters.unwrap(source); @@ -334,6 +336,7 @@ public Set getConvertibleTypes() { } @Nullable + @Contract("null -> null") @Override public final Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { @@ -498,7 +501,7 @@ public String toString() { + ")"; } - enum Cardinality { + public enum Cardinality { NONE, SINGLE, MULTI; } diff --git a/src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java b/src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java index 0f224cf1bc..8223d7a374 100644 --- a/src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java +++ b/src/main/java/org/springframework/data/repository/util/ReactiveWrapperConverters.java @@ -27,9 +27,9 @@ import java.util.function.Function; import org.reactivestreams.Publisher; + import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalConverter; import org.springframework.core.convert.converter.Converter; @@ -108,7 +108,7 @@ private ReactiveWrapperConverters() {} * * @param conversionService must not be {@literal null}. */ - private static ConversionService registerConvertersIn(ConfigurableConversionService conversionService) { + private static void registerConvertersIn(ConfigurableConversionService conversionService) { Assert.notNull(conversionService, "ConversionService must not be null"); @@ -125,8 +125,6 @@ private static ConversionService registerConvertersIn(ConfigurableConversionServ conversionService.addConverterFactory(ReactiveAdapterConverterFactory.INSTANCE); } } - - return conversionService; } /** @@ -167,8 +165,7 @@ public static TypeInformation unwrapWrapperTypes(TypeInformation type) { * @param targetWrapperType must not be {@literal null}. * @return */ - @Nullable - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "DataFlowIssue" }) public static T toWrapper(Object reactiveObject, Class targetWrapperType) { Assert.notNull(reactiveObject, "Reactive source object must not be null"); diff --git a/src/main/java/org/springframework/data/util/AnnotationDetectionFieldCallback.java b/src/main/java/org/springframework/data/util/AnnotationDetectionFieldCallback.java index 8c29cd65b0..c9feca347e 100755 --- a/src/main/java/org/springframework/data/util/AnnotationDetectionFieldCallback.java +++ b/src/main/java/org/springframework/data/util/AnnotationDetectionFieldCallback.java @@ -50,6 +50,7 @@ public AnnotationDetectionFieldCallback(Class annotationTy this.annotationType = annotationType; } + @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { if (this.field != null) { diff --git a/src/main/java/org/springframework/data/util/CustomCollectionRegistrar.java b/src/main/java/org/springframework/data/util/CustomCollectionRegistrar.java index 88e0367fa0..820b305f04 100644 --- a/src/main/java/org/springframework/data/util/CustomCollectionRegistrar.java +++ b/src/main/java/org/springframework/data/util/CustomCollectionRegistrar.java @@ -75,7 +75,7 @@ default Collection> getAllowedPaginationReturnTypes() { /** * Register all converters to convert instances of the types returned by {@link #getCollectionTypes()} and - * {@link #getMapTypes()} from an to their Java-native counterparts. + * {@link #getMapTypes()} to their Java-native counterparts. * * @param registry will never be {@literal null}. */ diff --git a/src/main/java/org/springframework/data/util/CustomCollections.java b/src/main/java/org/springframework/data/util/CustomCollections.java index 485b11c67f..c64f4ea0f4 100644 --- a/src/main/java/org/springframework/data/util/CustomCollections.java +++ b/src/main/java/org/springframework/data/util/CustomCollections.java @@ -27,6 +27,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Function; @@ -53,6 +54,7 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConverterRegistry; import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.lang.Contract; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -199,9 +201,9 @@ private static void registerMapType(Class type) { private static class SearchableTypes { - private static final BiPredicate, Class> EQUALS = (left, right) -> left.equals(right); - private static final BiPredicate, Class> IS_ASSIGNABLE = (left, right) -> left.isAssignableFrom(right); - private static final Function, Boolean> IS_NOT_NULL = it -> it != null; + private static final BiPredicate, Class> EQUALS = Object::equals; + private static final BiPredicate, Class> IS_ASSIGNABLE = Class::isAssignableFrom; + private static final Function, Boolean> IS_NOT_NULL = Objects::nonNull; private final Collection> types; @@ -246,7 +248,7 @@ public Class getSuperType(Class type) { Supplier message = () -> String.format("Type %s not contained in candidates %s", type, types); - return isOneOf(type, (l, r) -> l.isAssignableFrom(r), rejectNull(message)); + return isOneOf(type, Class::isAssignableFrom, rejectNull(message)); } /** @@ -354,6 +356,7 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { } @Nullable + @Contract("null -> null; !null -> !null") @Override public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { @@ -506,6 +509,7 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { } @Nullable + @Contract("null -> null; !null -> !null") @Override public Object convert(@Nullable Object source) { @@ -580,6 +584,7 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { } @Nullable + @Contract("null -> null; !null -> !null") @Override public Object convert(@Nullable Object source, TypeDescriptor sourceDescriptor, TypeDescriptor targetDescriptor) { diff --git a/src/main/java/org/springframework/data/util/DelegatingTypeScanner.java b/src/main/java/org/springframework/data/util/DelegatingTypeScanner.java index 4ea76ac375..b535ffdc55 100644 --- a/src/main/java/org/springframework/data/util/DelegatingTypeScanner.java +++ b/src/main/java/org/springframework/data/util/DelegatingTypeScanner.java @@ -40,12 +40,12 @@ class DelegatingTypeScanner implements TypeScanner { private final ResourceLoader resourceLoader; private final Environment environment; - private Collection packageNames; - private Collection includeFilters; + private final Collection packageNames; + private final Collection includeFilters; - private Consumer classNotFoundAction; + private final Consumer classNotFoundAction; - private Lazy>> scanResult = Lazy.of(this::collect); + private final Lazy>> scanResult = Lazy.of(this::collect); DelegatingTypeScanner(ResourceLoader resourceLoader) { this(new StandardEnvironment(), resourceLoader); diff --git a/src/main/java/org/springframework/data/util/IteratorSpliterator.java b/src/main/java/org/springframework/data/util/IteratorSpliterator.java index 6cfb376296..4ea01b998c 100644 --- a/src/main/java/org/springframework/data/util/IteratorSpliterator.java +++ b/src/main/java/org/springframework/data/util/IteratorSpliterator.java @@ -21,6 +21,8 @@ import java.util.Spliterators; import java.util.function.Consumer; +import org.springframework.lang.Nullable; + /** * A Spliterator using a given Iterator for element operations. The spliterator implements {@code trySplit} to permit * limited parallelism. @@ -44,6 +46,7 @@ public IteratorSpliterator(Iterator iterator) { this.est = Long.MAX_VALUE; } + @Nullable @Override public Spliterator trySplit() { /* @@ -107,6 +110,7 @@ public int characteristics() { return 0; } + @Nullable @Override public Comparator getComparator() { if (hasCharacteristics(Spliterator.SORTED)) { diff --git a/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java b/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java index 8d2104ae72..b2e0716f12 100644 --- a/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java +++ b/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java @@ -38,6 +38,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.core.KotlinDetector; import org.springframework.core.Ordered; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -151,6 +152,7 @@ private static void collectBasicJavaProperties(Class beanClass, Map null, _, !null -> !null") private static Method specialize(Class beanClass, @Nullable Method method) { if (method == null) { diff --git a/src/main/java/org/springframework/data/util/KotlinReflectionUtils.java b/src/main/java/org/springframework/data/util/KotlinReflectionUtils.java index f958bdc520..e4fbf452bf 100644 --- a/src/main/java/org/springframework/data/util/KotlinReflectionUtils.java +++ b/src/main/java/org/springframework/data/util/KotlinReflectionUtils.java @@ -260,7 +260,7 @@ private enum KotlinClassHeaderKind { CLASS(1), FILE(2), SYNTHETIC_CLASS(3), MULTI_FILE_CLASS_FACADE(4), MULTI_FILE_CLASS_PART(5); - int id; + final int id; KotlinClassHeaderKind(int val) { this.id = val; diff --git a/src/main/java/org/springframework/data/util/MethodInvocationRecorder.java b/src/main/java/org/springframework/data/util/MethodInvocationRecorder.java index dca81898f2..d39f569f94 100644 --- a/src/main/java/org/springframework/data/util/MethodInvocationRecorder.java +++ b/src/main/java/org/springframework/data/util/MethodInvocationRecorder.java @@ -48,7 +48,7 @@ public class MethodInvocationRecorder { public static PropertyNameDetectionStrategy DEFAULT = DefaultPropertyNameDetectionStrategy.INSTANCE; - private Optional interceptor; + private final Optional interceptor; /** * Creates a new {@link MethodInvocationRecorder}. For ad-hoc instantation prefer the static diff --git a/src/main/java/org/springframework/data/util/NullableWrapperConverters.java b/src/main/java/org/springframework/data/util/NullableWrapperConverters.java index 0fb04a0cc0..afc3e9ddbb 100644 --- a/src/main/java/org/springframework/data/util/NullableWrapperConverters.java +++ b/src/main/java/org/springframework/data/util/NullableWrapperConverters.java @@ -29,6 +29,7 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConverterRegistry; import org.springframework.core.convert.converter.GenericConverter; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -178,6 +179,7 @@ public static void registerConvertersIn(ConverterRegistry registry) { * @return */ @Nullable + @Contract("null -> null") public static Object unwrap(@Nullable Object source) { if (source == null || !supports(source.getClass())) { diff --git a/src/main/java/org/springframework/data/util/ProxyUtils.java b/src/main/java/org/springframework/data/util/ProxyUtils.java index eee2c47104..8d1f7b1839 100644 --- a/src/main/java/org/springframework/data/util/ProxyUtils.java +++ b/src/main/java/org/springframework/data/util/ProxyUtils.java @@ -32,7 +32,7 @@ */ public abstract class ProxyUtils { - private static Map, Class> USER_TYPES = new ConcurrentReferenceHashMap<>(); + private static final Map, Class> USER_TYPES = new ConcurrentReferenceHashMap<>(); private static final List DETECTORS = SpringFactoriesLoader.loadFactories(ProxyDetector.class, ProxyUtils.class.getClassLoader()); @@ -83,7 +83,7 @@ public static Class getUserClass(Object source) { * * @author Oliver Gierke */ - public static interface ProxyDetector { + public interface ProxyDetector { /** * Returns the user class for the given type. diff --git a/src/main/java/org/springframework/data/util/ReflectionUtils.java b/src/main/java/org/springframework/data/util/ReflectionUtils.java index fbee7fdaf4..5b2157a2ca 100644 --- a/src/main/java/org/springframework/data/util/ReflectionUtils.java +++ b/src/main/java/org/springframework/data/util/ReflectionUtils.java @@ -129,7 +129,7 @@ public static T createInstanceIfPresent(String classname, T defaultInstance) */ public static boolean isVoid(Class type) { - if (type == Void.class || Void.TYPE == type) { + if (ClassUtils.isVoidType(type)) { return true; } @@ -170,6 +170,7 @@ public AnnotationFieldFilter(Class annotationType) { this.annotationType = annotationType; } + @Override public boolean matches(Field field) { return AnnotationUtils.getAnnotation(field, annotationType) != null; } diff --git a/src/main/java/org/springframework/data/util/TypeCollector.java b/src/main/java/org/springframework/data/util/TypeCollector.java index 6d179d88aa..1f055a66ac 100644 --- a/src/main/java/org/springframework/data/util/TypeCollector.java +++ b/src/main/java/org/springframework/data/util/TypeCollector.java @@ -20,13 +20,24 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.core.ResolvableType; +import org.springframework.lang.Contract; import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; @@ -62,11 +73,13 @@ public class TypeCollector { private Predicate fieldFilter = createFieldFilter(); + @Contract("_ -> this") public TypeCollector filterFields(Predicate filter) { this.fieldFilter = filter.and(filter); return this; } + @Contract("_ -> this") public TypeCollector filterTypes(Predicate> filter) { this.typeFilter = this.typeFilter.and(filter); return this; diff --git a/src/main/java/org/springframework/data/util/TypeInformation.java b/src/main/java/org/springframework/data/util/TypeInformation.java index 2b08f3dd08..c1c4480bec 100644 --- a/src/main/java/org/springframework/data/util/TypeInformation.java +++ b/src/main/java/org/springframework/data/util/TypeInformation.java @@ -336,7 +336,7 @@ default TypeInformation getRequiredSuperTypeInformation(Class superType) { /** * Returns if the current {@link TypeInformation} can be safely assigned to the given one. Mimics semantics of - * {@link Class#isAssignableFrom(Class)} but takes generics into account. Thus it will allow to detect that a + * {@link Class#isAssignableFrom(Class)} but takes generics into account. Thus, it will allow to detect that a * {@code List} is assignable to {@code List}. * * @param target diff --git a/src/main/java/org/springframework/data/util/Version.java b/src/main/java/org/springframework/data/util/Version.java index dd87792096..888baafaf5 100644 --- a/src/main/java/org/springframework/data/util/Version.java +++ b/src/main/java/org/springframework/data/util/Version.java @@ -146,6 +146,7 @@ public boolean isLessThanOrEqualTo(Version version) { return compareTo(version) <= 0; } + @Override public int compareTo(@SuppressWarnings("null") Version that) { if (major != that.major) { diff --git a/src/main/java/org/springframework/data/web/HateoasPageableHandlerMethodArgumentResolver.java b/src/main/java/org/springframework/data/web/HateoasPageableHandlerMethodArgumentResolver.java index eb3968ac35..d6d7931ceb 100644 --- a/src/main/java/org/springframework/data/web/HateoasPageableHandlerMethodArgumentResolver.java +++ b/src/main/java/org/springframework/data/web/HateoasPageableHandlerMethodArgumentResolver.java @@ -98,7 +98,7 @@ public TemplateVariables getPaginationTemplateVariables(MethodParameter paramete } @Override - public void enhance(UriComponentsBuilder builder, @Nullable MethodParameter parameter, Object value) { + public void enhance(UriComponentsBuilder builder, @Nullable MethodParameter parameter, @Nullable Object value) { Assert.notNull(builder, "UriComponentsBuilder must not be null"); diff --git a/src/main/java/org/springframework/data/web/PageableHandlerMethodArgumentResolver.java b/src/main/java/org/springframework/data/web/PageableHandlerMethodArgumentResolver.java index 49c4460c20..ee01db6952 100644 --- a/src/main/java/org/springframework/data/web/PageableHandlerMethodArgumentResolver.java +++ b/src/main/java/org/springframework/data/web/PageableHandlerMethodArgumentResolver.java @@ -19,6 +19,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; @@ -77,6 +78,7 @@ public boolean supportsParameter(MethodParameter parameter) { return Pageable.class.equals(parameter.getParameterType()); } + @NonNull @Override public Pageable resolveArgument(MethodParameter methodParameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) { diff --git a/src/main/java/org/springframework/data/web/PageableMethodParameterUtils.java b/src/main/java/org/springframework/data/web/PageableMethodParameterUtils.java index f3c57e54d8..6390f9357a 100644 --- a/src/main/java/org/springframework/data/web/PageableMethodParameterUtils.java +++ b/src/main/java/org/springframework/data/web/PageableMethodParameterUtils.java @@ -25,6 +25,7 @@ import org.springframework.core.log.LogMessage; import org.springframework.data.domain.Pageable; import org.springframework.hateoas.server.core.MethodParameters; +import org.springframework.lang.Contract; import org.springframework.lang.Nullable; /** @@ -95,6 +96,7 @@ static MethodParameter findMatchingPageableParameter(MethodParameter parameter) } @Nullable + @Contract("_, null -> null") private static MethodParameter returnIfQualifiersMatch(MethodParameter pageableParameter, @Nullable Qualifier assemblerQualifier) { diff --git a/src/main/java/org/springframework/data/web/PagedModel.java b/src/main/java/org/springframework/data/web/PagedModel.java index a7a891bf7c..c948c06d4a 100644 --- a/src/main/java/org/springframework/data/web/PagedModel.java +++ b/src/main/java/org/springframework/data/web/PagedModel.java @@ -82,7 +82,7 @@ public int hashCode() { return Objects.hash(page); } - public static record PageMetadata(long size, long number, long totalElements, long totalPages) { + public record PageMetadata(long size, long number, long totalElements, long totalPages) { public PageMetadata { Assert.isTrue(size > -1, "Size must not be negative!"); diff --git a/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java b/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java index 27b8b5306e..2b7f772b9d 100644 --- a/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java +++ b/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java @@ -58,7 +58,7 @@ public class PagedResourcesAssembler implements RepresentationModelAssembler< private final EmbeddedWrappers wrappers = new EmbeddedWrappers(false); private boolean forceFirstAndLastRels = false; - private @Nullable MethodParameter parameter; + private final @Nullable MethodParameter parameter; /** * Creates a new {@link PagedResourcesAssembler} using the given {@link PageableHandlerMethodArgumentResolver} and diff --git a/src/main/java/org/springframework/data/web/SlicedResourcesAssembler.java b/src/main/java/org/springframework/data/web/SlicedResourcesAssembler.java index e5a79b8c46..a5bf0f0efc 100644 --- a/src/main/java/org/springframework/data/web/SlicedResourcesAssembler.java +++ b/src/main/java/org/springframework/data/web/SlicedResourcesAssembler.java @@ -58,7 +58,7 @@ public class SlicedResourcesAssembler private final EmbeddedWrappers wrappers = new EmbeddedWrappers(false); private boolean forceFirstRel = false; - private @Nullable MethodParameter parameter; + private final @Nullable MethodParameter parameter; /** * Creates a new {@link SlicedResourcesAssembler} using the given {@link PageableHandlerMethodArgumentResolver} and diff --git a/src/main/java/org/springframework/data/web/SortHandlerMethodArgumentResolver.java b/src/main/java/org/springframework/data/web/SortHandlerMethodArgumentResolver.java index 7f3c60230d..d17b48f265 100644 --- a/src/main/java/org/springframework/data/web/SortHandlerMethodArgumentResolver.java +++ b/src/main/java/org/springframework/data/web/SortHandlerMethodArgumentResolver.java @@ -20,6 +20,7 @@ import org.springframework.core.MethodParameter; import org.springframework.data.domain.Sort; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; import org.springframework.web.bind.support.WebDataBinderFactory; @@ -46,6 +47,7 @@ public boolean supportsParameter(MethodParameter parameter) { return Sort.class.equals(parameter.getParameterType()); } + @NonNull @Override public Sort resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) { diff --git a/src/main/java/org/springframework/data/web/XmlBeamHttpMessageConverter.java b/src/main/java/org/springframework/data/web/XmlBeamHttpMessageConverter.java index 7b26fa03e4..e5f5fc99d6 100644 --- a/src/main/java/org/springframework/data/web/XmlBeamHttpMessageConverter.java +++ b/src/main/java/org/springframework/data/web/XmlBeamHttpMessageConverter.java @@ -16,6 +16,7 @@ package org.springframework.data.web; import java.io.IOException; +import java.io.Serial; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -57,7 +58,7 @@ public XmlBeamHttpMessageConverter() { this(new XBProjector(new DefaultXMLFactoriesConfig() { - private static final long serialVersionUID = -1324345769124477493L; + private static final @Serial long serialVersionUID = -1324345769124477493L; @Override public DocumentBuilderFactory createDocumentBuilderFactory() { diff --git a/src/main/java/org/springframework/data/web/config/ProjectingArgumentResolverRegistrar.java b/src/main/java/org/springframework/data/web/config/ProjectingArgumentResolverRegistrar.java index 3e6badd215..0b1ee0e0bc 100644 --- a/src/main/java/org/springframework/data/web/config/ProjectingArgumentResolverRegistrar.java +++ b/src/main/java/org/springframework/data/web/config/ProjectingArgumentResolverRegistrar.java @@ -29,7 +29,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.ConversionService; import org.springframework.data.web.ProxyingHandlerMethodArgumentResolver; -import org.springframework.lang.Nullable; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; @@ -93,13 +92,11 @@ public void setBeanClassLoader(ClassLoader classLoader) { this.resolver.setBeanClassLoader(classLoader); } - @Nullable @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } - @Nullable @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { diff --git a/src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java b/src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java index 460abe39bd..4999a5751b 100644 --- a/src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java +++ b/src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java @@ -15,6 +15,7 @@ */ package org.springframework.data.web.config; +import java.io.Serial; import java.util.List; import org.slf4j.Logger; @@ -70,7 +71,7 @@ public PageModule pageModule() { */ public static class PageModule extends SimpleModule { - private static final long serialVersionUID = 275254460581626332L; + private static final @Serial long serialVersionUID = 275254460581626332L; private static final String UNPAGED_TYPE_NAME = "org.springframework.data.domain.Unpaged"; private static final Class UNPAGED_TYPE; @@ -104,7 +105,7 @@ public PageModule(@Nullable SpringDataWebSettings settings) { */ static class UnpagedAsInstanceSerializer extends ToStringSerializerBase { - private static final long serialVersionUID = -1213451755610144637L; + private static final @Serial long serialVersionUID = -1213451755610144637L; public UnpagedAsInstanceSerializer() { super(Object.class); @@ -142,7 +143,7 @@ static class WarningLoggingModifier extends BeanSerializerModifier { or Spring HATEOAS and Spring Data's PagedResourcesAssembler as documented in https://docs.spring.io/spring-data/commons/reference/repositories/core-extensions.html#core.web.pageables. """; - private static final long serialVersionUID = 954857444010009875L; + private static final @Serial long serialVersionUID = 954857444010009875L; private boolean warningRendered = false; diff --git a/src/main/java/org/springframework/data/web/querydsl/ReactiveQuerydslPredicateArgumentResolver.java b/src/main/java/org/springframework/data/web/querydsl/ReactiveQuerydslPredicateArgumentResolver.java index d6eb96be6f..aed8ae4313 100644 --- a/src/main/java/org/springframework/data/web/querydsl/ReactiveQuerydslPredicateArgumentResolver.java +++ b/src/main/java/org/springframework/data/web/querydsl/ReactiveQuerydslPredicateArgumentResolver.java @@ -15,9 +15,6 @@ */ package org.springframework.data.web.querydsl; -import java.util.List; -import java.util.Map; - import org.springframework.core.MethodParameter; import org.springframework.core.convert.ConversionService; import org.springframework.data.querydsl.binding.QuerydslBindingsFactory; @@ -64,9 +61,7 @@ private static MultiValueMap getQueryParameters(ServerWebExchang MultiValueMap queryParams = exchange.getRequest().getQueryParams(); MultiValueMap parameters = new LinkedMultiValueMap<>(queryParams.size()); - for (Map.Entry> entry : queryParams.entrySet()) { - parameters.put(entry.getKey(), entry.getValue()); - } + parameters.putAll(queryParams); return parameters; } diff --git a/src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java b/src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java index 621d1e2855..e4a6cad827 100644 --- a/src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java +++ b/src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java @@ -67,6 +67,7 @@ public DummyCdiRepositoryBean(Set qualifiers, Class repositoryTyp super(qualifiers, repositoryType, beanManager, detector); } + @Override public Class getScope() { return MyScope.class; }