From 1511c6020c90f4d62133c060692a2cd447ced162 Mon Sep 17 00:00:00 2001 From: rpanchyk Date: Thu, 25 Mar 2021 16:21:14 +0200 Subject: [PATCH 1/5] Add Module interface --- .../java/org/prebid/server/hooks/v1/Module.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/org/prebid/server/hooks/v1/Module.java diff --git a/src/main/java/org/prebid/server/hooks/v1/Module.java b/src/main/java/org/prebid/server/hooks/v1/Module.java new file mode 100644 index 00000000000..eb1464b887f --- /dev/null +++ b/src/main/java/org/prebid/server/hooks/v1/Module.java @@ -0,0 +1,13 @@ +package org.prebid.server.hooks.v1; + +import java.util.Set; + +/** + * Cares of the module identification among other modules and supplies a collection of available {@Hook}s. + */ +public interface Module { + + String code(); + + Set hooks(); +} From 9b43932d8bcbc018371cccd6fd28cddae3c5fdfd Mon Sep 17 00:00:00 2001 From: rpanchyk Date: Thu, 25 Mar 2021 16:58:12 +0200 Subject: [PATCH 2/5] Add HookCatalog as utility for searching hooks --- .../prebid/server/hooks/v1/HookCatalog.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/org/prebid/server/hooks/v1/HookCatalog.java diff --git a/src/main/java/org/prebid/server/hooks/v1/HookCatalog.java b/src/main/java/org/prebid/server/hooks/v1/HookCatalog.java new file mode 100644 index 00000000000..ead93fd5fca --- /dev/null +++ b/src/main/java/org/prebid/server/hooks/v1/HookCatalog.java @@ -0,0 +1,27 @@ +package org.prebid.server.hooks.v1; + +import java.util.Collection; +import java.util.Objects; +import java.util.Set; + +/** + * Provides simple access to all {@link Hook}s registered in application. + */ +public class HookCatalog { + + private final Set modules; + + public HookCatalog(Set modules) { + this.modules = Objects.requireNonNull(modules); + } + + public Hook getHookBy(String moduleCode, String hookImplCode) { + return modules.stream() + .filter(module -> Objects.equals(module.code(), moduleCode)) + .map(Module::hooks) + .flatMap(Collection::stream) + .filter(hook -> Objects.equals(hook.name(), hookImplCode)) + .findFirst() + .orElse(null); + } +} From 4a39b23671885110e5645590cf06357e50226207 Mon Sep 17 00:00:00 2001 From: rpanchyk Date: Thu, 25 Mar 2021 17:31:19 +0200 Subject: [PATCH 3/5] Add tests --- .../server/hooks/v1/HookCatalogTest.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/test/java/org/prebid/server/hooks/v1/HookCatalogTest.java diff --git a/src/test/java/org/prebid/server/hooks/v1/HookCatalogTest.java b/src/test/java/org/prebid/server/hooks/v1/HookCatalogTest.java new file mode 100644 index 00000000000..e0d4645bf18 --- /dev/null +++ b/src/test/java/org/prebid/server/hooks/v1/HookCatalogTest.java @@ -0,0 +1,63 @@ +package org.prebid.server.hooks.v1; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import static java.util.Collections.singleton; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +public class HookCatalogTest { + + @Rule + public final MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock + private Module sampleModule; + @Mock + private Hook sampleHook; + + private HookCatalog hookCatalog; + + @Before + public void setUp() { + given(sampleModule.code()).willReturn("sample-module"); + given(sampleModule.hooks()).willReturn(singleton(sampleHook)); + given(sampleHook.name()).willReturn("sample-hook"); + + hookCatalog = new HookCatalog(singleton(sampleModule)); + } + + @Test + public void getHookByShouldReturnHookByModuleCodeAndHookImplCode() { + // when + final Hook foundHook = hookCatalog.getHookBy("sample-module", "sample-hook"); + + // then + assertThat(foundHook).isNotNull() + .extracting(Hook::name) + .containsOnly("sample-hook"); + } + + @Test + public void getHookByShouldTolerateUnknownModule() { + // when + final Hook foundHook = hookCatalog.getHookBy("unknown-module", null); + + // then + assertThat(foundHook).isNull(); + } + + @Test + public void getHookByShouldTolerateUnknownHook() { + // when + final Hook foundHook = hookCatalog.getHookBy("sample-module", "unknown-hook"); + + // then + assertThat(foundHook).isNull(); + } +} From 8d841c3b8f72ad82adc5bb937eb465f545a03ea1 Mon Sep 17 00:00:00 2001 From: rpanchyk Date: Fri, 26 Mar 2021 11:36:43 +0200 Subject: [PATCH 4/5] Fix after review --- src/main/java/org/prebid/server/hooks/v1/Module.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/hooks/v1/Module.java b/src/main/java/org/prebid/server/hooks/v1/Module.java index eb1464b887f..4600ce2786f 100644 --- a/src/main/java/org/prebid/server/hooks/v1/Module.java +++ b/src/main/java/org/prebid/server/hooks/v1/Module.java @@ -3,11 +3,20 @@ import java.util.Set; /** - * Cares of the module identification among other modules and supplies a collection of available {@Hook}s. + * Cares of the module identification among other modules and supplies a collection of available {@link Hook}s. + *

+ * This interface is used to keep knowledge of which {@link Hook} is belongs to certain {@link Module} + * while running execution plan. */ public interface Module { + /** + * An identifier that should be unique among other available modules. + */ String code(); + /** + * Collection of hooks available through the module. + */ Set hooks(); } From 1449594e02e85ccd6c4dd2fa0540922bfee59c0f Mon Sep 17 00:00:00 2001 From: rpanchyk Date: Fri, 2 Apr 2021 10:36:36 +0300 Subject: [PATCH 5/5] Fixes after review --- .../prebid/server/hooks/v1/HookCatalog.java | 32 ++++++- .../org/prebid/server/hooks/v1/Module.java | 4 +- .../server/hooks/v1/HookCatalogTest.java | 92 ++++++++++++++++--- 3 files changed, 113 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/prebid/server/hooks/v1/HookCatalog.java b/src/main/java/org/prebid/server/hooks/v1/HookCatalog.java index ead93fd5fca..4a3cb762f49 100644 --- a/src/main/java/org/prebid/server/hooks/v1/HookCatalog.java +++ b/src/main/java/org/prebid/server/hooks/v1/HookCatalog.java @@ -1,5 +1,11 @@ package org.prebid.server.hooks.v1; +import org.prebid.server.hooks.v1.auction.AuctionResponseHook; +import org.prebid.server.hooks.v1.auction.RawAuctionRequestHook; +import org.prebid.server.hooks.v1.bidder.BidderRequestHook; +import org.prebid.server.hooks.v1.bidder.RawBidderResponseHook; +import org.prebid.server.hooks.v1.entrypoint.EntrypointHook; + import java.util.Collection; import java.util.Objects; import java.util.Set; @@ -15,12 +21,34 @@ public HookCatalog(Set modules) { this.modules = Objects.requireNonNull(modules); } - public Hook getHookBy(String moduleCode, String hookImplCode) { + public EntrypointHook entrypointHookBy(String moduleCode, String hookImplCode) { + return getHookBy(moduleCode, hookImplCode, EntrypointHook.class); + } + + public RawAuctionRequestHook rawAuctionRequestHookBy(String moduleCode, String hookImplCode) { + return getHookBy(moduleCode, hookImplCode, RawAuctionRequestHook.class); + } + + public BidderRequestHook bidderRequestHookBy(String moduleCode, String hookImplCode) { + return getHookBy(moduleCode, hookImplCode, BidderRequestHook.class); + } + + public RawBidderResponseHook rawBidderResponseHookBy(String moduleCode, String hookImplCode) { + return getHookBy(moduleCode, hookImplCode, RawBidderResponseHook.class); + } + + public AuctionResponseHook auctionResponseHookBy(String moduleCode, String hookImplCode) { + return getHookBy(moduleCode, hookImplCode, AuctionResponseHook.class); + } + + private T getHookBy(String moduleCode, String hookImplCode, Class clazz) { return modules.stream() .filter(module -> Objects.equals(module.code(), moduleCode)) .map(Module::hooks) .flatMap(Collection::stream) - .filter(hook -> Objects.equals(hook.name(), hookImplCode)) + .filter(hook -> Objects.equals(hook.code(), hookImplCode)) + .filter(clazz::isInstance) + .map(clazz::cast) .findFirst() .orElse(null); } diff --git a/src/main/java/org/prebid/server/hooks/v1/Module.java b/src/main/java/org/prebid/server/hooks/v1/Module.java index 4600ce2786f..c645915e4a0 100644 --- a/src/main/java/org/prebid/server/hooks/v1/Module.java +++ b/src/main/java/org/prebid/server/hooks/v1/Module.java @@ -1,6 +1,6 @@ package org.prebid.server.hooks.v1; -import java.util.Set; +import java.util.Collection; /** * Cares of the module identification among other modules and supplies a collection of available {@link Hook}s. @@ -18,5 +18,5 @@ public interface Module { /** * Collection of hooks available through the module. */ - Set hooks(); + Collection hooks(); } diff --git a/src/test/java/org/prebid/server/hooks/v1/HookCatalogTest.java b/src/test/java/org/prebid/server/hooks/v1/HookCatalogTest.java index e0d4645bf18..d9a5470da1f 100644 --- a/src/test/java/org/prebid/server/hooks/v1/HookCatalogTest.java +++ b/src/test/java/org/prebid/server/hooks/v1/HookCatalogTest.java @@ -4,12 +4,19 @@ import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import org.prebid.server.hooks.v1.auction.AuctionResponseHook; +import org.prebid.server.hooks.v1.auction.RawAuctionRequestHook; +import org.prebid.server.hooks.v1.bidder.BidderRequestHook; +import org.prebid.server.hooks.v1.bidder.RawBidderResponseHook; +import org.prebid.server.hooks.v1.entrypoint.EntrypointHook; import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doReturn; public class HookCatalogTest { @@ -26,38 +33,101 @@ public class HookCatalogTest { @Before public void setUp() { given(sampleModule.code()).willReturn("sample-module"); - given(sampleModule.hooks()).willReturn(singleton(sampleHook)); - given(sampleHook.name()).willReturn("sample-hook"); hookCatalog = new HookCatalog(singleton(sampleModule)); } @Test - public void getHookByShouldReturnHookByModuleCodeAndHookImplCode() { + public void entrypointHookByShouldTolerateUnknownModule() { // when - final Hook foundHook = hookCatalog.getHookBy("sample-module", "sample-hook"); + final Hook foundHook = hookCatalog.entrypointHookBy("unknown-module", null); + + // then + assertThat(foundHook).isNull(); + } + + @Test + public void entrypointHookByShouldTolerateUnknownHook() { + // when + final Hook foundHook = hookCatalog.entrypointHookBy("sample-module", "unknown-hook"); + + // then + assertThat(foundHook).isNull(); + } + + @Test + public void entrypointHookByShouldReturnExpectedResult() { + // given + givenHook(EntrypointHook.class); + + // when + final Hook foundHook = hookCatalog.entrypointHookBy("sample-module", "sample-hook"); // then assertThat(foundHook).isNotNull() - .extracting(Hook::name) + .extracting(Hook::code) .containsOnly("sample-hook"); } @Test - public void getHookByShouldTolerateUnknownModule() { + public void rawAuctionRequestHookByShouldReturnExpectedResult() { + // given + givenHook(RawAuctionRequestHook.class); + // when - final Hook foundHook = hookCatalog.getHookBy("unknown-module", null); + final Hook foundHook = hookCatalog.rawAuctionRequestHookBy("sample-module", "sample-hook"); // then - assertThat(foundHook).isNull(); + assertThat(foundHook).isNotNull() + .extracting(Hook::code) + .containsOnly("sample-hook"); } @Test - public void getHookByShouldTolerateUnknownHook() { + public void bidderRequestHookByShouldReturnExpectedResult() { + // given + givenHook(BidderRequestHook.class); + // when - final Hook foundHook = hookCatalog.getHookBy("sample-module", "unknown-hook"); + final Hook foundHook = hookCatalog.bidderRequestHookBy("sample-module", "sample-hook"); // then - assertThat(foundHook).isNull(); + assertThat(foundHook).isNotNull() + .extracting(Hook::code) + .containsOnly("sample-hook"); + } + + @Test + public void rawBidderResponseHookByShouldReturnExpectedResult() { + // given + givenHook(RawBidderResponseHook.class); + + // when + final Hook foundHook = hookCatalog.rawBidderResponseHookBy("sample-module", "sample-hook"); + + // then + assertThat(foundHook).isNotNull() + .extracting(Hook::code) + .containsOnly("sample-hook"); + } + + @Test + public void auctionResponseHookByShouldReturnExpectedResult() { + // given + givenHook(AuctionResponseHook.class); + + // when + final Hook foundHook = hookCatalog.auctionResponseHookBy("sample-module", "sample-hook"); + + // then + assertThat(foundHook).isNotNull() + .extracting(Hook::code) + .containsOnly("sample-hook"); + } + + private void givenHook(Class clazz) { + sampleHook = Mockito.mock(clazz); + given(sampleHook.code()).willReturn("sample-hook"); + doReturn(singleton(sampleHook)).when(sampleModule).hooks(); } }