From f20361730895a5f5a36b116a1bb1523b95db29c4 Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Fri, 6 Oct 2023 14:10:22 +0200
Subject: [PATCH] OZG-4428 map input data to formdata

---
 enterprise-adapter/pom.xml                    | 14 ++++
 .../enterprise/entry/EntryController.java     | 29 ++++++++
 .../eingang/enterprise/entry/EntryData.java   |  7 --
 .../enterprise/entry/EntryDataMapper.java     |  6 +-
 .../enterprise/entry/FormDataMapper.java      | 38 ++++++++++
 .../enterprise/entry/EntryControllerTest.java | 72 +++++++++++++++++++
 .../enterprise/entry/EntryDataMapperTest.java | 45 +++++++++++-
 .../src/test/resources/request/simple.json    |  2 +-
 8 files changed, 200 insertions(+), 13 deletions(-)
 create mode 100644 enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java
 create mode 100644 enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapper.java
 create mode 100644 enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java

diff --git a/enterprise-adapter/pom.xml b/enterprise-adapter/pom.xml
index 96d272d79..362c7f196 100644
--- a/enterprise-adapter/pom.xml
+++ b/enterprise-adapter/pom.xml
@@ -30,6 +30,20 @@
 			<groupId>de.itvsh.kop.eingangsadapter</groupId>
 			<artifactId>common</artifactId>
 		</dependency>
+
+		<!--dev tools-->
+		<dependency>
+			<groupId>org.mapstruct</groupId>
+			<artifactId>mapstruct</artifactId>
+		</dependency>
+		
+		<!--test -->
+		<dependency>
+			<groupId>de.itvsh.kop.eingangsadapter</groupId>
+			<artifactId>common</artifactId>
+			<type>test-jar</type>
+			<scope>test</scope>
+		</dependency>
 	</dependencies>
 
 	<build>
diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java
new file mode 100644
index 000000000..96ff9a79f
--- /dev/null
+++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java
@@ -0,0 +1,29 @@
+package de.ozgcloud.eingang.enterprise.entry;
+
+import java.io.IOException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@Controller
+@ResponseBody
+@RequestMapping("antrag")
+public class EntryController {
+
+	@Autowired
+	private EntryDataMapper mapper;
+
+	@ResponseStatus(HttpStatus.ACCEPTED)
+	@PostMapping(consumes = "multipart/form-data", produces = MediaType.APPLICATION_JSON_VALUE)
+	public void receiveAntrag(@RequestPart Resource formData) throws IOException {
+		mapper.mapEntryData(formData.getInputStream());
+	}
+}
diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryData.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryData.java
index fd0a4ed23..ac18bfda3 100644
--- a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryData.java
+++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryData.java
@@ -35,11 +35,4 @@ public class EntryData {
 			private String address;
 		}
 	}
-
-	@Builder
-	@Getter
-	@Jacksonized
-	public static class EntryFormData {
-
-	}
 }
diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapper.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapper.java
index bb40354bf..1c2c53404 100644
--- a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapper.java
+++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapper.java
@@ -15,10 +15,11 @@ class EntryDataMapper {
 
 	@Autowired
 	private ObjectMapper objectMapper;
+	@Autowired
+	private FormDataMapper formDataMapper;
 
 	public FormData mapEntryData(InputStream request) {
-		// TODO Auto-generated method stub
-		return null;
+		return formDataMapper.mapEntryData(readRequest(request));
 	}
 
 	EntryData readRequest(InputStream request) {
@@ -29,4 +30,5 @@ class EntryDataMapper {
 		}
 
 	}
+
 }
diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapper.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapper.java
new file mode 100644
index 000000000..6bf2030f3
--- /dev/null
+++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/FormDataMapper.java
@@ -0,0 +1,38 @@
+package de.ozgcloud.eingang.enterprise.entry;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.FormHeader;
+import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
+
+@Mapper
+public interface FormDataMapper {
+
+	@Mapping(target = "antragsteller", ignore = true)
+	@Mapping(target = "attachment", ignore = true)
+	@Mapping(target = "attachments", ignore = true)
+	@Mapping(target = "numberOfAttachments", ignore = true)
+	@Mapping(target = "representation", ignore = true)
+	@Mapping(target = "representations", ignore = true)
+	@Mapping(target = "numberOfRepresentations", ignore = true)
+
+	@Mapping(target = "id", ignore = true)
+	@Mapping(target = "header", source = "control")
+
+	@Mapping(target = "zustaendigeStelle", source = "control.zustaendigeStelle")
+	FormData mapEntryData(EntryData entryData);
+
+	@Mapping(target = "createdAt", ignore = true)
+	@Mapping(target = "formEngineName", constant = "EnterpriseSoftware")
+	@Mapping(target = "requestId", source = "transactionId")
+	@Mapping(target = "sender", ignore = true) // TODO fill from authentication
+	@Mapping(target = "serviceKonto", ignore = true)
+	FormHeader mapHeader(EntryData.ControlData controlData);
+
+	default ZustaendigeStelle fromId(String organisationsEinheitenId) {
+		return ZustaendigeStelle.builder().organisationseinheitenId(organisationsEinheitenId).build();
+	}
+
+}
diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java
new file mode 100644
index 000000000..bb94507c8
--- /dev/null
+++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java
@@ -0,0 +1,72 @@
+package de.ozgcloud.eingang.enterprise.entry;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import de.itvsh.kop.common.test.TestUtils;
+import lombok.SneakyThrows;
+
+class EntryControllerTest {
+
+	@InjectMocks
+	private EntryController controller;
+
+	@Mock
+	private EntryDataMapper mapper;
+
+	private MockMvc mockMvc;
+
+	@BeforeEach
+	void init() {
+		mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+	}
+
+	@Nested
+	class ReceiveAntrag {
+
+		@Captor
+		private ArgumentCaptor<InputStream> streamCaptor;
+
+		@Test
+		@SneakyThrows
+		void shouldReturnAccepted() {
+			doPostRequest().andExpect(status().isAccepted());
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldCallMapper() {
+			var request = TestUtils.loadTextFile("request/simple.json");
+
+			doPostRequest();
+
+			verify(mapper).mapEntryData(streamCaptor.capture());
+			var inputBytes = IOUtils.readFully(streamCaptor.getValue(), request.getBytes().length);
+			assertThat(inputBytes).hasSameSizeAs(request.getBytes()).isEqualTo(request.getBytes());
+		}
+
+		@SneakyThrows
+		private ResultActions doPostRequest() {
+			return mockMvc.perform(multipart("/antrag")
+					.file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/simple.json").getBytes())));
+		}
+	}
+
+}
diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapperTest.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapperTest.java
index 9ae7f4274..238ce95c1 100644
--- a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapperTest.java
+++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryDataMapperTest.java
@@ -1,40 +1,79 @@
 package de.ozgcloud.eingang.enterprise.entry;
 
 import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.InputStream;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.Spy;
 
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import de.itvsh.kop.common.test.TestUtils;
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.FormDataTestFactory;
+import lombok.SneakyThrows;
 
 class EntryDataMapperTest {
 
+	@Spy
 	@InjectMocks
 	private EntryDataMapper mapper;
+	@Mock
+	private FormDataMapper formDataMapper;
 
 	@Spy
-	private ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+	private ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
 
 	@Nested
 	class TestMappingEntryData {
 
+		private InputStream jsonInput = TestUtils.loadFile("request/simple.json");
+
 		@Nested
 		class TestReadRequest {
 			@Test
 			void shouldReadJson() {
-				var jsonInput = TestUtils.loadFile("request/simple.json");
-
 				var read = mapper.readRequest(jsonInput);
 
 				assertThat(read).usingRecursiveComparison().isEqualTo(EntryDataTestFactory.create());
 			}
 		}
 
+		@Test
+		void shouldReadRequest() {
+			mapper.mapEntryData(jsonInput);
+
+			verify(mapper).readRequest(jsonInput);
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldCallFormDataMapper() {
+			var entryData = EntryDataTestFactory.create();
+			doReturn(entryData).when(objectMapper).readValue(any(InputStream.class), Mockito.<Class<EntryData>>any());
+
+			mapper.mapEntryData(jsonInput);
+
+			verify(formDataMapper).mapEntryData(entryData);
+		}
+
+		@Test
+		void shouldReturnMappedResult() {
+			FormData formData = FormDataTestFactory.create();
+			when(formDataMapper.mapEntryData(any())).thenReturn(formData);
+
+			var result = mapper.mapEntryData(jsonInput);
+
+			assertThat(result).isSameAs(formData);
+		}
 	}
 
 }
diff --git a/enterprise-adapter/src/test/resources/request/simple.json b/enterprise-adapter/src/test/resources/request/simple.json
index bd399f1cb..f364c5827 100644
--- a/enterprise-adapter/src/test/resources/request/simple.json
+++ b/enterprise-adapter/src/test/resources/request/simple.json
@@ -26,7 +26,7 @@
 				},
 				"nachname": {
 					"label": "Nachname",
-					"stringValue": "Test"
+					"stringValue": "Täst"
 				}
 			}
 		}
-- 
GitLab