Skip to content

Commit 41be4ec

Browse files
committed
CWMSVUE-634 - Updated name to TypeTimeSeriesIdentifiers. Made dto represent mapping of location id to mapping of ts-type to ts-id.
1 parent bccf848 commit 41be4ec

File tree

6 files changed

+168
-84
lines changed

6 files changed

+168
-84
lines changed

cwms-data-api/src/main/java/cwms/cda/data/dto/AccessToWaterTimeSeriesIdentifier.java renamed to cwms-data-api/src/main/java/cwms/cda/data/dto/TypedTimeSeriesIdentifiers.java

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,68 +23,64 @@
2323
*/
2424
package cwms.cda.data.dto;
2525

26+
import com.fasterxml.jackson.annotation.JsonIgnore;
2627
import com.fasterxml.jackson.annotation.JsonInclude;
2728
import com.fasterxml.jackson.annotation.JsonProperty;
2829
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
2930
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
3031
import com.fasterxml.jackson.databind.annotation.JsonNaming;
32+
3133
import cwms.cda.formatters.Formats;
3234
import cwms.cda.formatters.annotations.FormattableWith;
3335
import cwms.cda.formatters.json.JsonV1;
36+
import java.util.HashMap;
37+
import java.util.Map;
3438

35-
@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.JSON, Formats.DEFAULT})
36-
@JsonDeserialize(builder = AccessToWaterTimeSeriesIdentifier.Builder.class)
39+
@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON})
40+
@JsonDeserialize(builder = TypedTimeSeriesIdentifiers.Builder.class)
3741
@JsonInclude(JsonInclude.Include.NON_NULL)
3842
@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class)
39-
public final class AccessToWaterTimeSeriesIdentifier extends CwmsDTOBase {
43+
public final class TypedTimeSeriesIdentifiers extends CwmsDTOBase {
4044
@JsonProperty(required = true)
4145
private final CwmsId locationId;
42-
@JsonProperty(required = true)
43-
private final TimeSeriesIdentifierDescriptor timeSeriesIdDescriptor;
44-
@JsonProperty(required = true)
45-
private final String tsType;
4646

47-
private AccessToWaterTimeSeriesIdentifier(Builder builder) {
47+
private final Map<String, TimeSeriesIdentifierDescriptor> typeToTsIdMap;
48+
49+
private TypedTimeSeriesIdentifiers(Builder builder) {
4850
this.locationId = builder.locationId;
49-
this.timeSeriesIdDescriptor = builder.timeSeriesIdDescriptor;
50-
this.tsType = builder.tsType;
51+
this.typeToTsIdMap = builder.typeToTsIdMap;
5152
}
5253

5354
public CwmsId getLocationId() {
5455
return locationId;
5556
}
5657

57-
public TimeSeriesIdentifierDescriptor getTimeSeriesIdDescriptor() {
58-
return timeSeriesIdDescriptor;
59-
}
60-
61-
public String getTsType() {
62-
return tsType;
58+
public Map<String, TimeSeriesIdentifierDescriptor> getTypeToTsIdMap() {
59+
return typeToTsIdMap;
6360
}
6461

6562
public static class Builder {
6663
private CwmsId locationId;
67-
private TimeSeriesIdentifierDescriptor timeSeriesIdDescriptor;
68-
private String tsType;
64+
private Map<String, TimeSeriesIdentifierDescriptor> typeToTsIdMap = new HashMap<>();
6965

7066
public Builder withLocationId(CwmsId locationId) {
7167
this.locationId = locationId;
7268
return this;
7369
}
7470

75-
public Builder withTimeSeriesIdDescriptor(TimeSeriesIdentifierDescriptor timeSeriesIdDescriptor) {
76-
this.timeSeriesIdDescriptor = timeSeriesIdDescriptor;
71+
public Builder withTypeToTsIdMap(Map<String, TimeSeriesIdentifierDescriptor> typeToTsIdMap) {
72+
this.typeToTsIdMap = typeToTsIdMap;
7773
return this;
7874
}
7975

80-
public Builder withTsType(String tsType) {
81-
this.tsType = tsType;
76+
@JsonIgnore
77+
public Builder withTypeToTsId(String type, TimeSeriesIdentifierDescriptor tsId) {
78+
this.typeToTsIdMap.put(type, tsId);
8279
return this;
8380
}
8481

85-
public AccessToWaterTimeSeriesIdentifier build() {
86-
return new AccessToWaterTimeSeriesIdentifier(this);
82+
public TypedTimeSeriesIdentifiers build() {
83+
return new TypedTimeSeriesIdentifiers(this);
8784
}
88-
8985
}
9086
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2025 Hydrologic Engineering Center
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package cwms.cda.data.dto;
25+
26+
import com.fasterxml.jackson.annotation.JsonInclude;
27+
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
28+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
29+
import com.fasterxml.jackson.databind.annotation.JsonNaming;
30+
import cwms.cda.formatters.Formats;
31+
import cwms.cda.formatters.annotations.FormattableWith;
32+
import cwms.cda.formatters.json.JsonV1;
33+
34+
import java.util.ArrayList;
35+
import java.util.Collection;
36+
import java.util.Collections;
37+
import java.util.List;
38+
39+
@JsonDeserialize(builder = TypedTimeSeriesIdentifiersList.Builder.class)
40+
@JsonInclude(JsonInclude.Include.NON_NULL)
41+
@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class)
42+
@FormattableWith(contentType = Formats.JSONV1, formatter = JsonV1.class, aliases = {Formats.DEFAULT, Formats.JSON})
43+
public class TypedTimeSeriesIdentifiersList extends CwmsDTOPaginated {
44+
45+
private final List<TypedTimeSeriesIdentifiers> typedTimeSeriesIdentifiers;
46+
private final int offset;
47+
48+
private TypedTimeSeriesIdentifiersList(int offset, int pageSize, Integer total, List<TypedTimeSeriesIdentifiers> identifiersList) {
49+
super(Integer.toString(offset), pageSize, total);
50+
this.typedTimeSeriesIdentifiers = new ArrayList<>(identifiersList);
51+
this.offset = offset;
52+
}
53+
54+
public List<TypedTimeSeriesIdentifiers> getTypedTimeSeriesIdentifiers() {
55+
return Collections.unmodifiableList(typedTimeSeriesIdentifiers);
56+
}
57+
58+
public static class Builder {
59+
private final int offset;
60+
private final int pageSize;
61+
private final Integer total;
62+
63+
private List<TypedTimeSeriesIdentifiers> typedTimeSeriesIdentifiers = new ArrayList<>();
64+
65+
public Builder(int offset, int pageSize, Integer total) {
66+
this.offset = offset;
67+
this.pageSize = pageSize;
68+
this.total = total;
69+
}
70+
71+
public Builder withTypedTimeSeriesIdentifiers(Collection<TypedTimeSeriesIdentifiers> identifiersList) {
72+
this.typedTimeSeriesIdentifiers = new ArrayList<>(identifiersList);
73+
return this;
74+
}
75+
76+
public TypedTimeSeriesIdentifiersList build() {
77+
TypedTimeSeriesIdentifiersList retval = new TypedTimeSeriesIdentifiersList(offset, pageSize, total, typedTimeSeriesIdentifiers);
78+
79+
if (this.typedTimeSeriesIdentifiers.size() == this.pageSize) {
80+
String cursor = Integer.toString(retval.offset + retval.typedTimeSeriesIdentifiers.size());
81+
retval.nextPage = encodeCursor(cursor, retval.pageSize, retval.total);
82+
} else {
83+
retval.nextPage = null;
84+
}
85+
return retval;
86+
}
87+
}
88+
}

cwms-data-api/src/test/java/cwms/cda/data/dto/AccessToWaterTimeSeriesIdentifierTest.java renamed to cwms-data-api/src/test/java/cwms/cda/data/dto/TypedTimeSeriesIdentifierTest.java

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
package cwms.cda.data.dto;
2626

2727
import java.time.ZoneId;
28+
import java.util.HashMap;
29+
import java.util.Map;
2830
import static org.junit.jupiter.api.Assertions.*;
2931

3032
import cwms.cda.api.errors.FieldException;
@@ -36,7 +38,7 @@
3638
import org.apache.commons.io.IOUtils;
3739
import org.junit.jupiter.api.Test;
3840

39-
final class AccessToWaterTimeSeriesIdentifierTest {
41+
final class TypedTimeSeriesIdentifierTest {
4042

4143
@Test
4244
void createAccessToWaterTimeSeriesData_allFieldsProvided_success() {
@@ -47,16 +49,23 @@ void createAccessToWaterTimeSeriesData_allFieldsProvided_success() {
4749
.withIntervalOffsetMinutes(0L)
4850
.withZoneId(ZoneId.of("UTC"))
4951
.build();
50-
AccessToWaterTimeSeriesIdentifier item = new AccessToWaterTimeSeriesIdentifier.Builder()
52+
TimeSeriesIdentifierDescriptor tsDescriptor2 = new TimeSeriesIdentifierDescriptor.Builder()
53+
.withTimeSeriesId("VANL.Flow.Inst.15Minutes.0.Ccp-Rev")
54+
.withOfficeId("SWT")
55+
.withActive(true)
56+
.withIntervalOffsetMinutes(0L)
57+
.withZoneId(ZoneId.of("UTC"))
58+
.build();
59+
TypedTimeSeriesIdentifiers items = new TypedTimeSeriesIdentifiers.Builder()
5160
.withLocationId(CwmsId.buildCwmsId("SWT", "VANL"))
52-
.withTimeSeriesIdDescriptor(tsDescriptor)
53-
.withTsType("STAGE")
61+
.withTypeToTsId("STAGE", tsDescriptor)
62+
.withTypeToTsId("OUTFLOW", tsDescriptor2)
5463
.build();
5564

5665
assertAll(
57-
() -> DTOMatch.assertMatch(CwmsId.buildCwmsId("SWT", "VANL"), item.getLocationId(), "The location ID does not match the provided value"),
58-
() -> DTOMatch.assertMatch(tsDescriptor, item.getTimeSeriesIdDescriptor()),
59-
() -> assertEquals("STAGE", item.getTsType(), "The time series type does not match the provided value")
66+
() -> DTOMatch.assertMatch(CwmsId.buildCwmsId("SWT", "VANL"), items.getLocationId(), "Location ID"),
67+
() -> DTOMatch.assertMatch(tsDescriptor, items.getTypeToTsIdMap().get("STAGE")),
68+
() -> DTOMatch.assertMatch(tsDescriptor2, items.getTypeToTsIdMap().get("OUTFLOW"))
6069
);
6170
}
6271

@@ -69,30 +78,15 @@ void createAccessToWaterTimeSeriesData_missingField_throwsFieldException() {
6978
.withIntervalOffsetMinutes(0L)
7079
.withZoneId(ZoneId.of("UTC"))
7180
.build();
81+
Map<String, TimeSeriesIdentifierDescriptor> typeToTsIdMap = new HashMap<>();
82+
typeToTsIdMap.put("STAGE", tsDescriptor);
7283
assertAll(
7384
() -> assertThrows(FieldException.class, () -> {
74-
AccessToWaterTimeSeriesIdentifier item = new AccessToWaterTimeSeriesIdentifier.Builder()
75-
.withTimeSeriesIdDescriptor(tsDescriptor)
76-
.withTsType("STAGE")
77-
.build();
78-
item.validate();
79-
}, "The validate method should have thrown a FieldException because the location ID is missing"),
80-
81-
() -> assertThrows(FieldException.class, () -> {
82-
AccessToWaterTimeSeriesIdentifier item = new AccessToWaterTimeSeriesIdentifier.Builder()
83-
.withLocationId(CwmsId.buildCwmsId("SWT", "VANL"))
84-
.withTsType("STAGE")
85-
.build();
86-
item.validate();
87-
}, "The validate method should have thrown a FieldException because the TimeSeries ID is missing"),
88-
89-
() -> assertThrows(FieldException.class, () -> {
90-
AccessToWaterTimeSeriesIdentifier item = new AccessToWaterTimeSeriesIdentifier.Builder()
91-
.withLocationId(CwmsId.buildCwmsId("SWT", "VANL"))
92-
.withTimeSeriesIdDescriptor(tsDescriptor)
85+
TypedTimeSeriesIdentifiers item = new TypedTimeSeriesIdentifiers.Builder()
86+
.withTypeToTsIdMap(typeToTsIdMap)
9387
.build();
9488
item.validate();
95-
}, "The validate method should have thrown a FieldException because the time series type is missing")
89+
}, "The validate method should have thrown a FieldException because the location ID is missing")
9690
);
9791
}
9892

@@ -105,15 +99,14 @@ void createAccessToWaterTimeSeriesData_serialize_roundtrip() {
10599
.withIntervalOffsetMinutes(0L)
106100
.withZoneId(ZoneId.of("UTC"))
107101
.build();
108-
AccessToWaterTimeSeriesIdentifier data = new AccessToWaterTimeSeriesIdentifier.Builder()
102+
TypedTimeSeriesIdentifiers data = new TypedTimeSeriesIdentifiers.Builder()
109103
.withLocationId(CwmsId.buildCwmsId("SWT", "VANL"))
110-
.withTimeSeriesIdDescriptor(tsDescriptor)
111-
.withTsType("STAGE")
104+
.withTypeToTsId("STAGE", tsDescriptor)
112105
.build();
113106

114107
ContentType contentType = new ContentType(Formats.JSON);
115108
String json = Formats.format(contentType, data);
116-
AccessToWaterTimeSeriesIdentifier deserialized = Formats.parseContent(contentType, json, AccessToWaterTimeSeriesIdentifier.class);
109+
TypedTimeSeriesIdentifiers deserialized = Formats.parseContent(contentType, json, TypedTimeSeriesIdentifiers.class);
117110
DTOMatch.assertMatch(data, deserialized);
118111
}
119112

@@ -126,17 +119,16 @@ void createAccessToWaterTimeSeriesData_deserialize() throws Exception {
126119
.withIntervalOffsetMinutes(0L)
127120
.withZoneId(ZoneId.of("UTC"))
128121
.build();
129-
AccessToWaterTimeSeriesIdentifier expected = new AccessToWaterTimeSeriesIdentifier.Builder()
122+
TypedTimeSeriesIdentifiers expected = new TypedTimeSeriesIdentifiers.Builder()
130123
.withLocationId(CwmsId.buildCwmsId("SWT", "VANL"))
131-
.withTimeSeriesIdDescriptor(tsDescriptor)
132-
.withTsType("STAGE")
124+
.withTypeToTsId("STAGE", tsDescriptor)
133125
.build();
134126

135-
InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/data/dto/access_to_water_time_series_data.json");
127+
InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/data/dto/typed_time_series_identifiers.json");
136128
assertNotNull(resource);
137129
String json = IOUtils.toString(resource, StandardCharsets.UTF_8);
138130
ContentType contentType = new ContentType(Formats.JSON);
139-
AccessToWaterTimeSeriesIdentifier deserialized = Formats.parseContent(contentType, json, AccessToWaterTimeSeriesIdentifier.class);
131+
TypedTimeSeriesIdentifiers deserialized = Formats.parseContent(contentType, json, TypedTimeSeriesIdentifiers.class);
140132
DTOMatch.assertMatch(expected, deserialized);
141133
}
142134
}

cwms-data-api/src/test/java/cwms/cda/helpers/DTOMatch.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@
2424

2525
package cwms.cda.helpers;
2626

27-
import cwms.cda.data.dto.AccessToWaterTimeSeriesIdentifier;
2827
import cwms.cda.data.dto.CwmsIdTimeExtentsEntry;
2928
import cwms.cda.data.dto.TimeExtents;
3029
import cwms.cda.data.dto.TimeSeriesExtents;
3130
import cwms.cda.data.dto.TimeSeriesIdentifierDescriptor;
31+
import cwms.cda.data.dto.TypedTimeSeriesIdentifiers;
32+
import cwms.cda.data.dto.TypedTimeSeriesIdentifiersList;
3233
import cwms.cda.data.dto.location.kind.Lock;
3334
import cwms.cda.data.dto.CwmsDTOBase;
3435
import cwms.cda.data.dto.location.kind.GateChange;
@@ -603,14 +604,6 @@ public static void assertMatch(CwmsIdTimeExtentsEntry first, CwmsIdTimeExtentsEn
603604
);
604605
}
605606

606-
public static void assertMatch(AccessToWaterTimeSeriesIdentifier first, AccessToWaterTimeSeriesIdentifier second) {
607-
assertAll(
608-
() -> assertMatch(first.getTimeSeriesIdDescriptor(), second.getTimeSeriesIdDescriptor()),
609-
() -> assertEquals(first.getTsType(), second.getTsType()),
610-
() -> assertMatch(first.getLocationId(), second.getLocationId())
611-
);
612-
}
613-
614607
public static void assertMatch(TimeSeriesIdentifierDescriptor tsDescriptor, TimeSeriesIdentifierDescriptor timeSeriesIdDescriptor) {
615608
assertAll(
616609
() -> assertEquals(tsDescriptor.getIntervalOffsetMinutes(), timeSeriesIdDescriptor.getIntervalOffsetMinutes(), "Identifier does not match"),
@@ -620,6 +613,20 @@ public static void assertMatch(TimeSeriesIdentifierDescriptor tsDescriptor, Time
620613
);
621614
}
622615

616+
public static void assertMatch(TypedTimeSeriesIdentifiers first, TypedTimeSeriesIdentifiers second)
617+
{
618+
assertAll(
619+
() -> assertMatch(first.getLocationId(), second.getLocationId()),
620+
() -> assertEquals(first.getTypeToTsIdMap().size(), second.getTypeToTsIdMap().size(), "Type to TS ID map sizes do not match"),
621+
() -> first.getTypeToTsIdMap().forEach((type, tsId) -> {
622+
if (!second.getTypeToTsIdMap().containsKey(type)) {
623+
fail("tsType " + type + " not found in both tsType to tsId maps");
624+
}
625+
assertMatch(tsId, second.getTypeToTsIdMap().get(type));
626+
})
627+
);
628+
}
629+
623630
@FunctionalInterface
624631
public interface AssertMatchMethod<T>{
625632
void assertMatch(T first, T second);

cwms-data-api/src/test/resources/cwms/cda/data/dto/access_to_water_time_series_data.json

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"location-id": {
3+
"name": "VANL",
4+
"office-id": "SWT"
5+
},
6+
"type-to-ts-id-map": {
7+
"STAGE": {
8+
"office-id": "SWT",
9+
"time-series-id": "VANL.Stage.Inst.15Minutes.0.Ccp-Rev",
10+
"timezone-name": "UTC",
11+
"interval-offset-minutes": 0,
12+
"active": true
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)