diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/Associations.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/Associations.java index 9fd76a7b6..bbcb67602 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/Associations.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/mapping/Associations.java @@ -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. * diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AssociationLinksUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AssociationLinksUnitTests.java index fe91ab5ed..bd577f152 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AssociationLinksUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AssociationLinksUnitTests.java @@ -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))); diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mapping/AssociationsUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mapping/AssociationsUnitTests.java index 515cc8af5..03ebecc56 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mapping/AssociationsUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mapping/AssociationsUnitTests.java @@ -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 links = associations.getLinksFor(getAssociation(Root.class, "relatedAndExported"), new Path("")); + + assertThat(links).hasSize(1); + assertThat(links).contains(new Link("/relatedAndExported{?" + projectionParameterName + "}", "relatedAndExported")); + } + private Association> getAssociation(Class type, String name) { KeyValuePersistentEntity> rootEntity = mappingContext @@ -148,4 +162,4 @@ public class AssociationsUnitTests { static class RelatedAndExported {} static class RelatedButNotExported {} -} +} \ No newline at end of file