From 9681169ca09195bdf17cf03f52afde33e63bae1a Mon Sep 17 00:00:00 2001 From: Colin Redmond Date: Thu, 22 Feb 2024 18:50:23 -0800 Subject: [PATCH] feat: part 1 of config container --- .../gestalt/config/decoder/ConfigDecoder.java | 43 ++++++++++++++ .../config/entity/ConfigContainer.java | 59 +++++++++++++++++++ gradle/libs.versions.toml | 10 ++-- 3 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 gestalt-core/src/main/java/org/github/gestalt/config/decoder/ConfigDecoder.java create mode 100644 gestalt-core/src/main/java/org/github/gestalt/config/entity/ConfigContainer.java diff --git a/gestalt-core/src/main/java/org/github/gestalt/config/decoder/ConfigDecoder.java b/gestalt-core/src/main/java/org/github/gestalt/config/decoder/ConfigDecoder.java new file mode 100644 index 000000000..5d7f14025 --- /dev/null +++ b/gestalt-core/src/main/java/org/github/gestalt/config/decoder/ConfigDecoder.java @@ -0,0 +1,43 @@ +package org.github.gestalt.config.decoder; + +import org.github.gestalt.config.entity.Config; +import org.github.gestalt.config.entity.ConfigContainer; +import org.github.gestalt.config.node.ConfigNode; +import org.github.gestalt.config.reflect.TypeCapture; +import org.github.gestalt.config.tag.Tags; +import org.github.gestalt.config.utils.GResultOf; + +import java.util.Optional; + +/** + * Decodes a generic optional type. + * + * @author Colin Redmond (c) 2024. + */ +public final class ConfigDecoder implements Decoder> { + + @Override + public Priority priority() { + return Priority.MEDIUM; + } + + @Override + public String name() { + return "Config"; + } + + @Override + public boolean canDecode(String path, Tags tags, ConfigNode node, TypeCapture type) { + return Optional.class.isAssignableFrom(type.getRawType()); + } + + @Override + public GResultOf> decode(String path, Tags tags, ConfigNode node, TypeCapture type, DecoderContext decoderContext) { + // decode the generic type of the optional. Then we will wrap the result into an Optional + GResultOf configValue = decoderContext.getDecoderService() + .decodeNode(path, tags, node, type.getFirstParameterType(), decoderContext); + + return configValue.mapWithError((it) -> new ConfigContainer(path, tags, decoderContext, it.results(), type)); + } + } +} diff --git a/gestalt-core/src/main/java/org/github/gestalt/config/entity/ConfigContainer.java b/gestalt-core/src/main/java/org/github/gestalt/config/entity/ConfigContainer.java new file mode 100644 index 000000000..c53b95f1b --- /dev/null +++ b/gestalt-core/src/main/java/org/github/gestalt/config/entity/ConfigContainer.java @@ -0,0 +1,59 @@ +package org.github.gestalt.config.entity; + +import org.github.gestalt.config.decoder.DecoderContext; +import org.github.gestalt.config.exceptions.GestaltException; +import org.github.gestalt.config.reflect.TypeCapture; +import org.github.gestalt.config.reload.CoreReloadListener; +import org.github.gestalt.config.tag.Tags; + +import java.util.Optional; + +/** + * A Container for a configuration value that supports dynamic config reloading. + * Allows users to get the config value. + * + * @param Type of the Config Container + */ +public class ConfigContainer implements CoreReloadListener { + + private static final System.Logger logger = System.getLogger(ConfigContainer.class.getName()); + + // Path used to get the config on reload. + protected final String path; + // Tags used to get the config on reload. + protected final Tags tags; + // Decoder Context hold gestalt to get the config on reload. + protected final DecoderContext decoderContext; + // Type of the Configuration value. + protected final TypeCapture klass; + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + Optional value; + + public ConfigContainer(String path, Tags tags, DecoderContext decoderContext, T value, TypeCapture klass) { + this.path = path; + this.tags = tags; + this.decoderContext = decoderContext; + this.klass = klass; + this.value = Optional.of(value); + } + + public T getValue() throws GestaltException { + return value.orElseThrow(() -> new GestaltException("No results for config path: " + path + ", tags: " + tags + + ", and class: " + klass.getName())); + } + + public void setValue(T value) { + this.value = Optional.of(value); + } + + @Override + public void reload() { + value = decoderContext.getGestalt().getConfigOptional(path, klass, tags); + + if (value.isEmpty()) { + logger.log(System.Logger.Level.WARNING, "On Reload, no results for config path: " + path + ", tags: " + tags + + ", and class: " + klass.getName()); + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b3951b6e4..bf438be66 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,8 +20,8 @@ weldCore = "4.0.3.Final" jackson = "2.16.1" hocon = "1.4.3" # Cloud -awsBom = "2.24.4" -gcpLibraries = "26.32.0" +awsBom = "2.24.9" +gcpLibraries = "26.33.0" # vault vault = "6.2.0" # Git support @@ -35,9 +35,9 @@ mockk = "1.13.9" koTestAssertions = "5.8.0" # @pin last version to support jdk 11 awsMock = "2.17.0" -testcontainers = "1.19.5" +testcontainers = "1.19.6" # static code analysis -errorprone = "2.24.1" +errorprone = "2.25.0" gradleErrorProne = "3.1.0" detekt = "1.23.5" checkStyle = "10.10.0" @@ -45,7 +45,7 @@ checkStyle = "10.10.0" jmh = "1.37" gradleJmh = "0.7.2" # @pin gestalt for integration tests. -gestalt = "0.24.3" +gestalt = "0.24.4" # Gradle utility gradleVersions = "0.51.0" gitVersions = "3.0.0"