diff --git a/cwms-data-api/src/main/java/cwms/cda/api/CatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/CatalogController.java
index fe6f715ae5..74f7240154 100644
--- a/cwms-data-api/src/main/java/cwms/cda/api/CatalogController.java
+++ b/cwms-data-api/src/main/java/cwms/cda/api/CatalogController.java
@@ -2,6 +2,7 @@
import static com.codahale.metrics.MetricRegistry.name;
import static cwms.cda.api.Controllers.ACCEPT;
+import static cwms.cda.api.Controllers.INCLUDE_ALIASES;
import static cwms.cda.api.Controllers.BOUNDING_OFFICE_LIKE;
import static cwms.cda.api.Controllers.CURSOR;
import static cwms.cda.api.Controllers.EXCLUDE_EMPTY;
@@ -168,6 +169,10 @@ public void getAll(Context ctx) {
description = "Posix regular expression matching "
+ "against the location type."
),
+ @OpenApiParam(name = INCLUDE_ALIASES, type = Boolean.class,
+ description = "Whether to add aliases to the catalog entries. "
+ + "Default is false. If true, the aliases will be added to the "
+ + "catalog entries in the response."),
},
pathParams = {
@OpenApiParam(name = "dataset",
@@ -230,7 +235,8 @@ public void getOne(@NotNull Context ctx, @NotNull String dataSet) {
String locationType = queryParamAsClass(ctx, new String[]{LOCATION_TYPE_LIKE},
String.class, null, metrics, name(CatalogController.class.getName(), GET_ONE));
-
+ boolean includeAliases = ctx.queryParamAsClass(INCLUDE_ALIASES, Boolean.class)
+ .getOrDefault(false);
String acceptHeader = ctx.header(ACCEPT);
ContentType contentType = Formats.parseHeader(acceptHeader, Catalog.class);
Catalog cat = null;
@@ -254,6 +260,7 @@ public void getOne(@NotNull Context ctx, @NotNull String dataSet) {
.withExcludeEmpty(excludeExtents)
.withLocationKind(locationKind)
.withLocationType(locationType)
+ .withIncludeAliases(includeAliases)
.build();
cat = tsDao.getTimeSeriesCatalog(cursor, pageSize, parameters);
diff --git a/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java b/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java
index b8be777f1b..c899567f70 100644
--- a/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java
+++ b/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java
@@ -146,6 +146,7 @@ public final class Controllers {
public static final String ISSUE_DATE = "issue-date";
public static final String LOCATION_KIND_LIKE = "location-kind-like";
public static final String LOCATION_TYPE_LIKE = "location-type-like";
+ public static final String INCLUDE_ALIASES = "include-aliases";
public static final String MIN_NUMBER = "min-number";
public static final String MAX_NUMBER = "max-number";
public static final String MIN_HEIGHT = "min-height";
diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/CatalogRequestParameters.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/CatalogRequestParameters.java
index f652d55384..60faf36d1b 100644
--- a/cwms-data-api/src/main/java/cwms/cda/data/dao/CatalogRequestParameters.java
+++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/CatalogRequestParameters.java
@@ -20,6 +20,7 @@ public class CatalogRequestParameters {
private final boolean excludeEmpty;
private final String locationKind;
private final String locationType;
+ private final boolean includeAliases;
private CatalogRequestParameters(Builder builder) {
this.office = builder.office;
@@ -34,6 +35,7 @@ private CatalogRequestParameters(Builder builder) {
this.excludeEmpty = builder.excludeEmpty;
this.locationKind = builder.locationKind;
this.locationType = builder.locationType;
+ this.includeAliases = builder.includeAliases;
}
public String getBoundingOfficeLike() {
@@ -84,6 +86,10 @@ public String getLocationType() {
return locationType;
}
+ public boolean includeAliases() {
+ return includeAliases;
+ }
+
public static class Builder {
String office;
@@ -98,6 +104,7 @@ public static class Builder {
private boolean excludeEmpty = true;
String locationKind;
String locationType;
+ private boolean includeAliases = false;
public Builder() {
@@ -163,6 +170,11 @@ public Builder withLocationType(String locationType) {
return this;
}
+ public Builder withIncludeAliases(boolean includeAliases) {
+ this.includeAliases = includeAliases;
+ return this;
+ }
+
public static Builder from(CatalogRequestParameters params) {
// This NEEDS to include every field in the CatalogRequestParameters
return new Builder()
diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java
index dce0f3344a..702f28cc11 100644
--- a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java
+++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java
@@ -1,6 +1,9 @@
package cwms.cda.data.dao;
+import cwms.cda.data.dto.catalog.TimeSeriesAlias;
import cwms.cda.helpers.DateUtils;
+import java.util.HashSet;
+import java.util.Set;
import static org.jooq.impl.DSL.asterisk;
import static org.jooq.impl.DSL.countDistinct;
import static org.jooq.impl.DSL.field;
@@ -9,6 +12,7 @@
import static org.jooq.impl.DSL.partitionBy;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.selectDistinct;
+import usace.cwms.db.jooq.codegen.tables.AV_CWMS_TS_ID;
import static org.jooq.impl.DSL.table;
import static usace.cwms.db.jooq.codegen.tables.AV_CWMS_TS_ID2.AV_CWMS_TS_ID2;
import static usace.cwms.db.jooq.codegen.tables.AV_TS_EXTENTS_UTC.AV_TS_EXTENTS_UTC;
@@ -84,7 +88,6 @@
import usace.cwms.db.jooq.codegen.packages.CWMS_LOC_PACKAGE;
import usace.cwms.db.jooq.codegen.packages.CWMS_TS_PACKAGE;
import usace.cwms.db.jooq.codegen.packages.CWMS_UTIL_PACKAGE;
-import usace.cwms.db.jooq.codegen.tables.AV_CWMS_TS_ID;
import usace.cwms.db.jooq.codegen.tables.AV_LOC;
import usace.cwms.db.jooq.codegen.tables.AV_LOC_GRP_ASSGN;
import usace.cwms.db.jooq.codegen.tables.AV_TSV;
@@ -107,7 +110,6 @@ public class TimeSeriesDaoImpl extends JooqDao implements TimeSeries
/** To be able to use a named inner table (otherwise JOOQ creates a random alias which messes
* with the planner) we need to use fixed names to be able to reference the required columns.
) */
- private static final AV_CWMS_TS_ID cwmsTsIdView = AV_CWMS_TS_ID.AV_CWMS_TS_ID;
private static final AV_TS_GRP_ASSGN tsGroupView = AV_TS_GRP_ASSGN.AV_TS_GRP_ASSGN;
private static final AV_LOC_GRP_ASSGN locGroupView = AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN;
@@ -128,7 +130,8 @@ public class TimeSeriesDaoImpl extends JooqDao implements TimeSeries
+ ".expireAfterSeconds", 600), TimeUnit.SECONDS)
.recordStats()
.build();
-
+ private static final FieldMapping AV_CWMS_TS_ID2_FIELD_MAP = new CwmsTsId2FieldMapping();
+ private static final FieldMapping AV_CWMS_TS_ID_FIELD_MAP = new CwmsTsIdFieldMapping();
public TimeSeriesDaoImpl(DSLContext dsl) {
this(dsl, null);
@@ -162,7 +165,6 @@ public String getTimeseries(String format, String names, String office, String u
timezone.getId(), office);
}
-
@Override
public TimeSeries getTimeseries(String page, int pageSize, String names, String office,
String units,
@@ -513,11 +515,13 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
String cursorTsId = "*";
String cursorOffice = null;
Catalog.CatalogPage catPage = null;
+ FieldMapping cwmsTsIdFields = inputParams.includeAliases() ? AV_CWMS_TS_ID2_FIELD_MAP : AV_CWMS_TS_ID_FIELD_MAP;
+ Table> table = inputParams.includeAliases() ? AV_CWMS_TS_ID2 : AV_CWMS_TS_ID.AV_CWMS_TS_ID;
if (page == null || page.isEmpty()) {
- CommonTableExpression> limiter = buildWithClause(inputParams, buildWhereConditions(inputParams),
+ CommonTableExpression> limiter = buildWithClause(cwmsTsIdFields, inputParams, buildWhereConditions(inputParams),
new ArrayList<>(), pageSize, true);
SelectJoinStep> totalQuery = dsl.with(limiter)
- .select(countDistinct(limiter.field(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE)))
+ .select(countDistinct(limiter.field(cwmsTsIdFields.getTsCode())))
.from(limiter);
logger.fine(() -> totalQuery.getSQL(ParamType.INLINED));
total = totalQuery.fetchOne(0, int.class);
@@ -544,20 +548,19 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
}
final CatalogRequestParameters params = inputParams;
- List> pageEntryFields = new ArrayList<>(getCwmsTsIdFields());
+ List> pageEntryFields = new ArrayList<>(getCwmsTsIdFieldsToIncludeInQuery(cwmsTsIdFields));
if (params.isIncludeExtents()) {
pageEntryFields.addAll(getExtentsFields());
}
List whereConditions = buildWhereConditions(params);
- List pagingConditions = buildPagingConditions(cursorOffice, cursorTsId);
- CommonTableExpression> limiter = buildWithClause(params, whereConditions, pagingConditions, pageSize, false);
- Field limiterCode = limiter.field(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE);
+ List pagingConditions = buildPagingConditions(cwmsTsIdFields, cursorOffice, cursorTsId);
+ CommonTableExpression> limiter = buildWithClause(cwmsTsIdFields, params, whereConditions, pagingConditions, pageSize, false);
+ Field limiterCode = limiter.field(cwmsTsIdFields.getTsCode());
SelectJoinStep> tmpQuery = dsl.with(limiter)
.select(pageEntryFields)
.from(limiter)
- .join(AV_CWMS_TS_ID.AV_CWMS_TS_ID)
- .on(limiterCode.eq(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE));
+ .join(table).on(limiterCode.eq(cwmsTsIdFields.getTsCode()));
if (params.isIncludeExtents()) {
@@ -566,30 +569,43 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
.eq(AV_TS_EXTENTS_UTC.TS_CODE.coerce(limiterCode)));
}
final SelectSeekStep2, String, String> overallQuery = tmpQuery
- .orderBy(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID,
- AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID);
+ .orderBy(cwmsTsIdFields.getDbOfficeId(),
+ cwmsTsIdFields.getCwmsTsId());
logger.fine(() -> overallQuery.getSQL(ParamType.INLINED));
Result> result = overallQuery.fetch();
Map tsIdExtentMap = new LinkedHashMap<>();
+ Map> tsCodeAliasMap = new LinkedHashMap<>();
+ Map tsIdToCodeMap = new LinkedHashMap<>(); //this is only for non-aliases
+ boolean includeAliases = params.includeAliases();
result.forEach(row -> {
- String officeTsId = row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID)
+ String officeTsId = row.get(cwmsTsIdFields.getDbOfficeId())
+ "/"
- + row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID);
+ + row.get(cwmsTsIdFields.getCwmsTsId());
if (!tsIdExtentMap.containsKey(officeTsId)) {
TimeseriesCatalogEntry.Builder builder = new TimeseriesCatalogEntry.Builder()
- .officeId(row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID))
- .cwmsTsId(row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID))
- .units(row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.UNIT_ID))
- .interval(row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.INTERVAL_ID))
- .intervalOffset(row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.INTERVAL_UTC_OFFSET));
+ .officeId(row.get(cwmsTsIdFields.getDbOfficeId()))
+ .cwmsTsId(row.get(cwmsTsIdFields.getCwmsTsId()))
+ .units(row.get(cwmsTsIdFields.getUnitId()))
+ .interval(row.get(cwmsTsIdFields.getIntervalId()))
+ .intervalOffset(row.get(cwmsTsIdFields.getIntervalUtcOffset()));
builder.timeZone(row.get("TIME_ZONE_ID", String.class));
if (params.isIncludeExtents()) {
builder.withExtents(new ArrayList<>());
}
- tsIdExtentMap.put(officeTsId, builder);
+ if(includeAliases) {
+ if(row.get(AV_CWMS_TS_ID2.ALIASED_ITEM) == null) {
+ tsIdExtentMap.put(officeTsId, builder); //only add non-aliases... aliases get added as a node to each entry later
+ }
+ } else {
+ tsIdExtentMap.put(officeTsId, builder);
+ }
+
+ }
+ if(includeAliases) {
+ updateAliasMapping(tsCodeAliasMap, tsIdToCodeMap, row, officeTsId);
}
if (params.isIncludeExtents()) {
@@ -599,10 +615,17 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
.withLastUpdate(DateUtils.toZdt(row.get(AV_TS_EXTENTS_UTC.LAST_UPDATE)))
.withVersionTime(DateUtils.toZdt(row.get(AV_TS_EXTENTS_UTC.VERSION_TIME)))
.build();
- tsIdExtentMap.get(officeTsId).withExtent(extents);
+ TimeseriesCatalogEntry.Builder entryBuilder = tsIdExtentMap.get(officeTsId);
+ if(entryBuilder != null) {
+ entryBuilder.withExtent(extents);
+ }
}
});
+ if(includeAliases) {
+ addAliasesToBuilders(tsIdExtentMap, tsCodeAliasMap, tsIdToCodeMap);
+ }
+
List extends CatalogEntry> entries = tsIdExtentMap.values().stream()
.map(TimeseriesCatalogEntry.Builder::build)
.collect(Collectors.toList());
@@ -611,18 +634,48 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
total, pageSize, entries, params);
}
- private static @NotNull List buildPagingConditions(String cursorOffice, String cursorTsId) {
+
+ private void addAliasesToBuilders(Map tsIdExtentMap, Map> tsCodeAliasMap, Map tsIdToCodeMap) {
+ for (Map.Entry> entry : tsCodeAliasMap.entrySet()) {
+ String tsCode = entry.getKey();
+ Set aliases = entry.getValue();
+ for (Map.Entry e : tsIdToCodeMap.entrySet()) {
+ String tsId = e.getKey();
+ String code = e.getValue();
+ if (code.equals(tsCode)) {
+ tsIdExtentMap.get(tsId).withAliases(aliases);
+ break;
+ }
+ }
+ }
+ }
+
+ private void updateAliasMapping(Map> tsCodeAliasMap, Map tsIdToCodeMap, Record row, String officeTsId) {
+ boolean isAlias = row.get(AV_CWMS_TS_ID2.ALIASED_ITEM) != null;
+ String tsCode = row.get(AV_CWMS_TS_ID2.TS_CODE).toString();
+ if(isAlias) {
+ tsCodeAliasMap.computeIfAbsent(tsCode, k -> new HashSet<>())
+ .add(new TimeSeriesAlias.Builder()
+ .withName(row.get(AV_CWMS_TS_ID2.TS_ALIAS_CATEGORY) + "-" + row.get(AV_CWMS_TS_ID2.TS_ALIAS_GROUP))
+ .withValue(row.get(AV_CWMS_TS_ID2.CWMS_TS_ID))
+ .build());
+ } else {
+ tsIdToCodeMap.put(officeTsId, tsCode);
+ }
+ }
+
+ private static @NotNull List buildPagingConditions(FieldMapping cwmsTsIdFields, String cursorOffice, String cursorTsId) {
List pagingConditions = new ArrayList<>();
// Can't do the rownum thing here b/c we want global ordering, not ordering within the page.
//pagingConditions.add(DSL.noCondition());
if (cursorOffice != null) {
- Condition moreInSameOffice = AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID
+ Condition moreInSameOffice = cwmsTsIdFields.getDbOfficeId()
.eq(cursorOffice.toUpperCase())
- .and(DSL.upper(AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID)
+ .and(DSL.upper(cwmsTsIdFields.getCwmsTsId())
.greaterThan(cursorTsId));
- Condition nextOffice = AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID
+ Condition nextOffice = cwmsTsIdFields.getDbOfficeId()
.greaterThan(cursorOffice.toUpperCase());
pagingConditions.add(moreInSameOffice.or(nextOffice));
}
@@ -638,16 +691,21 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
return extentsFields;
}
- private @NotNull List> getCwmsTsIdFields() {
- List> cwmsTsIdFields = new ArrayList<>();
- cwmsTsIdFields.add(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID);
- cwmsTsIdFields.add(AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID);
- cwmsTsIdFields.add(AV_CWMS_TS_ID.AV_CWMS_TS_ID.UNIT_ID);
- cwmsTsIdFields.add(AV_CWMS_TS_ID.AV_CWMS_TS_ID.INTERVAL_ID);
- cwmsTsIdFields.add(AV_CWMS_TS_ID.AV_CWMS_TS_ID.INTERVAL_UTC_OFFSET);
- cwmsTsIdFields.add(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TIME_ZONE_ID);
-
- return cwmsTsIdFields;
+ private @NotNull List> getCwmsTsIdFieldsToIncludeInQuery(FieldMapping cwmsTsIdFields) {
+ List> retVal = new ArrayList<>();
+ retVal.add(cwmsTsIdFields.getDbOfficeId());
+ retVal.add(cwmsTsIdFields.getCwmsTsId());
+ retVal.add(cwmsTsIdFields.getUnitId());
+ retVal.add(cwmsTsIdFields.getIntervalId());
+ retVal.add(cwmsTsIdFields.getIntervalUtcOffset());
+ retVal.add(cwmsTsIdFields.getTimeZoneId());
+ if(cwmsTsIdFields.includesAliases()) {
+ retVal.add(AV_CWMS_TS_ID2.ALIASED_ITEM);
+ retVal.add(AV_CWMS_TS_ID2.TS_CODE);
+ retVal.add(AV_CWMS_TS_ID2.TS_ALIAS_CATEGORY);
+ retVal.add(AV_CWMS_TS_ID2.TS_ALIAS_GROUP);
+ }
+ return retVal;
}
private @NotNull List buildWhereConditions(CatalogRequestParameters params) {
@@ -660,34 +718,33 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
return conditions;
}
- private static @NotNull CommonTableExpression> buildWithClause(CatalogRequestParameters params,
- List whereConditions, List pagingConditions, int pageSize, boolean forCount) {
- TableLike> fromTable = AV_CWMS_TS_ID.AV_CWMS_TS_ID;
-
+ private static @NotNull CommonTableExpression> buildWithClause(FieldMapping cwmsTsIdFields, CatalogRequestParameters params,
+ List whereConditions, List pagingConditions, int pageSize, boolean forCount) {
+ Table> fromTable = params.includeAliases() ? AV_CWMS_TS_ID2 : AV_CWMS_TS_ID.AV_CWMS_TS_ID;
List> selectFields = new ArrayList<>();
- selectFields.add(fromTable.field(cwmsTsIdView.TS_CODE));
- selectFields.add(fromTable.field(cwmsTsIdView.DB_OFFICE_ID));
+ selectFields.add(fromTable.field(cwmsTsIdFields.getTsCode()));
+ selectFields.add(fromTable.field(cwmsTsIdFields.getDbOfficeId()));
- selectFields.add(fromTable.field(cwmsTsIdView.CWMS_TS_ID));
+ selectFields.add(fromTable.field(cwmsTsIdFields.getCwmsTsId()));
TableOnConditionStep on = null;
-
+ Table> table = params.includeAliases() ? AV_CWMS_TS_ID2 : AV_CWMS_TS_ID.AV_CWMS_TS_ID;
if (params.needs(tsGroupView)) {
- on = AV_CWMS_TS_ID.AV_CWMS_TS_ID
+ on = table
.join(tsGroupView)
- .on(cwmsTsIdView.TS_CODE.eq(tsGroupView.TS_CODE));
+ .on(cwmsTsIdFields.getTsCode().eq(tsGroupView.TS_CODE));
fromTable = on;
}
if (params.needs(AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN)) {
if (on == null) {
- on = AV_CWMS_TS_ID.AV_CWMS_TS_ID
+ on = table
.leftJoin(AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN)
- .on(AV_CWMS_TS_ID.AV_CWMS_TS_ID.LOCATION_CODE
+ .on(cwmsTsIdFields.getLocationCode()
.eq(AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN.LOCATION_CODE));
} else {
on = on
.leftJoin(AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN)
- .on(AV_CWMS_TS_ID.AV_CWMS_TS_ID.LOCATION_CODE
+ .on(cwmsTsIdFields.getLocationCode()
.eq(AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN.LOCATION_CODE));
}
fromTable = on;
@@ -695,16 +752,16 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
if (params.needs(AV_LOC.AV_LOC)) {
if (on == null) {
- on = AV_CWMS_TS_ID.AV_CWMS_TS_ID
+ on = table
.leftJoin(AV_LOC.AV_LOC)
.on(AV_LOC.AV_LOC.LOCATION_CODE
- .eq(AV_CWMS_TS_ID.AV_CWMS_TS_ID.LOCATION_CODE
+ .eq(cwmsTsIdFields.getLocationCode()
.coerce(AV_LOC.AV_LOC.LOCATION_CODE)));
} else {
on = on
.leftJoin(AV_LOC.AV_LOC)
.on(AV_LOC.AV_LOC.LOCATION_CODE
- .eq(AV_CWMS_TS_ID.AV_CWMS_TS_ID.LOCATION_CODE
+ .eq(cwmsTsIdFields.getLocationCode()
.coerce(AV_LOC.AV_LOC.LOCATION_CODE)));
}
selectFields.add(AV_LOC.AV_LOC.BOUNDING_OFFICE_ID);
@@ -713,17 +770,17 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
if (params.isExcludeEmpty()) {
if (on == null) {
- on = AV_CWMS_TS_ID.AV_CWMS_TS_ID
+ on = table
.leftJoin(AV_TS_EXTENTS_UTC)
- .on(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE
+ .on(cwmsTsIdFields.getTsCode()
.eq(AV_TS_EXTENTS_UTC.TS_CODE
- .coerce(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE)));
+ .coerce(cwmsTsIdFields.getTsCode())));
} else {
on = on
.leftJoin(AV_TS_EXTENTS_UTC)
- .on(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE
+ .on(cwmsTsIdFields.getTsCode()
.eq(AV_TS_EXTENTS_UTC.TS_CODE
- .coerce(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE)));
+ .coerce(cwmsTsIdFields.getTsCode())));
}
fromTable = on;
}
@@ -731,23 +788,23 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar
TableLike> innerSelect = selectDistinct(selectFields)
.from(fromTable)
.where(whereConditions).and(DSL.and(pagingConditions))
- .orderBy(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID,
- AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID)
+ .orderBy(cwmsTsIdFields.getDbOfficeId(),
+ cwmsTsIdFields.getCwmsTsId())
.asTable("limiterInner");
if (forCount) {
return name("limiter").as(
select(asterisk())
.from(innerSelect)
- .orderBy(innerSelect.field(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID),
- innerSelect.field(AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID))
+ .orderBy(innerSelect.field(cwmsTsIdFields.getDbOfficeId()),
+ innerSelect.field(cwmsTsIdFields.getCwmsTsId()))
);
} else {
return name("limiter").as(
select(asterisk())
.from(innerSelect)
.where(field("rownum").lessOrEqual(pageSize))
- .orderBy(innerSelect.field(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID),
- innerSelect.field(AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID))
+ .orderBy(innerSelect.field(cwmsTsIdFields.getDbOfficeId()),
+ innerSelect.field(cwmsTsIdFields.getCwmsTsId()))
);
}
}
@@ -808,14 +865,14 @@ private Collection extends Condition> buildTsGrpAssgnConditions(CatalogRequest
private Collection extends Condition> buildCwmsTsIdConditions(CatalogRequestParameters params) {
List retval = new ArrayList<>();
-
+ FieldMapping cwmsTsIdFields = params.includeAliases() ? AV_CWMS_TS_ID2_FIELD_MAP : AV_CWMS_TS_ID_FIELD_MAP;
if (params.getOffice() != null) {
- retval.add(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID.eq(params.getOffice().toUpperCase()));
+ retval.add(cwmsTsIdFields.getDbOfficeId().eq(params.getOffice().toUpperCase()));
}
retval.add(
caseInsensitiveLikeRegexNullTrue(
- AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID,
+ cwmsTsIdFields.getCwmsTsId(),
params.getIdLike()));
return retval;
@@ -1386,4 +1443,110 @@ public DeleteOptions build() {
}
}
+ private interface FieldMapping {
+ Field getTsCode();
+ Field getLocationCode();
+ Field getDbOfficeId();
+ Field getCwmsTsId();
+ Field getUnitId();
+ Field getIntervalId();
+ Field getIntervalUtcOffset();
+ Field getTimeZoneId();
+ boolean includesAliases();
+ }
+
+ private static class CwmsTsIdFieldMapping implements FieldMapping {
+ @Override
+ public Field getTsCode() {
+ return AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE;
+ }
+
+ @Override
+ public Field getLocationCode() {
+ return AV_CWMS_TS_ID.AV_CWMS_TS_ID.LOCATION_CODE;
+ }
+
+ @Override
+ public Field getDbOfficeId() {
+ return AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID;
+ }
+
+ @Override
+ public Field getCwmsTsId() {
+ return AV_CWMS_TS_ID.AV_CWMS_TS_ID.CWMS_TS_ID;
+ }
+
+ @Override
+ public Field getUnitId() {
+ return AV_CWMS_TS_ID.AV_CWMS_TS_ID.UNIT_ID;
+ }
+
+ @Override
+ public Field getIntervalId() {
+ return AV_CWMS_TS_ID.AV_CWMS_TS_ID.INTERVAL_ID;
+ }
+
+ @Override
+ public Field getIntervalUtcOffset() {
+ return AV_CWMS_TS_ID.AV_CWMS_TS_ID.INTERVAL_UTC_OFFSET;
+ }
+
+ @Override
+ public Field getTimeZoneId() {
+ return AV_CWMS_TS_ID.AV_CWMS_TS_ID.TIME_ZONE_ID;
+ }
+
+ @Override
+ public boolean includesAliases() {
+ return false;
+ }
+ }
+
+ private static class CwmsTsId2FieldMapping implements FieldMapping {
+ @Override
+ public Field getTsCode() {
+ return AV_CWMS_TS_ID2.TS_CODE;
+ }
+
+ @Override
+ public Field getLocationCode() {
+ return AV_CWMS_TS_ID2.LOCATION_CODE;
+ }
+
+ @Override
+ public Field getDbOfficeId() {
+ return AV_CWMS_TS_ID2.DB_OFFICE_ID;
+ }
+
+ @Override
+ public Field getCwmsTsId() {
+ return AV_CWMS_TS_ID2.CWMS_TS_ID;
+ }
+
+ @Override
+ public Field getUnitId() {
+ return AV_CWMS_TS_ID2.UNIT_ID;
+ }
+
+ @Override
+ public Field getIntervalId() {
+ return AV_CWMS_TS_ID2.INTERVAL_ID;
+ }
+
+ @Override
+ public Field getIntervalUtcOffset() {
+ return AV_CWMS_TS_ID2.INTERVAL_UTC_OFFSET;
+ }
+
+ @Override
+ public Field getTimeZoneId() {
+ return AV_CWMS_TS_ID2.TIME_ZONE_ID;
+ }
+
+ @Override
+ public boolean includesAliases() {
+ return true;
+ }
+ }
+
}
diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/catalog/TimeSeriesAlias.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/catalog/TimeSeriesAlias.java
new file mode 100644
index 0000000000..5dae448608
--- /dev/null
+++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/catalog/TimeSeriesAlias.java
@@ -0,0 +1,76 @@
+package cwms.cda.data.dto.catalog;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonRootName;
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import cwms.cda.formatters.Formats;
+import cwms.cda.formatters.annotations.FormattableWith;
+import cwms.cda.formatters.json.JsonV2;
+import java.util.Objects;
+
+@JsonRootName("alias")
+@FormattableWith(contentType = Formats.JSONV2, formatter = JsonV2.class, aliases = {Formats.DEFAULT, Formats.JSON})
+@JsonDeserialize(builder = TimeSeriesAlias.Builder.class)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy.class)
+public final class TimeSeriesAlias {
+
+ @JacksonXmlProperty(isAttribute = true)
+ private final String name;
+ private final String value;
+
+ private TimeSeriesAlias(Builder builder) {
+ this.name = builder.name;
+ this.value = builder.value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TimeSeriesAlias that = (TimeSeriesAlias) o;
+ return Objects.equals(name, that.name) && Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, value);
+ }
+
+ public static final class Builder {
+ private String name;
+ private String value;
+
+ public Builder() {
+ }
+
+ public Builder withName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder withValue(String value) {
+ this.value = value;
+ return this;
+ }
+
+ public TimeSeriesAlias build() {
+ return new TimeSeriesAlias(this);
+ }
+ }
+}
diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/catalog/TimeseriesCatalogEntry.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/catalog/TimeseriesCatalogEntry.java
index 1493288f9a..44a3c8e613 100644
--- a/cwms-data-api/src/main/java/cwms/cda/data/dto/catalog/TimeseriesCatalogEntry.java
+++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/catalog/TimeseriesCatalogEntry.java
@@ -3,6 +3,7 @@
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
@@ -29,6 +30,9 @@ public class TimeseriesCatalogEntry extends CatalogEntry {
@JacksonXmlProperty(localName = "extents")
private List extents;
+ @JacksonXmlElementWrapper(localName = "aliases")
+ @JacksonXmlProperty(localName = "alias")
+ private Collection aliases;
public String getName() {
return this.name;
@@ -52,18 +56,23 @@ public List getExtents() {
return extents;
}
+ public Collection getAliases() {
+ return aliases;
+ }
+
private TimeseriesCatalogEntry() {
super(null);
}
- private TimeseriesCatalogEntry(String office, String name, String units, String interval, Long intervalOffset, String timeZone, List extents) {
- super(office);
- this.name = name;
- this.units = units;
- this.interval = interval;
- this.intervalOffset = intervalOffset;
- this.timeZone = timeZone;
- this.extents = extents;
+ private TimeseriesCatalogEntry(Builder builder) {
+ super(builder.office);
+ this.name = builder.tsName;
+ this.units = builder. units;
+ this.interval = builder.interval;
+ this.intervalOffset = builder.intervalOffset;
+ this.timeZone = builder.timeZone;
+ this.extents = builder.extents;
+ this.aliases = builder.aliases;
}
public String getUnits() {
@@ -90,6 +99,7 @@ public static class Builder {
private ZonedDateTime earliestTime;
private ZonedDateTime latestTime;
private List extents = null;
+ private Collection aliases = null;
public Builder officeId(final String office) {
this.office = office;
@@ -143,8 +153,17 @@ public Builder withExtents(final List newExtents) {
return this;
}
+ public Builder withAliases(final Collection aliases) {
+ if (aliases == null) {
+ this.aliases = null;
+ } else {
+ this.aliases = new ArrayList<>(aliases);
+ }
+ return this;
+ }
+
public TimeseriesCatalogEntry build() {
- return new TimeseriesCatalogEntry(office, tsName, units, interval, intervalOffset, timeZone, extents);
+ return new TimeseriesCatalogEntry(this);
}
}
}
diff --git a/cwms-data-api/src/main/java/cwms/cda/formatters/xml/XMLv1.java b/cwms-data-api/src/main/java/cwms/cda/formatters/xml/XMLv1.java
index 085fdd196a..f357b8f646 100644
--- a/cwms-data-api/src/main/java/cwms/cda/formatters/xml/XMLv1.java
+++ b/cwms-data-api/src/main/java/cwms/cda/formatters/xml/XMLv1.java
@@ -87,7 +87,7 @@ public T parseContent(InputStream content, Class type
}
}
- private static @NotNull XmlMapper buildObjectMapper() {
+ public static @NotNull XmlMapper buildObjectMapper() {
XmlMapper retval = new XmlMapper();
retval.findAndRegisterModules();
diff --git a/cwms-data-api/src/test/java/cwms/cda/api/CatalogControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/CatalogControllerTestIT.java
index 88e89f9952..e87e647c9a 100644
--- a/cwms-data-api/src/test/java/cwms/cda/api/CatalogControllerTestIT.java
+++ b/cwms-data-api/src/test/java/cwms/cda/api/CatalogControllerTestIT.java
@@ -1,13 +1,24 @@
package cwms.cda.api;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import static cwms.cda.api.Controllers.BOUNDING_OFFICE_LIKE;
import static cwms.cda.api.Controllers.EXCLUDE_EMPTY;
+import static cwms.cda.api.Controllers.INCLUDE_ALIASES;
import static cwms.cda.api.Controllers.LIKE;
import static cwms.cda.api.Controllers.LOCATION_CATEGORY_LIKE;
import static cwms.cda.api.Controllers.LOCATION_GROUP_LIKE;
import static cwms.cda.api.Controllers.LOCATION_KIND_LIKE;
import static cwms.cda.api.Controllers.TIMESERIES_CATEGORY_LIKE;
import static cwms.cda.api.Controllers.TIMESERIES_GROUP_LIKE;
+import cwms.cda.data.dto.catalog.TimeSeriesAlias;
+import cwms.cda.data.dto.catalog.TimeseriesCatalogEntry;
+import cwms.cda.formatters.json.JsonV2;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.*;
import cwms.cda.data.dao.DeleteRule;
@@ -125,6 +136,80 @@ void test_no_aliased_results_returned() {
.body("entries.size()",is(4));
}
+ @Test
+ void test_no_aliases_returned() {
+ Integer numAliases = given().accept(Formats.JSONV2)
+ .log().ifValidationFails(LogDetail.ALL, true)
+ .queryParam(Controllers.OFFICE, OFFICE)
+ .queryParam(EXCLUDE_EMPTY, false)
+ .when()
+ .get("/catalog/TIMESERIES")
+ .then()
+ .log().ifValidationFails(LogDetail.ALL, true)
+ .assertThat()
+ .statusCode(is(200))
+ .extract()
+ .jsonPath()
+ .getObject("entries.aliases.aliases.size()", Integer.class);
+ assertEquals(0, (int) numAliases, "Expected no aliases, but found some.");
+ }
+
+ @Test
+ void test_aliases_returned() {
+ Integer numAliases = given().accept(Formats.JSONV2)
+ .log().ifValidationFails(LogDetail.ALL, true)
+ .queryParam(Controllers.OFFICE, OFFICE)
+ .queryParam(EXCLUDE_EMPTY,false)
+ .queryParam(INCLUDE_ALIASES,true)
+ .when()
+ .get("/catalog/TIMESERIES")
+ .then()
+ .log().ifValidationFails(LogDetail.ALL, true)
+ .assertThat()
+ .statusCode(is(200))
+ .extract()
+ .jsonPath()
+ .getObject("entries.aliases.aliases.size()", Integer.class);
+ assertTrue(numAliases > 0, "Expected aliases, but found none.");
+ }
+
+ @Test
+ void test_alias_is_correct() throws JsonProcessingException {
+ Response response = given().accept(Formats.JSONV2)
+ .log().ifValidationFails(LogDetail.ALL, true)
+ .queryParam(Controllers.OFFICE, OFFICE)
+ .queryParam(EXCLUDE_EMPTY, false)
+ .queryParam(INCLUDE_ALIASES, true)
+ .when()
+ .get("/catalog/TIMESERIES");
+ String json = response.body().asPrettyString();
+ ObjectMapper om = JsonV2.buildObjectMapper();
+ JsonNode root = om.readTree(json);
+ JsonNode entriesNode = root.get("entries");
+ String entriesJson = om.writeValueAsString(entriesNode);
+ List entries = om.readValue(entriesJson, new TypeReference>() {});
+ assertNotNull(entries);
+ TimeseriesCatalogEntry alias = entries
+ .stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet()).stream()
+ .filter(e -> e.getName().equals("Pine Flat-Outflow.Stage.Inst.15Minutes.0.one"))
+ .findFirst()
+ .orElse(null);
+ assertNotNull(alias);
+ assertTrue(alias.getAliases().contains(new TimeSeriesAlias.Builder()
+ .withName("Test Category-LessThan3")
+ .withValue("test alias 1")
+ .build()));
+ //make sure no entries exist with name "test alias 1"
+ List aliasesAsAnEntry = entries
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(e -> e.getName().equals("test alias 1"))
+ .collect(Collectors.toList());
+ assertTrue(aliasesAsAnEntry.isEmpty(), "Found entries with name 'test alias 1', which should not exist.");
+ }
+
@Test
void test_queries_are_case_insensitive() {
diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dto/catalog/TimeSeriesAliasTest.java b/cwms-data-api/src/test/java/cwms/cda/data/dto/catalog/TimeSeriesAliasTest.java
new file mode 100644
index 0000000000..e3683f6aad
--- /dev/null
+++ b/cwms-data-api/src/test/java/cwms/cda/data/dto/catalog/TimeSeriesAliasTest.java
@@ -0,0 +1,57 @@
+package cwms.cda.data.dto.catalog;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import cwms.cda.formatters.json.JsonV2;
+import cwms.cda.formatters.xml.XMLv1;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.io.IOUtils;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import org.junit.jupiter.api.Test;
+
+final class TimeSeriesAliasTest {
+
+ @Test
+ void testJsonDeserialization() throws IOException {
+ InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/data/dto/time-series-alias.json");
+ assertNotNull(resource);
+ String json = IOUtils.toString(resource, StandardCharsets.UTF_8);
+ TimeSeriesAlias deserialized = JsonV2.buildObjectMapper().readValue(json, TimeSeriesAlias.class);
+ assertEquals(deserialized.getName(), "Test Category-LessThan3");
+ assertEquals(deserialized.getValue(), "test alias 1");
+ }
+
+ @Test
+ void testJsonSerializationRoundTrip() throws JsonProcessingException {
+ TimeSeriesAlias alias = new TimeSeriesAlias.Builder()
+ .withName("Test Category-LessThan3")
+ .withValue("test alias 1")
+ .build();
+
+ String json = JsonV2.buildObjectMapper().writeValueAsString(alias);
+
+ assertNotNull(json);
+
+ TimeSeriesAlias returned = JsonV2.buildObjectMapper().readValue(json, TimeSeriesAlias.class);
+
+ assertEquals(alias, returned);
+ }
+
+ @Test
+ void testXmlSerializationRoundTip() throws JsonProcessingException {
+ TimeSeriesAlias alias = new TimeSeriesAlias.Builder()
+ .withName("Test Category-LessThan3")
+ .withValue("test alias 1")
+ .build();
+
+ String xml = XMLv1.buildObjectMapper().writeValueAsString(alias);
+
+ assertNotNull(xml);
+
+ TimeSeriesAlias returned = XMLv1.buildObjectMapper().readValue(xml, TimeSeriesAlias.class);
+
+ assertEquals(alias, returned);
+ }
+}
diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dto/catalog/TimeseriesCatalogEntryTest.java b/cwms-data-api/src/test/java/cwms/cda/data/dto/catalog/TimeseriesCatalogEntryTest.java
index 03298ffca8..b729161f48 100644
--- a/cwms-data-api/src/test/java/cwms/cda/data/dto/catalog/TimeseriesCatalogEntryTest.java
+++ b/cwms-data-api/src/test/java/cwms/cda/data/dto/catalog/TimeseriesCatalogEntryTest.java
@@ -1,10 +1,18 @@
package cwms.cda.data.dto.catalog;
+import cwms.cda.formatters.json.JsonV2;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import io.restassured.path.json.JsonPath;
import io.restassured.path.xml.XmlPath;
+import java.util.Arrays;
+import java.util.Collection;
+import org.apache.commons.io.IOUtils;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import cwms.cda.data.dto.Catalog;
@@ -42,6 +50,10 @@ void test_xml_serialization_earliest(){
Object tmp = path.get("catalog.entries.entry.extents");
assertThat(path.getString("catalog.entries.entry.extents.extents.earliest-time"), equalTo("2017-07-27T05:00:00Z"));
assertThat(path.getString("catalog.entries.entry.extents.extents.latest-time"), equalTo("2017-11-24T22:30:00Z"));
+ assertThat(path.getString("catalog.entries.entry.aliases.alias[0].@name"), equalTo("alias1"));
+ assertThat(path.getString("catalog.entries.entry.aliases.alias[0].value"), equalTo("value1"));
+ assertThat(path.getString("catalog.entries.entry.aliases.alias[1].@name"), equalTo("alias2"));
+ assertThat(path.getString("catalog.entries.entry.aliases.alias[1].value"), equalTo("value2"));
}
@@ -66,6 +78,10 @@ void test_json_serialization_earliest(){
assertThat(path.getString("entries[0].time-zone"), equalTo("US/Central"));
assertThat(path.getString("entries[0].extents[0].earliest-time"), equalTo("2017-07-27T05:00:00Z"));
assertThat(path.getString("entries[0].extents[0].latest-time"), equalTo("2017-11-24T22:30:00Z"));
+ assertThat(path.getString("entries[0].aliases[0].name"), equalTo("alias1"));
+ assertThat(path.getString("entries[0].aliases[0].value"), equalTo("value1"));
+ assertThat(path.getString("entries[0].aliases[1].name"), equalTo("alias2"));
+ assertThat(path.getString("entries[0].aliases[1].value"), equalTo("value2"));
}
@@ -100,6 +116,22 @@ void test_xml_serialization_no_cursor() {
assertFalse(xml.contains("cursor"));
}
+ @Test
+ void test_json_deserialization() throws IOException {
+ InputStream resource = this.getClass().getResourceAsStream("/cwms/cda/data/dto/time-series-catalog-entry.json");
+ assertNotNull(resource);
+ String json = IOUtils.toString(resource, StandardCharsets.UTF_8);
+ TimeseriesCatalogEntry deserialized = JsonV2.buildObjectMapper().readValue(json, TimeseriesCatalogEntry.class);
+ assertEquals("Pine Flat-Outflow.Stage.Inst.15Minutes.0.one", deserialized.getName());
+ assertEquals("SPK", deserialized.getOffice());
+ assertEquals("m", deserialized.getUnits());
+ assertEquals("15Minutes", deserialized.getInterval());
+ Collection aliases = deserialized.getAliases();
+ assertEquals(1, aliases.size());
+ TimeSeriesAlias alias = aliases.iterator().next();
+ assertEquals("Test Category-LessThan3", alias.getName());
+ assertEquals("test alias 1", alias.getValue());
+ }
private TimeseriesCatalogEntry buildEntry()
{
@@ -113,7 +145,10 @@ private TimeseriesCatalogEntry buildEntry()
.withEarliestTime(ZonedDateTime.parse("2017-07-27T05:00:00Z"))
.withLatestTime(ZonedDateTime.parse("2017-11-24T22:30:00Z"))
.withLastUpdate(ZonedDateTime.parse("2017-11-24T22:30:00Z"))
- .build());
+ .build())
+ .withAliases(Arrays.asList(
+ new TimeSeriesAlias.Builder().withName("alias1").withValue("value1").build(),
+ new TimeSeriesAlias.Builder().withName("alias2").withValue("value2").build()));
return builder
.build();
diff --git a/cwms-data-api/src/test/resources/cwms/cda/data/dto/time-series-alias.json b/cwms-data-api/src/test/resources/cwms/cda/data/dto/time-series-alias.json
new file mode 100644
index 0000000000..68d3891f3f
--- /dev/null
+++ b/cwms-data-api/src/test/resources/cwms/cda/data/dto/time-series-alias.json
@@ -0,0 +1,4 @@
+{
+ "name":"Test Category-LessThan3",
+ "value":"test alias 1"
+}
\ No newline at end of file
diff --git a/cwms-data-api/src/test/resources/cwms/cda/data/dto/time-series-catalog-entry.json b/cwms-data-api/src/test/resources/cwms/cda/data/dto/time-series-catalog-entry.json
new file mode 100644
index 0000000000..1bfff729b9
--- /dev/null
+++ b/cwms-data-api/src/test/resources/cwms/cda/data/dto/time-series-catalog-entry.json
@@ -0,0 +1,18 @@
+{
+ "office": "SPK",
+ "name": "Pine Flat-Outflow.Stage.Inst.15Minutes.0.one",
+ "units": "m",
+ "interval": "15Minutes",
+ "interval-offset": 2147483647,
+ "time-zone": "UTC",
+ "extents": [
+ {},
+ {}
+ ],
+ "aliases": [
+ {
+ "name": "Test Category-LessThan3",
+ "value": "test alias 1"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cwms-data-api/src/test/resources/cwms/cda/data/sql/ts_catalog_setup.sql b/cwms-data-api/src/test/resources/cwms/cda/data/sql/ts_catalog_setup.sql
index b956e4e586..6b953da329 100644
--- a/cwms-data-api/src/test/resources/cwms/cda/data/sql/ts_catalog_setup.sql
+++ b/cwms-data-api/src/test/resources/cwms/cda/data/sql/ts_catalog_setup.sql
@@ -135,7 +135,7 @@ begin
p_ts_group_id=>'LessThan3',
p_ts_id=>'Pine Flat-Outflow.Stage.Inst.15Minutes.0.one',
p_ts_attribute=>0,
- p_ts_alias_id=>null,
+ p_ts_alias_id=>'test alias 1',
p_ref_ts_id=>NULL,
p_db_office_id=>l_office);