From dd550692f150c8e28d15741b682a1295bfb1b5d6 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 21 May 2026 17:32:57 +0200 Subject: [PATCH 1/4] Add map metric type --- .../dev/faststats/core/data/MapMetric.java | 30 ++++++++++++ .../java/dev/faststats/core/data/Metric.java | 49 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 core/src/main/java/dev/faststats/core/data/MapMetric.java diff --git a/core/src/main/java/dev/faststats/core/data/MapMetric.java b/core/src/main/java/dev/faststats/core/data/MapMetric.java new file mode 100644 index 00000000..aa4fa8ed --- /dev/null +++ b/core/src/main/java/dev/faststats/core/data/MapMetric.java @@ -0,0 +1,30 @@ +package dev.faststats.core.data; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.jspecify.annotations.Nullable; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.Callable; + +final class MapMetric extends SimpleMetric> { + public MapMetric(@SourceId final String id, final Callable<@Nullable Map> callable) throws IllegalArgumentException { + super(id, callable); + } + + @Override + public Optional getData() throws Exception { + return compute().map(data -> { + final var object = new JsonObject(); + data.forEach((key, value) -> { + final var entry = new JsonObject(); + if (value instanceof final Boolean bool) entry.addProperty(key, bool); + else if (value instanceof final Number number) entry.addProperty(key, number); + else entry.addProperty(key, value.toString()); + object.add(key, entry); + }); + return object; + }); + } +} diff --git a/core/src/main/java/dev/faststats/core/data/Metric.java b/core/src/main/java/dev/faststats/core/data/Metric.java index 7fb753cb..086bca8c 100644 --- a/core/src/main/java/dev/faststats/core/data/Metric.java +++ b/core/src/main/java/dev/faststats/core/data/Metric.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.Contract; import org.jspecify.annotations.Nullable; +import java.util.Map; import java.util.Optional; import java.util.concurrent.Callable; @@ -96,6 +97,54 @@ static Metric numberArray(@SourceId final String id, final Callable(id, callable); } + /** + * Create a string map metric. + * + * @param id the source id + * @param callable the metric data callable + * @return the string map metric + * @throws IllegalArgumentException if the source id is invalid + * @apiNote The callable must be thread-safe and pure (i.e. not modify any shared state). + * @see #compute() + * @since 0.23.0 + */ + @Contract(value = "_, _ -> new", pure = true) + static Metric> stringMap(@SourceId final String id, final Callable<@Nullable Map> callable) throws IllegalArgumentException { + return new MapMetric<>(id, callable); + } + + /** + * Create a boolean map metric. + * + * @param id the source id + * @param callable the metric data callable + * @return the boolean map metric + * @throws IllegalArgumentException if the source id is invalid + * @apiNote The callable must be thread-safe and pure (i.e. not modify any shared state). + * @see #compute() + * @since 0.23.0 + */ + @Contract(value = "_, _ -> new", pure = true) + static Metric> booleanMap(@SourceId final String id, final Callable<@Nullable Map> callable) throws IllegalArgumentException { + return new MapMetric<>(id, callable); + } + + /** + * Create a number map metric. + * + * @param id the source id + * @param callable the metric data callable + * @return the number map metric + * @throws IllegalArgumentException if the source id is invalid + * @apiNote The callable must be thread-safe and pure (i.e. not modify any shared state). + * @see #compute() + * @since 0.23.0 + */ + @Contract(value = "_, _ -> new", pure = true) + static Metric> numberMap(@SourceId final String id, final Callable<@Nullable Map> callable) throws IllegalArgumentException { + return new MapMetric<>(id, callable); + } + /** * Create a metric for a boolean value. * From 0642b1bb46e6030ca6a50905dbb5b4d2996fbfa1 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 25 May 2026 12:07:46 +0200 Subject: [PATCH 2/4] Bump version to 0.23.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 1df5d313..4433e215 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=0.22.1 +version=0.23.0 From e4286ce3b23a7ef9e88cca82a3b362f4161b6881 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 25 May 2026 12:27:30 +0200 Subject: [PATCH 3/4] Weaken types to accept sub instances --- .../main/java/dev/faststats/core/data/ArrayMetric.java | 2 +- core/src/main/java/dev/faststats/core/data/MapMetric.java | 4 ++-- core/src/main/java/dev/faststats/core/data/Metric.java | 8 ++++---- .../main/java/dev/faststats/core/data/SimpleMetric.java | 6 +++--- .../java/dev/faststats/core/data/SingleValueMetric.java | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/dev/faststats/core/data/ArrayMetric.java b/core/src/main/java/dev/faststats/core/data/ArrayMetric.java index bcba91a5..4a6e027b 100644 --- a/core/src/main/java/dev/faststats/core/data/ArrayMetric.java +++ b/core/src/main/java/dev/faststats/core/data/ArrayMetric.java @@ -8,7 +8,7 @@ import java.util.concurrent.Callable; final class ArrayMetric extends SimpleMetric { - public ArrayMetric(@SourceId final String id, final Callable callable) throws IllegalArgumentException { + public ArrayMetric(@SourceId final String id, final Callable callable) throws IllegalArgumentException { super(id, callable); } diff --git a/core/src/main/java/dev/faststats/core/data/MapMetric.java b/core/src/main/java/dev/faststats/core/data/MapMetric.java index aa4fa8ed..f6e1cbbd 100644 --- a/core/src/main/java/dev/faststats/core/data/MapMetric.java +++ b/core/src/main/java/dev/faststats/core/data/MapMetric.java @@ -8,8 +8,8 @@ import java.util.Optional; import java.util.concurrent.Callable; -final class MapMetric extends SimpleMetric> { - public MapMetric(@SourceId final String id, final Callable<@Nullable Map> callable) throws IllegalArgumentException { +final class MapMetric extends SimpleMetric> { + public MapMetric(@SourceId final String id, final Callable> callable) throws IllegalArgumentException { super(id, callable); } diff --git a/core/src/main/java/dev/faststats/core/data/Metric.java b/core/src/main/java/dev/faststats/core/data/Metric.java index 086bca8c..40ee7830 100644 --- a/core/src/main/java/dev/faststats/core/data/Metric.java +++ b/core/src/main/java/dev/faststats/core/data/Metric.java @@ -34,7 +34,7 @@ public interface Metric { * @since 0.16.0 */ @Contract(pure = true) - Optional compute() throws Exception; + Optional compute() throws Exception; /** * Get the metric data as a JSON element. @@ -109,7 +109,7 @@ static Metric numberArray(@SourceId final String id, final Callable> stringMap(@SourceId final String id, final Callable<@Nullable Map> callable) throws IllegalArgumentException { + static Metric> stringMap(@SourceId final String id, final Callable> callable) throws IllegalArgumentException { return new MapMetric<>(id, callable); } @@ -125,7 +125,7 @@ static Metric> stringMap(@SourceId final String id, final Ca * @since 0.23.0 */ @Contract(value = "_, _ -> new", pure = true) - static Metric> booleanMap(@SourceId final String id, final Callable<@Nullable Map> callable) throws IllegalArgumentException { + static Metric> booleanMap(@SourceId final String id, final Callable> callable) throws IllegalArgumentException { return new MapMetric<>(id, callable); } @@ -141,7 +141,7 @@ static Metric> booleanMap(@SourceId final String id, final * @since 0.23.0 */ @Contract(value = "_, _ -> new", pure = true) - static Metric> numberMap(@SourceId final String id, final Callable<@Nullable Map> callable) throws IllegalArgumentException { + static Metric> numberMap(@SourceId final String id, final Callable> callable) throws IllegalArgumentException { return new MapMetric<>(id, callable); } diff --git a/core/src/main/java/dev/faststats/core/data/SimpleMetric.java b/core/src/main/java/dev/faststats/core/data/SimpleMetric.java index 8d635e46..e3f55476 100644 --- a/core/src/main/java/dev/faststats/core/data/SimpleMetric.java +++ b/core/src/main/java/dev/faststats/core/data/SimpleMetric.java @@ -8,9 +8,9 @@ abstract class SimpleMetric implements Metric { private final @SourceId String id; - private final Callable<@Nullable T> callable; + private final Callable callable; - public SimpleMetric(@SourceId final String id, final Callable<@Nullable T> callable) throws IllegalArgumentException { + public SimpleMetric(@SourceId final String id, final Callable callable) throws IllegalArgumentException { if (!id.matches(SourceId.PATTERN)) { throw new IllegalArgumentException("Invalid source id '" + id + "', must match '" + SourceId.PATTERN + "'"); } @@ -28,7 +28,7 @@ public final Optional compute() throws Exception { } @Override - public boolean equals(final Object o) { + public boolean equals(@Nullable final Object o) { if (o == null || getClass() != o.getClass()) return false; final SimpleMetric that = (SimpleMetric) o; return Objects.equals(id, that.id); diff --git a/core/src/main/java/dev/faststats/core/data/SingleValueMetric.java b/core/src/main/java/dev/faststats/core/data/SingleValueMetric.java index 458679ce..cbfc7e69 100644 --- a/core/src/main/java/dev/faststats/core/data/SingleValueMetric.java +++ b/core/src/main/java/dev/faststats/core/data/SingleValueMetric.java @@ -8,7 +8,7 @@ import java.util.concurrent.Callable; final class SingleValueMetric extends SimpleMetric { - public SingleValueMetric(@SourceId final String id, final Callable<@Nullable T> callable) throws IllegalArgumentException { + public SingleValueMetric(@SourceId final String id, final Callable callable) throws IllegalArgumentException { super(id, callable); } From 12217a406e40c34df1db9d825e9cd56453b0bc81 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 25 May 2026 13:01:56 +0200 Subject: [PATCH 4/4] Fix map to data computation No idea what I smoked there --- core/src/main/java/dev/faststats/core/data/MapMetric.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/dev/faststats/core/data/MapMetric.java b/core/src/main/java/dev/faststats/core/data/MapMetric.java index f6e1cbbd..c9a5e80e 100644 --- a/core/src/main/java/dev/faststats/core/data/MapMetric.java +++ b/core/src/main/java/dev/faststats/core/data/MapMetric.java @@ -18,11 +18,9 @@ public Optional getData() throws Exception { return compute().map(data -> { final var object = new JsonObject(); data.forEach((key, value) -> { - final var entry = new JsonObject(); - if (value instanceof final Boolean bool) entry.addProperty(key, bool); - else if (value instanceof final Number number) entry.addProperty(key, number); - else entry.addProperty(key, value.toString()); - object.add(key, entry); + if (value instanceof final Boolean bool) object.addProperty(key, bool); + else if (value instanceof final Number number) object.addProperty(key, number); + else object.addProperty(key, value.toString()); }); return object; });