From 7e541e1f960a4dba075d7cb9cf0dc13ec78407b0 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Tue, 30 Jun 2026 14:44:59 -0700 Subject: [PATCH 1/5] Add example files for level endpoints. Add example loading methods to ApiServlet to read example files and add content to specified endpoints. --- .../src/main/java/cwms/cda/ApiServlet.java | 106 ++++++++++++++++-- .../data/levels/levels_constant_create.json | 9 ++ .../data/levels/levels_seasonal_create.json | 21 ++++ .../data/levels/levels_timeseries_create.json | 9 ++ .../data/levels/levels_virtual_create.json | 28 +++++ 5 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_constant_create.json create mode 100644 cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_seasonal_create.json create mode 100644 cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json create mode 100644 cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_virtual_create.json diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java index bc4d6f2dfa..0608607ca0 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java @@ -24,7 +24,6 @@ package cwms.cda; -import cwms.cda.api.PublishedController; import static cwms.cda.api.Controllers.CONTRACT_NAME; import static cwms.cda.api.Controllers.LOCATION_ID; import static cwms.cda.api.Controllers.NAME; @@ -78,13 +77,13 @@ import cwms.cda.api.PoolController; import cwms.cda.api.ProjectController; import cwms.cda.api.PropertyController; +import cwms.cda.api.PublishedController; import cwms.cda.api.SpecifiedLevelController; import cwms.cda.api.StandardTextController; import cwms.cda.api.StateController; import cwms.cda.api.StreamController; import cwms.cda.api.StreamLocationController; import cwms.cda.api.StreamReachController; -import cwms.cda.api.VerticalDatumController; import cwms.cda.api.TextTimeSeriesController; import cwms.cda.api.TextTimeSeriesValueController; import cwms.cda.api.TimeSeriesCategoryController; @@ -100,6 +99,7 @@ import cwms.cda.api.TurbineController; import cwms.cda.api.UnitsController; import cwms.cda.api.UpstreamLocationsGetController; +import cwms.cda.api.VerticalDatumController; import cwms.cda.api.auth.ApiKeyController; import cwms.cda.api.auth.users.UserProfileController; import cwms.cda.api.auth.users.UsersController; @@ -169,12 +169,22 @@ import cwms.cda.api.watersupply.WaterUserUpdateController; import cwms.cda.data.dao.JooqDao; import cwms.cda.data.dao.rss.QueueManager; +import cwms.cda.data.dto.CwmsDTOBase; +import cwms.cda.data.dto.csv.CwmsCsvDTO; +import cwms.cda.data.dto.locationlevel.ConstantLocationLevel; +import cwms.cda.data.dto.locationlevel.LocationLevel; +import cwms.cda.data.dto.locationlevel.SeasonalLocationLevel; +import cwms.cda.data.dto.locationlevel.TimeSeriesLocationLevel; +import cwms.cda.data.dto.locationlevel.VirtualLocationLevel; import cwms.cda.formatters.Formats; +import cwms.cda.formatters.csv.CsvExampleGenerator; import cwms.cda.security.Authenticator; import cwms.cda.security.CdaAccessManager; import cwms.cda.security.DataApiPrincipal; import cwms.cda.security.MissingRolesException; import cwms.cda.security.Role; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ScanResult; import io.javalin.Javalin; import io.javalin.apibuilder.CrudFunction; import io.javalin.apibuilder.CrudHandler; @@ -185,16 +195,14 @@ import io.javalin.core.validation.JavalinValidation; import io.javalin.http.BadRequestResponse; import io.javalin.http.Handler; -import io.javalin.http.HttpResponseException; import io.javalin.http.JavalinServlet; -import cwms.cda.data.dto.csv.CwmsCsvDTO; -import cwms.cda.formatters.csv.CsvExampleGenerator; import io.javalin.plugin.openapi.OpenApiOptions; import io.javalin.plugin.openapi.OpenApiPlugin; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.responses.ApiResponse; @@ -203,6 +211,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -223,13 +232,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; +import org.apache.commons.io.IOUtils; import org.apache.http.entity.ContentType; import org.jetbrains.annotations.NotNull; import org.jooq.exception.DataAccessException; import org.owasp.html.HtmlPolicyBuilder; import org.owasp.html.PolicyFactory; -import io.github.classgraph.ClassGraph; -import io.github.classgraph.ScanResult; /** @@ -1004,8 +1012,8 @@ private void getOpenApiOptions(JavalinConfig config) { ); }) .activateAnnotationScanningFor("cwms.cda.api"); + addEndpointExamples(ops); config.registerPlugin(new OpenApiPlugin(ops)); - } private static void setSecurityRequirements(String key, PathItem path,List secReqs) { @@ -1059,4 +1067,86 @@ public static String officeFromContext(String contextPath) { return System.getProperty(DEFAULT_OFFICE_KEY, office).toUpperCase(); } + // Enum to define example configurations by endpoint + // Add examples here for other endpoints + private enum EndpointExamples { + LEVELS(Arrays.asList( + new ExampleConfig(LocationLevel.class, "Constant Location Level", + ConstantLocationLevel.class, "cwms/cda/data/levels/levels_constant_create.json"), + new ExampleConfig(LocationLevel.class, "Seasonal Location Level", + SeasonalLocationLevel.class, "cwms/cda/data/levels/levels_seasonal_create.json"), + new ExampleConfig(LocationLevel.class, "Timeseries Location Level", + TimeSeriesLocationLevel.class, "cwms/cda/data/levels/levels_timeseries_create.json"), + new ExampleConfig(LocationLevel.class, "Virtual Location Level", + VirtualLocationLevel.class, "cwms/cda/data/levels/levels_virtual_create.json") + )); + // Add more endpoints as needed + + private final List examples; + + EndpointExamples(List examples) { + this.examples = examples; + } + + public List getExamples() { + return examples; + } + } + + /** + * Method to add specific input examples to API endpoints as defaults. + * Can be overridden with controller annotations. + * Primarily for use with endpoints that accept multiple classes as input and cannot be represented via annotations. + * Current annotation limitations are due to legacy Javalin library. + * + * @param ops the OpenApiOptions object to add the examples to. + */ + private static void addEndpointExamples(OpenApiOptions ops) { + String swaggerPath = "/swagger-docs"; + for (EndpointExamples endpoint : EndpointExamples.values()) { + endpoint.getExamples().forEach(config -> + ops.path(swaggerPath) + .addExample(config.targetClass, config.displayName, + buildExample(config.exampleClass, config.resourcePath)) + ); + } + } + + /** + * Builds an example object for the given class and resource path. + * @param exampleClass the class of the example object + * @param path the path to the example resource + * @return Example object + */ + private static Example buildExample(Class exampleClass, String path) { + cwms.cda.formatters.ContentType contentType = Formats.parseHeader(Formats.JSON, exampleClass); + Example example = new Example(); + try (InputStream stream = ApiServlet.class.getClassLoader().getResourceAsStream(path)) { + if (stream == null) { + throw new IllegalArgumentException("Unable to find example file: " + path); + } + String ex = IOUtils.toString(stream, StandardCharsets.UTF_8); + ex = Formats.format(contentType, Formats.parseContent(contentType, ex, exampleClass)); + example.value(ex); + } catch (IOException ex) { + throw new IllegalStateException("Unable to load example file: " + path, ex); + } + return example; + } + + // Data class to define an example configuration + private static class ExampleConfig { + final Class targetClass; + final String displayName; + final Class exampleClass; + final String resourcePath; + + ExampleConfig(Class targetClass, String displayName, + Class exampleClass, String resourcePath) { + this.targetClass = targetClass; + this.displayName = displayName; + this.exampleClass = exampleClass; + this.resourcePath = resourcePath; + } + } } diff --git a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_constant_create.json b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_constant_create.json new file mode 100644 index 0000000000..c93cca2a0f --- /dev/null +++ b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_constant_create.json @@ -0,0 +1,9 @@ +{ + "constant-value": 10, + "level-units-id": "ft", + "level-date": "2008-12-03T10:15:30+01:00[UTC]", + "level-comment": "Lowest Point", + "interpolate-string": "F", + "location-level-id": "Sacramento.Elev.Inst.0.Bottom of Inlet", + "office-id": "LRL" +} \ No newline at end of file diff --git a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_seasonal_create.json b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_seasonal_create.json new file mode 100644 index 0000000000..fb2588a891 --- /dev/null +++ b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_seasonal_create.json @@ -0,0 +1,21 @@ +{ + "seasonal-values": [ + { + "value": 10, + "offset-minutes": 0, + "offset-months": 0 + }, { + "value": 15, + "offset-minutes": 0, + "offset-months": 1 + } + ], + "level-units-id": "ft", + "level-date": "2008-12-03T10:15:30+01:00[UTC]", + "level-comment": "Lowest Point", + "interval-origin": "2008-12-03T10:15:30+01:00[UTC]", + "interval-months": 1, + "interpolate-string": "F", + "location-level-id": "Sacramento.Elev.Inst.0.Bottom of Inlet", + "office-id": "LRL" +} \ No newline at end of file diff --git a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json new file mode 100644 index 0000000000..1adea52805 --- /dev/null +++ b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json @@ -0,0 +1,9 @@ +{ + "seasonal-time-series-id": "RYAN3.Stage.Inst.5Minutes.0.ZSTORE_TS_TEST630", + "level-units-id":"ft", + "level-date":"2008-12-03T10:15:30+01:00[UTC]", + "level-comment":"for testing purposes", + "interpolate-string":"false", + "location-level-id":"LOC_TEST.Elev.Inst.0.Bottom of Inlet", + "office-id":"LRL" +} \ No newline at end of file diff --git a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_virtual_create.json b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_virtual_create.json new file mode 100644 index 0000000000..2cf3909a9e --- /dev/null +++ b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_virtual_create.json @@ -0,0 +1,28 @@ +{ + "office-id": "SPK", + "location-level-id": "Sacramento.Stage.Ave.1Day.Top of Normal", + "specified-level-id": "Top of Normal", + "parameter-id": "Stage", + "attribute-value": 12.5, + "attribute-units-id": "ft", + "attribute-parameter-id": "Stage", + "attribute-parameter-type-id": "Inst", + "level-units-id": "ft", + "level-date": "2023-06-01T00:00:00-07:00", + "expiration-date": "2025-06-01T00:00:00-07:00", + "constituents": [ + { + "type": "LOCATION_LEVEL", + "abbr": "L1", + "name": "Sonoma.Stage.Ave.1Day.Top of Normal", + "attribute-id": "Stage", + "attribute-value": 16.5 + }, + { + "type": "RATING", + "abbr": "R1", + "name": "Sacramento.Stage;Flow.COE.Production" + } + ], + "constituent-connections": "L1=R1I1" +} \ No newline at end of file From d3b7bed2e2ab98254dcc84a4a7bab919bdda762c Mon Sep 17 00:00:00 2001 From: zack-rma Date: Wed, 1 Jul 2026 15:10:09 -0700 Subject: [PATCH 2/5] Moved OpenAPI endpoint examples classes and helper methods to new openapi package. Updated example data. --- .../src/main/java/cwms/cda/ApiServlet.java | 84 +---------- .../java/cwms/cda/openapi/ExampleUtils.java | 132 ++++++++++++++++++ .../cda/api/levels_timeseries_create.json | 14 +- 3 files changed, 140 insertions(+), 90 deletions(-) create mode 100644 cwms-data-api/src/main/java/cwms/cda/openapi/ExampleUtils.java diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java index 0608607ca0..e7f735d60e 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java @@ -31,6 +31,7 @@ import static cwms.cda.api.Controllers.PROJECT_ID; import static cwms.cda.api.Controllers.RATING_ID; import static cwms.cda.api.Controllers.WATER_USER; +import static cwms.cda.openapi.ExampleUtils.addEndpointExamples; import static io.javalin.apibuilder.ApiBuilder.crud; import static io.javalin.apibuilder.ApiBuilder.delete; import static io.javalin.apibuilder.ApiBuilder.get; @@ -1066,87 +1067,4 @@ public static String officeFromContext(String contextPath) { } return System.getProperty(DEFAULT_OFFICE_KEY, office).toUpperCase(); } - - // Enum to define example configurations by endpoint - // Add examples here for other endpoints - private enum EndpointExamples { - LEVELS(Arrays.asList( - new ExampleConfig(LocationLevel.class, "Constant Location Level", - ConstantLocationLevel.class, "cwms/cda/data/levels/levels_constant_create.json"), - new ExampleConfig(LocationLevel.class, "Seasonal Location Level", - SeasonalLocationLevel.class, "cwms/cda/data/levels/levels_seasonal_create.json"), - new ExampleConfig(LocationLevel.class, "Timeseries Location Level", - TimeSeriesLocationLevel.class, "cwms/cda/data/levels/levels_timeseries_create.json"), - new ExampleConfig(LocationLevel.class, "Virtual Location Level", - VirtualLocationLevel.class, "cwms/cda/data/levels/levels_virtual_create.json") - )); - // Add more endpoints as needed - - private final List examples; - - EndpointExamples(List examples) { - this.examples = examples; - } - - public List getExamples() { - return examples; - } - } - - /** - * Method to add specific input examples to API endpoints as defaults. - * Can be overridden with controller annotations. - * Primarily for use with endpoints that accept multiple classes as input and cannot be represented via annotations. - * Current annotation limitations are due to legacy Javalin library. - * - * @param ops the OpenApiOptions object to add the examples to. - */ - private static void addEndpointExamples(OpenApiOptions ops) { - String swaggerPath = "/swagger-docs"; - for (EndpointExamples endpoint : EndpointExamples.values()) { - endpoint.getExamples().forEach(config -> - ops.path(swaggerPath) - .addExample(config.targetClass, config.displayName, - buildExample(config.exampleClass, config.resourcePath)) - ); - } - } - - /** - * Builds an example object for the given class and resource path. - * @param exampleClass the class of the example object - * @param path the path to the example resource - * @return Example object - */ - private static Example buildExample(Class exampleClass, String path) { - cwms.cda.formatters.ContentType contentType = Formats.parseHeader(Formats.JSON, exampleClass); - Example example = new Example(); - try (InputStream stream = ApiServlet.class.getClassLoader().getResourceAsStream(path)) { - if (stream == null) { - throw new IllegalArgumentException("Unable to find example file: " + path); - } - String ex = IOUtils.toString(stream, StandardCharsets.UTF_8); - ex = Formats.format(contentType, Formats.parseContent(contentType, ex, exampleClass)); - example.value(ex); - } catch (IOException ex) { - throw new IllegalStateException("Unable to load example file: " + path, ex); - } - return example; - } - - // Data class to define an example configuration - private static class ExampleConfig { - final Class targetClass; - final String displayName; - final Class exampleClass; - final String resourcePath; - - ExampleConfig(Class targetClass, String displayName, - Class exampleClass, String resourcePath) { - this.targetClass = targetClass; - this.displayName = displayName; - this.exampleClass = exampleClass; - this.resourcePath = resourcePath; - } - } } diff --git a/cwms-data-api/src/main/java/cwms/cda/openapi/ExampleUtils.java b/cwms-data-api/src/main/java/cwms/cda/openapi/ExampleUtils.java new file mode 100644 index 0000000000..a801ce5f01 --- /dev/null +++ b/cwms-data-api/src/main/java/cwms/cda/openapi/ExampleUtils.java @@ -0,0 +1,132 @@ +/* + * + * MIT License + * + * Copyright (c) 2026 Hydrologic Engineering Center + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE + * SOFTWARE. + */ + +package cwms.cda.openapi; + +import cwms.cda.ApiServlet; +import cwms.cda.data.dto.CwmsDTOBase; +import cwms.cda.data.dto.locationlevel.ConstantLocationLevel; +import cwms.cda.data.dto.locationlevel.LocationLevel; +import cwms.cda.data.dto.locationlevel.SeasonalLocationLevel; +import cwms.cda.data.dto.locationlevel.TimeSeriesLocationLevel; +import cwms.cda.data.dto.locationlevel.VirtualLocationLevel; +import cwms.cda.formatters.Formats; +import io.javalin.plugin.openapi.OpenApiOptions; +import io.swagger.v3.oas.models.examples.Example; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.List; +import org.apache.commons.io.IOUtils; + +public final class ExampleUtils { + private ExampleUtils() { + throw new IllegalStateException("Utility class"); + } + + /** + * Method to add specific input examples to API endpoints as defaults. + * Can be overridden with controller annotations. + * Primarily for use with endpoints that accept multiple classes as input and cannot be represented via annotations. + * Current annotation limitations are due to legacy Javalin library. + * + * @param ops the OpenApiOptions object to add the examples to. + */ + public static void addEndpointExamples(OpenApiOptions ops) { + String swaggerPath = "/swagger-docs"; + for (EndpointExamples endpoint : EndpointExamples.values()) { + endpoint.getExamples().forEach(config -> + ops.path(swaggerPath) + .addExample(config.targetClass, config.displayName, + buildExample(config.exampleClass, config.resourcePath)) + ); + } + } + + /** + * Builds an example object for the given class and resource path. + * @param exampleClass the class of the example object + * @param path the path to the example resource + * @return Example object + */ + private static Example buildExample(Class exampleClass, String path) { + cwms.cda.formatters.ContentType contentType = Formats.parseHeader(Formats.JSON, exampleClass); + Example example = new Example(); + try (InputStream stream = ApiServlet.class.getClassLoader().getResourceAsStream(path)) { + if (stream == null) { + throw new IllegalArgumentException("Unable to find example file: " + path); + } + String ex = IOUtils.toString(stream, StandardCharsets.UTF_8); + ex = Formats.format(contentType, Formats.parseContent(contentType, ex, exampleClass)); + example.value(ex); + } catch (IOException ex) { + throw new IllegalStateException("Unable to load example file: " + path, ex); + } + return example; + } + + // Enum to define example configurations by endpoint + // Add examples here for other endpoints + private enum EndpointExamples { + LEVELS(Arrays.asList( + new ExampleConfig(LocationLevel.class, "Constant Location Level", + ConstantLocationLevel.class, "cwms/cda/data/levels/levels_constant_create.json"), + new ExampleConfig(LocationLevel.class, "Seasonal Location Level", + SeasonalLocationLevel.class, "cwms/cda/data/levels/levels_seasonal_create.json"), + new ExampleConfig(LocationLevel.class, "Timeseries Location Level", + TimeSeriesLocationLevel.class, "cwms/cda/data/levels/levels_timeseries_create.json"), + new ExampleConfig(LocationLevel.class, "Virtual Location Level", + VirtualLocationLevel.class, "cwms/cda/data/levels/levels_virtual_create.json") + )); + // Add more endpoints as needed + + private final List examples; + + EndpointExamples(List examples) { + this.examples = examples; + } + + public List getExamples() { + return examples; + } + } + + private static class ExampleConfig { + final Class targetClass; + final String displayName; + final Class exampleClass; + final String resourcePath; + + ExampleConfig(Class targetClass, String displayName, + Class exampleClass, String resourcePath) { + this.targetClass = targetClass; + this.displayName = displayName; + this.exampleClass = exampleClass; + this.resourcePath = resourcePath; + } + } +} diff --git a/cwms-data-api/src/test/resources/cwms/cda/api/levels_timeseries_create.json b/cwms-data-api/src/test/resources/cwms/cda/api/levels_timeseries_create.json index 1adea52805..a2a84c8328 100644 --- a/cwms-data-api/src/test/resources/cwms/cda/api/levels_timeseries_create.json +++ b/cwms-data-api/src/test/resources/cwms/cda/api/levels_timeseries_create.json @@ -1,9 +1,9 @@ { - "seasonal-time-series-id": "RYAN3.Stage.Inst.5Minutes.0.ZSTORE_TS_TEST630", - "level-units-id":"ft", - "level-date":"2008-12-03T10:15:30+01:00[UTC]", - "level-comment":"for testing purposes", - "interpolate-string":"false", - "location-level-id":"LOC_TEST.Elev.Inst.0.Bottom of Inlet", - "office-id":"LRL" + "seasonal-time-series-id": "Sacramento.Stage.Inst.5Minutes.0.Bottom of Inlet", + "level-units-id": "ft", + "level-date": "2008-12-03T10:15:30+01:00[UTC]", + "level-comment": "Bottom of Inlet, lowest level", + "interpolate-string": "F", + "location-level-id": "Sacramento.Elev.Inst.0.Bottom of Inlet", + "office-id": "LRL" } \ No newline at end of file From 59dbc47fbe7c00bd1b68566267e659de285e2d6e Mon Sep 17 00:00:00 2001 From: zack-rma Date: Wed, 1 Jul 2026 15:19:24 -0700 Subject: [PATCH 3/5] Cleaned up ApiServlet imports --- cwms-data-api/src/main/java/cwms/cda/ApiServlet.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java index 2b4dc16df0..fb533449ec 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java @@ -170,13 +170,7 @@ import cwms.cda.api.watersupply.WaterUserUpdateController; import cwms.cda.data.dao.JooqDao; import cwms.cda.data.dao.rss.QueueManager; -import cwms.cda.data.dto.CwmsDTOBase; import cwms.cda.data.dto.csv.CwmsCsvDTO; -import cwms.cda.data.dto.locationlevel.ConstantLocationLevel; -import cwms.cda.data.dto.locationlevel.LocationLevel; -import cwms.cda.data.dto.locationlevel.SeasonalLocationLevel; -import cwms.cda.data.dto.locationlevel.TimeSeriesLocationLevel; -import cwms.cda.data.dto.locationlevel.VirtualLocationLevel; import cwms.cda.formatters.Formats; import cwms.cda.formatters.csv.CsvExampleGenerator; import cwms.cda.security.Authenticator; @@ -204,7 +198,6 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; -import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.responses.ApiResponse; @@ -213,7 +206,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -234,7 +226,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; -import org.apache.commons.io.IOUtils; import org.apache.http.entity.ContentType; import org.jetbrains.annotations.NotNull; import org.jooq.exception.DataAccessException; From 000e9e10871d545d2c591012ef8c5adee9d47927 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Wed, 1 Jul 2026 15:37:00 -0700 Subject: [PATCH 4/5] Reverted change to incorrect example, updated intended example --- .../cda/data/levels/levels_timeseries_create.json | 14 +++++++------- .../cwms/cda/api/levels_timeseries_create.json | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json index 1adea52805..a2a84c8328 100644 --- a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json +++ b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json @@ -1,9 +1,9 @@ { - "seasonal-time-series-id": "RYAN3.Stage.Inst.5Minutes.0.ZSTORE_TS_TEST630", - "level-units-id":"ft", - "level-date":"2008-12-03T10:15:30+01:00[UTC]", - "level-comment":"for testing purposes", - "interpolate-string":"false", - "location-level-id":"LOC_TEST.Elev.Inst.0.Bottom of Inlet", - "office-id":"LRL" + "seasonal-time-series-id": "Sacramento.Stage.Inst.5Minutes.0.Bottom of Inlet", + "level-units-id": "ft", + "level-date": "2008-12-03T10:15:30+01:00[UTC]", + "level-comment": "Bottom of Inlet, lowest level", + "interpolate-string": "F", + "location-level-id": "Sacramento.Elev.Inst.0.Bottom of Inlet", + "office-id": "LRL" } \ No newline at end of file diff --git a/cwms-data-api/src/test/resources/cwms/cda/api/levels_timeseries_create.json b/cwms-data-api/src/test/resources/cwms/cda/api/levels_timeseries_create.json index a2a84c8328..1adea52805 100644 --- a/cwms-data-api/src/test/resources/cwms/cda/api/levels_timeseries_create.json +++ b/cwms-data-api/src/test/resources/cwms/cda/api/levels_timeseries_create.json @@ -1,9 +1,9 @@ { - "seasonal-time-series-id": "Sacramento.Stage.Inst.5Minutes.0.Bottom of Inlet", - "level-units-id": "ft", - "level-date": "2008-12-03T10:15:30+01:00[UTC]", - "level-comment": "Bottom of Inlet, lowest level", - "interpolate-string": "F", - "location-level-id": "Sacramento.Elev.Inst.0.Bottom of Inlet", - "office-id": "LRL" + "seasonal-time-series-id": "RYAN3.Stage.Inst.5Minutes.0.ZSTORE_TS_TEST630", + "level-units-id":"ft", + "level-date":"2008-12-03T10:15:30+01:00[UTC]", + "level-comment":"for testing purposes", + "interpolate-string":"false", + "location-level-id":"LOC_TEST.Elev.Inst.0.Bottom of Inlet", + "office-id":"LRL" } \ No newline at end of file From 398e27fdf108eeaef745137991a33d71d7e440d7 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Wed, 1 Jul 2026 16:16:04 -0700 Subject: [PATCH 5/5] Scoping fixes per feedback --- .../src/main/java/cwms/cda/openapi/ExampleUtils.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/openapi/ExampleUtils.java b/cwms-data-api/src/main/java/cwms/cda/openapi/ExampleUtils.java index a801ce5f01..3203a0f886 100644 --- a/cwms-data-api/src/main/java/cwms/cda/openapi/ExampleUtils.java +++ b/cwms-data-api/src/main/java/cwms/cda/openapi/ExampleUtils.java @@ -110,18 +110,18 @@ private enum EndpointExamples { this.examples = examples; } - public List getExamples() { + private List getExamples() { return examples; } } private static class ExampleConfig { - final Class targetClass; - final String displayName; - final Class exampleClass; - final String resourcePath; + private final Class targetClass; + private final String displayName; + private final Class exampleClass; + private final String resourcePath; - ExampleConfig(Class targetClass, String displayName, + private ExampleConfig(Class targetClass, String displayName, Class exampleClass, String resourcePath) { this.targetClass = targetClass; this.displayName = displayName;