From 8981f292c0688a645c987bef5647aed669641823 Mon Sep 17 00:00:00 2001 From: Big Andy <8012398+big-andy-coates@users.noreply.github.com> Date: Thu, 21 Dec 2023 13:37:32 +0000 Subject: [PATCH] Drop `ResourceHandler`. `ResourceHandler` has moved to `creek-service` repo. This decouples things. The initializer that a reduced-scope call back for resource creation. BREAKING CHANGE: This is a braking change. Downstream projects won't build clean until they too are updated to work with this change. --- .../platform/metadata/ResourceHandler.java | 41 ----------------- .../resource/ResourceInitializer.java | 43 ++++++++--------- .../resource/ResourceInitializerTest.java | 46 ++++++++----------- 3 files changed, 41 insertions(+), 89 deletions(-) delete mode 100644 metadata/src/main/java/org/creekservice/api/platform/metadata/ResourceHandler.java diff --git a/metadata/src/main/java/org/creekservice/api/platform/metadata/ResourceHandler.java b/metadata/src/main/java/org/creekservice/api/platform/metadata/ResourceHandler.java deleted file mode 100644 index ffc888c..0000000 --- a/metadata/src/main/java/org/creekservice/api/platform/metadata/ResourceHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2022-2023 Creek Contributors (https://github.com/creek-service) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.creekservice.api.platform.metadata; - -import java.util.Collection; - -/** - * A Callback that Creek extensions implement to handler the resource types they support. - * - * @param the specific resource type the handler handles. - */ -public interface ResourceHandler { - - /** - * Ensure the supplied {@code resources} exists. - * - *

Instructs an extension to ensure the resources described by the supplied descriptor exist - * and are initialized. - * - *

Implementations should consider outputting a warning or failing if the resource already - * exists, but does not match the expected configuration. - * - * @param resources the resource instances to ensure exists and are initialized. Resources - * passed will be {@link ResourceDescriptor#isCreatable creatable}. - */ - void ensure(Collection resources); -} diff --git a/resource/src/main/java/org/creekservice/api/platform/resource/ResourceInitializer.java b/resource/src/main/java/org/creekservice/api/platform/resource/ResourceInitializer.java index 4e7f45c..7c7ea5a 100644 --- a/resource/src/main/java/org/creekservice/api/platform/resource/ResourceInitializer.java +++ b/resource/src/main/java/org/creekservice/api/platform/resource/ResourceInitializer.java @@ -36,8 +36,8 @@ import org.creekservice.api.observability.logging.structured.StructuredLogger; import org.creekservice.api.observability.logging.structured.StructuredLoggerFactory; import org.creekservice.api.platform.metadata.ComponentDescriptor; +import org.creekservice.api.platform.metadata.OwnedResource; import org.creekservice.api.platform.metadata.ResourceDescriptor; -import org.creekservice.api.platform.metadata.ResourceHandler; import org.creekservice.internal.platform.resource.ComponentValidator; /** @@ -58,38 +58,42 @@ public final class ResourceInitializer { private static final StructuredLogger LOGGER = StructuredLoggerFactory.internalLogger(ResourceInitializer.class); - private final ResourceHandlers handlers; + private final ResourceCreator resourceCreator; private final ComponentValidator componentValidator; - /** Type for retrieving resource handlers */ + /** Type for ensuring external resources exist */ @FunctionalInterface - public interface ResourceHandlers { + public interface ResourceCreator { /** - * Get the handler for a specific type + * Get the handler for a specific type. * - * @param type the type - * @param the type - * @return the handler + *

All {@code creatableResources} will be of the same type. + * + * @param creatableResources the resource instances to ensure exists and are initialized. + * Resources passed will be {@link ResourceDescriptor#isCreatable creatable}. + * @param the creatable resource descriptor type * @throws RuntimeException on unknown resource type */ - ResourceHandler get(Class type); + void ensure( + Collection creatableResources); } /** * Create an initializer instance. * - * @param handlers accessor to resource handlers, as exposed by Creek extensions. + * @param resourceCreator callback used to ensure external resources exist, as exposed by Creek + * extensions. * @return an initializer instance. */ - public static ResourceInitializer resourceInitializer(final ResourceHandlers handlers) { - return new ResourceInitializer(handlers, new ComponentValidator()); + public static ResourceInitializer resourceInitializer(final ResourceCreator resourceCreator) { + return new ResourceInitializer(resourceCreator, new ComponentValidator()); } @VisibleForTesting ResourceInitializer( - final ResourceHandlers handlers, final ComponentValidator componentValidator) { - this.handlers = requireNonNull(handlers, "handlers"); + final ResourceCreator resourceCreator, final ComponentValidator componentValidator) { + this.resourceCreator = requireNonNull(resourceCreator, "resourceCreator"); this.componentValidator = requireNonNull(componentValidator, "componentValidator"); } @@ -173,12 +177,14 @@ public void test( ensureResources(stream); } + @SuppressWarnings({"unchecked", "rawtypes"}) private void ensureResources(final Stream> resGroups) { resGroups .peek(this::validateResourceGroup) .map(this::creatableDescriptor) - .collect(groupingBy(this::resourceHandler)) - .forEach(ResourceHandler::ensure); + .collect(groupingBy(Object::getClass)) + .values() + .forEach(creatableResources -> resourceCreator.ensure((List) creatableResources)); } private ResourceDescriptor creatableDescriptor(final List resGroup) { @@ -237,11 +243,6 @@ private void validateResourceGroup(final List } } - @SuppressWarnings("unchecked") - private ResourceHandler resourceHandler(final T resource) { - return handlers.get((Class) resource.getClass()); - } - private static String formatResource(final List descriptors) { return descriptors.stream() .map(ResourceInitializer::formatResource) diff --git a/resource/src/test/java/org/creekservice/api/platform/resource/ResourceInitializerTest.java b/resource/src/test/java/org/creekservice/api/platform/resource/ResourceInitializerTest.java index a90c005..d67532d 100644 --- a/resource/src/test/java/org/creekservice/api/platform/resource/ResourceInitializerTest.java +++ b/resource/src/test/java/org/creekservice/api/platform/resource/ResourceInitializerTest.java @@ -36,7 +36,6 @@ import org.creekservice.api.platform.metadata.ComponentDescriptor; import org.creekservice.api.platform.metadata.OwnedResource; import org.creekservice.api.platform.metadata.ResourceDescriptor; -import org.creekservice.api.platform.metadata.ResourceHandler; import org.creekservice.api.platform.metadata.SharedResource; import org.creekservice.api.platform.metadata.UnownedResource; import org.creekservice.internal.platform.resource.ComponentValidator; @@ -58,9 +57,7 @@ class ResourceInitializerTest { @Mock private ComponentValidator validator; @Mock private ComponentDescriptor component0; @Mock private ComponentDescriptor component1; - @Mock private ResourceInitializer.ResourceHandlers handlers; - @Mock private ResourceHandler handlerA; - @Mock private ResourceHandler handlerB; + @Mock private ResourceInitializer.ResourceCreator resourceCreator; @Mock(extraInterfaces = SharedResource.class) private ResourceA sharedResource1; @@ -77,9 +74,7 @@ class ResourceInitializerTest { @BeforeEach void setUp() { - initializer = new ResourceInitializer(handlers, validator); - - when(handlers.get(any())).thenReturn(handlerA); + initializer = new ResourceInitializer(resourceCreator, validator); when(sharedResource1.id()).thenReturn(A1_ID); when(ownedResource1.id()).thenReturn(A1_ID); @@ -239,7 +234,7 @@ void shouldNotInitializeAnyResourceOnInitIfNoSharedResources() { initializer.init(List.of(component0, component1)); // Then: - verify(handlers, never()).get(any()); + verify(resourceCreator, never()).ensure(any()); } @Test @@ -254,7 +249,7 @@ void shouldNotInitializeAnyResourcesOnServiceIfNoOwnedResources() { initializer.service(List.of(component0, component1)); // Then: - verify(handlerA, never()).ensure(any()); + verify(resourceCreator, never()).ensure(any()); } @Test @@ -271,7 +266,7 @@ void shouldNotInitializeAnyResourcesOnTestIfNoUnownedResources() { initializer.test(List.of(component0), List.of(component1)); // Then: - verify(handlerA, never()).ensure(any()); + verify(resourceCreator, never()).ensure(any()); } @Test @@ -285,7 +280,7 @@ void shouldNotInitializeAnyResourcesOnTestIfNoUnownedResources() { initializer.test(List.of(component0, component1), List.of()); // Then: - verify(handlerA, never()).ensure(any()); + verify(resourceCreator, never()).ensure(any()); } @Test @@ -301,7 +296,7 @@ void shouldNotInitializeUnmanagedGroups() { initializer.init(List.of(component0, component1)); // Then: - verify(handlers, never()).get(any()); + verify(resourceCreator, never()).ensure(any()); } @Test @@ -325,6 +320,7 @@ void shouldThrowOnUncreatableResource() { assertThat(e.getMessage(), containsString("unownedResource1")); } + @SuppressWarnings({"unchecked", "rawtypes"}) @Test void shouldEnsureSharedResource() { // Given: @@ -336,9 +332,10 @@ void shouldEnsureSharedResource() { initializer.init(List.of(component0, component1)); // Then: - verify(handlerA).ensure(List.of(sharedResource1, sharedResource2)); + verify(resourceCreator).ensure((List) List.of(sharedResource1, sharedResource2)); } + @SuppressWarnings({"unchecked", "rawtypes"}) @Test void shouldEnsureOwnedResource() { // Given: @@ -350,9 +347,10 @@ void shouldEnsureOwnedResource() { initializer.service(List.of(component0, component1)); // Then: - verify(handlerA).ensure(List.of(ownedResource1, ownedResource2)); + verify(resourceCreator).ensure((List) List.of(ownedResource1, ownedResource2)); } + @SuppressWarnings({"unchecked", "rawtypes"}) @Test void shouldEnsureUnownedResource() { // Given: @@ -365,14 +363,14 @@ void shouldEnsureUnownedResource() { initializer.test(List.of(component0), List.of(component1)); // Then: - verify(handlerA).ensure(List.of(ownedResource2)); + verify(resourceCreator).ensure((List) List.of(ownedResource2)); } @Test void shouldThrowIfEnsureThrows() { // Given: final RuntimeException expected = new RuntimeException("boom"); - doThrow(expected).when(handlerA).ensure(any()); + doThrow(expected).when(resourceCreator).ensure(any()); when(component0.resources()).thenReturn(Stream.of(ownedResource1)); // When: @@ -384,16 +382,10 @@ void shouldThrowIfEnsureThrows() { assertThat(e, is(sameInstance(expected))); } + @SuppressWarnings({"unchecked", "rawtypes"}) @Test void shouldEnsureGroupingByHandler() { // Given - when(handlers.get(any())) - .thenAnswer( - inv -> - ResourceA.class.isAssignableFrom(inv.getArgument(0)) - ? handlerA - : handlerB); - final ResourceB ownedResourceB = resourceB(OwnedResource.class); when(component0.resources()).thenReturn(Stream.of(ownedResource1, ownedResourceB)); @@ -401,15 +393,15 @@ void shouldEnsureGroupingByHandler() { initializer.service(List.of(component0)); // Then: - verify(handlerA).ensure(List.of(ownedResource1)); - verify(handlerB).ensure(List.of(ownedResourceB)); + verify(resourceCreator).ensure((List) List.of(ownedResource1)); + verify(resourceCreator).ensure((List) List.of(ownedResourceB)); } @Test void shouldThrowOnUnknownResourceType() { // Given: final NullPointerException expected = new NullPointerException("unknown"); - when(handlers.get(any())).thenThrow(expected); + doThrow(expected).when(resourceCreator).ensure(any()); when(component0.resources()).thenReturn(Stream.of(sharedResource1)); // When: @@ -424,7 +416,7 @@ void shouldThrowOnUnknownResourceType() { @Test void shouldThrowOnInvalidComponentUsingActualValidator() { // Given: - initializer = ResourceInitializer.resourceInitializer(handlers); + initializer = ResourceInitializer.resourceInitializer(resourceCreator); // Then: assertThrows(RuntimeException.class, () -> initializer.init(List.of(component0)));