diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationLevelsDaoImpl.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationLevelsDaoImpl.java index fbb3150a9..bdfe4dd9e 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationLevelsDaoImpl.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationLevelsDaoImpl.java @@ -398,17 +398,21 @@ private void storeNormalLocationLevel(LocationLevel locationLevel) { final BigInteger minutesFinal = minutes; final SEASONAL_VALUE_TAB_T seasonalValuesFinal = seasonalValues; final String seasonalTimeSeriesIdFinal = seasonalTimeSeriesId; + final Timestamp expirationDate = Optional.ofNullable(locationLevel.getExpirationDate()) + .map(ZonedDateTime::toInstant) + .map(Timestamp::from) + .orElse(null); connection(dsl, c -> { String officeId = locationLevel.getOfficeId(); setOffice(c, officeId); - CWMS_LEVEL_PACKAGE.call_STORE_LOCATION_LEVEL3(DSL.using(c).configuration(), + CWMS_LEVEL_PACKAGE.call_STORE_LOCATION_LEVEL4(DSL.using(c).configuration(), locationLevel.getLocationLevelId(), constantValueFinal, locationLevel.getLevelUnitsId(), locationLevel.getLevelComment(), dateFinal, "UTC", locationLevel.getAttributeValue(), locationLevel.getAttributeUnitsId(), locationLevel.getAttributeDurationId(), locationLevel.getAttributeComment(), intervalOriginFinal, monthsFinal, minutesFinal, locationLevel.getInterpolateString(), - seasonalTimeSeriesIdFinal, seasonalValuesFinal, "F", officeId); + seasonalTimeSeriesIdFinal, expirationDate, seasonalValuesFinal, "F", officeId); }); } @@ -609,6 +613,10 @@ private VirtualLocationLevel buildVirtualLocationLevel(LOCATION_LEVEL_T level, S private ConstantLocationLevel buildConstantLocationLevel(LOCATION_LEVEL_T level, String officeId, String units, String locationLevelName, ZonedDateTime realEffectiveDate, Double constantValue) { + ZonedDateTime expirationDate = Optional.ofNullable(level.getEXPIRATION_DATE()) + .map(Timestamp::toInstant) + .map(i -> i.atZone(realEffectiveDate.getZone())) + .orElse(null); return new ConstantLocationLevel.Builder(locationLevelName, realEffectiveDate) .withLevelUnitsId(units) .withAttributeUnitsId(units) @@ -617,11 +625,16 @@ private ConstantLocationLevel buildConstantLocationLevel(LOCATION_LEVEL_T level, .withAttributeParameterId(level.getATTRIBUTE_PARAMETER_ID()) .withInterpolateString(level.getINTERPOLATE()) .withConstantValue(constantValue) + .withExpirationDate(expirationDate) .build(); } private SeasonalLocationLevel buildSeasonalLocationLevel(LOCATION_LEVEL_T level, String officeId, String units, String locationLevelName, ZonedDateTime effectiveDate, ZonedDateTime realEffectiveDate, List seasonalValues) { + ZonedDateTime expirationDate = Optional.ofNullable(level.getEXPIRATION_DATE()) + .map(Timestamp::toInstant) + .map(i -> i.atZone(realEffectiveDate.getZone())) + .orElse(null); return new SeasonalLocationLevel.Builder(locationLevelName, realEffectiveDate) .withLevelUnitsId(units) .withAttributeUnitsId(units) @@ -635,11 +648,16 @@ private SeasonalLocationLevel buildSeasonalLocationLevel(LOCATION_LEVEL_T level, .withIntervalMonths(Optional.ofNullable(level.getINTERVAL_MONTHS()) .map(BigInteger::intValue).orElse(null)) .withIntervalOrigin(level.getINTERVAL_ORIGIN(), effectiveDate) + .withExpirationDate(expirationDate) .build(); } private TimeSeriesLocationLevel buildTimeSeriesLocationLevel(LOCATION_LEVEL_T level, String officeId, String units, String locationLevelName, ZonedDateTime realEffectiveDate) { + ZonedDateTime expirationDate = Optional.ofNullable(level.getEXPIRATION_DATE()) + .map(Timestamp::toInstant) + .map(i -> i.atZone(realEffectiveDate.getZone())) + .orElse(null); return new TimeSeriesLocationLevel.Builder(locationLevelName, realEffectiveDate, level.getTSID()) .withLevelUnitsId(units) .withAttributeUnitsId(units) @@ -647,6 +665,7 @@ private TimeSeriesLocationLevel buildTimeSeriesLocationLevel(LOCATION_LEVEL_T le .withOfficeId(officeId) .withAttributeParameterId(level.getATTRIBUTE_PARAMETER_ID()) .withInterpolateString(level.getINTERPOLATE()) + .withExpirationDate(expirationDate) .build(); } @@ -667,6 +686,7 @@ private void parseLevels(Record r, Map build String officeId = r.get(mapping.getOfficeId()); String levelUnit = r.get(mapping.getLevelUnit()); String attrUnit = r.get(mapping.getAttributeUnit()); + Timestamp expirationDate = r.get(mapping.getExpirationDate()); // Virtual fields Timestamp virtualLevelDateTimestamp = r.get(mapping.getEffectiveDate()); @@ -674,7 +694,6 @@ private void parseLevels(Record r, Map build String virtLocLevelId = r.get(mapping.getVirtLocLevelId()); String virtOfficeId = r.get(mapping.getVirtOfficeId()); String connections = r.get(mapping.getConnections()); - Timestamp expirationDate = r.get(mapping.getExpirationDate()); ZonedDateTime expireDate = null; Date levelDate = null; @@ -758,6 +777,7 @@ private void parseLevels(Record r, Map build constantBuilder.withLevelComment(levelComment); constantBuilder.withAttributeComment(attributeComment); constantBuilder.withAliases(aliases); + constantBuilder.withExpirationDate(expireDate); builderMap.put(levelLookup, constantBuilder); } else if (seasonalLevel != null) { @@ -780,6 +800,7 @@ private void parseLevels(Record r, Map build seasonalBuilder.withIntervalMonths(offset.getMonths()); seasonalBuilder.withIntervalOrigin(intervalOrigin, levelZdt); seasonalBuilder.withAliases(aliases); + seasonalBuilder.withExpirationDate(expireDate); builderMap.put(levelLookup, seasonalBuilder); } else if (tsId != null) { TimeSeriesLocationLevel.Builder timeSeriesBuilder = new TimeSeriesLocationLevel.Builder(locLevelId, levelZdt, tsId); @@ -790,6 +811,7 @@ private void parseLevels(Record r, Map build timeSeriesBuilder.withAttributeComment(attributeComment); timeSeriesBuilder = withLocationLevelRef(timeSeriesBuilder, locationLevelRef); timeSeriesBuilder.withAliases(aliases); + timeSeriesBuilder.withExpirationDate(expireDate); builderMap.put(levelLookup, timeSeriesBuilder); } else if (virtual) { VirtualLocationLevel.Builder builder; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/ConstantLocationLevel.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/ConstantLocationLevel.java index c03bfe370..50387bf11 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/ConstantLocationLevel.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/ConstantLocationLevel.java @@ -87,14 +87,6 @@ public Builder(ConstantLocationLevel copyFrom) { withConstantValue(copyFrom.getConstantValue()); } - public Builder(JDomLocationLevelImpl copyFrom) { - super(copyFrom); - IParameterTypedValue constantLevel = copyFrom.getConstantLevel(); - if (constantLevel != null) { - withConstantValue(constantLevel.getSiParameterUnitsValue()); - } - } - public ConstantLocationLevel.Builder withConstantValue(Double value) { if (value != null && RMAConst.isUndefinedValue(value)) { value = null; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/LocationLevel.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/LocationLevel.java index 1ed572018..2542002ef 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/LocationLevel.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/LocationLevel.java @@ -80,6 +80,8 @@ public abstract class LocationLevel extends CwmsDTO { private final String specifiedLevelId; + @Schema(description = "The expiration date of the location level.") + @JsonFormat(shape = JsonFormat.Shape.STRING) private final ZonedDateTime expirationDate; @Schema(description = "Data Type such as Stage, Elevation, or others.") @@ -257,30 +259,7 @@ protected Builder(@JsonProperty(value = "location-level-id", required = true) St withOfficeId(copyFrom.getOfficeId()); withParameterTypeId(copyFrom.getParameterTypeId()); withSpecifiedLevelId(copyFrom.getSpecifiedLevelId()); - } - - Builder(JDomLocationLevelImpl copyFrom) { - withAttributeComment(copyFrom.getAttributeComment()); - withAttributeDurationId(copyFrom.getAttributeDurationId()); - withAttributeParameterId(copyFrom.getAttributeParameterId()); - ILocationLevelRef locationLevelRef = copyFrom.getLocationLevelRef(); - if (locationLevelRef != null) { - withLocationLevelId(locationLevelRef.getLocationLevelId()); - } - withAttributeValue(copyFrom.getAttributeValue()); - withAttributeParameterTypeId(copyFrom.getAttributeParameterTypeId()); - withAttributeUnitsId(copyFrom.getAttributeUnitsId()); - withDurationId(copyFrom.getDurationId()); - withLevelComment(copyFrom.getLevelComment()); - Date copyLevelDate = copyFrom.getLevelDate(); - if (copyLevelDate != null) { - withLevelDate(ZonedDateTime.ofInstant(copyLevelDate.toInstant(), ZoneId.of("UTC"))); - } - withLevelUnitsId(copyFrom.getLevelUnitsId()); - withOfficeId(copyFrom.getOfficeId()); - withParameterId(copyFrom.getParameterId()); - withParameterTypeId(copyFrom.getParameterTypeId()); - withSpecifiedLevelId(copyFrom.getSpecifiedLevelId()); + withExpirationDate(copyFrom.getExpirationDate()); } protected T self() { @@ -454,6 +433,8 @@ public static LocationLevel getUpdatedLocationLevel(LocationLevel existingLevel, ? constantLevel.getConstantValue() : updatedConstantLevel.getConstantValue()); builder = new ConstantLocationLevel.Builder(locationId, unmarshalledDate) + .withExpirationDate(updatedLevel.getExpirationDate() == null + ? existingLevel.getExpirationDate() : updatedLevel.getExpirationDate()) .withConstantValue(siParameterUnitsConstantValue); } else if (existingLevel instanceof TimeSeriesLocationLevel) { TimeSeriesLocationLevel timeSeriesLevel = (TimeSeriesLocationLevel) existingLevel; @@ -462,7 +443,9 @@ public static LocationLevel getUpdatedLocationLevel(LocationLevel existingLevel, String seasonalTimeSeriesId = (updatedTimeSeriesLevel.getSeasonalTimeSeriesId() == null ? timeSeriesLevel.getSeasonalTimeSeriesId() : updatedTimeSeriesLevel.getSeasonalTimeSeriesId()); - builder = new TimeSeriesLocationLevel.Builder(locationId, unmarshalledDate, seasonalTimeSeriesId); + builder = new TimeSeriesLocationLevel.Builder(locationId, unmarshalledDate, seasonalTimeSeriesId) + .withExpirationDate(updatedLevel.getExpirationDate() == null + ? existingLevel.getExpirationDate() : updatedLevel.getExpirationDate()); } else if (existingLevel instanceof SeasonalLocationLevel) { SeasonalLocationLevel seasonalLevel = (SeasonalLocationLevel) existingLevel; SeasonalLocationLevel updatedSeasonalLevel = (SeasonalLocationLevel) updatedLevel; @@ -491,7 +474,9 @@ public static LocationLevel getUpdatedLocationLevel(LocationLevel existingLevel, .withIntervalMinutes(intervalMinutes) .withIntervalMonths(intervalMonths) .withIntervalOrigin(intervalOrigin) - .withInterpolateString(interpolateString); + .withInterpolateString(interpolateString) + .withExpirationDate(updatedLevel.getExpirationDate() == null + ? existingLevel.getExpirationDate() : updatedLevel.getExpirationDate()); } else { throw new UnsupportedFormatException("Unsupported Location Level type: " + existingLevel.getClass().getName()); diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/SeasonalLocationLevel.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/SeasonalLocationLevel.java index c1e046eb1..d91bd1a32 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/SeasonalLocationLevel.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/SeasonalLocationLevel.java @@ -148,22 +148,6 @@ public Builder(SeasonalLocationLevel copyFrom) { withSpecifiedLevelId(copyFrom.getSpecifiedLevelId()); } - public Builder(JDomLocationLevelImpl copyFrom) { - super(copyFrom); - withInterpolateString(copyFrom.getInterpolateString()); - withIntervalMinutes(copyFrom.getIntervalMinutes()); - withIntervalMonths(copyFrom.getIntervalMonths()); - Date intervalOriginDate = copyFrom.getIntervalOrigin(); - if (intervalOriginDate != null) { - withIntervalOrigin(ZonedDateTime.ofInstant(intervalOriginDate.toInstant(), - ZoneId.of("UTC"))); - } - - withISeasonalValues(copyFrom.getSeasonalValues()); - - withSpecifiedLevelId(copyFrom.getSpecifiedLevelId()); - } - public SeasonalLocationLevel.Builder withSeasonalValues(List seasonalValues) { this.seasonalValues = seasonalValues; return this; diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/TimeSeriesLocationLevel.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/TimeSeriesLocationLevel.java index 7b475d70a..fbcbe6fc4 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/TimeSeriesLocationLevel.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/TimeSeriesLocationLevel.java @@ -92,11 +92,6 @@ public Builder(TimeSeriesLocationLevel copyFrom) { withSpecifiedLevelId(copyFrom.getSpecifiedLevelId()); } - public Builder(JDomLocationLevelImpl copyFrom) { - super(copyFrom); - this.seasonalTimeSeriesId = copyFrom.getSeasonalTimeSeriesId(); - } - public TimeSeriesLocationLevel.Builder withSeasonalTimeSeriesId(String seasonalTimeSeriesId) { this.seasonalTimeSeriesId = seasonalTimeSeriesId; return this; diff --git a/cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java index 5231ef238..fcc1c812e 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java @@ -1737,6 +1737,7 @@ void testStoreSeasonalLevel() throws Exception { .withIntervalOrigin(intervalOrigin) .withSeasonalValues(values) .withInterpolateString("T") + .withExpirationDate(levelDate.plusYears(50)) .build(); String levelJson = Formats.format(new ContentType(Formats.JSONV2), level); @@ -1775,6 +1776,7 @@ void testStoreSeasonalLevel() throws Exception { .log().ifValidationFails(LogDetail.ALL, true) .assertThat() .statusCode(is(HttpServletResponse.SC_OK)) + .body("expiration-date", equalTo(levelDate.plusYears(50).toInstant().toString())) .body("seasonal-values.size()", is(numValues)); } @@ -1785,11 +1787,12 @@ void testStoreTimeSeriesLevel() throws Exception { String levelId = String.format("%s.Elev.Ave.1Day.Regulating", locName); String tsId = String.format("%s.Elev.Ave.1Day.1Week.Regulating", locName); createTimeseries(OFFICE, tsId); - ZonedDateTime time = ZonedDateTime.now(); + ZonedDateTime time = ZonedDateTime.ofInstant(Instant.parse("2024-01-01T00:00:00Z"), ZoneId.of("UTC")); TimeSeriesLocationLevel level = new TimeSeriesLocationLevel.Builder(levelId, time, tsId) .withOfficeId(OFFICE) .withLevelUnitsId("ft") .withInterpolateString("T") + .withExpirationDate(time.plusYears(50)) .build(); String levelJson = Formats.format(new ContentType(Formats.JSONV2), level); @@ -1828,6 +1831,7 @@ void testStoreTimeSeriesLevel() throws Exception { .log().ifValidationFails(LogDetail.ALL, true) .assertThat() .statusCode(is(HttpServletResponse.SC_OK)) + .body("expiration-date", equalTo(time.plusYears(50).toInstant().toString())) .body("seasonal-time-series-id", equalTo(tsId)); } @@ -1836,11 +1840,12 @@ void testStoreConstantLevel() throws Exception { String locName = "constLocation123"; createLocation(locName, true, OFFICE); String levelId = String.format("%s.Elev.Ave.1Day.Regulating", locName); - ZonedDateTime time = ZonedDateTime.now(); + ZonedDateTime time = ZonedDateTime.ofInstant(Instant.parse("2024-01-01T00:00:00Z"), ZoneId.of("UTC")); ConstantLocationLevel level = new ConstantLocationLevel.Builder(levelId, time) .withOfficeId(OFFICE) .withLevelUnitsId("ft") .withConstantValue(8675.309) + .withExpirationDate(time.plusYears(50)) .build(); String levelJson = Formats.format(new ContentType(Formats.JSONV2), level); @@ -1880,6 +1885,7 @@ void testStoreConstantLevel() throws Exception { .log().ifValidationFails(LogDetail.ALL, true) .assertThat() .statusCode(is(HttpServletResponse.SC_OK)) + .body("expiration-date", equalTo(time.plusYears(50).toInstant().toString())) .body("constant-value", equalTo(8675.309f)); }