From 308edc89e0015cdfdd52f555dedc8dc36b5844f4 Mon Sep 17 00:00:00 2001
From: Lukas Malte Monnerjahn <lukasmalte.monnerjahn@dataport.de>
Date: Mon, 9 Sep 2024 15:45:29 +0200
Subject: [PATCH] OZG-6240 TransportReport Tests

---
 .../xta/test/app/config/XTAServer.java        |  7 ++
 .../data/XtaTransportReportRepository.java    | 32 +++++++
 .../xta/test/app/model/XtaCloseRequest.java   |  1 -
 .../test/app/model/XtaGetMessageRequest.java  |  1 -
 .../model/XtaGetTransportReportRequest.java   | 16 ++++
 .../XtaMessageMetaDataListingRequest.java     |  1 -
 .../test/app/model/XtaTransportReport.java    | 21 +++++
 .../test/app/service/XtaMessageService.java   | 27 ++++--
 .../XtaTransportReportRepositoryTest.java     | 90 +++++++++++++++++++
 .../app/service/XtaMessageServiceTest.java    | 83 ++++++++++++++---
 10 files changed, 258 insertions(+), 21 deletions(-)
 create mode 100644 src/main/java/de/ozgcloud/xta/test/app/data/XtaTransportReportRepository.java
 create mode 100644 src/main/java/de/ozgcloud/xta/test/app/model/XtaGetTransportReportRequest.java
 create mode 100644 src/main/java/de/ozgcloud/xta/test/app/model/XtaTransportReport.java
 create mode 100644 src/test/java/de/ozgcloud/xta/test/app/data/XtaTransportReportRepositoryTest.java

diff --git a/src/main/java/de/ozgcloud/xta/test/app/config/XTAServer.java b/src/main/java/de/ozgcloud/xta/test/app/config/XTAServer.java
index f5fd91b..dbd817b 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/config/XTAServer.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/config/XTAServer.java
@@ -1,5 +1,7 @@
 package de.ozgcloud.xta.test.app.config;
 
+import java.time.Clock;
+
 import jakarta.xml.ws.Endpoint;
 import jakarta.xml.ws.soap.SOAPBinding;
 
@@ -50,4 +52,9 @@ public class XTAServer {
 		SOAPBinding binding = (SOAPBinding) endpoint.getBinding();
 		binding.setMTOMEnabled(true);
 	}
+
+	@Bean
+	Clock clock() {
+		return Clock.systemDefaultZone();
+	}
 }
diff --git a/src/main/java/de/ozgcloud/xta/test/app/data/XtaTransportReportRepository.java b/src/main/java/de/ozgcloud/xta/test/app/data/XtaTransportReportRepository.java
new file mode 100644
index 0000000..4c05cb5
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/data/XtaTransportReportRepository.java
@@ -0,0 +1,32 @@
+package de.ozgcloud.xta.test.app.data;
+
+import java.time.Clock;
+import java.util.HashMap;
+import java.util.Optional;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.xta.test.app.model.XtaMessageMetaData;
+import de.ozgcloud.xta.test.app.model.XtaTransportReport;
+
+@Component
+@RequiredArgsConstructor
+public class XtaTransportReportRepository {
+	private final HashMap<String, XtaTransportReport> transportReports = new HashMap<>();
+	private final Clock clock;
+
+	public void add(XtaMessageMetaData messageMetaData) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void setClosedStatus(String messageId) {
+		// TODO Auto-generated method stub
+	}
+
+	public Optional<XtaTransportReport> get(String messageId) {
+		// TODO Auto-generated method stub
+		return Optional.empty();
+	}
+}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaCloseRequest.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaCloseRequest.java
index d6d2ac2..53a9727 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaCloseRequest.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaCloseRequest.java
@@ -3,7 +3,6 @@ package de.ozgcloud.xta.test.app.model;
 import static de.ozgcloud.xta.test.app.validation.ValidXtaId.*;
 
 import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 
 import de.ozgcloud.xta.test.app.validation.ValidXtaId;
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetMessageRequest.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetMessageRequest.java
index 443a9c6..8367465 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetMessageRequest.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetMessageRequest.java
@@ -3,7 +3,6 @@ package de.ozgcloud.xta.test.app.model;
 import static de.ozgcloud.xta.test.app.validation.ValidXtaId.*;
 
 import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 
 import de.ozgcloud.xta.test.app.validation.ValidXtaId;
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetTransportReportRequest.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetTransportReportRequest.java
new file mode 100644
index 0000000..0e0a5f1
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaGetTransportReportRequest.java
@@ -0,0 +1,16 @@
+package de.ozgcloud.xta.test.app.model;
+
+import static de.ozgcloud.xta.test.app.validation.ValidXtaId.*;
+
+		import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+
+import de.ozgcloud.xta.test.app.validation.ValidXtaId;
+import lombok.Builder;
+
+@Builder
+public record XtaGetTransportReportRequest (
+		@ValidXtaId(namespace = MESSAGE_ID_NAMESPACE) String messageId,
+		@NotNull @Valid XtaIdentifier clientIdentifier
+) {
+}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListingRequest.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListingRequest.java
index c19441d..d505196 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListingRequest.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaMessageMetaDataListingRequest.java
@@ -1,7 +1,6 @@
 package de.ozgcloud.xta.test.app.model;
 
 import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Positive;
 
diff --git a/src/main/java/de/ozgcloud/xta/test/app/model/XtaTransportReport.java b/src/main/java/de/ozgcloud/xta/test/app/model/XtaTransportReport.java
new file mode 100644
index 0000000..2c5fe2b
--- /dev/null
+++ b/src/main/java/de/ozgcloud/xta/test/app/model/XtaTransportReport.java
@@ -0,0 +1,21 @@
+package de.ozgcloud.xta.test.app.model;
+
+import java.time.LocalDateTime;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import lombok.Builder;
+
+@Builder
+public record XtaTransportReport(
+		@Valid XtaMessageMetaData messageMetaData,
+		@NotNull LocalDateTime reportTime,
+		@NotNull MessageStatus status) {
+
+	public enum MessageStatus {
+		OFFEN,
+		GRUEN,
+		GELB,
+		ROT
+	}
+}
diff --git a/src/main/java/de/ozgcloud/xta/test/app/service/XtaMessageService.java b/src/main/java/de/ozgcloud/xta/test/app/service/XtaMessageService.java
index 79864e4..8e4a953 100644
--- a/src/main/java/de/ozgcloud/xta/test/app/service/XtaMessageService.java
+++ b/src/main/java/de/ozgcloud/xta/test/app/service/XtaMessageService.java
@@ -9,18 +9,16 @@ import org.springframework.core.env.Environment;
 import org.springframework.stereotype.Service;
 
 import de.ozgcloud.xta.test.app.data.XtaMessageRepository;
-import de.ozgcloud.xta.test.app.model.XtaCloseRequest;
-import de.ozgcloud.xta.test.app.model.XtaGetMessageRequest;
-import de.ozgcloud.xta.test.app.model.XtaMessage;
-import de.ozgcloud.xta.test.app.model.XtaMessageMetaData;
-import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListing;
-import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListingRequest;
+import de.ozgcloud.xta.test.app.data.XtaTransportReportRepository;
+import de.ozgcloud.xta.test.app.model.*;
+
 import lombok.RequiredArgsConstructor;
 
 @Service
 @RequiredArgsConstructor
 public class XtaMessageService {
 	private final XtaMessageRepository messageRepository;
+	private final XtaTransportReportRepository transportReportRepository;
 
 	private final Environment environment;
 
@@ -50,8 +48,7 @@ public class XtaMessageService {
 	}
 
 	Predicate<XtaMessage> isAuthorOrReaderOfMessage(String clientIdentifierValue) {
-		return m -> m.metaData().readerIdentifier().value().equals(clientIdentifierValue)
-				|| m.metaData().authorIdentifier().value().equals(clientIdentifierValue);
+		return m -> isAuthorOrReaderOfMessageMetadata(clientIdentifierValue).test(m.metaData());
 	}
 
 	public boolean closeMessage(XtaCloseRequest request) {
@@ -61,6 +58,20 @@ public class XtaMessageService {
 		);
 	}
 
+	public Optional<XtaTransportReport> getTransportReport(XtaGetTransportReportRequest request) {
+		return transportReportRepository.get(request.messageId())
+				.filter(isAuthorOrReaderOfTransportReport(request.clientIdentifier().value()));
+	}
+
+	Predicate<XtaTransportReport> isAuthorOrReaderOfTransportReport(String clientIdentifierValue) {
+		return tr -> isAuthorOrReaderOfMessageMetadata(clientIdentifierValue).test(tr.messageMetaData());
+	}
+
+	Predicate<XtaMessageMetaData> isAuthorOrReaderOfMessageMetadata(String clientIdentifierValue) {
+		return m -> m.readerIdentifier().value().equals(clientIdentifierValue)
+				|| m.authorIdentifier().value().equals(clientIdentifierValue);
+	}
+
 	public String createMessageId() {
 		return generateXtaIdWithNamespace("de:xta:messageid");
 	}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/data/XtaTransportReportRepositoryTest.java b/src/test/java/de/ozgcloud/xta/test/app/data/XtaTransportReportRepositoryTest.java
new file mode 100644
index 0000000..51d147e
--- /dev/null
+++ b/src/test/java/de/ozgcloud/xta/test/app/data/XtaTransportReportRepositoryTest.java
@@ -0,0 +1,90 @@
+package de.ozgcloud.xta.test.app.data;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.LocalDateTime;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+
+import de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory;
+import de.ozgcloud.xta.test.app.model.XtaMessageMetaData;
+import de.ozgcloud.xta.test.app.model.XtaTransportReport;
+
+public class XtaTransportReportRepositoryTest {
+	private XtaTransportReportRepository repository;
+	@Mock
+	private Clock clock;
+
+	private final XtaMessageMetaData messageMetaData = XtaMessageMetaDataTestFactory.create();
+
+	@BeforeEach
+	void beforeEach() {
+		repository = new XtaTransportReportRepository(clock);
+	}
+
+	@Nested
+	class Add{
+		@Test
+		void shouldAddTransportReport() {
+			repository.add(messageMetaData);
+
+			var result = repository.get(messageMetaData.messageId());
+
+			assertThat(result).isPresent();
+			assertThat(result.get().messageMetaData()).isEqualTo(messageMetaData);
+		}
+	}
+
+	@Nested
+	class Get {
+		private final Instant instant = Instant.now();
+
+		@Test
+		void shouldReturnEmpty() {
+			var result = repository.get(messageMetaData.messageId());
+
+			assertThat(result).isEmpty();
+		}
+
+		@Test
+		void shouldSetStatusOffen() {
+			repository.add(messageMetaData);
+
+			var result = repository.get(messageMetaData.messageId());
+
+			assertThat(result).isPresent();
+			assertThat(result.get().status()).isEqualTo(XtaTransportReport.MessageStatus.OFFEN);
+		}
+
+		@Test
+		void shouldSetReportTimeNow() {
+			when(clock.instant()).thenReturn(instant);
+			repository.add(messageMetaData);
+
+			var result = repository.get(messageMetaData.messageId());
+
+			assertThat(result).isPresent();
+			assertThat(result.get().reportTime()).isEqualTo(LocalDateTime.from(instant));
+		}
+	}
+
+	@Nested
+	class SetClosedStatus {
+		@Test
+		void shouldSetClosedStatus() {
+			repository.add(messageMetaData);
+			repository.setClosedStatus(messageMetaData.messageId());
+
+			var result = repository.get(messageMetaData.messageId());
+
+			assertThat(result).isPresent();
+			assertThat(result.get().status()).isEqualTo(XtaTransportReport.MessageStatus.GRUEN);
+		}
+	}
+}
diff --git a/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageServiceTest.java b/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageServiceTest.java
index 6723c0e..14bef27 100644
--- a/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageServiceTest.java
+++ b/src/test/java/de/ozgcloud/xta/test/app/service/XtaMessageServiceTest.java
@@ -23,17 +23,18 @@ import org.mockito.Spy;
 import org.springframework.core.env.Environment;
 
 import de.ozgcloud.xta.test.app.data.XtaMessageRepository;
+import de.ozgcloud.xta.test.app.data.XtaTransportReportRepository;
 import de.ozgcloud.xta.test.app.factory.XtaCloseRequestTestFactory;
+import de.ozgcloud.xta.test.app.factory.XtaMessageMetaDataTestFactory;
 import de.ozgcloud.xta.test.app.factory.XtaMessageTestFactory;
-import de.ozgcloud.xta.test.app.model.XtaGetMessageRequest;
-import de.ozgcloud.xta.test.app.model.XtaMessage;
-import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListing;
-import de.ozgcloud.xta.test.app.model.XtaMessageMetaDataListingRequest;
+import de.ozgcloud.xta.test.app.model.*;
 
 public class XtaMessageServiceTest {
 	@Mock
 	private XtaMessageRepository messageRepository;
 	@Mock
+	private XtaTransportReportRepository transportReportRepository;
+	@Mock
 	private Environment environment;
 
 	@Spy
@@ -50,6 +51,15 @@ public class XtaMessageServiceTest {
 			message = XtaMessageTestFactory.create(MESSAGE_ID);
 		}
 
+		@Test
+		void shouldSaveTransportReport() {
+			message = XtaMessageTestFactory.create(MESSAGE_ID);
+
+			service.sendMessage(message);
+
+			verify(transportReportRepository).add(message.metaData());
+		}
+
 		@Test
 		void shouldSaveMessage() {
 			message = XtaMessageTestFactory.create(MESSAGE_ID);
@@ -157,9 +167,9 @@ public class XtaMessageServiceTest {
 		@DisplayName("should return true if reader identifier value matches")
 		@Test
 		void shouldReturnTrueIfReaderIdentifierValueMatches() {
-			var message = XtaMessageTestFactory.create(MESSAGE_ID_1);
+			var messageMetaData = XtaMessageMetaDataTestFactory.create(MESSAGE_ID_1);
 
-			var result = service.isAuthorOrReaderOfMessage(READER_IDENTIFIER.value()).test(message);
+			var result = service.isAuthorOrReaderOfMessageMetadata(READER_IDENTIFIER.value()).test(messageMetaData);
 
 			assertThat(result).isTrue();
 		}
@@ -167,9 +177,9 @@ public class XtaMessageServiceTest {
 		@DisplayName("should return true if author identifier value matches")
 		@Test
 		void shouldReturnTrueIfAuthorIdentifierValueMatches() {
-			var message = XtaMessageTestFactory.create(MESSAGE_ID_1);
+			var messageMetaData = XtaMessageMetaDataTestFactory.create(MESSAGE_ID_1);
 
-			var result = service.isAuthorOrReaderOfMessage(AUTHOR_IDENTIFIER.value()).test(message);
+			var result = service.isAuthorOrReaderOfMessageMetadata(AUTHOR_IDENTIFIER.value()).test(messageMetaData);
 
 			assertThat(result).isTrue();
 		}
@@ -177,9 +187,9 @@ public class XtaMessageServiceTest {
 		@DisplayName("should return false if neither reader nor author identifier value matches")
 		@Test
 		void shouldReturnFalseIfNeitherReaderNorAuthorIdentifierValueMatches() {
-			var message = XtaMessageTestFactory.create(MESSAGE_ID_1);
+			var messageMetaData = XtaMessageMetaDataTestFactory.create(MESSAGE_ID_1);
 
-			var result = service.isAuthorOrReaderOfMessage("unknown").test(message);
+			var result = service.isAuthorOrReaderOfMessageMetadata("unknown").test(messageMetaData);
 
 			assertThat(result).isFalse();
 		}
@@ -201,7 +211,60 @@ public class XtaMessageServiceTest {
 			boolean result = service.closeMessage(request);
 
 			assertThat(result).isEqualTo(deleted);
+		}
+
+		@Test
+		void shouldSetTransportReportClosedStatus() {
+			var request = XtaCloseRequestTestFactory.create();
+
+			service.closeMessage(request);
+
+			verify(transportReportRepository).setClosedStatus(request.messageId());
+		}
+	}
+
+	@Nested
+	class TestGetTransportReport {
+		private static final XtaGetTransportReportRequest GET_TRANSPORT_REPORT_REQUEST = XtaGetTransportReportRequest.builder()
+				.messageId(MESSAGE_ID_1)
+				.clientIdentifier(READER_IDENTIFIER)
+				.build();
+		private static final Predicate<XtaMessage> IS_AUTHOR_OR_READER = m -> true;
+		private static final Predicate<XtaMessage> IS_NOT_AUTHOR_OR_READER = m -> false;
+
+		@Mock
+		XtaTransportReport report;
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			when(transportReportRepository.get(MESSAGE_ID_1)).thenReturn(Optional.of(report));
+			doReturn(IS_AUTHOR_OR_READER).when(service).isAuthorOrReaderOfMessage(READER_IDENTIFIER.value());
+
+			var result = service.getTransportReport(GET_TRANSPORT_REPORT_REQUEST);
+
+			assertThat(result).contains(report);
+		}
+
+		@DisplayName("should return empty if message id not found")
+		@Test
+		void shouldReturnEmptyIfMessageIdNotFound() {
+			when(transportReportRepository.get(MESSAGE_ID_1)).thenReturn(Optional.empty());
+
+			var result = service.getTransportReport(GET_TRANSPORT_REPORT_REQUEST);
+
+			assertThat(result).isEmpty();
+		}
+
+		@DisplayName("should return empty if not author or reader")
+		@Test
+		void shouldReturnEmptyIfNotAuthorOrReader() {
+			when(transportReportRepository.get(MESSAGE_ID_1)).thenReturn(Optional.of(report));
+			doReturn(IS_NOT_AUTHOR_OR_READER).when(service).isAuthorOrReaderOfMessage(READER_IDENTIFIER.value());
+
+			var result = service.getTransportReport(GET_TRANSPORT_REPORT_REQUEST);
 
+			assertThat(result).isEmpty();
 		}
 	}
 
-- 
GitLab