From eac0f4df94b934ee606d57a59a45af2fca554fed Mon Sep 17 00:00:00 2001 From: Felix Reichenbach <felix.reichenbach@mgm-tp.com> Date: Tue, 25 Feb 2025 09:05:29 +0100 Subject: [PATCH] OZG-3936 process linked resources in collection models --- .../LinkedResourceCollectionProcessor.java | 23 +++++ ...nkedResourceCollectionProcessorITCase.java | 46 ++++++++++ ...LinkedResourceCollectionProcessorTest.java | 44 ++++++++++ .../common/LinkedResourceProcessorITCase.java | 69 +-------------- .../common/LinkedResourceProcessorTest.java | 60 ------------- .../de/ozgcloud/alfa/common/TestEntity.java | 87 +++++++++++++++++++ 6 files changed, 204 insertions(+), 125 deletions(-) create mode 100644 alfa-service/src/main/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessor.java create mode 100644 alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessorITCase.java create mode 100644 alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessorTest.java create mode 100644 alfa-service/src/test/java/de/ozgcloud/alfa/common/TestEntity.java diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessor.java new file mode 100644 index 0000000000..84b28c84e7 --- /dev/null +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessor.java @@ -0,0 +1,23 @@ +package de.ozgcloud.alfa.common; + +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.server.RepresentationModelProcessor; +import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Component +@RequiredArgsConstructor +public class LinkedResourceCollectionProcessor<T> implements RepresentationModelProcessor<CollectionModel<EntityModel<T>>> { + + private final LinkedResourceProcessor<T> elementProcessor; + + @Override + public CollectionModel<EntityModel<T>> process(CollectionModel<EntityModel<T>> model) { + model.getContent().forEach(elementProcessor::process); + return model; + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessorITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessorITCase.java new file mode 100644 index 0000000000..da59cd2da2 --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessorITCase.java @@ -0,0 +1,46 @@ +package de.ozgcloud.alfa.common; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.assertj.MockMvcTester; +import org.springframework.test.web.servlet.assertj.MvcTestResult; +import org.springframework.web.context.WebApplicationContext; + +import de.ozgcloud.common.test.ITCase; +import lombok.SneakyThrows; + +@ITCase +class LinkedResourceCollectionProcessorITCase { + + @Autowired + private WebApplicationContext context; + private MockMvcTester mockMvc; + + @BeforeEach + void setup() { + this.mockMvc = MockMvcTester.from(this.context); + } + + @Test + @SneakyThrows + void shouldHaveAddLinkByLinkedResource() { + var result = doRequest(); + + result.assertThat().bodyJson().extractingPath("$._embedded.testEntityList[0]._links.linkedResource.href") + .isEqualTo("http://localhost" + TestIdController.PATH + "/" + TestEntityTestFactory.LINKED_RESOURCE); + } + + @Test + @SneakyThrows + void shouldHaveUserProfileLink() { + var result = doRequest(); + + result.assertThat().bodyJson().extractingPath("$._embedded.testEntityList[0]._links.user.href") + .isEqualTo("https://localhost/api/userProfiles/" + TestEntityTestFactory.USER); + } + + private MvcTestResult doRequest() { + return mockMvc.get().uri(TestEntityController.PATH + TestEntityController.GET_ALL).exchange(); + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessorTest.java new file mode 100644 index 0000000000..0335276c6a --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceCollectionProcessorTest.java @@ -0,0 +1,44 @@ +package de.ozgcloud.alfa.common; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.List; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.EntityModel; + +class LinkedResourceCollectionProcessorTest { + + @InjectMocks + private LinkedResourceCollectionProcessor<TestEntity> processor; + @Mock + private LinkedResourceProcessor<TestEntity> elementProcessor; + + @Nested + class TestProcess { + + @Test + void shouldReturnSameCollectionModel() { + var collectionModel = CollectionModel.of(List.of(EntityModel.of(TestEntityTestFactory.create()))); + + var result = processor.process(collectionModel); + + assertThat(collectionModel).isSameAs(result); + } + + @Test + void shouldCallLinkedResourceprocessor() { + var entityModel = EntityModel.of(TestEntityTestFactory.create()); + var collectionModel = CollectionModel.of(List.of(entityModel)); + + processor.process(collectionModel); + + verify(elementProcessor).process(entityModel); + } + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceProcessorITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceProcessorITCase.java index 894a5c1243..e765af8f16 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceProcessorITCase.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceProcessorITCase.java @@ -1,34 +1,25 @@ package de.ozgcloud.alfa.common; -import java.util.UUID; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.EntityModel; import org.springframework.test.web.servlet.assertj.MockMvcTester; import org.springframework.test.web.servlet.assertj.MvcTestResult; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; import de.ozgcloud.common.test.ITCase; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; import lombok.SneakyThrows; @ITCase class LinkedResourceProcessorITCase { @Autowired - private WebApplicationContext wac; + private WebApplicationContext context; private MockMvcTester mockMvc; @BeforeEach void setup() { - this.mockMvc = MockMvcTester.from(this.wac); + this.mockMvc = MockMvcTester.from(this.context); } @Test @@ -36,8 +27,8 @@ class LinkedResourceProcessorITCase { void shouldHaveAddLinkByLinkedResource() { var result = doRequest(); - result.assertThat().bodyJson().extractingPath("$._links.id.href") - .isEqualTo("http://localhost" + TestIdController.PATH + "/" + TestEntityTestFactory.ID); + result.assertThat().bodyJson().extractingPath("$._links.linkedResource.href") + .isEqualTo("http://localhost" + TestIdController.PATH + "/" + TestEntityTestFactory.LINKED_RESOURCE); } @Test @@ -52,56 +43,4 @@ class LinkedResourceProcessorITCase { private MvcTestResult doRequest() { return mockMvc.get().uri(TestEntityController.PATH).exchange(); } - - @Builder - @Getter - @EqualsAndHashCode - static class TestEntity { - - @LinkedResource(controllerClass = TestIdController.class) - private String id; - - private String foo; - - @LinkedUserProfileResource - private String user; - } - - @RequestMapping(TestEntityController.PATH) - @RestController - static class TestEntityController { - - static final String PATH = "/api/entity"; - - @GetMapping - public EntityModel<TestEntity> getTestEntity() { - return EntityModel.of(TestEntityTestFactory.create()); - } - } - - @RequestMapping(TestIdController.PATH) - static class TestIdController { - - static final String PATH = "/api/test"; - - static final String USER_REL = "user"; - static final String ID_REL = "id"; - - } - - static class TestEntityTestFactory { - - static final String USER = UUID.randomUUID().toString(); - static final String ID = UUID.randomUUID().toString(); - - public static TestEntity create() { - return createBuilder().build(); - } - - public static TestEntity.TestEntityBuilder createBuilder() { - return TestEntity.builder() - .id(ID) - .user(USER); - } - } } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceProcessorTest.java index 8262128113..c97c4f96fe 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceProcessorTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/LinkedResourceProcessorTest.java @@ -6,9 +6,7 @@ import static org.mockito.Mockito.*; import java.lang.reflect.Field; import java.util.Arrays; -import java.util.Collection; import java.util.List; -import java.util.UUID; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; @@ -21,14 +19,10 @@ import org.mockito.Mock; import org.mockito.Spy; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; -import org.springframework.web.bind.annotation.RequestMapping; import com.thedeanda.lorem.LoremIpsum; import de.ozgcloud.alfa.common.user.UserManagerUrlProvider; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; import lombok.SneakyThrows; class LinkedResourceProcessorTest { @@ -371,58 +365,4 @@ class LinkedResourceProcessorTest { return TestEntity.class.getDeclaredField(fieldName); } } - - @Builder - @Getter - @EqualsAndHashCode - static class TestEntity { - - @LinkedResource(controllerClass = TestIdController.class) - private String linkedResource; - @LinkedResource(controllerClass = TestIdController.class) - private String testId; - - private String foo; - private Collection<String> collectionField; - private String[] arrayField; - - @LinkedUserProfileResource - private String user; - - @LinkedUserProfileResource - private String differentUserId; - } - - @RequestMapping(TestIdController.PATH) - static class TestIdController { - - static final String PATH = "/api/test"; - - static final String USER_REL = "user"; - static final String DIFFERENT_USER_REL = "differentUser"; - static final String ID_REL = "test"; - static final String LINKED_RESOURCE_REL = "linkedResource"; - - } - - static class TestEntityTestFactory { - - static final String USER = UUID.randomUUID().toString(); - static final String DIFFERENT_USER_ID = UUID.randomUUID().toString(); - static final String ID = UUID.randomUUID().toString(); - static final String LINKED_RESOURCE = UUID.randomUUID().toString(); - - public static TestEntity create() { - return createBuilder().build(); - } - - public static TestEntity.TestEntityBuilder createBuilder() { - return TestEntity.builder() - .testId(ID) - .linkedResource(LINKED_RESOURCE) - .user(USER) - .differentUserId(DIFFERENT_USER_ID) - .foo("bar"); - } - } } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/TestEntity.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/TestEntity.java new file mode 100644 index 0000000000..8416ecbcde --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/TestEntity.java @@ -0,0 +1,87 @@ +package de.ozgcloud.alfa.common; + +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.EntityModel; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +@Builder +@Getter +@EqualsAndHashCode +class TestEntity { + + @LinkedResource(controllerClass = TestIdController.class) + private String linkedResource; + @LinkedResource(controllerClass = TestIdController.class) + private String testId; + + private String foo; + private Collection<String> collectionField; + private String[] arrayField; + + @LinkedUserProfileResource + private String user; + + @LinkedUserProfileResource + private String differentUserId; +} + +@RequestMapping(TestEntityController.PATH) +@RestController +class TestEntityController { + + static final String PATH = "/api/entity"; + static final String GET_ALL = "/all"; + + @GetMapping + public EntityModel<TestEntity> getTestEntity() { + return EntityModel.of(TestEntityTestFactory.create()); + } + + @GetMapping(GET_ALL) + public CollectionModel<EntityModel<TestEntity>> getAll() { + return CollectionModel.of(List.of(EntityModel.of(TestEntityTestFactory.create()))); + } +} + +@RequestMapping(TestIdController.PATH) +class TestIdController { + + static final String PATH = "/api/test"; + + static final String USER_REL = "user"; + static final String DIFFERENT_USER_REL = "differentUser"; + static final String ID_REL = "test"; + static final String LINKED_RESOURCE_REL = "linkedResource"; + +} + +class TestEntityTestFactory { + + static final String USER = UUID.randomUUID().toString(); + static final String DIFFERENT_USER_ID = UUID.randomUUID().toString(); + static final String ID = UUID.randomUUID().toString(); + static final String LINKED_RESOURCE = UUID.randomUUID().toString(); + + public static TestEntity create() { + return createBuilder().build(); + } + + public static TestEntity.TestEntityBuilder createBuilder() { + return TestEntity.builder() + .testId(ID) + .linkedResource(LINKED_RESOURCE) + .user(USER) + .differentUserId(DIFFERENT_USER_ID) + .foo("bar"); + } +} -- GitLab