From c05b36b0bdf64c70a418b39fe5c35feba2137cf2 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Wed, 31 May 2023 11:34:01 -0700 Subject: [PATCH 1/6] flag metadata Signed-off-by: Kavindu Dodanduwa --- .../sdk/FlagEvaluationDetails.java | 11 +- .../dev/openfeature/sdk/FlagMetadata.java | 170 ++++++++++++++++++ .../openfeature/sdk/ProviderEvaluation.java | 2 + .../openfeature/sdk/DoSomethingProvider.java | 17 +- .../sdk/FlagEvaluationSpecTest.java | 16 +- .../dev/openfeature/sdk/FlagMetadataTest.java | 50 ++++++ 6 files changed, 253 insertions(+), 13 deletions(-) create mode 100644 src/main/java/dev/openfeature/sdk/FlagMetadata.java create mode 100644 src/test/java/dev/openfeature/sdk/FlagMetadataTest.java diff --git a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java index 67ee853d1..7fccaff04 100644 --- a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java +++ b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java @@ -7,23 +7,25 @@ /** * Contains information about how the evaluation happened, including any resolved values. + * * @param the type of the flag being evaluated. */ -@Data @Builder -public class FlagEvaluationDetails implements BaseEvaluation { +@Data @Builder public class FlagEvaluationDetails implements BaseEvaluation { + private String flagKey; private T value; @Nullable private String variant; @Nullable private String reason; private ErrorCode errorCode; @Nullable private String errorMessage; + @Builder.Default private FlagMetadata flagMetadata = FlagMetadata.builder().build(); /** * Generate detail payload from the provider response. * * @param providerEval provider response - * @param flagKey key for the flag being evaluated - * @param type of flag being returned + * @param flagKey key for the flag being evaluated + * @param type of flag being returned * @return detail payload */ public static FlagEvaluationDetails from(ProviderEvaluation providerEval, String flagKey) { @@ -33,6 +35,7 @@ public static FlagEvaluationDetails from(ProviderEvaluation providerEv .variant(providerEval.getVariant()) .reason(providerEval.getReason()) .errorCode(providerEval.getErrorCode()) + .flagMetadata(providerEval.getFlagMetadata()) .build(); } } diff --git a/src/main/java/dev/openfeature/sdk/FlagMetadata.java b/src/main/java/dev/openfeature/sdk/FlagMetadata.java new file mode 100644 index 000000000..9a84f03bc --- /dev/null +++ b/src/main/java/dev/openfeature/sdk/FlagMetadata.java @@ -0,0 +1,170 @@ +package dev.openfeature.sdk; + +import dev.openfeature.sdk.exceptions.GeneralError; +import dev.openfeature.sdk.exceptions.ParseError; + +import java.util.HashMap; +import java.util.Map; + +/** + * Immutable Flag Metadata representation. Implementation is backed by a {@link Map} and immutability is provided + * through builder and accessors. + */ +public class FlagMetadata { + private final Map metadata; + + private FlagMetadata(Map metadata) { + this.metadata = metadata; + } + + /** + * Retrieve a {@link String} value for the given key. If a value is not found, {@link GeneralError} will be thrown. + * If value exist but of another type, {@link ParseError} will be thrown. + * + * @param key flag metadata key to retrieve + */ + public String getString(final String key) { + return getValue(key, String.class); + } + + /** + * Retrieve an {@link Integer} value for the given key. + * If a value is not found, {@link GeneralError} will be thrown. + * If value exist but of another type, {@link ParseError} will be thrown. + * + * @param key flag metadata key to retrieve + */ + public Integer getInteger(final String key) { + return getValue(key, Integer.class); + } + + /** + * Retrieve an {@link Float} value for the given key. If a value is not found, {@link GeneralError} will be thrown. + * If value exist but of another type, {@link ParseError} will be thrown. + * + * @param key flag metadata key to retrieve + */ + public Float getFloat(final String key) { + return getValue(key, Float.class); + } + + /** + * Retrieve an {@link Double} value for the given key. + * If a value is not found, {@link GeneralError} will be thrown. + * If value exist but of another type, {@link ParseError} will be thrown. + * + * @param key flag metadata key to retrieve + */ + public Double getDouble(final String key) { + return getValue(key, Double.class); + } + + /** + * Retrieve an {@link Boolean} value for the given key. + * If a value is not found, {@link GeneralError} will be thrown. + * If value exist but of another type, {@link ParseError} will be thrown. + * + * @param key flag metadata key to retrieve + */ + public Boolean getBoolean(final String key) { + return getValue(key, Boolean.class); + } + + private T getValue(final String key, final Class type) { + final Object o = metadata.get(key); + + if (o == null) { + throw new GeneralError("key " + key + " does not exist in metadata"); + } + + try { + return type.cast(o); + } catch (ClassCastException e) { + throw new ParseError( + "wrong type for key " + key + + ". Expected" + type.getSimpleName() + "but got " + o.getClass().getSimpleName(), e); + } + } + + + /** + * Obtain a builder for {@link FlagMetadata}. + */ + public static FlagMetadataBuilder builder() { + return new FlagMetadataBuilder(); + } + + /** + * Immutable builder for {@link FlagMetadata}. + */ + public static class FlagMetadataBuilder { + private final Map metadata; + + private FlagMetadataBuilder() { + metadata = new HashMap<>(); + } + + /** + * Add String value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addString(final String key, final String value) { + metadata.put(key, value); + return this; + } + + /** + * Add Integer value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addInteger(final String key, final Integer value) { + metadata.put(key, value); + return this; + } + + /** + * Add Float value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addFloat(final String key, final Float value) { + metadata.put(key, value); + return this; + } + + /** + * Add Double value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addDouble(final String key, final Double value) { + metadata.put(key, value); + return this; + } + + /** + * Add Boolean value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addBoolean(final String key, final Boolean value) { + metadata.put(key, value); + return this; + } + + /** + * Retrieve {@link FlagMetadata} with provided key,value pairs. + */ + public FlagMetadata build() { + return new FlagMetadata(this.metadata); + } + + } +} diff --git a/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java b/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java index 9ba1ab9a1..ffa5c3ccc 100644 --- a/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java +++ b/src/main/java/dev/openfeature/sdk/ProviderEvaluation.java @@ -13,4 +13,6 @@ public class ProviderEvaluation implements BaseEvaluation { @Nullable private String reason; ErrorCode errorCode; @Nullable private String errorMessage; + @Builder.Default + private FlagMetadata flagMetadata = FlagMetadata.builder().build(); } diff --git a/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java b/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java index d87fa3749..26e6737bb 100644 --- a/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java +++ b/src/test/java/dev/openfeature/sdk/DoSomethingProvider.java @@ -1,11 +1,14 @@ package dev.openfeature.sdk; -public class DoSomethingProvider implements FeatureProvider { +class DoSomethingProvider implements FeatureProvider { + + static final String name = "Something"; + // Flag evaluation metadata + static final FlagMetadata flagMetadata = FlagMetadata.builder().build(); - public static final String name = "Something"; private EvaluationContext savedContext; - public EvaluationContext getMergedContext() { + EvaluationContext getMergedContext() { return savedContext; } @@ -18,13 +21,16 @@ public Metadata getMetadata() { public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) { savedContext = ctx; return ProviderEvaluation.builder() - .value(!defaultValue).build(); + .value(!defaultValue) + .flagMetadata(flagMetadata) + .build(); } @Override public ProviderEvaluation getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) { return ProviderEvaluation.builder() .value(new StringBuilder(defaultValue).reverse().toString()) + .flagMetadata(flagMetadata) .build(); } @@ -33,6 +39,7 @@ public ProviderEvaluation getIntegerEvaluation(String key, Integer defa savedContext = ctx; return ProviderEvaluation.builder() .value(defaultValue * 100) + .flagMetadata(flagMetadata) .build(); } @@ -41,6 +48,7 @@ public ProviderEvaluation getDoubleEvaluation(String key, Double default savedContext = ctx; return ProviderEvaluation.builder() .value(defaultValue * 100) + .flagMetadata(flagMetadata) .build(); } @@ -49,6 +57,7 @@ public ProviderEvaluation getObjectEvaluation(String key, Value defaultVa savedContext = invocationContext; return ProviderEvaluation.builder() .value(null) + .flagMetadata(flagMetadata) .build(); } } diff --git a/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java b/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java index e508bdd07..57f0c0454 100644 --- a/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagEvaluationSpecTest.java @@ -1,6 +1,8 @@ package dev.openfeature.sdk; -import static org.assertj.core.api.Assertions.*; +import static dev.openfeature.sdk.DoSomethingProvider.flagMetadata; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -15,18 +17,18 @@ import java.util.List; import java.util.Map; -import dev.openfeature.sdk.exceptions.FlagNotFoundError; -import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - -import dev.openfeature.sdk.fixtures.HookFixtures; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.simplify4u.slf4jmock.LoggerMock; import org.slf4j.Logger; +import dev.openfeature.sdk.exceptions.FlagNotFoundError; +import dev.openfeature.sdk.fixtures.HookFixtures; +import dev.openfeature.sdk.testutils.FeatureProviderTestUtils; + class FlagEvaluationSpecTest implements HookFixtures { private Logger logger; @@ -150,6 +152,7 @@ void getApiInstance() { .flagKey(key) .value(false) .variant(null) + .flagMetadata(flagMetadata) .build(); assertEquals(bd, c.getBooleanDetails(key, true)); assertEquals(bd, c.getBooleanDetails(key, true, new ImmutableContext())); @@ -159,6 +162,7 @@ void getApiInstance() { .flagKey(key) .value("tset") .variant(null) + .flagMetadata(flagMetadata) .build(); assertEquals(sd, c.getStringDetails(key, "test")); assertEquals(sd, c.getStringDetails(key, "test", new ImmutableContext())); @@ -167,6 +171,7 @@ void getApiInstance() { FlagEvaluationDetails id = FlagEvaluationDetails.builder() .flagKey(key) .value(400) + .flagMetadata(flagMetadata) .build(); assertEquals(id, c.getIntegerDetails(key, 4)); assertEquals(id, c.getIntegerDetails(key, 4, new ImmutableContext())); @@ -175,6 +180,7 @@ void getApiInstance() { FlagEvaluationDetails dd = FlagEvaluationDetails.builder() .flagKey(key) .value(40.0) + .flagMetadata(flagMetadata) .build(); assertEquals(dd, c.getDoubleDetails(key, .4)); assertEquals(dd, c.getDoubleDetails(key, .4, new ImmutableContext())); diff --git a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java new file mode 100644 index 000000000..97ec5a4c3 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java @@ -0,0 +1,50 @@ +package dev.openfeature.sdk; + +import dev.openfeature.sdk.exceptions.GeneralError; +import dev.openfeature.sdk.exceptions.ParseError; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class FlagMetadataTest { + + @Test + public void builder_validation() { + // given + FlagMetadata flagMetadata = FlagMetadata.builder() + .addString("string", "string") + .addInteger("integer", 1) + .addFloat("float", 1.5f) + .addDouble("double", Double.MAX_VALUE) + .addBoolean("boolean", Boolean.FALSE) + .build(); + + // then + assertThat(flagMetadata.getString("string")).isEqualTo("string"); + assertThat(flagMetadata.getInteger("integer")).isEqualTo(1); + assertThat(flagMetadata.getFloat("float")).isEqualTo(1.5f); + assertThat(flagMetadata.getDouble("double")).isEqualTo(Double.MAX_VALUE); + assertThat(flagMetadata.getBoolean("boolean")).isEqualTo(Boolean.FALSE); + } + + @Test + public void parse_error_validation() { + // given + FlagMetadata flagMetadata = FlagMetadata.builder() + .addString("string", "string") + .build(); + + // then + assertThatThrownBy(() -> flagMetadata.getBoolean("string")).isInstanceOf(ParseError.class); + } + + @Test + public void notfound_error_validation() { + // given + FlagMetadata flagMetadata = FlagMetadata.builder().build(); + + // then + assertThatThrownBy(() -> flagMetadata.getBoolean("string")).isInstanceOf(GeneralError.class); + } +} \ No newline at end of file From 3d636caa8195579351fb1f8aab37f338ae99c669 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Wed, 31 May 2023 11:34:55 -0700 Subject: [PATCH 2/6] fix formatting Signed-off-by: Kavindu Dodanduwa --- src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java index 7fccaff04..24e6a3985 100644 --- a/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java +++ b/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.java @@ -10,7 +10,9 @@ * * @param the type of the flag being evaluated. */ -@Data @Builder public class FlagEvaluationDetails implements BaseEvaluation { +@Data +@Builder +public class FlagEvaluationDetails implements BaseEvaluation { private String flagKey; private T value; From e6f1356660e7f6c65b82f3004eb28fa1ec615190 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Wed, 31 May 2023 15:25:54 -0700 Subject: [PATCH 3/6] linting Signed-off-by: Kavindu Dodanduwa --- src/main/java/dev/openfeature/sdk/FlagMetadata.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/openfeature/sdk/FlagMetadata.java b/src/main/java/dev/openfeature/sdk/FlagMetadata.java index 9a84f03bc..345f27c31 100644 --- a/src/main/java/dev/openfeature/sdk/FlagMetadata.java +++ b/src/main/java/dev/openfeature/sdk/FlagMetadata.java @@ -39,7 +39,7 @@ public Integer getInteger(final String key) { } /** - * Retrieve an {@link Float} value for the given key. If a value is not found, {@link GeneralError} will be thrown. + * Retrieve a {@link Float} value for the given key. If a value is not found, {@link GeneralError} will be thrown. * If value exist but of another type, {@link ParseError} will be thrown. * * @param key flag metadata key to retrieve @@ -49,7 +49,7 @@ public Float getFloat(final String key) { } /** - * Retrieve an {@link Double} value for the given key. + * Retrieve a {@link Double} value for the given key. * If a value is not found, {@link GeneralError} will be thrown. * If value exist but of another type, {@link ParseError} will be thrown. * @@ -60,7 +60,7 @@ public Double getDouble(final String key) { } /** - * Retrieve an {@link Boolean} value for the given key. + * Retrieve a {@link Boolean} value for the given key. * If a value is not found, {@link GeneralError} will be thrown. * If value exist but of another type, {@link ParseError} will be thrown. * From 6f0d28da2f19dfa00e46820b2cec729699ce1b7d Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Mon, 5 Jun 2023 09:59:34 -0700 Subject: [PATCH 4/6] review changes Signed-off-by: Kavindu Dodanduwa --- .../dev/openfeature/sdk/FlagMetadata.java | 35 +++++++++---------- .../dev/openfeature/sdk/FlagMetadataTest.java | 15 ++++---- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/main/java/dev/openfeature/sdk/FlagMetadata.java b/src/main/java/dev/openfeature/sdk/FlagMetadata.java index 345f27c31..cf357b57a 100644 --- a/src/main/java/dev/openfeature/sdk/FlagMetadata.java +++ b/src/main/java/dev/openfeature/sdk/FlagMetadata.java @@ -1,7 +1,6 @@ package dev.openfeature.sdk; -import dev.openfeature.sdk.exceptions.GeneralError; -import dev.openfeature.sdk.exceptions.ParseError; +import lombok.extern.slf4j.Slf4j; import java.util.HashMap; import java.util.Map; @@ -10,6 +9,7 @@ * Immutable Flag Metadata representation. Implementation is backed by a {@link Map} and immutability is provided * through builder and accessors. */ +@Slf4j public class FlagMetadata { private final Map metadata; @@ -18,8 +18,8 @@ private FlagMetadata(Map metadata) { } /** - * Retrieve a {@link String} value for the given key. If a value is not found, {@link GeneralError} will be thrown. - * If value exist but of another type, {@link ParseError} will be thrown. + * Retrieve a {@link String} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. * * @param key flag metadata key to retrieve */ @@ -28,9 +28,8 @@ public String getString(final String key) { } /** - * Retrieve an {@link Integer} value for the given key. - * If a value is not found, {@link GeneralError} will be thrown. - * If value exist but of another type, {@link ParseError} will be thrown. + * Retrieve a {@link Integer} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. * * @param key flag metadata key to retrieve */ @@ -39,8 +38,8 @@ public Integer getInteger(final String key) { } /** - * Retrieve a {@link Float} value for the given key. If a value is not found, {@link GeneralError} will be thrown. - * If value exist but of another type, {@link ParseError} will be thrown. + * Retrieve a {@link Float} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. * * @param key flag metadata key to retrieve */ @@ -49,9 +48,8 @@ public Float getFloat(final String key) { } /** - * Retrieve a {@link Double} value for the given key. - * If a value is not found, {@link GeneralError} will be thrown. - * If value exist but of another type, {@link ParseError} will be thrown. + * Retrieve a {@link Double} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. * * @param key flag metadata key to retrieve */ @@ -60,9 +58,8 @@ public Double getDouble(final String key) { } /** - * Retrieve a {@link Boolean} value for the given key. - * If a value is not found, {@link GeneralError} will be thrown. - * If value exist but of another type, {@link ParseError} will be thrown. + * Retrieve a {@link Boolean} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. * * @param key flag metadata key to retrieve */ @@ -74,15 +71,15 @@ private T getValue(final String key, final Class type) { final Object o = metadata.get(key); if (o == null) { - throw new GeneralError("key " + key + " does not exist in metadata"); + log.debug("Metadata key "+ key+ "does not exist"); + return null; } try { return type.cast(o); } catch (ClassCastException e) { - throw new ParseError( - "wrong type for key " + key - + ". Expected" + type.getSimpleName() + "but got " + o.getClass().getSimpleName(), e); + log.debug("Error retrieving value for key "+ key, e); + return null; } } diff --git a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java index 97ec5a4c3..c8f4d91c7 100644 --- a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java @@ -1,15 +1,14 @@ package dev.openfeature.sdk; -import dev.openfeature.sdk.exceptions.GeneralError; -import dev.openfeature.sdk.exceptions.ParseError; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; class FlagMetadataTest { @Test + @DisplayName("Test metadata payload construction and retrieval") public void builder_validation() { // given FlagMetadata flagMetadata = FlagMetadata.builder() @@ -29,22 +28,24 @@ public void builder_validation() { } @Test - public void parse_error_validation() { + @DisplayName("Value type mismatch returns a null") + public void value_type_validation() { // given FlagMetadata flagMetadata = FlagMetadata.builder() .addString("string", "string") .build(); // then - assertThatThrownBy(() -> flagMetadata.getBoolean("string")).isInstanceOf(ParseError.class); + assertThat(flagMetadata.getBoolean("string")).isNull(); } @Test + @DisplayName("A null is returned if key does not exist") public void notfound_error_validation() { // given FlagMetadata flagMetadata = FlagMetadata.builder().build(); // then - assertThatThrownBy(() -> flagMetadata.getBoolean("string")).isInstanceOf(GeneralError.class); + assertThat(flagMetadata.getBoolean("string")).isNull(); } -} \ No newline at end of file +} From 7e54a2696a84e8290f7051e66e6365256b4b8f9f Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Mon, 5 Jun 2023 10:03:37 -0700 Subject: [PATCH 5/6] lint fix Signed-off-by: Kavindu Dodanduwa --- src/main/java/dev/openfeature/sdk/FlagMetadata.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/openfeature/sdk/FlagMetadata.java b/src/main/java/dev/openfeature/sdk/FlagMetadata.java index cf357b57a..64560fcef 100644 --- a/src/main/java/dev/openfeature/sdk/FlagMetadata.java +++ b/src/main/java/dev/openfeature/sdk/FlagMetadata.java @@ -71,14 +71,14 @@ private T getValue(final String key, final Class type) { final Object o = metadata.get(key); if (o == null) { - log.debug("Metadata key "+ key+ "does not exist"); + log.debug("Metadata key " + key + "does not exist"); return null; } try { return type.cast(o); } catch (ClassCastException e) { - log.debug("Error retrieving value for key "+ key, e); + log.debug("Error retrieving value for key " + key, e); return null; } } From e78fed78ce8d8bd0e34ab6dc0ef8d5fb0d028783 Mon Sep 17 00:00:00 2001 From: Kavindu Dodanduwa Date: Mon, 5 Jun 2023 11:01:08 -0700 Subject: [PATCH 6/6] add long value support Signed-off-by: Kavindu Dodanduwa --- .../dev/openfeature/sdk/FlagMetadata.java | 21 +++++++++++++++++++ .../dev/openfeature/sdk/FlagMetadataTest.java | 2 ++ 2 files changed, 23 insertions(+) diff --git a/src/main/java/dev/openfeature/sdk/FlagMetadata.java b/src/main/java/dev/openfeature/sdk/FlagMetadata.java index 64560fcef..e9b6ccb6b 100644 --- a/src/main/java/dev/openfeature/sdk/FlagMetadata.java +++ b/src/main/java/dev/openfeature/sdk/FlagMetadata.java @@ -37,6 +37,16 @@ public Integer getInteger(final String key) { return getValue(key, Integer.class); } + /** + * Retrieve a {@link Long} value for the given key. A {@code null} value is returned if the key does not exist + * or if the value is of a different type. + * + * @param key flag metadata key to retrieve + */ + public Long getLong(final String key) { + return getValue(key, Long.class); + } + /** * Retrieve a {@link Float} value for the given key. A {@code null} value is returned if the key does not exist * or if the value is of a different type. @@ -123,6 +133,17 @@ public FlagMetadataBuilder addInteger(final String key, final Integer value) { return this; } + /** + * Add Long value to the metadata. + * + * @param key flag metadata key to add + * @param value flag metadata value to add + */ + public FlagMetadataBuilder addLong(final String key, final Long value) { + metadata.put(key, value); + return this; + } + /** * Add Float value to the metadata. * diff --git a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java index c8f4d91c7..b52eb6de7 100644 --- a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java @@ -14,6 +14,7 @@ public void builder_validation() { FlagMetadata flagMetadata = FlagMetadata.builder() .addString("string", "string") .addInteger("integer", 1) + .addLong("long", 1L) .addFloat("float", 1.5f) .addDouble("double", Double.MAX_VALUE) .addBoolean("boolean", Boolean.FALSE) @@ -22,6 +23,7 @@ public void builder_validation() { // then assertThat(flagMetadata.getString("string")).isEqualTo("string"); assertThat(flagMetadata.getInteger("integer")).isEqualTo(1); + assertThat(flagMetadata.getLong("long")).isEqualTo(1L); assertThat(flagMetadata.getFloat("float")).isEqualTo(1.5f); assertThat(flagMetadata.getDouble("double")).isEqualTo(Double.MAX_VALUE); assertThat(flagMetadata.getBoolean("boolean")).isEqualTo(Boolean.FALSE);