DATAREST-1523 - Delombok production sources.

Hacking.
This commit is contained in:
Oliver Drotbohm
2020-08-11 12:50:57 +02:00
parent be2fa72904
commit b17fed5fa6
50 changed files with 1366 additions and 440 deletions

View File

@@ -139,13 +139,6 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>

View File

@@ -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<T, ID> converter, Lookup<R, ID> lookup) {
new MappingBuilder<T, ID, R>(repositoryType).withIdMapping(converter).withLookup(lookup);
return this;
}
@@ -65,7 +62,9 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
*/
@Override
public <T, ID, R extends Repository<T, ?>> IdMappingRegistrar<T, R> forLookupRepository(Class<R> type) {
this.lookupTypes.add(AbstractRepositoryMetadata.getMetadata(type).getDomainType());
return forRepository(type);
}
@@ -87,6 +86,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar {
Converter<T, ID> identifierMapping, Lookup<R, ID> 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<T, ID, R extends Repository<T, ?>>
implements LookupRegistrar<T, ID, R>, IdMappingRegistrar<T, R> {
private @NonNull final Class<R> repositoryType;
private final Class<R> repositoryType;
private Converter<T, ID> idMapping;
/**
* Creates a new {@link MappingBuilder} for the given repository type.
*
* @param type must not be {@literal null}.
*/
public MappingBuilder(Class<R> 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<R> repositoryType, Converter<T, ID> 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<Object, Object, Repository<? extends T, ?>> lookupInfo;
private final Repository<? extends T, ?> repository;
private final Class<?> domainType;
private final @Getter Optional<String> lookupProperty;
private final Optional<String> 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<Object, Object, Repository<? extends T, ?>> 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<? extends T, ?>) 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<? extends T, ?>) //
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<String> getLookupProperty() {
return this.lookupProperty;
}
}
@Value
private static class LookupInformation<T, ID, R extends Repository<? extends T, ?>> {
private static final class LookupInformation<T, ID, R extends Repository<? extends T, ?>> {
private final Class<R> repositoryType;
private final Converter<T, ID> identifierMapping;
private final Lookup<R, ID> lookup;
public LookupInformation(Class<R> repositoryType, Converter<T, ID> identifierMapping,
Lookup<R, ID> 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<R> getRepositoryType() {
return this.repositoryType;
}
public Converter<T, ID> getIdentifierMapping() {
return this.identifierMapping;
}
public Lookup<R, ID> 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() + ")";
}
}
}

View File

@@ -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() + ")";
}
}
}

View File

@@ -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;
}
}

View File

@@ -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<Reposit
handlerMethods.put(eventType, events);
}
@ToString
@EqualsAndHashCode
@RequiredArgsConstructor
static class EventHandlerMethod implements Comparable<EventHandlerMethod> {
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<Reposit
public int compareTo(EventHandlerMethod o) {
return AnnotationAwareOrderComparator.INSTANCE.compare(this.method, o.method);
}
/*
* (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 EventHandlerMethod)) {
return false;
}
EventHandlerMethod other = (AnnotatedEventHandlerInvoker.EventHandlerMethod) o;
return Objects.equals(targetType, other.targetType) //
&& Objects.equals(method, other.method) //
&& Objects.equals(handler, other.handler);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return Objects.hash(targetType, method, handler);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public java.lang.String toString() {
return "AnnotatedEventHandlerInvoker.EventHandlerMethod(targetType=" + this.targetType + ", method=" + this.method
+ ", handler=" + this.handler + ")";
}
}
}

View File

@@ -15,9 +15,6 @@
*/
package org.springframework.data.rest.core.mapping;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
@@ -34,7 +31,6 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @since 3.1
*/
@RequiredArgsConstructor(staticName = "of", access = AccessLevel.PACKAGE)
public class ConfigurableHttpMethods implements HttpMethods {
public static final ConfigurableHttpMethods NONE = ConfigurableHttpMethods.of();
@@ -42,6 +38,17 @@ public class ConfigurableHttpMethods implements HttpMethods {
private final Collection<HttpMethod> methods;
private ConfigurableHttpMethods(Collection<HttpMethod> methods) {
Assert.notNull(methods, "HttpMethods must not be null!");
this.methods = methods;
}
static ConfigurableHttpMethods of(Collection<HttpMethod> methods) {
return new ConfigurableHttpMethods(methods);
}
/**
* Creates a new {@link ConfigurableHttpMethods} of the given {@link HttpMethod}s.
*

View File

@@ -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()
*/

View File

@@ -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()
*/

View File

@@ -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<EntityLookup<?>> lookup;
private final RepositoryInvoker delegate;
private final Optional<EntityLookup<?>> lookup;
public UnwrappingRepositoryInvoker(RepositoryInvoker delegate, Optional<EntityLookup<?>> 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)

View File

@@ -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<T extends Plugin<S>, S> {
private final PluginRegistry<T, S> registry;
public Java8PluginRegistry(PluginRegistry<T, S> registry) {
this.registry = registry;
}
public static <T extends Plugin<S>, S> Java8PluginRegistry<T, S> of(List<? extends T> plugins) {
return Java8PluginRegistry.of(PluginRegistry.of(plugins));
}

View File

@@ -43,6 +43,13 @@
<version>${groovy.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -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

View File

@@ -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;
}
/**

View File

@@ -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<Object> {
private final PersistentEntity<?, ?> entity;
private final Iterable<EmbeddedWrapper> 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<Object> {
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.
*

View File

@@ -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;

View File

@@ -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> repositories;
private final ResourceMappings mappings;
private final StringValueResolver embeddedValueResolver;
private final Optional<Repositories> repositories;
public RepositoryCorsConfigurationAccessor(ResourceMappings mappings, StringValueResolver embeddedValueResolver,
Optional<Repositories> 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<CorsConfiguration> findCorsConfiguration(String lookupPath) {

View File

@@ -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<EntityModel<?>> toResponseEntity(Supplier<PersistentEntityResource> supplier) {
return modified ? new ResponseEntity<EntityModel<?>>(supplier.get(), headers, HttpStatus.OK)
return modified //
? new ResponseEntity<EntityModel<?>>(supplier.get(), headers, HttpStatus.OK) //
: new ResponseEntity<EntityModel<?>>(headers, HttpStatus.NOT_MODIFIED);
}
}

View File

@@ -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<HttpMethod> 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)

View File

@@ -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<HandlerMapping> delegates;
private final List<HandlerMapping> 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<HandlerMapping> 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<HandlerMapping> 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 + ")";
}
}
}

View File

@@ -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);
}
}

View File

@@ -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<HttpMessageConverter<?>> messageConverters;
private final @NonNull RootResourceInformationHandlerMethodArgumentResolver resourceInformationResolver;
private final @NonNull BackendIdHandlerMethodArgumentResolver idResolver;
private final @NonNull DomainObjectReader reader;
private final @NonNull PluginRegistry<EntityLookup<?>, Class<?>> lookups;
private final List<HttpMessageConverter<?>> messageConverters;
private final RootResourceInformationHandlerMethodArgumentResolver resourceInformationResolver;
private final BackendIdHandlerMethodArgumentResolver idResolver;
private final DomainObjectReader reader;
private final PluginRegistry<EntityLookup<?>, Class<?>> lookups;
private final ConversionService conversionService = new DefaultConversionService();
public PersistentEntityResourceHandlerMethodArgumentResolver(
List<HttpMessageConverter<?>> messageConverters,
RootResourceInformationHandlerMethodArgumentResolver resourceInformationResolver,
BackendIdHandlerMethodArgumentResolver idResolver, DomainObjectReader reader,
PluginRegistry<EntityLookup<?>, 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)

View File

@@ -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<? extends PersistentProperty<?>> 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)

View File

@@ -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()

View File

@@ -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<String> persistentPropertyPath = new ArrayList<String>(iteratorSource.size());
TypedSegment typedSegment = TypedSegment.create(persistentEntities, objectMapper, rootEntity);
TypedSegment typedSegment = TypedSegment.create(entities, objectMapper, rootEntity);
for (String field : iteratorSource) {

View File

@@ -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<PersistentProperty<?>, BeanPropertyDefinition> propertyToFieldName;
@@ -55,6 +51,17 @@ class MappedProperties {
private final Set<String> ignoredPropertyNames;
private final boolean anySetterFound;
private MappedProperties(Map<PersistentProperty<?>, BeanPropertyDefinition> propertyToFieldName,
Map<String, PersistentProperty<?>> fieldNameToProperty, Set<BeanPropertyDefinition> unmappedProperties,
Set<String> 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}.
*

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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<EntityLookup<?>, Class<?>> lookups;
public LookupObjectSerializer(PluginRegistry<EntityLookup<?>, 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)

View File

@@ -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<AbstractJsonSchemaProperty<?>> 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<AbstractJsonSchemaProperty<?>>();
}
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<? extends PersistentProperty<?>> property;
private final BeanPropertyDefinition definition;
public JacksonProperty(JacksonMetadata metadata, Optional<? extends PersistentProperty<?>> 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("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])");
private final MessageSourceResolvable delegate;
/**
@@ -570,17 +562,13 @@ public class PersistentEntityToJsonSchemaConverter implements ConditionalGeneric
*/
@Override
public String getDefaultMessage() {
String defaultMessage = delegate.getDefaultMessage();
if (defaultMessage != null) {
return defaultMessage;
}
String[] split = getCodes()[0].split("\\.");
String tail = split[split.length - 1];
tail = "_title".equals(tail) ? split[split.length - 2] : tail;
return StringUtils.capitalize(StringUtils
.collectionToDelimitedString(Arrays.asList(SPLIT_CAMEL_CASE.split(tail)), " ").toLowerCase(Locale.US));
}

View File

@@ -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.HashMap;
@@ -117,11 +114,19 @@ class WrappedProperties {
*
* @author Mark Paluch
*/
@RequiredArgsConstructor
static class JacksonUnwrappedPropertiesResolver {
private final @NonNull PersistentEntities persistentEntities;
private final @NonNull ObjectMapper mapper;
private final PersistentEntities entities;
private final ObjectMapper mapper;
public JacksonUnwrappedPropertiesResolver(PersistentEntities entities, ObjectMapper mapper) {
Assert.notNull(entities, "PersistentEntities must not be null!");
Assert.notNull(mapper, "ObjectMapper must not be null!");
this.entities = entities;
this.mapper = mapper;
}
/**
* Resolve {@code @JsonUnwrapped} field names to a list of involved {@link PersistentProperty properties}.
@@ -139,7 +144,7 @@ class WrappedProperties {
private Map<String, List<PersistentProperty<?>>> findUnwrappedPropertyPaths(Class<?> type,
NameTransformer nameTransformer, boolean considerRegularProperties) {
return persistentEntities.getPersistentEntity(type).map(entity -> {
return entities.getPersistentEntity(type).map(entity -> {
Map<String, List<PersistentProperty<?>>> mapping = new HashMap<String, List<PersistentProperty<?>>>();

View File

@@ -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;
/**
* <p>
@@ -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));
}

View File

@@ -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);
}
}
}

View File

@@ -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<JsonNode> {
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<JsonNode> {
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);
}

View File

@@ -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;
/**
* <p>
@@ -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));
}

View File

@@ -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}.
*

View File

@@ -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;
}
}
/*

View File

@@ -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<String, UntypedSpelPath> 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> 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);
}
}
}

View File

@@ -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);
}

View File

@@ -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}.

View File

@@ -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!";

View File

@@ -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<Link> links = new ArrayList<Link>();
private final Path basePath;
private final Associations associationLinks;
private final List<Link> links = new ArrayList<Link>();
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<Link> links = new ArrayList<Link>();
private final List<Link> links = new ArrayList<Link>();
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<Link> 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<Object> asCollection(Object object) {
if (object instanceof Collection) {
return (Collection<Object>) object;
}
return Collections.singleton(object);
return object instanceof Collection //
? (Collection<Object>) object //
: Collections.singleton(object);
}
}
}

View File

@@ -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<Link> links = new ArrayList<Link>();
private final @Getter List<Link> links = new ArrayList<Link>();
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<Link> getLinks() {
return this.links;
}
/*
* (non-Javadoc)
@@ -54,29 +64,20 @@ public class NestedLinkCollectingAssociationHandler implements SimpleAssociation
*/
@Override
public void doWithAssociation(Association<? extends PersistentProperty<?>> 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()));
}

View File

@@ -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)

View File

@@ -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 + ")";
}
}

View File

@@ -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}

View File

@@ -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);
}
}

View File

@@ -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 + ")";
}
}
}

View File

@@ -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<BackendIdConverter, Class<?>> idConverters;
private final Repositories repositories;
private final ResourceMappings mappings;
private final RepositoryRestConfiguration config;
private final PagingAndSortingTemplateVariables templateVariables;
private final PluginRegistry<BackendIdConverter, Class<?>> idConverters;
public RepositoryEntityLinks(Repositories repositories, ResourceMappings mappings, RepositoryRestConfiguration config,
PagingAndSortingTemplateVariables templateVariables, PluginRegistry<BackendIdConverter, Class<?>> 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)

View File

@@ -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)