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:
committed by
Oliver Gierke
parent
c922ba38d2
commit
0d7d84571f
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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 {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user