From 9f5452affb743783d8eed833b1aa34aa998cea69 Mon Sep 17 00:00:00 2001
From: Krzysztof <krzysztof.witukiewicz@mgm-tp.com>
Date: Mon, 28 Apr 2025 16:11:21 +0200
Subject: [PATCH] OZG-7811 OZG-8099 Registration of loaders

---
 .../aggregation/AggregationDataLoader.java    |  4 --
 .../AggregationDataLoaderRegistry.java        | 23 ++------
 .../AggregationWarehouseDataLoader.java       |  9 +--
 .../extern/AggregationRemoteDataLoader.java   |  8 +--
 .../AggregationDataLoaderRegistryTest.java    | 58 ++++---------------
 .../AggregationWarehouseDataLoaderTest.java   | 18 ++----
 .../AggregationRemoteDataLoaderTest.java      | 19 ++----
 7 files changed, 30 insertions(+), 109 deletions(-)

diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationDataLoader.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationDataLoader.java
index f116b96..0bd3bd6 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationDataLoader.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationDataLoader.java
@@ -23,11 +23,7 @@
  */
 package de.ozgcloud.aggregation;
 
-import de.ozgcloud.aggregation.transformation.AggregationMapping;
-
 public interface AggregationDataLoader {
 
 	void loadIntoTarget(Aggregation aggregation);
-
-	boolean supportsScope(AggregationMapping.Scope scope);
 }
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationDataLoaderRegistry.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationDataLoaderRegistry.java
index 363333b..4d7e2ff 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationDataLoaderRegistry.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationDataLoaderRegistry.java
@@ -23,12 +23,8 @@
  */
 package de.ozgcloud.aggregation;
 
-import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
-import java.util.function.Predicate;
-
-import javax.annotation.PostConstruct;
+import java.util.Optional;
 
 import org.springframework.stereotype.Component;
 
@@ -40,24 +36,13 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 class AggregationDataLoaderRegistry {
 
-	private final List<AggregationDataLoader> loaders;
-	private final Map<AggregationMapping.Scope, AggregationDataLoader> scopeToLoader = new HashMap<>();
-
-	@PostConstruct
-	void buildLoadersMap() {
-
-	}
+	private final Map<String, AggregationDataLoader> loaders;
 
 	public boolean hasLoader(AggregationMapping.Scope scope) {
-		return loaders.stream().anyMatch(supportsScope(scope));
+		return loaders.containsKey(scope.name());
 	}
 
 	public AggregationDataLoader getLoader(AggregationMapping.Scope scope) {
-		return loaders.stream().filter(supportsScope(scope)).findFirst()
-				.orElseThrow(() -> new TechnicalException("No loader found for scope " + scope));
-	}
-
-	private Predicate<AggregationDataLoader> supportsScope(AggregationMapping.Scope scope) {
-		return loader -> loader.supportsScope(scope);
+		return Optional.ofNullable(loaders.get(scope.name())).orElseThrow(() -> new TechnicalException("No data loader for scope " + scope));
 	}
 }
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationWarehouseDataLoader.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationWarehouseDataLoader.java
index 5694975..51ead0e 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationWarehouseDataLoader.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/AggregationWarehouseDataLoader.java
@@ -24,19 +24,21 @@
 package de.ozgcloud.aggregation;
 
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.aggregation.transformation.AggregationMapping;
 import de.ozgcloud.aggregation.warehouse.DocumentEntry;
 import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Component
+@Qualifier(AggregationWarehouseDataLoader.SCOPE)
 @RequiredArgsConstructor
 @Log4j2
 public class AggregationWarehouseDataLoader implements AggregationDataLoader {
 
+	static final String SCOPE = "INTERN";
 	private final WarehouseRepository repository;
 
 	@Override
@@ -49,9 +51,4 @@ public class AggregationWarehouseDataLoader implements AggregationDataLoader {
 	String getCollectionName(Aggregation aggregation) {
 		return StringUtils.isNotBlank(aggregation.aggregationName()) ? aggregation.aggregationName() : DocumentEntry.COLLECTION;
 	}
-
-	@Override
-	public boolean supportsScope(AggregationMapping.Scope scope) {
-		return AggregationMapping.Scope.INTERN.equals(scope);
-	}
 }
diff --git a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/extern/AggregationRemoteDataLoader.java b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/extern/AggregationRemoteDataLoader.java
index 29ed0db..12a9e4d 100644
--- a/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/extern/AggregationRemoteDataLoader.java
+++ b/aggregation-manager-job/src/main/java/de/ozgcloud/aggregation/extern/AggregationRemoteDataLoader.java
@@ -25,22 +25,24 @@ package de.ozgcloud.aggregation.extern;
 
 import java.util.concurrent.ExecutionException;
 
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Component;
 
 import de.ozgcloud.aggregation.Aggregation;
 import de.ozgcloud.aggregation.AggregationDataLoader;
-import de.ozgcloud.aggregation.transformation.AggregationMapping;
 import de.ozgcloud.common.errorhandling.TechnicalException;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Component
+@Qualifier(AggregationRemoteDataLoader.SCOPE)
 @ConditionalOnProperty("grpc.client.aggregation-manager.address")
 @RequiredArgsConstructor
 @Log4j2
 public class AggregationRemoteDataLoader implements AggregationDataLoader {
 
+	static final String SCOPE = "EXTERN";
 	private final AggregationDataRemoteService service;
 
 	@Override
@@ -54,8 +56,4 @@ public class AggregationRemoteDataLoader implements AggregationDataLoader {
 			throw new TechnicalException("Error on sending aggregation data.", e);
 		}
 	}
-
-	public boolean supportsScope(AggregationMapping.Scope scope) {
-		return AggregationMapping.Scope.EXTERN.equals(scope);
-	}
 }
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationDataLoaderRegistryTest.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationDataLoaderRegistryTest.java
index cd7127d..02d5b4b 100644
--- a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationDataLoaderRegistryTest.java
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationDataLoaderRegistryTest.java
@@ -26,7 +26,6 @@ package de.ozgcloud.aggregation;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
-import java.util.List;
 import java.util.Map;
 
 import org.junit.jupiter.api.BeforeEach;
@@ -36,58 +35,36 @@ import org.mockito.Mock;
 
 import de.ozgcloud.aggregation.transformation.AggregationMapping;
 import de.ozgcloud.common.errorhandling.TechnicalException;
-import de.ozgcloud.common.test.ReflectionTestUtils;
 
 class AggregationDataLoaderRegistryTest {
 
+	private static final String SCOPE_KEY = AggregationWarehouseDataLoader.SCOPE;
+	private final AggregationMapping.Scope registeredScope = AggregationMapping.Scope.INTERN;
+	private final AggregationMapping.Scope notRegisteredScope = AggregationMapping.Scope.EXTERN;
+
+
 	@Mock
 	private AggregationDataLoader loader;
 	private AggregationDataLoaderRegistry registry;
 
 	@BeforeEach
 	void init() {
-		registry = spy(new AggregationDataLoaderRegistry(List.of(loader)));
-	}
-
-	@Nested
-	class TestBuildLoadersMap {
-
-		@Test
-		void shouldAddLoader() {
-		}
-
-		@SuppressWarnings("unchecked")
-		private Map<AggregationMapping.Scope, AggregationDataLoader> getScopeToLoader() {
-			return ReflectionTestUtils.getField(registry, "scopeToLoader", Map.class);
-		}
+		registry = spy(new AggregationDataLoaderRegistry(Map.of(SCOPE_KEY, loader)));
 	}
 
 	@Nested
 	class TestHasLoader {
 
-		@Test
-		void shouldCheckIfLoaderSupportsScope() {
-			var scope = AggregationMapping.Scope.INTERN;
-
-			registry.hasLoader(scope);
-
-			verify(loader).supportsScope(scope);
-		}
-
 		@Test
 		void shouldReturnFalseIfNoLoaderRegisteredForScope() {
-			when(loader.supportsScope(any())).thenReturn(false);
-
-			var hasLoader = registry.hasLoader(AggregationMapping.Scope.INTERN);
+			var hasLoader = registry.hasLoader(notRegisteredScope);
 
 			assertThat(hasLoader).isFalse();
 		}
 
 		@Test
 		void shouldReturnTrueIfLoaderRegisteredForScope() {
-			when(loader.supportsScope(any())).thenReturn(true);
-
-			var hasLoader = registry.hasLoader(AggregationMapping.Scope.INTERN);
+			var hasLoader = registry.hasLoader(registeredScope);
 
 			assertThat(hasLoader).isTrue();
 		}
@@ -96,31 +73,16 @@ class AggregationDataLoaderRegistryTest {
 	@Nested
 	class TestGetLoader {
 
-		private final AggregationMapping.Scope scope = AggregationMapping.Scope.INTERN;
-
-		@Test
-		void shouldCheckIfLoaderSupportsScope() {
-			when(loader.supportsScope(any())).thenReturn(true);
-
-			registry.getLoader(scope);
-
-			verify(loader).supportsScope(scope);
-		}
-
 		@Test
 		void shouldReturnLoaderThatSupportsScope() {
-			when(loader.supportsScope(any())).thenReturn(true);
-
-			var loaderSupportingScope = registry.getLoader(scope);
+			var loaderSupportingScope = registry.getLoader(registeredScope);
 
 			assertThat(loaderSupportingScope).isSameAs(loader);
 		}
 
 		@Test
 		void shouldThrowExceptionIfNoLoaderRegisteredForScope() {
-			when(loader.supportsScope(any())).thenReturn(false);
-
-			assertThatThrownBy(() -> registry.getLoader(scope)).isInstanceOf(TechnicalException.class);
+			assertThatThrownBy(() -> registry.getLoader(notRegisteredScope)).isInstanceOf(TechnicalException.class);
 		}
 	}
 }
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationWarehouseDataLoaderTest.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationWarehouseDataLoaderTest.java
index 27ce28c..9cd225c 100644
--- a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationWarehouseDataLoaderTest.java
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/AggregationWarehouseDataLoaderTest.java
@@ -32,13 +32,13 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
 import org.junit.jupiter.params.provider.NullAndEmptySource;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 import com.thedeanda.lorem.LoremIpsum;
 
@@ -111,21 +111,13 @@ class AggregationWarehouseDataLoaderTest {
 	}
 
 	@Nested
-	class TestSupportsScope {
-
-		@ParameterizedTest
-		@EnumSource(mode = EnumSource.Mode.EXCLUDE, names = "INTERN")
-		void shouldReturnFalse(AggregationMapping.Scope scope) {
-			var supported = loader.supportsScope(scope);
-
-			assertThat(supported).isFalse();
-		}
+	class TestQualifier {
 
 		@Test
-		void shouldReturnTrue() {
-			var supported = loader.supportsScope(AggregationMapping.Scope.INTERN);
+		void shouldBeIntern() {
+			var qualifierValue = AggregationWarehouseDataLoader.class.getAnnotation(Qualifier.class).value();
 
-			assertThat(supported).isTrue();
+			assertThat(qualifierValue).isEqualTo(AggregationMapping.Scope.INTERN.name());
 		}
 	}
 }
diff --git a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/extern/AggregationRemoteDataLoaderTest.java b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/extern/AggregationRemoteDataLoaderTest.java
index e76d39f..49e0b07 100644
--- a/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/extern/AggregationRemoteDataLoaderTest.java
+++ b/aggregation-manager-job/src/test/java/de/ozgcloud/aggregation/extern/AggregationRemoteDataLoaderTest.java
@@ -34,11 +34,10 @@ import java.util.concurrent.Future;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
+import org.springframework.beans.factory.annotation.Qualifier;
 
 import de.ozgcloud.aggregation.Aggregation;
 import de.ozgcloud.aggregation.AggregationTestFactory;
@@ -129,21 +128,13 @@ class AggregationRemoteDataLoaderTest {
 	}
 
 	@Nested
-	class TestSupportsScope {
-
-		@ParameterizedTest
-		@EnumSource(mode = EnumSource.Mode.EXCLUDE, names = "EXTERN")
-		void shouldReturnFalse(AggregationMapping.Scope scope) {
-			var supported = loader.supportsScope(scope);
-
-			assertThat(supported).isFalse();
-		}
+	class TestQualifier {
 
 		@Test
-		void shouldReturnTrue() {
-			var supported = loader.supportsScope(AggregationMapping.Scope.EXTERN);
+		void shouldBeExtern() {
+			var qualifierValue = AggregationRemoteDataLoader.class.getAnnotation(Qualifier.class).value();
 
-			assertThat(supported).isTrue();
+			assertThat(qualifierValue).isEqualTo(AggregationMapping.Scope.EXTERN.name());
 		}
 	}
 }
-- 
GitLab