diff --git a/pom.xml b/pom.xml index 91b60f68c..e4ffd29e6 100644 --- a/pom.xml +++ b/pom.xml @@ -139,13 +139,6 @@ test - - org.projectlombok - lombok - ${lombok} - provided - - diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupConfiguration.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupConfiguration.java index 9ac4ca69a..034edacd7 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupConfiguration.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupConfiguration.java @@ -15,13 +15,9 @@ */ package org.springframework.data.rest.core.config; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.Value; - import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Optional; import org.springframework.core.convert.converter.Converter; @@ -56,6 +52,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { Converter converter, Lookup lookup) { new MappingBuilder(repositoryType).withIdMapping(converter).withLookup(lookup); + return this; } @@ -65,7 +62,9 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { */ @Override public > IdMappingRegistrar forLookupRepository(Class type) { + this.lookupTypes.add(AbstractRepositoryMetadata.getMetadata(type).getDomainType()); + return forRepository(type); } @@ -87,6 +86,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { Converter identifierMapping, Lookup lookup) { this.lookupTypes.add(AbstractRepositoryMetadata.getMetadata(type).getDomainType()); + return forRepository(type, identifierMapping, lookup); } @@ -95,13 +95,24 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * * @author Oliver Gierke */ - @RequiredArgsConstructor private class MappingBuilder> implements LookupRegistrar, IdMappingRegistrar { - private @NonNull final Class repositoryType; + private final Class repositoryType; private Converter idMapping; + /** + * Creates a new {@link MappingBuilder} for the given repository type. + * + * @param type must not be {@literal null}. + */ + public MappingBuilder(Class type) { + + Assert.notNull(type, "Repository type must not be null!"); + + this.repositoryType = type; + } + /** * Creates a new {@link MappingBuilder} using the given repository type and identifier mapping. * @@ -109,11 +120,8 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * @param mapping must not be {@literal null}. */ private MappingBuilder(Class repositoryType, Converter mapping) { - this(repositoryType); - Assert.notNull(mapping, "Converter must not be null!"); - this.idMapping = mapping; } @@ -152,8 +160,8 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { Assert.notNull(repositories, "Repositories must not be null!"); - return lookupInformation.stream()// - .map(it -> new RepositoriesEntityLookup<>(repositories, it))// + return lookupInformation.stream() // + .map(it -> new RepositoriesEntityLookup<>(repositories, it)) // .collect(StreamUtils.toUnmodifiableList()); } @@ -171,7 +179,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { private final LookupInformation> lookupInfo; private final Repository repository; private final Class domainType; - private final @Getter Optional lookupProperty; + private final Optional lookupProperty; /** * Creates a new {@link RepositoriesEntityLookup} for the given {@link Repositories} and {@link LookupInformation}. @@ -182,24 +190,21 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { @SuppressWarnings("unchecked") public RepositoriesEntityLookup(Repositories repositories, LookupInformation> lookupInformation) { - Assert.notNull(repositories, "Repositories must not be null!"); Assert.notNull(lookupInformation, "LookupInformation must not be null!"); - - RepositoryInformation information = repositories.getRepositoryInformation(lookupInformation.repositoryType)// - .orElseThrow(() -> new IllegalStateException( - "No repository found for type " + lookupInformation.repositoryType.getName() + "!")); - + RepositoryInformation information = // + repositories.getRepositoryInformation(lookupInformation.repositoryType) + .orElseThrow(() -> new IllegalStateException( + "No repository found for type " + lookupInformation.repositoryType.getName() + "!")); this.domainType = information.getDomainType(); this.lookupInfo = lookupInformation; - this.repository = (Repository) repositories.getRepositoryFor(information.getDomainType())// - .orElseThrow(() -> new IllegalStateException( - "No repository found for type " + information.getDomainType().getName() + "!")); - - this.lookupProperty = Optional.of(domainType) // - .flatMap(it -> MethodInvocationRecorder.forProxyOf(it) // - .record(lookupInfo.identifierMapping::convert) // - .getPropertyPath()); + this.repository = (Repository) // + repositories.getRepositoryFor(information.getDomainType()).orElseThrow(() -> new IllegalStateException( + "No repository found for type " + information.getDomainType().getName() + "!")); + this.lookupProperty = // + Optional.of(domainType).flatMap(it -> // + // + MethodInvocationRecorder.forProxyOf(it).record(lookupInfo.identifierMapping::convert).getPropertyPath()); } /* @@ -232,13 +237,86 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { public boolean supports(Class delimiter) { return domainType.isAssignableFrom(delimiter); } + + /* + * (non-Javadoc) + * @see org.springframework.data.rest.core.support.EntityLookup#getLookupProperty() + */ + public Optional getLookupProperty() { + return this.lookupProperty; + } } - @Value - private static class LookupInformation> { + private static final class LookupInformation> { private final Class repositoryType; private final Converter identifierMapping; private final Lookup lookup; + + public LookupInformation(Class repositoryType, Converter identifierMapping, + Lookup lookup) { + + Assert.notNull(repositoryType, "Repository type must not be null!"); + Assert.notNull(identifierMapping, "Identifier mapping must not be null!"); + Assert.notNull(lookup, "Lookup must not be null!"); + + this.repositoryType = repositoryType; + this.identifierMapping = identifierMapping; + this.lookup = lookup; + } + + public Class getRepositoryType() { + return this.repositoryType; + } + + public Converter getIdentifierMapping() { + return this.identifierMapping; + } + + public Lookup getLookup() { + return this.lookup; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(final java.lang.Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof EntityLookupConfiguration.LookupInformation)) { + return false; + } + + LookupInformation that = (LookupInformation) o; + + return Objects.equals(getRepositoryType(), that.getRepositoryType()) // + && Objects.equals(getIdentifierMapping(), that.getIdentifierMapping()) // + && Objects.equals(getLookup(), that.getLookup()); + } + + /* + * + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(getRepositoryType(), getIdentifierMapping(), getLookup()); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public java.lang.String toString() { + return "EntityLookupConfiguration.LookupInformation(repositoryType=" + this.getRepositoryType() + + ", identifierMapping=" + this.getIdentifierMapping() + ", lookup=" + this.getLookup() + ")"; + } } } diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/ProjectionDefinitionConfiguration.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/ProjectionDefinitionConfiguration.java index 9fd8246fa..d4732b7ad 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/ProjectionDefinitionConfiguration.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/ProjectionDefinitionConfiguration.java @@ -15,14 +15,10 @@ */ package org.springframework.data.rest.core.config; -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.Value; - import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; import org.springframework.core.annotation.AnnotationUtils; @@ -80,6 +76,7 @@ public class ProjectionDefinitionConfiguration implements ProjectionDefinitions public ProjectionDefinitionConfiguration addProjection(Class projectionType) { Assert.notNull(projectionType, "Projection type must not be null!"); + Projection annotation = AnnotationUtils.findAnnotation(projectionType, Projection.class); if (annotation == null) { @@ -89,7 +86,8 @@ public class ProjectionDefinitionConfiguration implements ProjectionDefinitions String name = annotation.name(); Class[] sourceTypes = annotation.types(); - return StringUtils.hasText(name) ? addProjection(projectionType, name, sourceTypes) + return StringUtils.hasText(name) // + ? addProjection(projectionType, name, sourceTypes) // : addProjection(projectionType, sourceTypes); } @@ -104,6 +102,7 @@ public class ProjectionDefinitionConfiguration implements ProjectionDefinitions public ProjectionDefinitionConfiguration addProjection(Class projectionType, Class... sourceTypes) { Assert.notNull(projectionType, "Projection type must not be null!"); + return addProjection(projectionType, StringUtils.uncapitalize(projectionType.getSimpleName()), sourceTypes); } @@ -146,6 +145,7 @@ public class ProjectionDefinitionConfiguration implements ProjectionDefinitions public boolean hasProjectionFor(Class sourceType) { for (ProjectionDefinition definition : projectionDefinitions) { + if (definition.sourceType.isAssignableFrom(sourceType)) { return true; } @@ -194,12 +194,21 @@ public class ProjectionDefinitionConfiguration implements ProjectionDefinitions * * @author Oliver Gierke */ - @Value - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) static final class ProjectionDefinition { - private final @NonNull Class sourceType, targetType; - private final @NonNull String name; + private final Class sourceType, targetType; + private final String name; + + private ProjectionDefinition(Class sourceType, Class targetType, String name) { + + Assert.notNull(sourceType, "Source type must not be null!"); + Assert.notNull(targetType, "Target type must not be null!"); + Assert.notNull(name, "Name must not be null!"); + + this.sourceType = sourceType; + this.targetType = targetType; + this.name = name; + } /** * Creates a new {@link ProjectionDefinitionKey} for the given source type and name; @@ -214,5 +223,58 @@ public class ProjectionDefinitionConfiguration implements ProjectionDefinitions return new ProjectionDefinition(sourceType, targetType, name); } + + public Class getSourceType() { + return this.sourceType; + } + + public Class getTargetType() { + return this.targetType; + } + + public String getName() { + return this.name; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof ProjectionDefinitionConfiguration.ProjectionDefinition)) { + return false; + } + + ProjectionDefinition that = (ProjectionDefinitionConfiguration.ProjectionDefinition) o; + + return Objects.equals(getSourceType(), that.getSourceType()) // + && Objects.equals(getTargetType(), that.getTargetType()) // + && Objects.equals(getName(), that.getName()); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(getSourceType(), getTargetType(), getName()); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public java.lang.String toString() { + return "ProjectionDefinitionConfiguration.ProjectionDefinition(sourceType=" + this.getSourceType() + + ", targetType=" + this.getTargetType() + ", name=" + this.getName() + ")"; + } } } diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/RepositoryRestConfiguration.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/RepositoryRestConfiguration.java index 893d5f7f0..6f1567421 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/RepositoryRestConfiguration.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/RepositoryRestConfiguration.java @@ -15,10 +15,6 @@ */ package org.springframework.data.rest.core.config; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; - import java.net.URI; import java.util.ArrayList; import java.util.Collections; @@ -74,13 +70,12 @@ public class RepositoryRestConfiguration { /** * The {@link RelProvider} to be used to calculate the link relation defaults for repositories. */ - private @Getter @Setter @NonNull LinkRelationProvider relProvider = new EvoInflectorLinkRelationProvider(); - + private LinkRelationProvider relProvider = new EvoInflectorLinkRelationProvider(); private final ProjectionDefinitionConfiguration projectionConfiguration; private final MetadataConfiguration metadataConfiguration; private final EntityLookupConfiguration entityLookupConfiguration; - private final @Getter ExposureConfiguration exposureConfiguration; + private final ExposureConfiguration exposureConfiguration; private final EnumTranslationConfiguration enumTranslationConfiguration; private boolean enableEnumTranslation = false; @@ -667,4 +662,25 @@ public class RepositoryRestConfiguration { public boolean isLookupType(Class type) { return this.entityLookupConfiguration.isLookupType(type); } + + /** + * The {@link RelProvider} to be used to calculate the link relation defaults for repositories. + */ + public LinkRelationProvider getRelProvider() { + return this.relProvider; + } + + /** + * The {@link RelProvider} to be used to calculate the link relation defaults for repositories. + */ + public void setRelProvider(LinkRelationProvider relProvider) { + + Assert.notNull(relProvider, "LinkRelationProvider must not be null!"); + + this.relProvider = relProvider; + } + + public ExposureConfiguration getExposureConfiguration() { + return this.exposureConfiguration; + } } diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvoker.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvoker.java index b88d9fbd6..272623f57 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvoker.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/event/AnnotatedEventHandlerInvoker.java @@ -15,15 +15,12 @@ */ package org.springframework.data.rest.core.event; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; -import lombok.ToString; - import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,6 +33,7 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.rest.core.annotation.*; import org.springframework.data.util.ProxyUtils; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -175,18 +173,27 @@ public class AnnotatedEventHandlerInvoker implements ApplicationListener { final Class targetType; final Method method; final Object handler; + public EventHandlerMethod(Class targetType, Method method, Object handler) { + + Assert.notNull(targetType, "Target type must not be null!"); + Assert.notNull(method, "Method must not be null!"); + Assert.notNull(handler, "Handler must not be null!"); + + this.targetType = targetType; + this.method = method; + this.handler = handler; + } + public static EventHandlerMethod of(Class targetType, Object handler, Method method) { ReflectionUtils.makeAccessible(method); + return new EventHandlerMethod(targetType, method, handler); } @@ -198,5 +205,46 @@ public class AnnotatedEventHandlerInvoker implements ApplicationListener methods; + private ConfigurableHttpMethods(Collection methods) { + + Assert.notNull(methods, "HttpMethods must not be null!"); + + this.methods = methods; + } + + static ConfigurableHttpMethods of(Collection methods) { + return new ConfigurableHttpMethods(methods); + } + /** * Creates a new {@link ConfigurableHttpMethods} of the given {@link HttpMethod}s. * diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ConfigurationApplyingSupportedHttpMethodsAdapter.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ConfigurationApplyingSupportedHttpMethodsAdapter.java index d57cc4d4a..2a9bdc3fb 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ConfigurationApplyingSupportedHttpMethodsAdapter.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ConfigurationApplyingSupportedHttpMethodsAdapter.java @@ -1,3 +1,4 @@ +// Generated by delombok at Tue Aug 11 12:16:38 CEST 2020 /* * Copyright 2018-2020 the original author or authors. * @@ -15,27 +16,36 @@ */ package org.springframework.data.rest.core.mapping; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import org.springframework.data.mapping.PersistentProperty; +import org.springframework.util.Assert; /** * Adapter for a {@link SupportedHttpMethods} instance that applies settings made through {@link ExposureConfiguration} * to the calculated {@link ConfigurableHttpMethods} - * + * * @author Oliver Gierke * @see ExposureConfiguration * @since 3.1 */ -@RequiredArgsConstructor -public class ConfigurationApplyingSupportedHttpMethodsAdapter implements SupportedHttpMethods { +class ConfigurationApplyingSupportedHttpMethodsAdapter implements SupportedHttpMethods { - private final @NonNull ExposureConfiguration configuration; - private final @NonNull ResourceMetadata resourceMetadata; - private final @NonNull SupportedHttpMethods delegate; + private final ExposureConfiguration configuration; + private final ResourceMetadata resourceMetadata; + private final SupportedHttpMethods delegate; - /* + ConfigurationApplyingSupportedHttpMethodsAdapter(ExposureConfiguration configuration, + ResourceMetadata resourceMetadata, SupportedHttpMethods delegate) { + + Assert.notNull(configuration, "Configuration must not be null!"); + Assert.notNull(resourceMetadata, "ResourceMetadata must not be null!"); + Assert.notNull(delegate, "SupportedHttpMethods must not be null!"); + + this.configuration = configuration; + this.resourceMetadata = resourceMetadata; + this.delegate = delegate; + } + + /* * (non-Javadoc) * @see org.springframework.data.rest.core.mapping.SupportedHttpMethods#getMethodsFor(org.springframework.data.rest.core.mapping.ResourceType) */ @@ -47,7 +57,7 @@ public class ConfigurationApplyingSupportedHttpMethodsAdapter implements Support return configuration.filter(ConfigurableHttpMethods.of(methods), type, resourceMetadata); } - /* + /* * (non-Javadoc) * @see org.springframework.data.rest.core.mapping.SupportedHttpMethods#getMethodsFor(org.springframework.data.mapping.PersistentProperty) */ @@ -66,7 +76,7 @@ public class ConfigurationApplyingSupportedHttpMethodsAdapter implements Support return configuration.filter(methods, PropertyAwareResourceMapping.class.cast(mapping)); } - /* + /* * (non-Javadoc) * @see org.springframework.data.rest.core.mapping.SupportedHttpMethods#allowsPutForCreation() */ diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ExposureConfiguration.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ExposureConfiguration.java index e43239c5d..6bbb0e326 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ExposureConfiguration.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ExposureConfiguration.java @@ -17,8 +17,6 @@ package org.springframework.data.rest.core.mapping; import static org.springframework.http.HttpMethod.*; -import lombok.RequiredArgsConstructor; - import java.util.function.Function; import org.springframework.http.HttpMethod; @@ -28,7 +26,7 @@ import org.springframework.util.Assert; * Configuration type to register filters customizing the HTTP methods supported. By default, filters registered are * applied globally. Domain type specific filters can be registered via {@link #forDomainType(Class)}. Useful global * shortcuts like {@link #disablePutOnItemResources()} do exist as well. - * + * * @author Oliver Gierke * @see #forDomainType(Class) * @since 3.1 @@ -92,7 +90,7 @@ public class ExposureConfiguration implements ExposureConfigurer { * {@link AggregateResourceHttpMethodsFilter} and {@link AssociationResourceHttpMethodsFilter}s which means the * configured filters will only be invoked for aggregates of the given type and properties owned by that type * respectively. - * + * * @param type must not be {@literal null}. * @return */ @@ -104,7 +102,7 @@ public class ExposureConfiguration implements ExposureConfigurer { /** * Disables the support for {@link HttpMethod#PUT} for item resources. - * + * * @return */ public ExposureConfiguration disablePutOnItemResources() { @@ -115,7 +113,7 @@ public class ExposureConfiguration implements ExposureConfigurer { /** * Disables the support for {@link HttpMethod#PATCH} for item resources. - * + * * @return */ public ExposureConfiguration disablePatchOnItemResources() { @@ -127,7 +125,7 @@ public class ExposureConfiguration implements ExposureConfigurer { /** * Returns whether PUT requests can be used to create new instances for the type backing the given * {@link ResourceMetadata}. - * + * * @param metadata must not be {@literal null}. * @return */ @@ -140,7 +138,7 @@ public class ExposureConfiguration implements ExposureConfigurer { /** * Returns whether PUT requests can be used to create new instances of the given domain type. - * + * * @param metadata must not be {@literal null}. * @return */ @@ -182,11 +180,17 @@ public class ExposureConfiguration implements ExposureConfigurer { * * @author Oliver Gierke */ - @RequiredArgsConstructor private class TypeBasedExposureConfigurer implements ExposureConfigurer { private final Class type; + public TypeBasedExposureConfigurer(Class type) { + + Assert.notNull(type, " must not be null!"); + + this.type = type; + } + /* * (non-Javadoc) * @see org.springframework.data.rest.core.mapping.ExposureConfigurer#withCollectionExposure(org.springframework.data.rest.core.mapping.ExposureConfigurer.AggregateResourceHttpMethodsFilter) @@ -211,7 +215,7 @@ public class ExposureConfiguration implements ExposureConfigurer { return this; } - /* + /* * (non-Javadoc) * @see org.springframework.data.rest.core.mapping.ExposureConfiguration.ExposureConfigurer#withAssociationExposure(java.util.function.BiFunction) */ @@ -229,7 +233,7 @@ public class ExposureConfiguration implements ExposureConfigurer { return this; } - /* + /* * (non-Javadoc) * @see org.springframework.data.rest.core.mapping.ExposureConfigurer#disableCreationViaPut() */ diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactory.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactory.java index 28696b4b9..0aa44e0ad 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactory.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactory.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.core.support; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.io.Serializable; import java.lang.reflect.Method; import java.util.List; @@ -75,11 +72,19 @@ public class UnwrappingRepositoryInvokerFactory implements RepositoryInvokerFact * * @author Oliver Gierke */ - @RequiredArgsConstructor private static class UnwrappingRepositoryInvoker implements RepositoryInvoker { - private final @NonNull RepositoryInvoker delegate; - private final @NonNull Optional> lookup; + private final RepositoryInvoker delegate; + private final Optional> lookup; + + public UnwrappingRepositoryInvoker(RepositoryInvoker delegate, Optional> lookup) { + + Assert.notNull(delegate, "Delegate RepositoryInvoker must not be null!"); + Assert.notNull(lookup, "EntityLookup must not be null!"); + + this.delegate = delegate; + this.lookup = lookup; + } /* * (non-Javadoc) diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/util/Java8PluginRegistry.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/util/Java8PluginRegistry.java index c1d08d4de..fe1f5c4eb 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/util/Java8PluginRegistry.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/util/Java8PluginRegistry.java @@ -15,8 +15,6 @@ */ package org.springframework.data.rest.core.util; -import lombok.RequiredArgsConstructor; - import java.util.Collections; import java.util.List; import java.util.Optional; @@ -29,11 +27,14 @@ import org.springframework.plugin.core.PluginRegistry; * @deprecated since 3.2, for removal 3.3. */ @Deprecated -@RequiredArgsConstructor public class Java8PluginRegistry, S> { private final PluginRegistry registry; + public Java8PluginRegistry(PluginRegistry registry) { + this.registry = registry; + } + public static , S> Java8PluginRegistry of(List plugins) { return Java8PluginRegistry.of(PluginRegistry.of(plugins)); } diff --git a/spring-data-rest-tests/pom.xml b/spring-data-rest-tests/pom.xml index 9be906d68..1a690c34b 100644 --- a/spring-data-rest-tests/pom.xml +++ b/spring-data-rest-tests/pom.xml @@ -43,6 +43,13 @@ ${groovy.version} + + org.projectlombok + lombok + ${lombok} + provided + + diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EmbeddedResourcesAssembler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EmbeddedResourcesAssembler.java index b8a10d05a..8aa5af16f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EmbeddedResourcesAssembler.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EmbeddedResourcesAssembler.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -38,13 +35,24 @@ import org.springframework.util.Assert; /** * @author Oliver Gierke */ -@RequiredArgsConstructor public class EmbeddedResourcesAssembler { - private final @NonNull PersistentEntities entities; - private final @NonNull Associations associations; - private final @NonNull ExcerptProjector projector; - private final @NonNull EmbeddedWrappers wrappers = new EmbeddedWrappers(false); + private final PersistentEntities entities; + private final Associations associations; + private final ExcerptProjector projector; + private final EmbeddedWrappers wrappers = new EmbeddedWrappers(false); + + public EmbeddedResourcesAssembler(PersistentEntities entities, Associations associations, + ExcerptProjector projector) { + + Assert.notNull(entities, "PersistentEntities must not be null!"); + Assert.notNull(associations, "Associations must not be null!"); + Assert.notNull(projector, "ExcerptProjector must not be null!"); + + this.entities = entities; + this.associations = associations; + this.projector = projector; + } /** * Returns the embedded resources to render. This will add an {@link RelatedResource} for linkable associations if diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/HttpHeadersPreparer.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/HttpHeadersPreparer.java index c07e5b7ec..82f2990de 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/HttpHeadersPreparer.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/HttpHeadersPreparer.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.time.Instant; import java.util.Date; import java.util.Optional; @@ -39,14 +36,18 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @soundtrack Ron Spielman Trio - Matchstick */ -@RequiredArgsConstructor public class HttpHeadersPreparer { - private final @NonNull AuditableBeanWrapperFactory auditableBeanWrapperFactory; + private final AuditableBeanWrapperFactory auditableBeanWrapperFactory; private final ConfigurableConversionService conversionService = new DefaultConversionService(); - { + public HttpHeadersPreparer(AuditableBeanWrapperFactory auditableBeanWrapperFactory) { + + Assert.notNull(auditableBeanWrapperFactory, "AuditableBeanWrapperFactory must not be null!"); + Jsr310Converters.getConvertersToRegister().forEach(conversionService::addConverter); + + this.auditableBeanWrapperFactory = auditableBeanWrapperFactory; } /** diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResource.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResource.java index bcf6e144c..b0fa1275e 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResource.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResource.java @@ -15,8 +15,6 @@ */ package org.springframework.data.rest.webmvc; -import lombok.Getter; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -46,15 +44,7 @@ public class PersistentEntityResource extends EntityModel { private final PersistentEntity entity; private final Iterable embeddeds; - - /** - * Returns whether the content of the resource is a new entity about to be created. Used to distinguish between - * creation and updates for incoming requests. - * - * @return - */ - private final @Getter boolean isNew; - private final @Getter boolean nested; + private final boolean isNew, nested; /** * Creates a new {@link PersistentEntityResource} for the given {@link PersistentEntity}, content, embedded @@ -79,6 +69,20 @@ public class PersistentEntityResource extends EntityModel { this.nested = nested; } + /** + * Returns whether the content of the resource is a new entity about to be created. Used to distinguish between + * creation and updates for incoming requests. + * + * @return + */ + public boolean isNew() { + return this.isNew; + } + + public boolean isNested() { + return this.nested; + } + /** * Returns the {@link PersistentEntity} for the underlying instance. * diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java index eed60d59c..7e3a27cd5 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java @@ -19,9 +19,6 @@ import static java.util.stream.Collectors.*; import static org.springframework.data.rest.webmvc.RestMediaTypes.*; import static org.springframework.web.bind.annotation.RequestMethod.*; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import java.io.Serializable; import java.util.Arrays; import java.util.Collection; @@ -62,6 +59,8 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -460,7 +459,6 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro } } - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) static class HttpRequestMethodNotSupportedException extends RuntimeException { private static final long serialVersionUID = 3704212056962845475L; @@ -469,6 +467,17 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro private final HttpMethod[] allowedMethods; private final String message; + private HttpRequestMethodNotSupportedException(HttpMethod rejectedMethod, HttpMethod[] allowedMethods, + @Nullable String message) { + + Assert.notNull(rejectedMethod, "Rejected HttpMethod must not be null!"); + Assert.notNull(allowedMethods, "Allowed HttpMethod must not be null!"); + + this.rejectedMethod = rejectedMethod; + this.allowedMethods = allowedMethods; + this.message = message; + } + public static HttpRequestMethodNotSupportedException forRejectedMethod(HttpMethod method) { return new HttpRequestMethodNotSupportedException(method, new HttpMethod[0], null); } @@ -486,6 +495,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro * (non-Javadoc) * @see java.lang.Throwable#getMessage() */ + @Nullable @Override public String getMessage() { return message; diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMapping.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMapping.java index 5d2a7aba6..8840059b8 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMapping.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMapping.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; @@ -300,12 +297,23 @@ public class RepositoryRestHandlerMapping extends BasePathAwareHandlerMapping { * @author Oliver Gierke * @since 2.6 */ - @RequiredArgsConstructor static class RepositoryCorsConfigurationAccessor { - private final @NonNull ResourceMappings mappings; - private final @NonNull StringValueResolver embeddedValueResolver; - private final @NonNull Optional repositories; + private final ResourceMappings mappings; + private final StringValueResolver embeddedValueResolver; + private final Optional repositories; + + public RepositoryCorsConfigurationAccessor(ResourceMappings mappings, StringValueResolver embeddedValueResolver, + Optional repositories) { + + Assert.notNull(mappings, "ResourceMappings must not be null!"); + Assert.notNull(embeddedValueResolver, "StringValueResolver must not be null!"); + Assert.notNull(repositories, "Repositories must not be null!"); + + this.mappings = mappings; + this.embeddedValueResolver = embeddedValueResolver; + this.repositories = repositories; + } Optional findCorsConfiguration(String lookupPath) { diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceStatus.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceStatus.java index 4b74fc95a..435ba6e71 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceStatus.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ResourceStatus.java @@ -15,11 +15,6 @@ */ package org.springframework.data.rest.webmvc; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.List; import java.util.function.Supplier; @@ -39,12 +34,22 @@ import org.springframework.util.Assert; * @since 2.6 * @soundtrack Blumentopf - Dass ich nicht lache (Kein Zufall) */ -@RequiredArgsConstructor(staticName = "of") class ResourceStatus { private static final String INVALID_DOMAIN_OBJECT = "Domain object %s is not an instance of the given PersistentEntity of type %s!"; - private final @NonNull HttpHeadersPreparer preparer; + private final HttpHeadersPreparer preparer; + + private ResourceStatus(HttpHeadersPreparer preparer) { + + Assert.notNull(preparer, "HttpHeadersPreparer must not be null!"); + + this.preparer = preparer; + } + + public static ResourceStatus of(HttpHeadersPreparer preparer) { + return new ResourceStatus(preparer); + } /** * Returns the {@link StatusAndHeaders} calculated from the given {@link HttpHeaders}, domain object and @@ -77,11 +82,22 @@ class ResourceStatus { : StatusAndHeaders.modified(responseHeaders); } - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) public static class StatusAndHeaders { - private final @NonNull HttpHeaders headers; - private final @Getter(AccessLevel.PACKAGE) boolean modified; + private final HttpHeaders headers; + private final boolean modified; + + private StatusAndHeaders(HttpHeaders headers, boolean modified) { + + Assert.notNull(headers, "HttpHeaders must not be null!"); + + this.headers = headers; + this.modified = modified; + } + + boolean isModified() { + return this.modified; + } private static StatusAndHeaders notModified(HttpHeaders headers) { return new StatusAndHeaders(headers, false); @@ -99,7 +115,9 @@ class ResourceStatus { * @return */ public ResponseEntity> toResponseEntity(Supplier supplier) { - return modified ? new ResponseEntity>(supplier.get(), headers, HttpStatus.OK) + + return modified // + ? new ResponseEntity>(supplier.get(), headers, HttpStatus.OK) // : new ResponseEntity>(headers, HttpStatus.NOT_MODIFIED); } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/alps/RootResourceInformationToAlpsDescriptorConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/alps/RootResourceInformationToAlpsDescriptorConverter.java index 304e08fba..b2da81a8e 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/alps/RootResourceInformationToAlpsDescriptorConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/alps/RootResourceInformationToAlpsDescriptorConverter.java @@ -17,9 +17,6 @@ package org.springframework.data.rest.webmvc.alps; import static org.springframework.hateoas.mediatype.alps.Alps.*; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -66,6 +63,7 @@ import org.springframework.hateoas.mediatype.alps.Format; import org.springframework.hateoas.mediatype.alps.Type; import org.springframework.hateoas.server.EntityLinks; import org.springframework.http.HttpMethod; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import com.fasterxml.jackson.databind.ObjectMapper; @@ -78,19 +76,41 @@ import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; * @author Oliver Gierke * @author Greg Turnquist */ -@RequiredArgsConstructor public class RootResourceInformationToAlpsDescriptorConverter { private static final List UNDOCUMENTED_METHODS = Arrays.asList(HttpMethod.OPTIONS, HttpMethod.HEAD); - private final @NonNull Associations associations; - private final @NonNull Repositories repositories; - private final @NonNull PersistentEntities persistentEntities; - private final @NonNull EntityLinks entityLinks; - private final @NonNull MessageResolver resolver; - private final @NonNull RepositoryRestConfiguration configuration; - private final @NonNull ObjectMapper mapper; - private final @NonNull EnumTranslator translator; + private final Associations associations; + private final Repositories repositories; + private final PersistentEntities persistentEntities; + private final EntityLinks entityLinks; + private final MessageResolver resolver; + private final RepositoryRestConfiguration configuration; + private final ObjectMapper mapper; + private final EnumTranslator translator; + + public RootResourceInformationToAlpsDescriptorConverter(Associations associations, Repositories repositories, + PersistentEntities persistentEntities, EntityLinks entityLinks, MessageResolver resolver, + RepositoryRestConfiguration configuration, ObjectMapper mapper, EnumTranslator translator) { + + Assert.notNull(associations, "Associations must not be null!"); + Assert.notNull(repositories, "Repositories must not be null!"); + Assert.notNull(persistentEntities, "PersistentEntities must not be null!"); + Assert.notNull(entityLinks, "EntityLinks must not be null!"); + Assert.notNull(resolver, "MessageResolver must not be null!"); + Assert.notNull(configuration, "RepositoryRestConfiguration must not be null!"); + Assert.notNull(mapper, "ObjectMapper must not be null!"); + Assert.notNull(translator, "EnumTranslator must not be null!"); + + this.associations = associations; + this.repositories = repositories; + this.persistentEntities = persistentEntities; + this.entityLinks = entityLinks; + this.resolver = resolver; + this.configuration = configuration; + this.mapper = mapper; + this.translator = translator; + } /* * (non-Javadoc) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/DelegatingHandlerMapping.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/DelegatingHandlerMapping.java index a20917a97..bad7de073 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/DelegatingHandlerMapping.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/DelegatingHandlerMapping.java @@ -15,12 +15,9 @@ */ package org.springframework.data.rest.webmvc.config; -import lombok.Getter; -import lombok.NonNull; -import lombok.Value; - import java.util.Iterator; import java.util.List; +import java.util.Objects; import javax.servlet.http.HttpServletRequest; @@ -47,7 +44,7 @@ import org.springframework.web.util.pattern.PathPatternParser; class DelegatingHandlerMapping extends AbstractHandlerMapping implements org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping { - private final @Getter List delegates; + private final List delegates; /** * Creates a new {@link DelegatingHandlerMapping} for the given delegates. @@ -61,6 +58,11 @@ class DelegatingHandlerMapping extends AbstractHandlerMapping this.delegates = delegates; } + @java.lang.SuppressWarnings("all") + public List getDelegates() { + return this.delegates; + } + @Override public void setPatternParser(PathPatternParser parser) { @@ -113,13 +115,12 @@ class DelegatingHandlerMapping extends AbstractHandlerMapping } } - @Value private static class HandlerSelectionResult { - @NonNull HttpServletRequest request; - HandlerMapping mapping; - HandlerExecutionChain result; - Exception ignoredException; + private final HttpServletRequest request; + private final HandlerMapping mapping; + private final HandlerExecutionChain result; + private final Exception ignoredException; public static HandlerSelectionResult from(HttpServletRequest request, Iterable delegates) throws Exception { @@ -174,5 +175,58 @@ class DelegatingHandlerMapping extends AbstractHandlerMapping ? ((MatchableHandlerMapping) mapping).match(request, pattern) // : null; } + + public HandlerSelectionResult(HttpServletRequest request, HandlerMapping mapping, HandlerExecutionChain result, + Exception ignoredException) { + + Assert.notNull(request, "HttpServletRequest must not be null!"); + + this.request = request; + this.mapping = mapping; + this.result = result; + this.ignoredException = ignoredException; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(final java.lang.Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof DelegatingHandlerMapping.HandlerSelectionResult)) { + return false; + } + + HandlerSelectionResult other = (HandlerSelectionResult) o; + + return Objects.equals(request, other.request) // + && Objects.equals(mapping, other.mapping) // + && Objects.equals(result, other.result) // + && Objects.equals(ignoredException, other.ignoredException); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(request, mapping, result, ignoredException); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public java.lang.String toString() { + return "DelegatingHandlerMapping.HandlerSelectionResult(request=" + request + ", mapping=" + mapping + ", result=" + + result + ", ignoredException=" + ignoredException + ")"; + } } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceAssemblerArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceAssemblerArgumentResolver.java index 424a6dd6a..e9cb579ac 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceAssemblerArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceAssemblerArgumentResolver.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc.config; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import org.springframework.core.MethodParameter; import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.projection.ProjectionFactory; @@ -26,6 +23,7 @@ import org.springframework.data.rest.core.support.SelfLinkProvider; import org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler; import org.springframework.data.rest.webmvc.mapping.Associations; import org.springframework.data.rest.webmvc.support.PersistentEntityProjector; +import org.springframework.util.Assert; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -36,14 +34,30 @@ import org.springframework.web.method.support.ModelAndViewContainer; * * @author Oliver Gierke */ -@RequiredArgsConstructor public class PersistentEntityResourceAssemblerArgumentResolver implements HandlerMethodArgumentResolver { - private final @NonNull PersistentEntities entities; - private final @NonNull SelfLinkProvider linkProvider; - private final @NonNull ProjectionDefinitions projectionDefinitions; - private final @NonNull ProjectionFactory projectionFactory; - private final @NonNull Associations links; + private final PersistentEntities entities; + private final SelfLinkProvider linkProvider; + private final ProjectionDefinitions projectionDefinitions; + private final ProjectionFactory projectionFactory; + private final Associations associations; + + public PersistentEntityResourceAssemblerArgumentResolver(PersistentEntities entities, SelfLinkProvider linkProvider, + ProjectionDefinitions projectionDefinitions, ProjectionFactory projectionFactory, + Associations associations) { + + Assert.notNull(entities, "PersistentEntities must not be null!"); + Assert.notNull(linkProvider, "SelfLinkProvider must not be null!"); + Assert.notNull(projectionDefinitions, "ProjectionDefinitions must not be null!"); + Assert.notNull(projectionFactory, "ProjectionFactory must not be null!"); + Assert.notNull(associations, "Associations must not be null!"); + + this.entities = entities; + this.linkProvider = linkProvider; + this.projectionDefinitions = projectionDefinitions; + this.projectionFactory = projectionFactory; + this.associations = associations; + } /* * (non-Javadoc) @@ -64,8 +78,8 @@ public class PersistentEntityResourceAssemblerArgumentResolver implements Handle String projectionParameter = webRequest.getParameter(projectionDefinitions.getParameterName()); PersistentEntityProjector projector = new PersistentEntityProjector(projectionDefinitions, projectionFactory, - projectionParameter, links.getMappings()); + projectionParameter, associations.getMappings()); - return new PersistentEntityResourceAssembler(entities, projector, links, linkProvider); + return new PersistentEntityResourceAssembler(entities, projector, associations, linkProvider); } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java index 6036bd1cc..af4bd2e8e 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc.config; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.io.IOException; import java.io.Serializable; import java.util.List; @@ -48,6 +45,7 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.plugin.core.PluginRegistry; +import org.springframework.util.Assert; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -63,19 +61,37 @@ import com.fasterxml.jackson.databind.node.ObjectNode; * @author Jon Brisbin * @author Oliver Gierke */ -@RequiredArgsConstructor public class PersistentEntityResourceHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { private static final String ERROR_MESSAGE = "Could not read an object of type %s from the request!"; private static final String NO_CONVERTER_FOUND = "No suitable HttpMessageConverter found to read request body into object of type %s from request with content type of %s!"; - private final @NonNull List> messageConverters; - private final @NonNull RootResourceInformationHandlerMethodArgumentResolver resourceInformationResolver; - private final @NonNull BackendIdHandlerMethodArgumentResolver idResolver; - private final @NonNull DomainObjectReader reader; - private final @NonNull PluginRegistry, Class> lookups; + private final List> messageConverters; + private final RootResourceInformationHandlerMethodArgumentResolver resourceInformationResolver; + private final BackendIdHandlerMethodArgumentResolver idResolver; + private final DomainObjectReader reader; + private final PluginRegistry, Class> lookups; private final ConversionService conversionService = new DefaultConversionService(); + public PersistentEntityResourceHandlerMethodArgumentResolver( + List> messageConverters, + RootResourceInformationHandlerMethodArgumentResolver resourceInformationResolver, + BackendIdHandlerMethodArgumentResolver idResolver, DomainObjectReader reader, + PluginRegistry, Class> lookups) { + + Assert.notNull(messageConverters, "HttpMessageConverters must not be null!"); + Assert.notNull(resourceInformationResolver, "RootResourceInformation resolver must not be null!"); + Assert.notNull(idResolver, "IdResolver must not be null!"); + Assert.notNull(reader, "DomainObjectReader must not be null!"); + Assert.notNull(lookups, "EntityLookups must not be null!"); + + this.messageConverters = messageConverters; + this.resourceInformationResolver = resourceInformationResolver; + this.idResolver = idResolver; + this.reader = reader; + this.lookups = lookups; + } + /* * (non-Javadoc) * @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java index e46614e60..d1432db4f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java @@ -15,10 +15,6 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; @@ -66,11 +62,19 @@ import com.fasterxml.jackson.databind.node.ObjectNode; * @author Thomas Mrozinski * @since 2.2 */ -@RequiredArgsConstructor public class DomainObjectReader { - private final @NonNull PersistentEntities entities; - private final @NonNull Associations associationLinks; + private final PersistentEntities entities; + private final Associations associationLinks; + + public DomainObjectReader(PersistentEntities entities, Associations associationLinks) { + + Assert.notNull(entities, "PersistentEntities must not be null!"); + Assert.notNull(associationLinks, "Associations must not be null!"); + + this.entities = entities; + this.associationLinks = associationLinks; + } /** * Reads the given input stream into an {@link ObjectNode} and applies that to the given existing instance. @@ -572,11 +576,19 @@ public class DomainObjectReader { * * @author Oliver Gierke */ - @RequiredArgsConstructor - private final class LinkedAssociationSkippingAssociationHandler implements SimpleAssociationHandler { + private static final class LinkedAssociationSkippingAssociationHandler implements SimpleAssociationHandler { - private final @NonNull Associations associations; - private final @NonNull SimplePropertyHandler delegate; + private final Associations associations; + private final SimplePropertyHandler delegate; + + public LinkedAssociationSkippingAssociationHandler(Associations associations, SimplePropertyHandler delegate) { + + Assert.notNull(associations, "Associations must not be null!"); + Assert.notNull(delegate, "Delegate SimplePropertyHandler must not be null!"); + + this.associations = associations; + this.delegate = delegate; + } /* * (non-Javadoc) @@ -585,7 +597,7 @@ public class DomainObjectReader { @Override public void doWithAssociation(Association> association) { - if (associationLinks.isLinkableAssociation(association)) { + if (associations.isLinkableAssociation(association)) { return; } @@ -600,7 +612,7 @@ public class DomainObjectReader { */ private class MergingPropertyHandler implements SimplePropertyHandler { - private final @Getter MappedProperties properties; + private final MappedProperties properties; private final PersistentPropertyAccessor targetAccessor; private final PersistentPropertyAccessor sourceAccessor; private final ObjectMapper mapper; @@ -628,6 +640,10 @@ public class DomainObjectReader { this.mapper = mapper; } + public MappedProperties getProperties() { + return this.properties; + } + /* * (non-Javadoc) * @see org.springframework.data.mapping.SimplePropertyHandler#doWithPersistentProperty(org.springframework.data.mapping.PersistentProperty) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/EnumTranslator.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/EnumTranslator.java index d220b57ee..1667d1012 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/EnumTranslator.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/EnumTranslator.java @@ -15,8 +15,6 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.RequiredArgsConstructor; - import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -178,12 +176,21 @@ public class EnumTranslator implements EnumTranslationConfiguration { * @since 3.2 * @soundtrack Dave Matthews Band - #41 [4.20.02] (Best of What's Around – Encore Vol. 1) */ - @RequiredArgsConstructor(staticName = "of") private static class TranslatedEnum implements MessageSourceResolvable { private final Enum value; private final boolean withDefaultTranslation; + private TranslatedEnum(Enum value, boolean withDefaultTranslation) { + + this.value = value; + this.withDefaultTranslation = withDefaultTranslation; + } + + public static TranslatedEnum of(Enum value, boolean withDefaultTranslation) { + return new TranslatedEnum(value, withDefaultTranslation); + } + /* * (non-Javadoc) * @see org.springframework.context.MessageSourceResolvable#getCodes() diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/JacksonMappingAwareSortTranslator.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/JacksonMappingAwareSortTranslator.java index 9e67ed0dc..cbe5cfbff 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/JacksonMappingAwareSortTranslator.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/JacksonMappingAwareSortTranslator.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -49,7 +46,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Oliver Gierke * @since 2.6 */ -@RequiredArgsConstructor public class JacksonMappingAwareSortTranslator { private final Repositories repositories; @@ -111,7 +107,6 @@ public class JacksonMappingAwareSortTranslator { * @author Oliver Gierke * @since 2.6 */ - @RequiredArgsConstructor public static class SortTranslator { private static final String DELIMITERS = "_\\."; @@ -119,9 +114,20 @@ public class JacksonMappingAwareSortTranslator { private static final Pattern SPLITTER = Pattern.compile("(?:[%s]?([%s]*?[^%s]+))".replaceAll("%s", DELIMITERS)); - private final @NonNull PersistentEntities persistentEntities; - private final @NonNull ObjectMapper objectMapper; - private final @NonNull Associations associations; + private final PersistentEntities entities; + private final ObjectMapper objectMapper; + private final Associations associations; + + public SortTranslator(PersistentEntities entities, ObjectMapper objectMapper, Associations associations) { + + Assert.notNull(entities, "PersistentEntities must not be null!"); + Assert.notNull(objectMapper, "ObjectMapper must not be null!"); + Assert.notNull(associations, "Associations must not be null!"); + + this.entities = entities; + this.objectMapper = objectMapper; + this.associations = associations; + } /** * Translates {@link Sort} orders from Jackson-mapped field names to {@link PersistentProperty} names. Properties @@ -172,7 +178,7 @@ public class JacksonMappingAwareSortTranslator { List persistentPropertyPath = new ArrayList(iteratorSource.size()); - TypedSegment typedSegment = TypedSegment.create(persistentEntities, objectMapper, rootEntity); + TypedSegment typedSegment = TypedSegment.create(entities, objectMapper, rootEntity); for (String field : iteratorSource) { diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java index d6a139200..814b347fb 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -46,7 +43,6 @@ import com.fasterxml.jackson.databind.introspect.ClassIntrospector; * @author Mark Paluch * @author Mathias Düsterhöft */ -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) class MappedProperties { private final Map, BeanPropertyDefinition> propertyToFieldName; @@ -55,6 +51,17 @@ class MappedProperties { private final Set ignoredPropertyNames; private final boolean anySetterFound; + private MappedProperties(Map, BeanPropertyDefinition> propertyToFieldName, + Map> fieldNameToProperty, Set unmappedProperties, + Set ignoredPropertyNames, boolean anySetterFound) { + + this.propertyToFieldName = propertyToFieldName; + this.fieldNameToProperty = fieldNameToProperty; + this.unmappedProperties = unmappedProperties; + this.ignoredPropertyNames = ignoredPropertyNames; + this.anySetterFound = anySetterFound; + } + /** * Creates a new {@link MappedProperties} instance for the given {@link PersistentEntity} and {@link BeanDescription}. * diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwareDefaultedPageableArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwareDefaultedPageableArgumentResolver.java index 00d3fc5eb..95ae0e73a 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwareDefaultedPageableArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwareDefaultedPageableArgumentResolver.java @@ -15,15 +15,13 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import org.springframework.core.MethodParameter; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.rest.webmvc.support.DefaultedPageable; import org.springframework.data.web.PageableHandlerMethodArgumentResolver; +import org.springframework.util.Assert; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -41,11 +39,20 @@ import org.springframework.web.method.support.ModelAndViewContainer; * @author Oliver Gierke * @since 2.6 */ -@RequiredArgsConstructor public class MappingAwareDefaultedPageableArgumentResolver implements HandlerMethodArgumentResolver { - private final @NonNull JacksonMappingAwareSortTranslator translator; - private final @NonNull PageableHandlerMethodArgumentResolver delegate; + private final JacksonMappingAwareSortTranslator translator; + private final PageableHandlerMethodArgumentResolver delegate; + + public MappingAwareDefaultedPageableArgumentResolver(JacksonMappingAwareSortTranslator translator, + PageableHandlerMethodArgumentResolver delegate) { + + Assert.notNull(translator, "JacksonMappingAwareSortTranslator must not be null!"); + Assert.notNull(delegate, "Delegate PageableHandlerMethodArgumentResolver must not be null!"); + + this.translator = translator; + this.delegate = delegate; + } /* * (non-Javadoc) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwarePageableArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwarePageableArgumentResolver.java index 578c68a1e..e63af1823 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwarePageableArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwarePageableArgumentResolver.java @@ -15,14 +15,12 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import org.springframework.core.MethodParameter; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableArgumentResolver; +import org.springframework.util.Assert; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -40,11 +38,20 @@ import org.springframework.web.method.support.ModelAndViewContainer; * @author Oliver Gierke * @since 2.6 */ -@RequiredArgsConstructor public class MappingAwarePageableArgumentResolver implements HandlerMethodArgumentResolver, PageableArgumentResolver { - private final @NonNull JacksonMappingAwareSortTranslator translator; - private final @NonNull PageableArgumentResolver delegate; + private final JacksonMappingAwareSortTranslator translator; + private final PageableArgumentResolver delegate; + + public MappingAwarePageableArgumentResolver(JacksonMappingAwareSortTranslator translator, + PageableArgumentResolver delegate) { + + Assert.notNull(translator, "JacksonMappingAwareSortTranslator must not be null!"); + Assert.notNull(delegate, "Delegate PageableArgumentResolver must not be null!"); + + this.translator = translator; + this.delegate = delegate; + } /* * (non-Javadoc) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwareSortArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwareSortArgumentResolver.java index c8e27af59..b5318d06d 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwareSortArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappingAwareSortArgumentResolver.java @@ -15,13 +15,11 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import org.springframework.core.MethodParameter; import org.springframework.data.domain.Sort; import org.springframework.data.web.SortArgumentResolver; import org.springframework.data.web.SortHandlerMethodArgumentResolver; +import org.springframework.util.Assert; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -38,11 +36,19 @@ import org.springframework.web.method.support.ModelAndViewContainer; * @author Oliver Gierke * @since 2.6 */ -@RequiredArgsConstructor public class MappingAwareSortArgumentResolver implements HandlerMethodArgumentResolver, SortArgumentResolver { - private final @NonNull JacksonMappingAwareSortTranslator translator; - private final @NonNull SortArgumentResolver delegate; + private final JacksonMappingAwareSortTranslator translator; + private final SortArgumentResolver delegate; + + public MappingAwareSortArgumentResolver(JacksonMappingAwareSortTranslator translator, SortArgumentResolver delegate) { + + Assert.notNull(translator, "JacksonMappingAwareSortTranslator must not be null!"); + Assert.notNull(delegate, "Delegate SortArgumentResolver must not be null!"); + + this.translator = translator; + this.delegate = delegate; + } /* * (non-Javadoc) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java index a02d63439..303e8cf88 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.io.IOException; import java.lang.reflect.Field; import java.net.URI; @@ -231,13 +228,26 @@ public class PersistentEntityJackson2Module extends SimpleModule { * * @author Oliver Gierke */ - @RequiredArgsConstructor static class AssociationOmittingSerializerModifier extends BeanSerializerModifier { - private final @NonNull PersistentEntities entities; - private final @NonNull Associations associations; - private final @NonNull NestedEntitySerializer nestedEntitySerializer; - private final @NonNull LookupObjectSerializer lookupObjectSerializer; + private final PersistentEntities entities; + private final Associations associations; + private final NestedEntitySerializer nestedEntitySerializer; + private final LookupObjectSerializer lookupObjectSerializer; + + public AssociationOmittingSerializerModifier(PersistentEntities entities, Associations associations, + NestedEntitySerializer nestedEntitySerializer, LookupObjectSerializer lookupObjectSerializer) { + + Assert.notNull(entities, "PersistentEntities must not be null!"); + Assert.notNull(associations, "Associations must not be null!"); + Assert.notNull(nestedEntitySerializer, "NestedEntitySerializer must not be null!"); + Assert.notNull(lookupObjectSerializer, "LookupObjectSerializer must not be null!"); + + this.entities = entities; + this.associations = associations; + this.nestedEntitySerializer = nestedEntitySerializer; + this.lookupObjectSerializer = lookupObjectSerializer; + } /* * (non-Javadoc) @@ -403,13 +413,27 @@ public class PersistentEntityJackson2Module extends SimpleModule { * * @author Oliver Gierke */ - @RequiredArgsConstructor public static class AssociationUriResolvingDeserializerModifier extends BeanDeserializerModifier { - private final @NonNull PersistentEntities entities; - private final @NonNull Associations associationLinks; - private final @NonNull UriToEntityConverter converter; - private final @NonNull RepositoryInvokerFactory factory; + private final PersistentEntities entities; + private final Associations associationLinks; + private final UriToEntityConverter converter; + private final RepositoryInvokerFactory factory; + + @java.lang.SuppressWarnings("all") + public AssociationUriResolvingDeserializerModifier(PersistentEntities entities, Associations associations, + UriToEntityConverter converter, RepositoryInvokerFactory factory) { + + Assert.notNull(entities, "PersistentEntities must not be null!"); + Assert.notNull(associations, "Associations must not be null!"); + Assert.notNull(converter, "UriToEntityConverter must not be null!"); + Assert.notNull(factory, "RepositoryInvokerFactory must not be null!"); + + this.entities = entities; + this.associationLinks = associations; + this.converter = converter; + this.factory = factory; + } /* * (non-Javadoc) @@ -846,12 +870,19 @@ public class PersistentEntityJackson2Module extends SimpleModule { } } - @RequiredArgsConstructor public static class LookupObjectSerializer extends ToStringSerializer { private static final long serialVersionUID = -3033458643050330913L; + private final PluginRegistry, Class> lookups; + public LookupObjectSerializer(PluginRegistry, Class> lookups) { + + Assert.notNull(lookups, "EntityLookups must not be null!"); + + this.lookups = lookups; + } + /* * (non-Javadoc) * @see com.fasterxml.jackson.databind.ser.std.ToStringSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java index a551712e1..b3bf88973 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityToJsonSchemaConverter.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc.json; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -91,7 +88,7 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric * * @param entities must not be {@literal null}. * @param mappings must not be {@literal null}. - * @param accessor must not be {@literal null}. + * @param resolver must not be {@literal null}. * @param objectMapper must not be {@literal null}. * @param configuration must not be {@literal null}. */ @@ -275,28 +272,8 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric return getPropertiesFor(property.getActualType(), associations.getMappings().getMetadataFor(property.getActualType()), descriptors); } - // - // private JsonSchemaProperty getSchemaProperty(BeanPropertyDefinition definition, TypeInformation type, - // ResourceDescription description) { - // - // String name = definition.getName(); - // String title = resolver.resolveWithDefault(new ResolvableProperty(definition)); - // String resolvedDescription = resolver.resolve(description); - // boolean required = definition.isRequired(); - // Class rawType = type.getType(); - // - // if (!rawType.isEnum()) { - // return new JsonSchemaProperty(name, title, resolvedDescription, required).with(type); - // } - // - // String message = resolver.resolve(new DefaultMessageSourceResolvable(description.getMessage())); - // - // return new EnumProperty(name, title, rawType, - // description.getDefaultMessage().equals(resolvedDescription) ? message : resolvedDescription, required); - // } private ResourceDescription getDescriptionFor(PersistentProperty property, ResourceMetadata metadata) { - ResourceMapping propertyMapping = metadata.getMappingFor(property); return propertyMapping.getDescription(); } @@ -308,7 +285,6 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric * @since 2.4 */ private class JsonSchemaPropertyRegistrar { - private final JacksonMetadata metadata; private final List> properties; @@ -318,32 +294,25 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric * @param metadata must not be {@literal null}. */ public JsonSchemaPropertyRegistrar(JacksonMetadata metadata) { - Assert.notNull(metadata, "Metadata must not be null!"); - this.metadata = metadata; this.properties = new ArrayList>(); } public void register(JsonSchemaProperty property, TypeInformation type) { - if (type == null) { properties.add(property); return; } - JsonSerializer serializer = metadata.getTypeSerializer(type.getType()); - if (serializer instanceof JsonSchemaPropertyCustomizer) { properties.add(((JsonSchemaPropertyCustomizer) serializer).customize(property, type)); return; } - if (configuration.isLookupType(type.getType())) { properties.add(customizerFactory.getCustomizerFor(type.getType()).customize(property, type)); return; } - properties.add(property); } @@ -352,10 +321,16 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric } } - @RequiredArgsConstructor public static class ValueTypeSchemaPropertyCustomizerFactory { - private final @NonNull RepositoryInvokerFactory factory; + private final RepositoryInvokerFactory factory; + + public ValueTypeSchemaPropertyCustomizerFactory(RepositoryInvokerFactory factory) { + + Assert.notNull(factory, "RepositoryInvokerFactory must not be null!"); + + this.factory = factory; + } public JsonSchemaPropertyCustomizer getCustomizerFor(final Class type) { @@ -442,13 +417,24 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric } } - @RequiredArgsConstructor private static class JacksonProperty { private final JacksonMetadata metadata; private final Optional> property; private final BeanPropertyDefinition definition; + public JacksonProperty(JacksonMetadata metadata, Optional> property, + BeanPropertyDefinition definition) { + + Assert.notNull(metadata, "JacksonMetadata must not be null!"); + Assert.notNull(property, "PersistentProperty must not be null!"); + Assert.notNull(definition, "BeanPropertyDefinition must not be null!"); + + this.metadata = metadata; + this.property = property; + this.definition = definition; + } + @SuppressWarnings("rawtypes") public TypeInformation getPropertyType() { return property.map(it -> (TypeInformation) it.getTypeInformation()) @@ -499,12 +485,20 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric } } - @RequiredArgsConstructor private static class DefaultMessageResolver implements InternalMessageResolver { - private final MessageResolver accessor; + private final MessageResolver resolver; private final RepositoryRestConfiguration configuration; + public DefaultMessageResolver(MessageResolver resolver, RepositoryRestConfiguration configuration) { + + Assert.notNull(resolver, "MessageResolver must not be null!"); + Assert.notNull(configuration, "RepositoryRestConfiguration must not be null!"); + + this.resolver = resolver; + this.configuration = configuration; + } + public String resolve(MessageSourceResolvable resolvable) { if (resolvable == null) { @@ -512,7 +506,7 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric } try { - return accessor.resolve(resolvable); + return resolver.resolve(resolvable); } catch (NoSuchMessageException o_O) { if (configuration.getMetadataConfiguration().omitUnresolvableDescriptionKeys()) { @@ -532,9 +526,7 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric * @since 2.4 */ private static class DefaultingMessageSourceResolvable implements MessageSourceResolvable { - private static Pattern SPLIT_CAMEL_CASE = Pattern.compile("(?>> findUnwrappedPropertyPaths(Class type, NameTransformer nameTransformer, boolean considerRegularProperties) { - return persistentEntities.getPersistentEntity(type).map(entity -> { + return entities.getPersistentEntity(type).map(entity -> { Map>> mapping = new HashMap>>(); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/CopyOperation.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/CopyOperation.java index f57f78063..416571bd1 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/CopyOperation.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/CopyOperation.java @@ -15,9 +15,8 @@ */ package org.springframework.data.rest.webmvc.json.patch; -import lombok.RequiredArgsConstructor; - import org.springframework.data.rest.webmvc.json.patch.SpelPath.UntypedSpelPath; +import org.springframework.util.Assert; /** *

@@ -62,11 +61,17 @@ class CopyOperation extends PatchOperation { return new CopyOperationBuilder(from); } - @RequiredArgsConstructor static class CopyOperationBuilder { private final String from; + public CopyOperationBuilder(String from) { + + Assert.hasText(from, "From must not be null!"); + + this.from = from; + } + CopyOperation to(String to) { return new CopyOperation(SpelPath.untyped(to), SpelPath.untyped(from)); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonLateObjectEvaluator.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonLateObjectEvaluator.java index 6474b44d6..5a0dce93e 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonLateObjectEvaluator.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonLateObjectEvaluator.java @@ -15,8 +15,7 @@ */ package org.springframework.data.rest.webmvc.json.patch; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; +import org.springframework.util.Assert; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -29,11 +28,19 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Oliver Gierke * @author Simon Allegraud */ -@RequiredArgsConstructor class JsonLateObjectEvaluator implements LateObjectEvaluator { - private final @NonNull ObjectMapper mapper; - private final @NonNull JsonNode valueNode; + private final ObjectMapper mapper; + private final JsonNode node; + + public JsonLateObjectEvaluator(ObjectMapper mapper, JsonNode node) { + + Assert.notNull(mapper, "ObjectMapper must not be null!"); + Assert.notNull(node, "JsonNode must not be null!"); + + this.mapper = mapper; + this.node = node; + } /* * (non-Javadoc) @@ -43,9 +50,9 @@ class JsonLateObjectEvaluator implements LateObjectEvaluator { public Object evaluate(Class type) { try { - return mapper.readValue(valueNode.traverse(mapper.getFactory().getCodec()), type); + return mapper.readValue(node.traverse(mapper.getFactory().getCodec()), type); } catch (Exception o_O) { - throw new PatchException(String.format("Could not read %s into %s!", valueNode, type), o_O); + throw new PatchException(String.format("Could not read %s into %s!", node, type), o_O); } } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonPatchPatchConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonPatchPatchConverter.java index 7464dac4a..71201002c 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonPatchPatchConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonPatchPatchConverter.java @@ -15,13 +15,12 @@ */ package org.springframework.data.rest.webmvc.json.patch; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.springframework.util.Assert; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -34,10 +33,16 @@ import com.fasterxml.jackson.databind.node.ArrayNode; * @author Mathias Düsterhöft * @author Oliver Trosien */ -@RequiredArgsConstructor public class JsonPatchPatchConverter implements PatchConverter { - private final @NonNull ObjectMapper mapper; + private final ObjectMapper mapper; + + public JsonPatchPatchConverter(ObjectMapper mapper) { + + Assert.notNull(mapper, "ObjectMapper must not be null!"); + + this.mapper = mapper; + } /** * Constructs a {@link Patch} object given a JsonNode. @@ -99,7 +104,7 @@ public class JsonPatchPatchConverter implements PatchConverter { return valueNode.asInt(); } else if (valueNode.isLong()) { return valueNode.asLong(); - } else if (valueNode.isObject() || (valueNode.isArray())) { + } else if (valueNode.isObject() || valueNode.isArray()) { return new JsonLateObjectEvaluator(mapper, valueNode); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/MoveOperation.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/MoveOperation.java index d757ccdc3..929f1ab3c 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/MoveOperation.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/MoveOperation.java @@ -15,10 +15,8 @@ */ package org.springframework.data.rest.webmvc.json.patch; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import org.springframework.data.rest.webmvc.json.patch.SpelPath.UntypedSpelPath; +import org.springframework.util.Assert; /** *

@@ -56,11 +54,17 @@ class MoveOperation extends PatchOperation { return new MoveOperationBuilder(from); } - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) static class MoveOperationBuilder { private final String from; + private MoveOperationBuilder(String from) { + + Assert.hasText(from, "From must not be null or empty!"); + + this.from = from; + } + public MoveOperation to(String to) { return new MoveOperation(SpelPath.untyped(to), SpelPath.untyped(from)); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/PatchOperation.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/PatchOperation.java index ddea57348..46e38bb19 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/PatchOperation.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/PatchOperation.java @@ -15,10 +15,8 @@ */ package org.springframework.data.rest.webmvc.json.patch; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import org.springframework.data.rest.webmvc.json.patch.SpelPath.UntypedSpelPath; +import org.springframework.util.Assert; /** * Abstract base class representing and providing support methods for patch operations. @@ -27,11 +25,10 @@ import org.springframework.data.rest.webmvc.json.patch.SpelPath.UntypedSpelPath; * @author Mathias Düsterhöft * @author Oliver Gierke */ -@RequiredArgsConstructor public abstract class PatchOperation { - protected final @NonNull String op; - protected final @NonNull UntypedSpelPath path; + protected final String op; + protected final UntypedSpelPath path; protected final Object value; /** @@ -44,6 +41,16 @@ public abstract class PatchOperation { this(op, path, null); } + protected PatchOperation(String op, UntypedSpelPath path, Object value) { + + Assert.hasText(op, "Operation must not be null or empty!"); + Assert.notNull(path, "UntypedSpelPath must not be null!"); + + this.op = op; + this.path = path; + this.value = value; + } + /** * Performs late-value evaluation on the operation value if the value is a {@link LateObjectEvaluator}. * diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/ReplaceOperation.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/ReplaceOperation.java index 9813405de..665e6baac 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/ReplaceOperation.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/ReplaceOperation.java @@ -1,3 +1,4 @@ +// Generated by delombok at Tue Aug 11 12:51:25 CEST 2020 /* * Copyright 2014-2020 the original author or authors. * @@ -15,9 +16,6 @@ */ package org.springframework.data.rest.webmvc.json.patch; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import org.springframework.data.rest.webmvc.json.patch.SpelPath.UntypedSpelPath; /** @@ -27,7 +25,6 @@ import org.springframework.data.rest.webmvc.json.patch.SpelPath.UntypedSpelPath; * @author Oliver Gierke */ class ReplaceOperation extends PatchOperation { - /** * Constructs the replace operation * @@ -42,14 +39,18 @@ class ReplaceOperation extends PatchOperation { return new ReplaceOperationBuilder(path); } - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) - static class ReplaceOperationBuilder { + static class ReplaceOperationBuilder { private final String path; public ReplaceOperation with(Object value) { return new ReplaceOperation(SpelPath.untyped(path), value); } + + @java.lang.SuppressWarnings("all") + private ReplaceOperationBuilder(final String path) { + this.path = path; + } } /* diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/SpelPath.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/SpelPath.java index 964dabce6..25becfaa1 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/SpelPath.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/SpelPath.java @@ -15,16 +15,11 @@ */ package org.springframework.data.rest.webmvc.json.patch; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Value; - import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; @@ -52,14 +47,24 @@ import org.springframework.util.StringUtils; * * @author Oliver Gierke */ -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) class SpelPath { private static final SpelExpressionParser SPEL_EXPRESSION_PARSER = new SpelExpressionParser(); private static final String APPEND_CHARACTER = "-"; private static final Map UNTYPED_PATHS = new ConcurrentReferenceHashMap<>(32); - protected final @Getter String path; + protected final String path; + + private SpelPath(String path) { + + Assert.notNull(path, "Path must not be null!"); + + this.path = path; + } + + public String getPath() { + return this.path; + } /** * Returns a {@link UntypedSpelPath} for the given source. @@ -153,7 +158,6 @@ class SpelPath { * * @author Oliver Gierke */ - @EqualsAndHashCode(callSuper = true) static class TypedSpelPath extends SpelPath { private static final String INVALID_PATH_REFERENCE = "Invalid path reference %s on type %s!"; @@ -164,10 +168,62 @@ class SpelPath { private final Expression expression; private final Class type; - @Value(staticConstructor = "of") - private static class CacheKey { - Class type; - UntypedSpelPath path; + private static final class CacheKey { + + private final Class type; + private final UntypedSpelPath path; + + private CacheKey(Class type, UntypedSpelPath path) { + + Assert.notNull(type, "Type must not be null!"); + Assert.notNull(path, "UntypedSpelPath must not be null!"); + + this.type = type; + this.path = path; + } + + public static CacheKey of(final Class type, final UntypedSpelPath path) { + return new CacheKey(type, path); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof CacheKey)) { + return false; + } + + CacheKey that = (CacheKey) o; + + return Objects.equals(type, that.type) // + && Objects.equals(path, that.path); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(type, path); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public java.lang.String toString() { + return "SpelPath.TypedSpelPath.CacheKey(type=" + type + ", path=" + path + ")"; + } } private TypedSpelPath(UntypedSpelPath path, Class type) { @@ -441,17 +497,31 @@ class SpelPath { } } - @Value - @RequiredArgsConstructor(access = AccessLevel.PRIVATE, staticName = "of") - private static class SkippedPropertyPath { + private static final class SkippedPropertyPath { - PropertyPath path; - boolean skipped; + private final PropertyPath path; + private final boolean skipped; + + private SkippedPropertyPath(PropertyPath path, boolean skipped) { + + Assert.notNull(path, "PropertyPath must not be null!"); + + this.path = path; + this.skipped = skipped; + } public static SkippedPropertyPath of(String segment, Class type) { return of(PropertyPath.from(segment, type), false); } + private static SkippedPropertyPath of(PropertyPath path, boolean skipped) { + return new SkippedPropertyPath(path, skipped); + } + + public PropertyPath getPath() { + return this.path; + } + public SkippedPropertyPath nested(String segment) { if (skipped) { @@ -464,6 +534,44 @@ class SpelPath { ? SkippedPropertyPath.of(path, true) // : SkippedPropertyPath.of(path.nested(segment), false); } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof SkippedPropertyPath)) { + return false; + } + SkippedPropertyPath other = (SkippedPropertyPath) o; + + return Objects.equals(path, other.path) // + && skipped == other.skipped; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(path, skipped); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public java.lang.String toString() { + return "SpelPath.TypedSpelPath.SkippedPropertyPath(path=" + path + ", skipped=" + skipped + ")"; + } } private static Expression toSpel(String path, Class type) { @@ -494,8 +602,7 @@ class SpelPath { .orElseGet(() -> SkippedPropertyPath.of(next, type)); } - @Value - private static class SpelExpressionBuilder { + private static final class SpelExpressionBuilder { private static final TypeInformation STRING_TYPE = ClassTypeInformation.from(String.class); @@ -504,6 +611,35 @@ class SpelPath { private final String spelSegment; private final boolean skipped; + public SpelExpressionBuilder(@Nullable PropertyPath basePath, Class type, String spelSegment, + boolean skipped) { + + Assert.notNull(type, "Type must not be null!"); + Assert.notNull(spelSegment, "SpEL segment must not be null!"); + + this.basePath = basePath; + this.type = type; + this.spelSegment = spelSegment; + this.skipped = skipped; + } + + @Nullable + public PropertyPath getBasePath() { + return this.basePath; + } + + public Class getType() { + return this.type; + } + + public String getSpelSegment() { + return this.spelSegment; + } + + public boolean isSkipped() { + return this.skipped; + } + public String getExpression() { return StringUtils.hasText(spelSegment) ? spelSegment : null; } @@ -570,6 +706,77 @@ class SpelPath { return nested(segment); } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (o == this) { + return true; + } + if (!(o instanceof SpelExpressionBuilder)) { + return false; + } + + SpelExpressionBuilder that = (SpelExpressionBuilder) o; + + return Objects.equals(basePath, that.basePath) // + && Objects.equals(type, that.type) // + && Objects.equals(spelSegment, that.spelSegment) // + && skipped == that.skipped; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(basePath, type, spelSegment, skipped); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public java.lang.String toString() { + return "SpelPath.TypedSpelPath.SpelExpressionBuilder(basePath=" + this.getBasePath() + ", type=" + + this.getType() + ", spelSegment=" + this.getSpelSegment() + ", skipped=" + this.isSkipped() + ")"; + } + } + + /* + * (non-Javadoc) + * @see org.springframework.data.rest.webmvc.json.patch.SpelPath#equals(java.lang.Object) + */ + @Override + public boolean equals(final java.lang.Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof TypedSpelPath) || !super.equals(o)) { + return false; + } + + TypedSpelPath that = (TypedSpelPath) o; + + return Objects.equals(expression, that.expression) // + && Objects.equals(type, that.type); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.rest.webmvc.json.patch.SpelPath#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(expression, type); } } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/TestOperation.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/TestOperation.java index 4df260c06..65ad7040f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/TestOperation.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/TestOperation.java @@ -15,13 +15,11 @@ */ package org.springframework.data.rest.webmvc.json.patch; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; - import java.math.BigDecimal; import java.math.BigInteger; import org.springframework.data.rest.webmvc.json.patch.SpelPath.UntypedSpelPath; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** @@ -52,11 +50,17 @@ class TestOperation extends PatchOperation { return new TestOperationBuilder(path); } - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) static class TestOperationBuilder { private final String path; + private TestOperationBuilder(String path) { + + Assert.hasText(path, "Path must not be null or empty!"); + + this.path = path; + } + public TestOperation hasValue(Object value) { return new TestOperation(SpelPath.untyped(path), value); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/Associations.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/Associations.java index f0aa9cf03..473124b77 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/Associations.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/Associations.java @@ -17,10 +17,6 @@ package org.springframework.data.rest.webmvc.mapping; import static org.springframework.hateoas.TemplateVariable.VariableType.*; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.Collections; import java.util.List; @@ -47,11 +43,23 @@ import org.springframework.util.Assert; * @author Haroun Pacquee * @since 2.1 */ -@RequiredArgsConstructor public class Associations { - private final @NonNull @Getter ResourceMappings mappings; - private final @NonNull RepositoryRestConfiguration config; + private final ResourceMappings mappings; + private final RepositoryRestConfiguration config; + + public Associations(ResourceMappings mappings, RepositoryRestConfiguration config) { + + Assert.notNull(mappings, "ResourceMappings must not be null!"); + Assert.notNull(config, "RepositoryRestConfiguration must not be null!"); + + this.mappings = mappings; + this.config = config; + } + + public ResourceMappings getMappings() { + return this.mappings; + } /** * Returns the links to render for the given {@link Association}. diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollectingAssociationHandler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollectingAssociationHandler.java index addd4287a..e9c6e3a86 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollectingAssociationHandler.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollectingAssociationHandler.java @@ -33,7 +33,10 @@ import org.springframework.util.Assert; * * @author Oliver Gierke * @since 2.1 + * @deprecated no replacement, internal usage only. For removal in 3.5. + * @see LinkCollector */ +@Deprecated public class LinkCollectingAssociationHandler implements SimpleAssociationHandler { private static final String AMBIGUOUS_ASSOCIATIONS = "Detected multiple association links with same relation type! Disambiguate association %s using @RestResource!"; diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollector.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollector.java index f60068ab4..d370d8866 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollector.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/LinkCollector.java @@ -15,10 +15,6 @@ */ package org.springframework.data.rest.webmvc.mapping; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -99,7 +95,7 @@ public class LinkCollector { Path path = new Path(selfLink.expand().getHref()); - LinkCollectingAssociationHandler handler = new LinkCollectingAssociationHandler(entities, path, associationLinks); + LinkCollectingAssociationHandler handler = new LinkCollectingAssociationHandler(path, associationLinks); entities.getRequiredPersistentEntity(object.getClass()).doWithAssociations(handler); return addSelfLinkIfNecessary(object, existingLinks.and(handler.getLinks())); @@ -117,11 +113,8 @@ public class LinkCollector { } private Links addSelfLinkIfNecessary(Object object, Links existing) { - - return existing.hasLink(IanaLinkRelations.SELF) // - ? existing // - : Links.of(createSelfLink(object, existing)) // - .and(existing); + return existing.andIf(!existing.hasLink(IanaLinkRelations.SELF), + () -> links.createSelfLinkFor(object).withSelfRel()); } private Link createSelfLink(Object object, Links existing) { @@ -136,15 +129,22 @@ public class LinkCollector { * @author Oliver Gierke * @since 2.1 */ - @RequiredArgsConstructor private static class LinkCollectingAssociationHandler implements SimpleAssociationHandler { private static final String AMBIGUOUS_ASSOCIATIONS = "Detected multiple association links with same relation type! Disambiguate association %s using @RestResource!"; - private final @NonNull PersistentEntities entities; - private final @NonNull Path basePath; - private final @NonNull Associations associationLinks; - private final @NonNull List links = new ArrayList(); + private final Path basePath; + private final Associations associationLinks; + private final List links = new ArrayList(); + + public LinkCollectingAssociationHandler(Path basePath, Associations associationLinks) { + + Assert.notNull(basePath, "Base Path must not be null!"); + Assert.notNull(associationLinks, "Associations must not be null!"); + + this.basePath = basePath; + this.associationLinks = associationLinks; + } /** * Returns the links collected after the {@link Association} has been traversed. @@ -178,13 +178,28 @@ public class LinkCollector { } } - @RequiredArgsConstructor private static class NestedLinkCollectingAssociationHandler implements SimpleAssociationHandler { private final SelfLinkProvider selfLinks; private final PersistentPropertyAccessor accessor; private final Associations associations; - private final @Getter List links = new ArrayList(); + private final List links = new ArrayList(); + + public NestedLinkCollectingAssociationHandler(SelfLinkProvider selfLinks, + PersistentPropertyAccessor accessor, Associations associations) { + + Assert.notNull(selfLinks, "SelfLinkProvider must not be null!"); + Assert.notNull(accessor, "PersistentPropertyAccessor must not be null!"); + Assert.notNull(associations, "Associations must not be null!"); + + this.selfLinks = selfLinks; + this.accessor = accessor; + this.associations = associations; + } + + public List getLinks() { + return this.links; + } /* * (non-Javadoc) @@ -198,7 +213,6 @@ public class LinkCollector { } PersistentProperty property = association.getInverse(); - Object value = accessor.getProperty(property); if (value == null) { @@ -236,11 +250,9 @@ public class LinkCollector { @SuppressWarnings("unchecked") private static Collection asCollection(Object object) { - if (object instanceof Collection) { - return (Collection) object; - } - - return Collections.singleton(object); + return object instanceof Collection // + ? (Collection) object // + : Collections.singleton(object); } } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/NestedLinkCollectingAssociationHandler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/NestedLinkCollectingAssociationHandler.java index df3e9b770..158c8132c 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/NestedLinkCollectingAssociationHandler.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/NestedLinkCollectingAssociationHandler.java @@ -1,3 +1,4 @@ +// Generated by delombok at Tue Aug 11 12:51:25 CEST 2020 /* * Copyright 2016-2020 the original author or authors. * @@ -15,9 +16,6 @@ */ package org.springframework.data.rest.webmvc.mapping; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -37,16 +35,28 @@ import org.springframework.hateoas.server.EntityLinks; /** * @author Oliver Gierke + * @deprecated no replacement, internal usage only. For removal in 3.5 + * @see LinkCollector */ -@RequiredArgsConstructor +@Deprecated public class NestedLinkCollectingAssociationHandler implements SimpleAssociationHandler { - private final EntityLinks entityLinks; private final PersistentEntities entities; private final PersistentPropertyAccessor accessor; private final ResourceMappings mappings; + private final List links = new ArrayList(); - private final @Getter List links = new ArrayList(); + public NestedLinkCollectingAssociationHandler(final EntityLinks entityLinks, final PersistentEntities entities, + final PersistentPropertyAccessor accessor, final ResourceMappings mappings) { + this.entityLinks = entityLinks; + this.entities = entities; + this.accessor = accessor; + this.mappings = mappings; + } + + public List getLinks() { + return this.links; + } /* * (non-Javadoc) @@ -54,29 +64,20 @@ public class NestedLinkCollectingAssociationHandler implements SimpleAssociation */ @Override public void doWithAssociation(Association> association) { - PersistentProperty property = association.getInverse(); Object propertyValue = accessor.getProperty(property); - ResourceMetadata metadata = mappings.getMetadataFor(property.getOwner().getType()); ResourceMapping propertyMapping = metadata.getMappingFor(property); - if (property.isCollectionLike()) { - for (Object element : (Collection) propertyValue) { - PersistentEntity entity = entities.getRequiredPersistentEntity(element.getClass()); IdentifierAccessor identifierAccessor = entity.getIdentifierAccessor(element); - links.add(entityLinks.linkForItemResource(element.getClass(), identifierAccessor.getIdentifier()) .withRel(propertyMapping.getRel())); } - } else { - PersistentEntity entity = entities.getRequiredPersistentEntity(propertyValue.getClass()); IdentifierAccessor identifierAccessor = entity.getIdentifierAccessor(propertyValue); - links.add(entityLinks.linkForItemResource(propertyValue.getClass(), identifierAccessor.getIdentifier()) .withRel(propertyMapping.getRel())); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DefaultExcerptProjector.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DefaultExcerptProjector.java index 1ec985419..c918caab8 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DefaultExcerptProjector.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DefaultExcerptProjector.java @@ -15,8 +15,6 @@ */ package org.springframework.data.rest.webmvc.support; -import lombok.RequiredArgsConstructor; - import java.util.Optional; import org.springframework.data.projection.ProjectionFactory; @@ -31,12 +29,20 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @since 2.5 */ -@RequiredArgsConstructor public class DefaultExcerptProjector implements ExcerptProjector { private final ProjectionFactory factory; private final ResourceMappings mappings; + public DefaultExcerptProjector(ProjectionFactory factory, ResourceMappings mappings) { + + Assert.notNull(factory, "ProjectionFactory must not be null!"); + Assert.notNull(mappings, "ResourceMappings must not be null!"); + + this.factory = factory; + this.mappings = mappings; + } + /* * (non-Javadoc) * @see org.springframework.data.rest.webmvc.support.ExcerptProjector#projectExcerpt(java.lang.Object) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DefaultedPageable.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DefaultedPageable.java index 7e9ea33fe..a75131307 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DefaultedPageable.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DefaultedPageable.java @@ -15,28 +15,37 @@ */ package org.springframework.data.rest.webmvc.support; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NonNull; -import lombok.Value; +import java.util.Objects; import org.springframework.data.domain.Pageable; +import org.springframework.util.Assert; /** * Value object to capture a {@link Pageable} as well whether it is the default one configured. * * @author Oliver Gierke */ -@Value -public class DefaultedPageable { +public final class DefaultedPageable { + + private final Pageable pageable; + private final boolean isDefault; + + public DefaultedPageable(Pageable pageable, boolean isDefault) { + + Assert.notNull(pageable, "Pageable must not be null!"); + + this.pageable = pageable; + this.isDefault = isDefault; + } /** * Returns the delegate {@link Pageable}. * * @return can be {@literal null}. */ - private final @NonNull Pageable pageable; - private final @Getter(value = AccessLevel.NONE) boolean isDefault; + public Pageable getPageable() { + return this.pageable; + } /** * Returns whether the contained {@link Pageable} is the default one configured. @@ -56,4 +65,43 @@ public class DefaultedPageable { public Pageable unpagedIfDefault() { return isDefault ? Pageable.unpaged() : pageable; } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof DefaultedPageable)) { + return false; + } + + DefaultedPageable that = (DefaultedPageable) o; + + return Objects.equals(pageable, that.pageable) // + && isDefault == that.isDefault; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(pageable, isDefault); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public java.lang.String toString() { + return "DefaultedPageable(pageable=" + pageable + ", isDefault=" + isDefault + ")"; + } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DomainClassResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DomainClassResolver.java index 433079f9e..eae685657 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DomainClassResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/DomainClassResolver.java @@ -15,9 +15,6 @@ */ package org.springframework.data.rest.webmvc.support; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.lang.reflect.Method; import java.util.List; @@ -38,12 +35,28 @@ import org.springframework.web.context.request.NativeWebRequest; * @author Oliver Gierke * @since 2.6 */ -@RequiredArgsConstructor(staticName = "of") public class DomainClassResolver { - private final @NonNull Repositories repositories; - private final @NonNull ResourceMappings mappings; - private final @NonNull BaseUri baseUri; + private final Repositories repositories; + private final ResourceMappings mappings; + private final BaseUri baseUri; + + private DomainClassResolver(Repositories repositories, ResourceMappings mappings, + BaseUri baseUri) { + + Assert.notNull(repositories, "Repositories must not be null!"); + Assert.notNull(mappings, "ResourceMappings must not be null!"); + Assert.notNull(baseUri, "BaseUri must not be null!"); + + this.repositories = repositories; + this.mappings = mappings; + this.baseUri = baseUri; + } + + public static DomainClassResolver of(Repositories repositories, + ResourceMappings mappings, BaseUri baseUri) { + return new DomainClassResolver(repositories, mappings, baseUri); + } /** * Resolves a domain class that is associated with the {@link NativeWebRequest} diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ETag.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ETag.java index 53571b258..1d5ceec7b 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ETag.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/ETag.java @@ -17,8 +17,7 @@ package org.springframework.data.rest.webmvc.support; import static org.springframework.util.StringUtils.*; -import lombok.EqualsAndHashCode; - +import java.util.Objects; import java.util.Optional; import org.springframework.data.mapping.PersistentEntity; @@ -33,7 +32,6 @@ import org.springframework.util.Assert; * * @author Oliver Gierke */ -@EqualsAndHashCode public final class ETag { public static final ETag NO_ETAG = new ETag(null); @@ -173,4 +171,33 @@ public final class ETag { .map(it -> accessor.getProperty(it))// .map(Object::toString); } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof ETag)) { + return false; + } + + ETag other = (ETag) o; + + return Objects.equals(value, other.value); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(value); + } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessage.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessage.java index 097b7f049..45a813f59 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessage.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryConstraintViolationExceptionMessage.java @@ -15,13 +15,13 @@ */ package org.springframework.data.rest.webmvc.support; -import lombok.Value; - import java.util.ArrayList; import java.util.List; +import java.util.Objects; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.data.rest.core.RepositoryConstraintViolationException; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.validation.FieldError; @@ -59,10 +59,86 @@ public class RepositoryConstraintViolationExceptionMessage { return errors; } - @Value(staticConstructor = "of") - public static class ValidationError { - String entity, property; - Object invalidValue; - String message; + public static final class ValidationError { + + private final String entity; + private final String property; + private final @Nullable Object invalidValue; + private final String message; + + private ValidationError(String entity, String property, Object invalidValue, String message) { + + Assert.hasText(entity, "Entity must not be null or empty!"); + Assert.hasText(property, "Property must not be null or empty!"); + Assert.hasText(message, "Message must not be null or empty!"); + + this.entity = entity; + this.property = property; + this.invalidValue = invalidValue; + this.message = message; + } + + public static ValidationError of(String entity, String property, Object invalidValue, String message) { + return new ValidationError(entity, property, invalidValue, message); + } + + public String getEntity() { + return this.entity; + } + + public String getProperty() { + return this.property; + } + + @Nullable + public Object getInvalidValue() { + return this.invalidValue; + } + + public String getMessage() { + return this.message; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (!(o instanceof ValidationError)) { + return false; + } + + ValidationError other = (ValidationError) o; + + return Objects.equals(entity, other.entity) // + && Objects.equals(property, other.property) // + && Objects.equals(invalidValue, other.invalidValue) // + && Objects.equals(message, other.message); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return Objects.hash(entity, property, invalidValue, message); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public java.lang.String toString() { + return "RepositoryConstraintViolationExceptionMessage.ValidationError(entity=" + entity + ", property=" + property + + ", invalidValue=" + invalidValue + ", message=" + message + ")"; + } } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.java index d43baf65b..22f02c9ce 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.java @@ -17,9 +17,6 @@ package org.springframework.data.rest.webmvc.support; import static org.springframework.hateoas.TemplateVariable.VariableType.*; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -60,14 +57,29 @@ import org.springframework.web.util.UriComponentsBuilder; * @author Jon Brisbin * @author Oliver Gierke */ -@RequiredArgsConstructor public class RepositoryEntityLinks extends AbstractEntityLinks { - private final @NonNull Repositories repositories; - private final @NonNull ResourceMappings mappings; - private final @NonNull RepositoryRestConfiguration config; - private final @NonNull PagingAndSortingTemplateVariables templateVariables; - private final @NonNull PluginRegistry> idConverters; + private final Repositories repositories; + private final ResourceMappings mappings; + private final RepositoryRestConfiguration config; + private final PagingAndSortingTemplateVariables templateVariables; + private final PluginRegistry> idConverters; + + public RepositoryEntityLinks(Repositories repositories, ResourceMappings mappings, RepositoryRestConfiguration config, + PagingAndSortingTemplateVariables templateVariables, PluginRegistry> idConverters) { + + Assert.notNull(repositories, "Repositories must not be null!"); + Assert.notNull(mappings, "ResourceMappings must not be null!"); + Assert.notNull(config, "RepositoryRestConfiguration must not be null!"); + Assert.notNull(templateVariables, "PagingAndSortingTemplateVariables must not be null!"); + Assert.notNull(idConverters, "BackendIdConverters must not be null!"); + + this.repositories = repositories; + this.mappings = mappings; + this.config = config; + this.templateVariables = templateVariables; + this.idConverters = idConverters; + } /* * (non-Javadoc) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/util/InputStreamHttpInputMessage.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/util/InputStreamHttpInputMessage.java index 883dd7679..af382c01b 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/util/InputStreamHttpInputMessage.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/util/InputStreamHttpInputMessage.java @@ -15,23 +15,39 @@ */ package org.springframework.data.rest.webmvc.util; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - import java.io.InputStream; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; +import org.springframework.util.Assert; /** * {@link HttpInputMessage} based on a plain {@link InputStream}, i.e. exposing no headers. * * @author Oliver Drotbohm */ -@RequiredArgsConstructor(staticName = "of") public class InputStreamHttpInputMessage implements HttpInputMessage { - private final @Getter InputStream body; + private final InputStream body; + + private InputStreamHttpInputMessage(final InputStream body) { + + Assert.notNull(body, "InputStream must not be null!"); + + this.body = body; + } + + public static InputStreamHttpInputMessage of(final InputStream body) { + return new InputStreamHttpInputMessage(body); + } + + /* + * (non-Javadoc) + * @see org.springframework.http.HttpInputMessage#getBody() + */ + public InputStream getBody() { + return this.body; + } /* * (non-Javadoc)