DATAREST-1105 - Association links now advertise projections.

Association links now explicitly indicate projections are available in case there are projection types registered for the association target type.

Original pull request: #273.
This commit is contained in:
Haroun Pacquee
2017-07-06 16:25:39 +02:00
committed by Oliver Gierke
parent c922ba38d2
commit 0d7d84571f
3 changed files with 49 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,23 +21,31 @@ import lombok.RequiredArgsConstructor;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.rest.core.Path;
import org.springframework.data.rest.core.config.ProjectionDefinitionConfiguration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.core.mapping.ResourceMapping;
import org.springframework.data.rest.core.mapping.ResourceMappings;
import org.springframework.data.rest.core.mapping.ResourceMetadata;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.TemplateVariable;
import org.springframework.hateoas.TemplateVariables;
import org.springframework.hateoas.UriTemplate;
import org.springframework.util.Assert;
import static org.springframework.hateoas.TemplateVariable.VariableType.REQUEST_PARAM;
/**
* A value object to for {@link Link}s representing associations.
*
*
* @author Oliver Gierke
* @author Greg Turnquist
* @author Haroun Pacquee
* @since 2.1
*/
@RequiredArgsConstructor
@@ -48,7 +56,7 @@ public class Associations {
/**
* Returns the links to render for the given {@link Association}.
*
*
* @param association must not be {@literal null}.
* @param path must not be {@literal null}.
* @return
@@ -65,14 +73,31 @@ public class Associations {
ResourceMapping propertyMapping = metadata.getMappingFor(property);
String href = path.slash(propertyMapping.getPath()).toString();
String rel = propertyMapping.getRel();
return Collections.singletonList(new Link(href, rel));
String uri = new UriTemplate(href, getProjectionVariable(property)).toString();
return Collections.singletonList(new Link(uri, propertyMapping.getRel()));
}
return Collections.emptyList();
}
private TemplateVariables getProjectionVariable(PersistentProperty<?> property) {
ProjectionDefinitionConfiguration projectionConfiguration = config.getProjectionConfiguration();
if (isProjectionPresent(property, projectionConfiguration)) {
return new TemplateVariables(new TemplateVariable(projectionConfiguration.getParameterName(), REQUEST_PARAM));
} else {
return TemplateVariables.NONE;
}
}
private boolean isProjectionPresent(PersistentProperty<?> property, ProjectionDefinitionConfiguration projectionConfiguration) {
return Stream.of(property.getType(),
property.getActualType(),
property.getRawType(),
property.getComponentType(),
property.getMapValueType())
.anyMatch(projectionConfiguration::hasProjectionFor);
}
/**
* Returns the {@link ResourceMetadata} for the given type.
*

View File

@@ -33,6 +33,7 @@ import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.rest.core.Path;
import org.springframework.data.rest.core.annotation.RestResource;
import org.springframework.data.rest.core.config.ProjectionDefinitionConfiguration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.core.mapping.PersistentEntitiesResourceMappings;
import org.springframework.data.rest.core.mapping.ResourceMappings;
@@ -56,10 +57,11 @@ public class AssociationLinksUnitTests {
ResourceMetadata sampleResourceMetadata;
@Mock RepositoryRestConfiguration config;
@Mock ProjectionDefinitionConfiguration projectionDefinitionConfig;
@Before
public void setUp() {
doReturn(projectionDefinitionConfig).when(config).getProjectionConfiguration();
this.mappingContext = new KeyValueMappingContext<>();
this.entity = mappingContext.getRequiredPersistentEntity(Sample.class);
this.mappings = new PersistentEntitiesResourceMappings(new PersistentEntities(Arrays.asList(mappingContext)));

View File

@@ -36,6 +36,7 @@ import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.rest.core.Path;
import org.springframework.data.rest.core.annotation.RestResource;
import org.springframework.data.rest.core.config.ProjectionDefinitionConfiguration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.core.mapping.PersistentEntitiesResourceMappings;
import org.springframework.data.rest.core.mapping.ResourceMappings;
@@ -48,6 +49,7 @@ import org.springframework.hateoas.Link;
public class AssociationsUnitTests {
@Mock RepositoryRestConfiguration configuration;
@Mock ProjectionDefinitionConfiguration projectionDefinitionConfiguration;
@Mock PersistentEntity<?, ?> entity;
@Mock PersistentProperty<?> property;
@@ -59,6 +61,7 @@ public class AssociationsUnitTests {
@Before
public void setUp() {
doReturn(projectionDefinitionConfiguration).when(configuration).getProjectionConfiguration();
this.mappingContext = new KeyValueMappingContext<>();
this.mappingContext.getPersistentEntity(Root.class);
@@ -130,6 +133,17 @@ public class AssociationsUnitTests {
assertThat(links).hasSize(0);
}
@Test
public void detectsProjectionsForAssociationLinks() {
String projectionParameterName = "projection";
doReturn(true).when(projectionDefinitionConfiguration).hasProjectionFor(RelatedAndExported.class);
doReturn(projectionParameterName).when(projectionDefinitionConfiguration).getParameterName();
List<Link> links = associations.getLinksFor(getAssociation(Root.class, "relatedAndExported"), new Path(""));
assertThat(links).hasSize(1);
assertThat(links).contains(new Link("/relatedAndExported{?" + projectionParameterName + "}", "relatedAndExported"));
}
private Association<? extends PersistentProperty<?>> getAssociation(Class<?> type, String name) {
KeyValuePersistentEntity<?, ? extends KeyValuePersistentProperty<?>> rootEntity = mappingContext
@@ -148,4 +162,4 @@ public class AssociationsUnitTests {
static class RelatedAndExported {}
static class RelatedButNotExported {}
}
}