From 9adf31e909cbb6634bcc69453f74d57e9d6f7978 Mon Sep 17 00:00:00 2001 From: Samuel Dumitru Date: Mon, 20 Oct 2025 18:01:36 +0300 Subject: [PATCH 1/6] [enh] added seasonal shapshot clases --- .../trolie/client/TrolieApiConstants.java | 10 ++ .../SeasonalSnapshotRequest.java | 78 +++++++++++++++ .../SeasonalSnapshotResponseParser.java | 96 +++++++++++++++++++ .../SeasonalSnapshotSubscribedRequest.java | 75 +++++++++++++++ .../SeasonalPeriodSnapshot.java | 54 +++++++++++ .../SeasonalSnapshotHeader.java | 35 +++++++ .../SeasonalSnapshotReceiver.java | 60 ++++++++++++ .../SeasonalSnapshotSubscribedReceiver.java | 16 ++++ 8 files changed, 424 insertions(+) create mode 100644 java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotRequest.java create mode 100644 java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java create mode 100644 java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotSubscribedRequest.java create mode 100644 java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java create mode 100644 java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalSnapshotHeader.java create mode 100644 java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotReceiver.java create mode 100644 java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java diff --git a/java-client/src/main/java/energy/trolie/client/TrolieApiConstants.java b/java-client/src/main/java/energy/trolie/client/TrolieApiConstants.java index aa09429..cd6dd6d 100644 --- a/java-client/src/main/java/energy/trolie/client/TrolieApiConstants.java +++ b/java-client/src/main/java/energy/trolie/client/TrolieApiConstants.java @@ -8,6 +8,11 @@ public class TrolieApiConstants { private TrolieApiConstants() { } + /** + * Path to getRealTimeLimits + */ + public static final String PATH_SEASONAL_SNAPSHOT = "/seasonal-ratings/snapshot"; + /** * Path to getRealTimeLimits */ @@ -48,6 +53,11 @@ private TrolieApiConstants() { */ public static final String PATH_DEFAULT_MONITORING_SET = "/default-monitoring-set"; + /** + * Content type for seasonal rating snapshots + */ + public static final String CONTENT_TYPE_SEASONAL_SNAPSHOT = "application/vnd.trolie.seasonal-rating-snapshot.v1+json"; + /** * Content type for real-time limit snapshots */ diff --git a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotRequest.java b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotRequest.java new file mode 100644 index 0000000..af51080 --- /dev/null +++ b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotRequest.java @@ -0,0 +1,78 @@ +package energy.trolie.client.impl.request.operatingsnapshots; + +import com.fasterxml.jackson.databind.ObjectMapper; +import energy.trolie.client.TrolieApiConstants; +import energy.trolie.client.TrolieHost; +import energy.trolie.client.impl.request.AbstractStreamingGet; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotReceiver; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.net.URIBuilder; + +import java.io.InputStream; +import java.net.URISyntaxException; +import java.util.Map; + +/** + * On-demand GET request for seasonal limits with ETAG usage + */ +public class SeasonalSnapshotRequest extends AbstractStreamingGet { + + String monitoringSet; + String resourceId; + + public SeasonalSnapshotRequest( + HttpClient httpClient, + TrolieHost host, + RequestConfig requestConfig, + int bufferSize, + ObjectMapper objectMapper, + Map httpHeaders, + SeasonalSnapshotReceiver receiver, // seasonal + String monitoringSet, + String resourceId) { + + super(httpClient, host, requestConfig, bufferSize, objectMapper, httpHeaders, receiver); + this.monitoringSet = monitoringSet; + this.resourceId = resourceId; + } + + @Override + protected String getPath() { + return TrolieApiConstants.PATH_SEASONAL_SNAPSHOT; + } + + @Override + protected String getContentType() { + return TrolieApiConstants.CONTENT_TYPE_SEASONAL_SNAPSHOT; + } + + @Override + protected HttpGet createRequest() throws URISyntaxException { + + HttpGet get = super.createRequest(); + URIBuilder uriBuilder = new URIBuilder(get.getUri()); + + if (monitoringSet != null) { + + //add the monitoring set parameter to the base URI + uriBuilder.addParameter(TrolieApiConstants.PARAM_MONITORING_SET, monitoringSet); + } + + if (resourceId != null) { + //add the resource ID parameter to the base URI + uriBuilder.addParameter(TrolieApiConstants.PARAM_RESOURCE_ID, resourceId); + } + + get.setUri(uriBuilder.build()); + return get; + } + + @Override + protected Boolean handleResponseContent(InputStream inputStream) { + return new SeasonalSnapshotResponseParser(receiver).parseResponse(inputStream, jsonFactory); + } + + +} diff --git a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java new file mode 100644 index 0000000..e73d6c7 --- /dev/null +++ b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java @@ -0,0 +1,96 @@ +package energy.trolie.client.impl.request.operatingsnapshots; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import energy.trolie.client.exception.StreamingGetConnectionException; +import energy.trolie.client.exception.StreamingGetHandlingException; +import energy.trolie.client.model.operatingsnapshots.SeasonalPeriodSnapshot; +import energy.trolie.client.model.operatingsnapshots.SeasonalSnapshotHeader; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotReceiver; +import lombok.AllArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Implementation for parsing a real-time snapshot response shared between subscribed and on-demand requests + */ +@AllArgsConstructor +public class SeasonalSnapshotResponseParser { + + private static final Logger logger = LoggerFactory.getLogger(SeasonalSnapshotResponseParser.class); + + SeasonalSnapshotReceiver receiver; // seasonal + + public Boolean parseResponse(InputStream inputStream, JsonFactory jsonFactory) { + + try (JsonParser parser = jsonFactory.createParser(inputStream);) { + + receiver.beginSnapshot(); + + //START_OBJECT forecast + parser.nextToken(); + //FIELD_NAME snapshot-header + parser.nextToken(); + //START_OBJECT header + parser.nextToken(); + + //read header + SeasonalSnapshotHeader header = parser.readValueAs(SeasonalSnapshotHeader.class); + receiver.header(header); + + //FIELD_NAME ratings + parser.nextToken(); + //START_ARRAY + parser.nextToken(); + + //for each rating + while (parser.nextToken() == JsonToken.START_OBJECT ) { + + //FIELD_NAME resource-id + parser.nextToken(); + //resource-id + parser.nextToken(); + + String id = parser.getValueAsString(); + receiver.beginResource(id); + + //FIELD_NAME periods + parser.nextToken(); + //START_ARRAY + parser.nextToken(); + + //for each period + while (parser.nextToken() == JsonToken.START_OBJECT ) { + SeasonalPeriodSnapshot period = parser.readValueAs(SeasonalPeriodSnapshot.class); + receiver.period(period); + } + //exit loop on END_ARRAY periods + + //END_OBJECT rating + parser.nextToken(); + receiver.endResource(); + + //next token will be START_OBJECT | END_ARRAY ratings + + } + //exit loop on END_ARRAY ratings + + receiver.endSnapshot(); + return true; + + } catch (IOException e) { + logger.error("I/O error handling response",e); + receiver.error(new StreamingGetConnectionException(e)); + } catch (Exception e) { + logger.error("Error handling response data",e); + receiver.error(new StreamingGetHandlingException(e)); + } + + return false; + } + +} diff --git a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotSubscribedRequest.java b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotSubscribedRequest.java new file mode 100644 index 0000000..c44169f --- /dev/null +++ b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotSubscribedRequest.java @@ -0,0 +1,75 @@ +package energy.trolie.client.impl.request.operatingsnapshots; + +import com.fasterxml.jackson.databind.ObjectMapper; +import energy.trolie.client.ETagStore; +import energy.trolie.client.TrolieApiConstants; +import energy.trolie.client.TrolieHost; +import energy.trolie.client.impl.request.AbstractStreamingSubscribedGet; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotSubscribedReceiver; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.net.URIBuilder; + +import java.io.InputStream; +import java.net.URISyntaxException; +import java.util.Map; + +/** + * subscription for seasonal rating snapshots + */ +public class SeasonalSnapshotSubscribedRequest extends AbstractStreamingSubscribedGet { + + String monitoringSet; + + public SeasonalSnapshotSubscribedRequest( + HttpClient httpClient, + TrolieHost host, + RequestConfig requestConfig, + int bufferSize, + ObjectMapper objectMapper, + Map httpHeaders, + int pollingRateMillis, + SeasonalSnapshotSubscribedReceiver receiver, + ETagStore eTagStore, + String monitoringSet) { + + super(httpClient, host, requestConfig, bufferSize, objectMapper, httpHeaders, pollingRateMillis, + receiver, eTagStore); + this.monitoringSet = monitoringSet; + } + + @Override + protected String getPath() { + return TrolieApiConstants.PATH_SEASONAL_SNAPSHOT; + } + + @Override + protected String getContentType() { + return TrolieApiConstants.CONTENT_TYPE_SEASONAL_SNAPSHOT; + } + + @Override + protected HttpGet createRequest() throws URISyntaxException { + + HttpGet get = super.createRequest(); + + if (monitoringSet != null) { + + //add the monitoring set parameter to the base URI + URIBuilder uriBuilder = new URIBuilder(get.getUri()) + .addParameter(TrolieApiConstants.PARAM_MONITORING_SET, monitoringSet); + get.setUri(uriBuilder.build()); + } + + return get; + } + + @Override + protected Boolean handleResponseContent(InputStream inputStream) { + + return new SeasonalSnapshotResponseParser(receiver).parseResponse(inputStream, jsonFactory); + + } + +} diff --git a/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java new file mode 100644 index 0000000..bacbde2 --- /dev/null +++ b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java @@ -0,0 +1,54 @@ +/* + * =========================================================================== + * + * Copyright and Proprietary Information + * + * Copyright (c) 1993, 2024 General Electric Technology GmbH. All Rights Reserved. + * + * NOTE: CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION OF GENERAL ELECTRIC + * TECHNOLOGY GMBH AND MAY NOT BE REPRODUCED, TRANSMITTED, STORED, OR COPIED IN + * WHOLE OR IN PART, OR USED TO FURNISH INFORMATION TO OTHERS, WITHOUT THE PRIOR + * WRITTEN PERMISSION OF GENERAL ELECTRIC TECHNOLOGY GMBH OR GRID SOLUTIONS. + * + * ========================================================================== + */ + +package energy.trolie.client.model.operatingsnapshots; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import energy.trolie.client.model.common.EmergencyRatingValue; +import energy.trolie.client.model.common.RatingValue; +import lombok.*; + +import java.time.Instant; +import java.util.List; + +/** + * For a given resource, represents a rating value set for a given forecast period. + */ +@ToString +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Getter +@EqualsAndHashCode +public class SeasonalPeriodSnapshot { + + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("period-start") + private Instant periodStart; + + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("period-end") + private Instant periodEnd; + + @JsonProperty("season-name") + private String seasonName; + + @JsonProperty("continuous-operating-limit") + private RatingValue continuousOperatingLimit; + + @JsonProperty("emergency-operating-limits") + private List emergencyOperatingLimits; +} diff --git a/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalSnapshotHeader.java b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalSnapshotHeader.java new file mode 100644 index 0000000..61fc3e7 --- /dev/null +++ b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalSnapshotHeader.java @@ -0,0 +1,35 @@ +/* + * =========================================================================== + * + * Copyright and Proprietary Information + * + * Copyright (c) 1993, 2024 General Electric Technology GmbH. All Rights Reserved. + * + * NOTE: CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION OF GENERAL ELECTRIC + * TECHNOLOGY GMBH AND MAY NOT BE REPRODUCED, TRANSMITTED, STORED, OR COPIED IN + * WHOLE OR IN PART, OR USED TO FURNISH INFORMATION TO OTHERS, WITHOUT THE PRIOR + * WRITTEN PERMISSION OF GENERAL ELECTRIC TECHNOLOGY GMBH OR GRID SOLUTIONS. + * + * ========================================================================== + */ + +package energy.trolie.client.model.operatingsnapshots; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import lombok.experimental.SuperBuilder; + +/** + * {@link SnapshotHeader} for real-time rating snapshots + */ +@AllArgsConstructor +@SuperBuilder +@Getter +@ToString +@EqualsAndHashCode(callSuper = true) +public class SeasonalSnapshotHeader extends SnapshotHeader { + + +} diff --git a/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotReceiver.java b/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotReceiver.java new file mode 100644 index 0000000..d5b0638 --- /dev/null +++ b/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotReceiver.java @@ -0,0 +1,60 @@ +package energy.trolie.client.request.operatingsnapshots; + +import energy.trolie.client.StreamingResponseReceiver; +import energy.trolie.client.exception.StreamingGetException; +import energy.trolie.client.model.operatingsnapshots.ForecastPeriodSnapshot; +import energy.trolie.client.model.operatingsnapshots.ForecastSnapshotHeader; +import energy.trolie.client.model.operatingsnapshots.SeasonalPeriodSnapshot; +import energy.trolie.client.model.operatingsnapshots.SeasonalSnapshotHeader; + +/** + * Streaming receiver for updated seasonal snapshot data and errors from subscriber. + * The current request handling can be terminated in any of these methods by throwing an exception. + * Errors originating from the subscriber thread will be sent to {@link #error(StreamingGetException)} + */ +public interface SeasonalSnapshotReceiver extends StreamingResponseReceiver { + + /** + * Invoked when a new snapshot is received. This will be the first method invoked when the snapshot is received. + */ + void beginSnapshot(); + + /** + * Invoked when the header has been processed. Will + * be invoked before processing resources + * @param header parsed header + */ + void header(SeasonalSnapshotHeader header); + + /** + * Invoked to indicate that a new resource has been found while parsing. + * Implementations may assume that all period ratings for this resource will + * be consumed through invocations to {@link #period(SeasonalPeriodSnapshot)} + * until {@link #endResource()} is invoked. + * @param resourceId the next resource Id. + */ + void beginResource(String resourceId); + + /** + * Invoked as a new rating value set is encountered in the stream + * @param period rating data for a given period. The resource ID + * is implied from the context, assuming the last call + * to {@link #beginResource(String)}. + */ + void period(SeasonalPeriodSnapshot period); + + /** + * Invoked when the end of a set of ratings for the current resource has been encountered. + * Users may assume that the last resource set by {@link #beginResource(String)} is no longer valid. + */ + void endResource(); + + /** + * Invoked when the snapshot has reached its end. + */ + void endSnapshot(); + +} + + + diff --git a/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java b/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java new file mode 100644 index 0000000..562f9ad --- /dev/null +++ b/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java @@ -0,0 +1,16 @@ +package energy.trolie.client.request.operatingsnapshots; + +import energy.trolie.client.StreamingSubscribedResponseReceiver; +import energy.trolie.client.exception.StreamingGetException; + +/** + * Streaming receiver for updated forecast snapshot data and errors from subscriber. + * The current request handling can be terminated in any of these methods by throwing an exception. + * Errors originating from the subscriber thread will be sent to {@link #error(StreamingGetException)} + */ +public interface SeasonalSnapshotSubscribedReceiver extends StreamingSubscribedResponseReceiver, SeasonalSnapshotReceiver { + +} + + + From 46ff573f2f40c83eb929faf5290be25d282c00cc Mon Sep 17 00:00:00 2001 From: Samuel Dumitru Date: Wed, 22 Oct 2025 13:51:32 +0300 Subject: [PATCH 2/6] [enh] added seasonal snapshot to the TrolieClientImpl --- .../energy/trolie/client/TrolieClient.java | 59 +++++++++++++-- .../trolie/client/impl/TrolieClientImpl.java | 71 +++++++++++++++---- .../SeasonalSnapshotResponseParser.java | 2 +- 3 files changed, 115 insertions(+), 17 deletions(-) diff --git a/java-client/src/main/java/energy/trolie/client/TrolieClient.java b/java-client/src/main/java/energy/trolie/client/TrolieClient.java index fc790d1..3326842 100644 --- a/java-client/src/main/java/energy/trolie/client/TrolieClient.java +++ b/java-client/src/main/java/energy/trolie/client/TrolieClient.java @@ -2,10 +2,7 @@ import energy.trolie.client.request.monitoringsets.MonitoringSetsReceiver; import energy.trolie.client.request.monitoringsets.MonitoringSetsSubscribedReceiver; -import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotReceiver; -import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotSubscribedReceiver; -import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotReceiver; -import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotSubscribedReceiver; +import energy.trolie.client.request.operatingsnapshots.*; import energy.trolie.client.request.ratingproposals.ForecastRatingProposalUpdate; import energy.trolie.client.request.ratingproposals.RealTimeRatingProposalUpdate; import lombok.NonNull; @@ -385,6 +382,60 @@ RequestSubscription subscribeToRegionalRealTimeLimits( */ RealTimeRatingProposalUpdate createRealTimeRatingProposalStreamingUpdate(); + /** + * Execute a synchronous + * request for the current seasonal limits with a streaming response handler, + * assuming this user's default monitoring set. + * + * @param receiver Streaming data receiver for snapshot data + */ + void getInUseSeasonalSnapshots( + SeasonalSnapshotReceiver receiver); + + /** + * Execute a request for the current seasonal limits with a streaming response handler + * with the given monitoring set. + * + * @param receiver Streaming data receiver for snapshot data + * @param monitoringSet filter for monitoring set name + */ + void getInUseSeasonalSnapshots( + SeasonalSnapshotReceiver receiver, + String monitoringSet); + + /** + * Execute a request for the current seasonal limits with a streaming response handler + * + * @param receiver Streaming data receiver for snapshot data + * @param monitoringSet filter for monitoring set name + * @param resourceId Only return snapshots for this power system resource + */ + void getInUseSeasonalSnapshots( + SeasonalSnapshotReceiver receiver, + String monitoringSet, + String resourceId + ); + + /** + * Create a polling subscription for seasonal limits data updates + * + * @param receiver Streaming data receiver for snapshot data + * @param monitoringSet filter for monitoring set name + * @return request handle + */ + RequestSubscription subscribeToInUseSeasonalSnapshotUpdates( + SeasonalSnapshotSubscribedReceiver receiver, + String monitoringSet); + + /** + * Create a polling subscription for seasonal snapshot data updates + * + * @param receiver Streaming data receiver for snapshot data + * @return request handle + */ + RequestSubscription subscribeToInUseSeasonalSnapshotUpdates( + SeasonalSnapshotSubscribedReceiver receiver); + /** * Un-subscribe an active polling request * diff --git a/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java b/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java index 8ba7ef2..5e838c0 100644 --- a/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java +++ b/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java @@ -10,20 +10,10 @@ import energy.trolie.client.impl.request.monitoringsets.DefaultMonitoringSetSubscribedRequest; import energy.trolie.client.impl.request.monitoringsets.MonitoringSetsRequest; import energy.trolie.client.impl.request.monitoringsets.MonitoringSetsSubscribedRequest; -import energy.trolie.client.impl.request.operatingsnapshots.ForecastSnapshotRequest; -import energy.trolie.client.impl.request.operatingsnapshots.ForecastSnapshotSubscribedRequest; -import energy.trolie.client.impl.request.operatingsnapshots.RealTimeSnapshotRequest; -import energy.trolie.client.impl.request.operatingsnapshots.RealTimeSnapshotSubscribedRequest; -import energy.trolie.client.impl.request.operatingsnapshots.RegionalForecastSnapshotRequest; -import energy.trolie.client.impl.request.operatingsnapshots.RegionalForecastSubscribedSnapshotRequest; -import energy.trolie.client.impl.request.operatingsnapshots.RegionalRealTimeSnapshotRequest; -import energy.trolie.client.impl.request.operatingsnapshots.RegionalRealTimeSnapshotSubscribedRequest; +import energy.trolie.client.impl.request.operatingsnapshots.*; import energy.trolie.client.request.monitoringsets.MonitoringSetsReceiver; import energy.trolie.client.request.monitoringsets.MonitoringSetsSubscribedReceiver; -import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotReceiver; -import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotSubscribedReceiver; -import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotReceiver; -import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotSubscribedReceiver; +import energy.trolie.client.request.operatingsnapshots.*; import energy.trolie.client.request.ratingproposals.ForecastRatingProposalUpdate; import energy.trolie.client.request.ratingproposals.RealTimeRatingProposalUpdate; import org.apache.hc.client5.http.config.RequestConfig; @@ -373,6 +363,63 @@ public DefaultMonitoringSetSubscribedRequest subscribeToDefaultMonitoringSetUpda return subscription; } + @Override + public void getInUseSeasonalSnapshots(SeasonalSnapshotReceiver receiver) { + getInUseSeasonalSnapshots(receiver, null, null); + } + + @Override + public void getInUseSeasonalSnapshots(SeasonalSnapshotReceiver receiver, String monitoringSet) { + getInUseSeasonalSnapshots(receiver, monitoringSet, null); + } + + @Override + public void getInUseSeasonalSnapshots( + SeasonalSnapshotReceiver receiver, + String monitoringSet, + String resourceId) { + + new SeasonalSnapshotRequest( + httpClient, + host, + requestConfig, + bufferSize, + objectMapper, + httpHeaders, + receiver, + monitoringSet, + resourceId).executeRequest(); + } + + @Override + public SeasonalSnapshotSubscribedRequest subscribeToInUseSeasonalSnapshotUpdates( + SeasonalSnapshotSubscribedReceiver receiver) { + return subscribeToInUseSeasonalSnapshotUpdates(receiver, null); + } + + @Override + public SeasonalSnapshotSubscribedRequest subscribeToInUseSeasonalSnapshotUpdates( + SeasonalSnapshotSubscribedReceiver receiver, + String monitoringSet) { + + SeasonalSnapshotSubscribedRequest subscription = new SeasonalSnapshotSubscribedRequest( + httpClient, + host, + requestConfig, + bufferSize, + objectMapper, + httpHeaders, + forecastRatingsPollMs, + receiver, + eTagStore, + monitoringSet); + + addSubscription(subscription); + return subscription; + + } + + @Override public void close() throws IOException { logger.info("Closing all subscriptions"); diff --git a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java index e73d6c7..e411e23 100644 --- a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java +++ b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java @@ -23,7 +23,7 @@ public class SeasonalSnapshotResponseParser { private static final Logger logger = LoggerFactory.getLogger(SeasonalSnapshotResponseParser.class); - SeasonalSnapshotReceiver receiver; // seasonal + SeasonalSnapshotReceiver receiver; public Boolean parseResponse(InputStream inputStream, JsonFactory jsonFactory) { From 0090cbfc5ea4e4b59c1806057513d2f199f19d64 Mon Sep 17 00:00:00 2001 From: Samuel Dumitru Date: Wed, 22 Oct 2025 18:03:21 +0300 Subject: [PATCH 3/6] [enh] unit tests for seasonal ratings --- .../trolie/client/TrolieClientBuilder.java | 16 +- .../trolie/client/impl/TrolieClientImpl.java | 7 +- .../energy/trolie/client/TrolieClientIT.java | 310 ++++++++++++++++++ 3 files changed, 330 insertions(+), 3 deletions(-) diff --git a/java-client/src/main/java/energy/trolie/client/TrolieClientBuilder.java b/java-client/src/main/java/energy/trolie/client/TrolieClientBuilder.java index 77988d5..0700e25 100644 --- a/java-client/src/main/java/energy/trolie/client/TrolieClientBuilder.java +++ b/java-client/src/main/java/energy/trolie/client/TrolieClientBuilder.java @@ -7,6 +7,7 @@ import energy.trolie.client.impl.TrolieClientImpl; import energy.trolie.client.request.monitoringsets.MonitoringSetsSubscribedReceiver; import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotSubscribedReceiver; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotSubscribedReceiver; import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotSubscribedReceiver; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; @@ -54,6 +55,7 @@ public class TrolieClientBuilder { private int realTimeRatingsPollMs = 10000; private int forecastRatingsPollMs = 30000; private int monitoringSetPollMs = 60000; + private int seasonalRatingsPollMs = 30000; /** * Initializes a new builder with a preconfigured apache HTTP client @@ -178,6 +180,18 @@ public TrolieClientBuilder monitoringSetPollMs(int monitoringSetPollMs) { return this; } + /** + * Sets the period at which + * {@link TrolieClient#subscribeToInUseSeasonalSnapshotUpdates(SeasonalSnapshotSubscribedReceiver)} + * and similar methods for forecast ratings poll for new ratings. Defaults to 30 seconds + * @param seasonalRatingsPollMs new poll periodicity in milliseconds + * @return fluent builder + */ + public TrolieClientBuilder seasonalRatingsPollMs(int seasonalRatingsPollMs) { + this.seasonalRatingsPollMs = seasonalRatingsPollMs; + return this; + } + /** * Construct a new client * @return new client @@ -204,6 +218,6 @@ public TrolieClient build() { return new TrolieClientImpl(httpClient, host, requestConfig, bufferSize, objectMapper, eTagStore, httpHeaders, periodLengthMinutes, realTimeRatingsPollMs, - forecastRatingsPollMs, monitoringSetPollMs); + forecastRatingsPollMs, monitoringSetPollMs, seasonalRatingsPollMs); } } diff --git a/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java b/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java index 5e838c0..0bacaf3 100644 --- a/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java +++ b/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java @@ -44,13 +44,15 @@ public class TrolieClientImpl implements TrolieClient { private final int realTimeRatingsPollMs; private final int forecastRatingsPollMs; private final int monitoringSetPollMs; + private final int seasonalRatingsPollMs; public TrolieClientImpl(CloseableHttpClient httpClient, TrolieHost host, RequestConfig requestConfig, int bufferSize, ObjectMapper objectMapper, ETagStore eTagStore, Map httpHeaders, int defaultIntervalMinutes, int realTimeRatingsPollMs, int forecastRatingsPollMs, - int monitoringSetPollMs) { + int monitoringSetPollMs, + int seasonalRatingsPollMs) { super(); this.httpClient = httpClient; this.host = host; @@ -63,6 +65,7 @@ public TrolieClientImpl(CloseableHttpClient httpClient, TrolieHost host, Request this.realTimeRatingsPollMs = realTimeRatingsPollMs; this.forecastRatingsPollMs = forecastRatingsPollMs; this.monitoringSetPollMs = monitoringSetPollMs; + this.seasonalRatingsPollMs = seasonalRatingsPollMs; } final Set activeSubscriptions = new HashSet<>(); @@ -409,7 +412,7 @@ public SeasonalSnapshotSubscribedRequest subscribeToInUseSeasonalSnapshotUpdates bufferSize, objectMapper, httpHeaders, - forecastRatingsPollMs, + seasonalRatingsPollMs, receiver, eTagStore, monitoringSet); diff --git a/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java b/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java index 5fb5c75..0193f06 100644 --- a/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java +++ b/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java @@ -15,6 +15,8 @@ import energy.trolie.client.model.operatingsnapshots.ForecastSnapshotHeader; import energy.trolie.client.model.operatingsnapshots.RealTimeLimit; import energy.trolie.client.model.operatingsnapshots.RealTimeSnapshotHeader; +import energy.trolie.client.model.operatingsnapshots.SeasonalPeriodSnapshot; +import energy.trolie.client.model.operatingsnapshots.SeasonalSnapshotHeader; import energy.trolie.client.model.ratingproposals.ForecastProposalHeader; import energy.trolie.client.model.ratingproposals.ForecastRatingPeriod; import energy.trolie.client.model.ratingproposals.ForecastRatingProposalStatus; @@ -27,6 +29,8 @@ import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotSubscribedReceiver; import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotReceiver; import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotSubscribedReceiver; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotReceiver; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotSubscribedReceiver; import energy.trolie.client.request.ratingproposals.ForecastRatingProposalUpdate; import energy.trolie.client.request.ratingproposals.RealTimeRatingProposalUpdate; import lombok.extern.slf4j.Slf4j; @@ -1518,6 +1522,274 @@ public void setSubscription(RequestSubscription subscription) { } } + @Test + void testSeasonalSnapshotGet() throws Exception { + + Instant startTime = Instant.now(); + String season = "FALL"; // this should get automatically by date? + + requestHandler = request -> { + + BasicClassicHttpResponse response = new BasicClassicHttpResponse(200); + + try { + + //we expect to get the monitoring set name as a query param + Assertions.assertEquals( + TrolieApiConstants.PARAM_MONITORING_SET + "=abc", + request.getUri().getQuery()); + + //on 1st and 3rd request, return a new snapshot to indicate an update + PipedOutputStream out = new PipedOutputStream(); + PipedInputStream in = new PipedInputStream(out); + + response.setEntity( + new GzipCompressingEntity(new InputStreamEntity(in,ContentType.create(TrolieApiConstants.CONTENT_TYPE_SEASONAL_SNAPSHOT)))); + response.addHeader(HttpHeaders.CONTENT_ENCODING, "gzip"); + threadPoolExecutor.submit(new Callable() { + @Override + public Void call() throws Exception { + + try (JsonGenerator json = new JsonFactory(objectMapper).createGenerator(out)) { + + writeSeasonalSnapshot(json, startTime, season); + + return null; + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + }); + + } catch (Exception e) { + e.printStackTrace(); + response.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR); + } + + return response; + }; + + + HttpClientBuilder builder = HttpClientBuilder.create(); + try (TrolieClient trolieClient = new TrolieClientBuilder(baseUri,builder.build()).build();) { + + AtomicInteger snapshotsReceived = new AtomicInteger(0); + AtomicInteger errorCount = new AtomicInteger(0); + + //subscribe for snapshots and validate they are transmitted correctly + trolieClient.getInUseSeasonalSnapshots(new SeasonalSnapshotReceiver() { + + int numResources; + int numPeriods; + + @Override + public void header(SeasonalSnapshotHeader header) { + Assertions.assertNotNull(header); + + } + + + @Override + public void endSnapshot() { + Assertions.assertEquals(100, numResources); + numResources = 0; + } + + @Override + public void beginSnapshot() { + snapshotsReceived.incrementAndGet(); + } + + @Override + public void error(StreamingGetException t) { + errorCount.incrementAndGet(); + } + + + @Override + public void beginResource(String resourceId) { + numResources++; + } + + + @Override + public void period(SeasonalPeriodSnapshot period) { + + Assertions.assertEquals( season, period.getSeasonName()); + numPeriods++; + } + + + @Override + public void endResource() { + Assertions.assertEquals(24, numPeriods); + numPeriods = 0; + } + + + }, "abc", null); + + Assertions.assertEquals(1, snapshotsReceived.get()); + Assertions.assertEquals(0, errorCount.get()); + + } + } + + @Test + void testSeasonalSnapshotSubscription() throws Exception { + + //we will run the subscription for fixed number of requests + AtomicInteger requestCounter = new AtomicInteger(0); + Instant startTime = Instant.now(); + String season = "FALL"; + String etag = UUID.randomUUID().toString(); + + requestHandler = request -> { + + BasicClassicHttpResponse response = new BasicClassicHttpResponse(200); + + try { + + //we expect to get the configured monitoring set name as a query param + Assertions.assertEquals("monitoring-set=abc", request.getUri().getQuery()); + + Header requestEtag = request.getHeader(HttpHeaders.IF_NONE_MATCH); + + //2nd+ request should have an etag header + if (requestCounter.get() > 0) { + Assertions.assertNotNull(requestEtag); + Assertions.assertEquals(etag, requestEtag.getValue()); + } + + if (requestCounter.get() == 3) { + + //on 4th request return error to test error propagation to receiver + response.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR); + + } else if (requestCounter.get() % 2 == 0) { + + //on 1st and 3rd request, return a new snapshot to indicate an update + PipedOutputStream out = new PipedOutputStream(); + PipedInputStream in = new PipedInputStream(out); + + response.setHeader(HttpHeaders.ETAG, etag); + response.setEntity( + new GzipCompressingEntity(new InputStreamEntity(in,ContentType.create(TrolieApiConstants.CONTENT_TYPE_SEASONAL_SNAPSHOT)))); + response.addHeader(HttpHeaders.CONTENT_ENCODING, "gzip"); + threadPoolExecutor.submit(new Callable() { + @Override + public Void call() throws Exception { + + try (JsonGenerator json = new JsonFactory(objectMapper).createGenerator(out)) { + writeSeasonalSnapshot(json, startTime, season ); + return null; + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + }); + + } else { + + //on 2nd request, indicate existing etag is valid to test that request is short-circuited + response.setCode(HttpStatus.SC_NOT_MODIFIED); + } + + } catch (Exception e) { + e.printStackTrace(); + response.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR); + } finally { + requestCounter.incrementAndGet(); + } + + return response; + }; + + + HttpClientBuilder builder = HttpClientBuilder.create(); + try (TrolieClient trolieClient = new TrolieClientBuilder(baseUri,builder.build()) + .seasonalRatingsPollMs(200) + .build();) { + + AtomicInteger snapshotsReceived = new AtomicInteger(0); + AtomicInteger errorCount = new AtomicInteger(0); + + //subscribe for snapshots and validate they are transmitted correctly + var subscription = trolieClient.subscribeToInUseSeasonalSnapshotUpdates(new SeasonalSnapshotSubscribedReceiver() { + + RequestSubscription subscription; + int numResources; + int numPeriods; + + @Override + public void period(SeasonalPeriodSnapshot period) { + numPeriods++; + Assertions.assertEquals(season, period.getSeasonName()); + + } + + @Override + public void header(SeasonalSnapshotHeader header) { + + Assertions.assertNotNull(header); + } + + @Override + public void endSnapshot() { + Assertions.assertEquals(100, numResources); + numResources = 0; + } + + @Override + public void endResource() { + Assertions.assertEquals(24, numPeriods); + numPeriods = 0; + } + + @Override + public void beginSnapshot() { + snapshotsReceived.incrementAndGet(); + } + + @Override + public void beginResource(String resourceId) { + numResources++; + } + + @Override + public void error(StreamingGetException t) { + errorCount.incrementAndGet(); + ((RequestSubscriptionInternal)subscription).stop(); + } + + @Override + public void setSubscription(RequestSubscription subscription) { + this.subscription = subscription; + } + + + }, "abc"); + int counter = 0; + while (subscription.isSubscribed()) { + Thread.sleep(100); + if(subscription.isHealthy()){ +// log.info("Subscription is healthy"); + counter++; + } else { + log.warn("Subscription is not healthy"); + } + assertTrue(subscription.isHealthy()); + } + + //we should have received 2 snapshots, 1 304 code and 1 500 code + Assertions.assertEquals(2, snapshotsReceived.get()); + Assertions.assertEquals(1, errorCount.get()); + } + } + private void writeMonitoringSet(JsonGenerator json, String id) throws IOException { var source = DataProvenance.builder().provider(id).lastUpdated( Instant.now()).originId(id).build(); @@ -1594,4 +1866,42 @@ private void writeRealTimeSnapshot(JsonGenerator json) throws IOException { json.writeEndArray(); json.writeEndObject(); } + + private void writeSeasonalSnapshot(JsonGenerator json, Instant startTime, String season) throws IOException { + + SeasonalSnapshotHeader header = new SeasonalSnapshotHeader(); + + json.writeStartObject(); + + json.writeFieldName("snapshot-header"); + json.writeObject(header); + + json.writeFieldName("ratings"); + json.writeStartArray(); + + for (int i=0;i<100;i++) { + json.writeStartObject(); + json.writeFieldName("resource-id"); + json.writeString("resource" + i); + json.writeFieldName("periods"); + json.writeStartArray(); + for (int j=0;j<24;j++) { + SeasonalPeriodSnapshot period = new SeasonalPeriodSnapshot( + startTime, + startTime, + season, + RatingValue.fromMva(100f), + Collections.emptyList() + ); + json.writeObject(period); + } + json.writeEndArray(); + json.writeEndObject(); + } + + json.writeEndArray(); + json.writeEndObject(); + + } + } From ec8154c44595c2be85b46d7d3ec8568df79ac4eb Mon Sep 17 00:00:00 2001 From: Samuel Dumitru Date: Thu, 23 Oct 2025 13:46:31 +0300 Subject: [PATCH 4/6] [enh] investigating subscription test --- .../java/energy/trolie/client/TrolieClientIT.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java b/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java index 0193f06..747a61f 100644 --- a/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java +++ b/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java @@ -80,9 +80,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; @Slf4j @SuppressWarnings("unchecked") @@ -1626,8 +1624,6 @@ public void endResource() { Assertions.assertEquals(24, numPeriods); numPeriods = 0; } - - }, "abc", null); Assertions.assertEquals(1, snapshotsReceived.get()); @@ -1775,13 +1771,6 @@ public void setSubscription(RequestSubscription subscription) { int counter = 0; while (subscription.isSubscribed()) { Thread.sleep(100); - if(subscription.isHealthy()){ -// log.info("Subscription is healthy"); - counter++; - } else { - log.warn("Subscription is not healthy"); - } - assertTrue(subscription.isHealthy()); } //we should have received 2 snapshots, 1 304 code and 1 500 code From df4d760c6a514b2bb7494b8e44aa29967c164f31 Mon Sep 17 00:00:00 2001 From: Samuel Dumitru Date: Thu, 23 Oct 2025 14:48:59 +0300 Subject: [PATCH 5/6] [enh] fixing comments --- .../src/main/java/energy/trolie/client/TrolieApiConstants.java | 2 +- .../operatingsnapshots/SeasonalSnapshotResponseParser.java | 2 +- .../client/model/operatingsnapshots/SeasonalPeriodSnapshot.java | 2 +- .../client/model/operatingsnapshots/SeasonalSnapshotHeader.java | 2 +- .../operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-client/src/main/java/energy/trolie/client/TrolieApiConstants.java b/java-client/src/main/java/energy/trolie/client/TrolieApiConstants.java index cd6dd6d..194cba1 100644 --- a/java-client/src/main/java/energy/trolie/client/TrolieApiConstants.java +++ b/java-client/src/main/java/energy/trolie/client/TrolieApiConstants.java @@ -9,7 +9,7 @@ private TrolieApiConstants() { } /** - * Path to getRealTimeLimits + * Path to getSeasonalRatings */ public static final String PATH_SEASONAL_SNAPSHOT = "/seasonal-ratings/snapshot"; diff --git a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java index e411e23..4f7925f 100644 --- a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java +++ b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java @@ -31,7 +31,7 @@ public Boolean parseResponse(InputStream inputStream, JsonFactory jsonFactory) { receiver.beginSnapshot(); - //START_OBJECT forecast + //START_OBJECT seasonal parser.nextToken(); //FIELD_NAME snapshot-header parser.nextToken(); diff --git a/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java index bacbde2..1fb16ef 100644 --- a/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java +++ b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java @@ -25,7 +25,7 @@ import java.util.List; /** - * For a given resource, represents a rating value set for a given forecast period. + * For a given resource, represents a rating value set for a given season. */ @ToString @AllArgsConstructor diff --git a/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalSnapshotHeader.java b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalSnapshotHeader.java index 61fc3e7..7449653 100644 --- a/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalSnapshotHeader.java +++ b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalSnapshotHeader.java @@ -22,7 +22,7 @@ import lombok.experimental.SuperBuilder; /** - * {@link SnapshotHeader} for real-time rating snapshots + * {@link SnapshotHeader} for seasonal rating snapshots */ @AllArgsConstructor @SuperBuilder diff --git a/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java b/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java index 562f9ad..5f5b4cd 100644 --- a/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java +++ b/java-client/src/main/java/energy/trolie/client/request/operatingsnapshots/SeasonalSnapshotSubscribedReceiver.java @@ -4,7 +4,7 @@ import energy.trolie.client.exception.StreamingGetException; /** - * Streaming receiver for updated forecast snapshot data and errors from subscriber. + * Streaming receiver for updated seasonal snapshot data and errors from subscriber. * The current request handling can be terminated in any of these methods by throwing an exception. * Errors originating from the subscriber thread will be sent to {@link #error(StreamingGetException)} */ From a192f85136f44db1bc27523f06004f5ba194d7fe Mon Sep 17 00:00:00 2001 From: Samuel Dumitru Date: Thu, 30 Oct 2025 11:18:50 +0200 Subject: [PATCH 6/6] [enh] fixing comments and imports --- .../energy/trolie/client/TrolieClient.java | 7 ++++++- .../trolie/client/impl/TrolieClientImpl.java | 18 ++++++++++++++++-- .../SeasonalSnapshotResponseParser.java | 2 +- .../SeasonalPeriodSnapshot.java | 7 ++++++- .../energy/trolie/client/TrolieClientIT.java | 6 ++++-- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/java-client/src/main/java/energy/trolie/client/TrolieClient.java b/java-client/src/main/java/energy/trolie/client/TrolieClient.java index 3326842..17b895b 100644 --- a/java-client/src/main/java/energy/trolie/client/TrolieClient.java +++ b/java-client/src/main/java/energy/trolie/client/TrolieClient.java @@ -2,7 +2,12 @@ import energy.trolie.client.request.monitoringsets.MonitoringSetsReceiver; import energy.trolie.client.request.monitoringsets.MonitoringSetsSubscribedReceiver; -import energy.trolie.client.request.operatingsnapshots.*; +import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotReceiver; +import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotSubscribedReceiver; +import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotReceiver; +import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotSubscribedReceiver; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotReceiver; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotSubscribedReceiver; import energy.trolie.client.request.ratingproposals.ForecastRatingProposalUpdate; import energy.trolie.client.request.ratingproposals.RealTimeRatingProposalUpdate; import lombok.NonNull; diff --git a/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java b/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java index 0bacaf3..807c92e 100644 --- a/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java +++ b/java-client/src/main/java/energy/trolie/client/impl/TrolieClientImpl.java @@ -10,10 +10,24 @@ import energy.trolie.client.impl.request.monitoringsets.DefaultMonitoringSetSubscribedRequest; import energy.trolie.client.impl.request.monitoringsets.MonitoringSetsRequest; import energy.trolie.client.impl.request.monitoringsets.MonitoringSetsSubscribedRequest; -import energy.trolie.client.impl.request.operatingsnapshots.*; +import energy.trolie.client.impl.request.operatingsnapshots.ForecastSnapshotRequest; +import energy.trolie.client.impl.request.operatingsnapshots.ForecastSnapshotSubscribedRequest; +import energy.trolie.client.impl.request.operatingsnapshots.RealTimeSnapshotRequest; +import energy.trolie.client.impl.request.operatingsnapshots.RealTimeSnapshotSubscribedRequest; +import energy.trolie.client.impl.request.operatingsnapshots.RegionalForecastSnapshotRequest; +import energy.trolie.client.impl.request.operatingsnapshots.RegionalForecastSubscribedSnapshotRequest; +import energy.trolie.client.impl.request.operatingsnapshots.RegionalRealTimeSnapshotRequest; +import energy.trolie.client.impl.request.operatingsnapshots.RegionalRealTimeSnapshotSubscribedRequest; +import energy.trolie.client.impl.request.operatingsnapshots.SeasonalSnapshotRequest; +import energy.trolie.client.impl.request.operatingsnapshots.SeasonalSnapshotSubscribedRequest; import energy.trolie.client.request.monitoringsets.MonitoringSetsReceiver; import energy.trolie.client.request.monitoringsets.MonitoringSetsSubscribedReceiver; -import energy.trolie.client.request.operatingsnapshots.*; +import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotReceiver; +import energy.trolie.client.request.operatingsnapshots.ForecastSnapshotSubscribedReceiver; +import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotReceiver; +import energy.trolie.client.request.operatingsnapshots.RealTimeSnapshotSubscribedReceiver; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotReceiver; +import energy.trolie.client.request.operatingsnapshots.SeasonalSnapshotSubscribedReceiver; import energy.trolie.client.request.ratingproposals.ForecastRatingProposalUpdate; import energy.trolie.client.request.ratingproposals.RealTimeRatingProposalUpdate; import org.apache.hc.client5.http.config.RequestConfig; diff --git a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java index 4f7925f..21b4683 100644 --- a/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java +++ b/java-client/src/main/java/energy/trolie/client/impl/request/operatingsnapshots/SeasonalSnapshotResponseParser.java @@ -16,7 +16,7 @@ import java.io.InputStream; /** - * Implementation for parsing a real-time snapshot response shared between subscribed and on-demand requests + * Implementation for parsing a seasonal snapshot response shared between subscribed and on-demand requests */ @AllArgsConstructor public class SeasonalSnapshotResponseParser { diff --git a/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java index 1fb16ef..fcd6df7 100644 --- a/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java +++ b/java-client/src/main/java/energy/trolie/client/model/operatingsnapshots/SeasonalPeriodSnapshot.java @@ -19,7 +19,12 @@ import com.fasterxml.jackson.annotation.JsonProperty; import energy.trolie.client.model.common.EmergencyRatingValue; import energy.trolie.client.model.common.RatingValue; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; import java.time.Instant; import java.util.List; diff --git a/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java b/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java index 747a61f..688252b 100644 --- a/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java +++ b/java-client/src/test/java/energy/trolie/client/TrolieClientIT.java @@ -80,7 +80,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; @Slf4j @SuppressWarnings("unchecked") @@ -1524,7 +1526,7 @@ public void setSubscription(RequestSubscription subscription) { void testSeasonalSnapshotGet() throws Exception { Instant startTime = Instant.now(); - String season = "FALL"; // this should get automatically by date? + String season = "FALL"; requestHandler = request -> {