Skip to content

Commit 32c68f1

Browse files
zack-rmaMikeNeilson
authored andcommitted
CTO-259: Fixed seasonal data retrieval for location level GetAll (#1508)
Fixed seasonal data retrieval for location level getAll. Only the most recent single value was being included in the response. Added test case for coverage and updated virtual level test case to include expiration date verification. (cherry picked from commit 6ef8b2f)
1 parent 7bb4301 commit 32c68f1

File tree

3 files changed

+124
-36
lines changed

3 files changed

+124
-36
lines changed

cwms-data-api/src/main/java/cwms/cda/data/dao/LocationLevelsDaoImpl.java

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@
3737
import cwms.cda.api.enums.VersionType;
3838
import cwms.cda.api.errors.NotFoundException;
3939
import cwms.cda.data.dto.CwmsDTOPaginated;
40+
import cwms.cda.data.dto.TimeSeries;
4041
import cwms.cda.data.dto.catalog.LocationAlias;
4142
import cwms.cda.data.dto.locationlevel.ConstantLocationLevel;
4243
import cwms.cda.data.dto.locationlevel.LocationLevel;
4344
import cwms.cda.data.dto.locationlevel.LocationLevels;
4445
import cwms.cda.data.dto.locationlevel.SeasonalLocationLevel;
4546
import cwms.cda.data.dto.locationlevel.SeasonalValueBean;
46-
import cwms.cda.data.dto.TimeSeries;
47+
import cwms.cda.data.dto.locationlevel.TimeSeriesLocationLevel;
48+
import cwms.cda.data.dto.locationlevel.VirtualLocationLevel;
49+
import cwms.cda.formatters.UnsupportedFormatException;
4750
import hec.data.Duration;
4851
import hec.data.Parameter;
4952
import hec.data.ParameterType;
@@ -73,9 +76,6 @@
7376
import java.util.logging.Level;
7477
import java.util.logging.Logger;
7578
import java.util.regex.Pattern;
76-
import cwms.cda.data.dto.locationlevel.TimeSeriesLocationLevel;
77-
import cwms.cda.data.dto.locationlevel.VirtualLocationLevel;
78-
import cwms.cda.formatters.UnsupportedFormatException;
7979
import mil.army.usace.hec.metadata.Interval;
8080
import mil.army.usace.hec.metadata.IntervalFactory;
8181
import mil.army.usace.hec.metadata.constants.NumericalConstants;
@@ -783,25 +783,31 @@ private void parseLevels(Record r, Map<LevelLookup, LocationLevel.Builder> build
783783

784784
JDomSeasonalIntervalImpl newSeasonalOffset = buildSeasonalOffset(calOffset, timeOffset);
785785
SeasonalValueBean seasonalValue = buildSeasonalValueBean(seasonalLevel, newSeasonalOffset);
786-
SeasonalLocationLevel.Builder seasonalBuilder = new SeasonalLocationLevel.Builder(locLevelId, levelZdt);
787-
seasonalBuilder.withSeasonalValue(seasonalValue);
788-
seasonalBuilder.withInterpolateString(interp);
789-
if (timeInterval != null) {
790-
seasonalBuilder.withIntervalMinutes(timeInterval.getMinutes());
786+
if (builderMap.containsKey(levelLookup)) {
787+
SeasonalLocationLevel.Builder existingBuilder = (SeasonalLocationLevel.Builder) builderMap.get(levelLookup);
788+
existingBuilder.withSeasonalValue(seasonalValue);
789+
builderMap.put(levelLookup, existingBuilder);
790+
} else {
791+
SeasonalLocationLevel.Builder seasonalBuilder = new SeasonalLocationLevel.Builder(locLevelId, levelZdt);
792+
seasonalBuilder.withSeasonalValue(seasonalValue);
793+
seasonalBuilder.withInterpolateString(interp);
794+
if (timeInterval != null) {
795+
seasonalBuilder.withIntervalMinutes(timeInterval.getMinutes());
796+
}
797+
seasonalBuilder.withAttributeParameterId(attrId);
798+
seasonalBuilder.withAttributeUnitsId(attrUnit);
799+
seasonalBuilder.withLevelUnitsId(levelUnit);
800+
seasonalBuilder.withLevelComment(levelComment);
801+
seasonalBuilder.withAttributeComment(attributeComment);
802+
seasonalBuilder = withLocationLevelRef(seasonalBuilder, locationLevelRef);
803+
JDomSeasonalIntervalImpl offset = new JDomSeasonalIntervalImpl();
804+
offset.setYearMonthString(calendarInterval);
805+
seasonalBuilder.withIntervalMonths(offset.getMonths());
806+
seasonalBuilder.withIntervalOrigin(intervalOrigin, levelZdt);
807+
seasonalBuilder.withAliases(aliases);
808+
seasonalBuilder.withExpirationDate(expireDate);
809+
builderMap.put(levelLookup, seasonalBuilder);
791810
}
792-
seasonalBuilder.withAttributeParameterId(attrId);
793-
seasonalBuilder.withAttributeUnitsId(attrUnit);
794-
seasonalBuilder.withLevelUnitsId(levelUnit);
795-
seasonalBuilder.withLevelComment(levelComment);
796-
seasonalBuilder.withAttributeComment(attributeComment);
797-
seasonalBuilder = withLocationLevelRef(seasonalBuilder, locationLevelRef);
798-
JDomSeasonalIntervalImpl offset = new JDomSeasonalIntervalImpl();
799-
offset.setYearMonthString(calendarInterval);
800-
seasonalBuilder.withIntervalMonths(offset.getMonths());
801-
seasonalBuilder.withIntervalOrigin(intervalOrigin, levelZdt);
802-
seasonalBuilder.withAliases(aliases);
803-
seasonalBuilder.withExpirationDate(expireDate);
804-
builderMap.put(levelLookup, seasonalBuilder);
805811
} else if (tsId != null) {
806812
TimeSeriesLocationLevel.Builder timeSeriesBuilder = new TimeSeriesLocationLevel.Builder(locLevelId, levelZdt, tsId);
807813
timeSeriesBuilder.withAttributeParameterId(attrId);
@@ -1172,7 +1178,7 @@ public Field<String> getConnections() {
11721178

11731179
@Override
11741180
public Field<Timestamp> getExpirationDate() {
1175-
return AV_VIRTUAL_LOCATION_LEVEL.EXPIRATION_DATE_UTC;
1181+
return AV_LOCATION_LEVEL.EXPIRATION_DATE;
11761182
}
11771183

11781184
@Override
@@ -1314,7 +1320,7 @@ public Field<String> getConnections() {
13141320

13151321
@Override
13161322
public Field<Timestamp> getExpirationDate() {
1317-
return DSL.field(DSL.name(TABLE_ALIAS2, "EXPIRATION_DATE_UTC"), Timestamp.class);
1323+
return DSL.field(DSL.name(TABLE_ALIAS2, "EXPIRATION_DATE"), Timestamp.class);
13181324
}
13191325

13201326
@Override
@@ -1403,13 +1409,13 @@ private static void buildLocationLevelSelectFields() {
14031409
LOCATION_LEVEL_FIELDS.add(virtView.EFFECTIVE_DATE_UTC);
14041410
LOCATION_LEVEL_FIELDS.add(virtView.CONNECTIONS);
14051411
LOCATION_LEVEL_FIELDS.add(virtView.DURATION_ID);
1406-
LOCATION_LEVEL_FIELDS.add(virtView.EXPIRATION_DATE_UTC);
14071412
LOCATION_LEVEL_FIELDS.add(virtView.ATTR_UNIT_EN);
14081413
LOCATION_LEVEL_FIELDS.add(virtView.ATTR_VALUE_EN);
14091414
LOCATION_LEVEL_FIELDS.add(virtView.ATTR_UNIT_SI);
14101415
LOCATION_LEVEL_FIELDS.add(virtView.ATTR_VALUE_SI);
14111416
LOCATION_LEVEL_FIELDS.add(view.OFFICE_ID);
14121417
LOCATION_LEVEL_FIELDS.add(view.LOCATION_LEVEL_ID);
1418+
LOCATION_LEVEL_FIELDS.add(view.EXPIRATION_DATE);
14131419
LOCATION_LEVEL_FIELDS.add(view.LEVEL_DATE);
14141420
LOCATION_LEVEL_FIELDS.add(view.TSID);
14151421
LOCATION_LEVEL_FIELDS.add(view.CONSTANT_LEVEL);
@@ -1440,12 +1446,12 @@ private static void buildAliasedLocationLevelSelectFields() {
14401446
LOCATION_ALIAS_FIELDS.add(field(virtView.EFFECTIVE_DATE_UTC.getUnqualifiedName()));
14411447
LOCATION_ALIAS_FIELDS.add(field(virtView.CONNECTIONS.getUnqualifiedName()));
14421448
LOCATION_ALIAS_FIELDS.add(field(DSL.name(TABLE_ALIAS1, "DURATION_ID")));
1443-
LOCATION_ALIAS_FIELDS.add(field(virtView.EXPIRATION_DATE_UTC.getUnqualifiedName()));
14441449
LOCATION_ALIAS_FIELDS.add(field(virtView.ATTR_UNIT_EN.getUnqualifiedName()));
14451450
LOCATION_ALIAS_FIELDS.add(field(virtView.ATTR_VALUE_EN.getUnqualifiedName()));
14461451
LOCATION_ALIAS_FIELDS.add(field(virtView.ATTR_UNIT_SI.getUnqualifiedName()));
14471452
LOCATION_ALIAS_FIELDS.add(field(virtView.ATTR_VALUE_SI.getUnqualifiedName()));
14481453
LOCATION_ALIAS_FIELDS.add(field(view.LEVEL_DATE.getUnqualifiedName()));
1454+
LOCATION_ALIAS_FIELDS.add(field(view.EXPIRATION_DATE.getUnqualifiedName()));
14491455
LOCATION_ALIAS_FIELDS.add(field(view.TSID.getUnqualifiedName()));
14501456
LOCATION_ALIAS_FIELDS.add(field(view.CONSTANT_LEVEL.getUnqualifiedName()));
14511457
LOCATION_ALIAS_FIELDS.add(field(view.INTERVAL_ORIGIN.getUnqualifiedName()));

cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/SeasonalLocationLevel.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@
2626

2727
package cwms.cda.data.dto.locationlevel;
2828

29-
import java.math.BigInteger;
30-
import java.time.ZoneId;
31-
import java.time.ZonedDateTime;
32-
import java.util.ArrayList;
33-
import java.util.Date;
34-
import java.util.List;
35-
3629
import com.fasterxml.jackson.annotation.JsonCreator;
3730
import com.fasterxml.jackson.annotation.JsonFormat;
3831
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -50,13 +43,16 @@
5043
import cwms.cda.formatters.json.JsonV1;
5144
import cwms.cda.formatters.json.JsonV2;
5245
import cwms.cda.formatters.xml.XMLv2;
53-
import io.swagger.v3.oas.annotations.media.Schema;
54-
5546
import hec.data.level.IParameterTypedValue;
5647
import hec.data.level.ISeasonalInterval;
5748
import hec.data.level.ISeasonalValue;
5849
import hec.data.level.ISeasonalValues;
59-
import hec.data.level.JDomLocationLevelImpl;
50+
import io.swagger.v3.oas.annotations.media.Schema;
51+
import java.math.BigInteger;
52+
import java.time.ZonedDateTime;
53+
import java.util.ArrayList;
54+
import java.util.Date;
55+
import java.util.List;
6056
import rma.util.RMAConst;
6157

6258
@JsonRootName("SeasonalLocationLevel")

cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,7 @@ void testStoreDeleteVirtualLocationLevel(String deletionMethod) throws Exception
16111611
assertThat(response.path("constituents[0].attribute-id"), equalTo("Stage"));
16121612
assertThat(response.path("constituents[1].name"), equalTo(existingSpec));
16131613
assertThat(response.path("constituents[1].type"), equalTo("RATING"));
1614+
assertThat(response.path("expiration-date"), equalTo(Instant.ofEpochMilli(1685689200000L).toString()));
16141615

16151616
// Delete the level
16161617
switch (deletionMethod) {
@@ -1780,6 +1781,91 @@ void testStoreSeasonalLevel() throws Exception {
17801781
.body("seasonal-values.size()", is(numValues));
17811782
}
17821783

1784+
@Test
1785+
void testRetrieveAllSeasonalLevel() throws Exception {
1786+
String locName = "seasonalLoc18";
1787+
createLocation(locName, true, OFFICE);
1788+
String levelId = String.format("%s.Elev.Ave.1Day.Top of Spillway", locName);
1789+
ZonedDateTime intervalOrigin = ZonedDateTime.ofInstant(Instant.parse("2012-01-01T00:00:00Z"), ZoneId.of("UTC"));
1790+
ZonedDateTime levelDate = ZonedDateTime.ofInstant(Instant.parse("2024-01-01T00:00:00Z"), ZoneId.of("UTC"));
1791+
List<SeasonalValueBean> values = new ArrayList<>();
1792+
int numValues = 12;
1793+
for (int i = 1; i <= numValues; i++) {
1794+
values.add(new SeasonalValueBean.Builder()
1795+
.withValue(i + 1.0)
1796+
.withOffsetMonths(i)
1797+
.build());
1798+
}
1799+
SeasonalLocationLevel level = new SeasonalLocationLevel.Builder(levelId, levelDate)
1800+
.withOfficeId(OFFICE)
1801+
.withLevelUnitsId("ft")
1802+
.withIntervalMonths(12)
1803+
.withIntervalOrigin(intervalOrigin)
1804+
.withSeasonalValues(values)
1805+
.withInterpolateString("T")
1806+
.withExpirationDate(levelDate.plusYears(50))
1807+
.build();
1808+
1809+
String levelJson = Formats.format(new ContentType(Formats.JSONV2), level);
1810+
1811+
given()
1812+
.log().ifValidationFails(LogDetail.ALL, true)
1813+
.queryParam(Controllers.OFFICE, OFFICE)
1814+
.header("Authorization", TestAccounts.KeyUser.SPK_NORMAL.toHeaderValue())
1815+
.body(levelJson)
1816+
.contentType(Formats.JSONV2)
1817+
.when()
1818+
.redirects()
1819+
.follow(true)
1820+
.redirects()
1821+
.max(3)
1822+
.post("/levels/")
1823+
.then()
1824+
.log().ifValidationFails(LogDetail.ALL, true)
1825+
.assertThat()
1826+
.statusCode(is(HttpServletResponse.SC_CREATED))
1827+
.body(OFFICE_ID, equalTo(OFFICE))
1828+
.body(MESSAGE, equalTo("Created Location Level"))
1829+
.body(IDENTIFIER, equalTo(levelId));
1830+
1831+
given()
1832+
.log().ifValidationFails(LogDetail.ALL, true)
1833+
.queryParam(Controllers.OFFICE, OFFICE)
1834+
.queryParam(EFFECTIVE_DATE, levelDate.toInstant().toString())
1835+
.when()
1836+
.redirects()
1837+
.follow(true)
1838+
.redirects()
1839+
.max(3)
1840+
.get("/levels/{level-id}", levelId)
1841+
.then()
1842+
.log().ifValidationFails(LogDetail.ALL, true)
1843+
.assertThat()
1844+
.statusCode(is(HttpServletResponse.SC_OK))
1845+
.body("expiration-date", equalTo(levelDate.plusYears(50).toInstant().toString()))
1846+
.body("seasonal-values.size()", is(numValues));
1847+
1848+
given()
1849+
.log().ifValidationFails(LogDetail.ALL, true)
1850+
.queryParam(Controllers.OFFICE, OFFICE)
1851+
.queryParam(EFFECTIVE_DATE, levelDate.toInstant().toString())
1852+
.when()
1853+
.redirects()
1854+
.follow(true)
1855+
.redirects()
1856+
.max(3)
1857+
.queryParam(LEVEL_ID_MASK, levelId)
1858+
.get("/levels/")
1859+
.then()
1860+
.log().ifValidationFails(LogDetail.ALL, true)
1861+
.assertThat()
1862+
.statusCode(is(HttpServletResponse.SC_OK))
1863+
.body("levels.size()", is(1))
1864+
.body("levels[0].expiration-date", equalTo(levelDate.plusYears(50).toInstant().toString()))
1865+
.body("levels[0].seasonal-values.size()", is(numValues))
1866+
.body("total", is(numValues));
1867+
}
1868+
17831869
@Test
17841870
void testStoreTimeSeriesLevel() throws Exception {
17851871
String locName = "tsLocation123";

0 commit comments

Comments
 (0)