From 4ffb43fe688c3006dfc667455b4aeefa7fcdb355 Mon Sep 17 00:00:00 2001 From: Adam Korynta Date: Wed, 13 Nov 2024 10:52:10 -0800 Subject: [PATCH 1/6] updates for loc/ts group assignments with category/group offices --- .../cwms/cda/data/dao/LocationGroupDao.java | 18 ++++++++++-------- .../cwms/cda/data/dao/TimeSeriesGroupDao.java | 17 +++++++---------- .../fixtures/CwmsDataApiSetupCallback.java | 4 +++- gradle/libs.versions.toml | 2 +- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationGroupDao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationGroupDao.java index c2172669b..e0fe44a23 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationGroupDao.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationGroupDao.java @@ -439,14 +439,16 @@ public FeatureCollection buildFeatureCollectionForLocationGroup(String officeId, AV_LOC al = AV_LOC.AV_LOC; SelectSeekStep1 select = dsl.select(al.asterisk(), alga.CATEGORY_ID, - alga.GROUP_ID, alga.ATTRIBUTE, alga.ALIAS_ID, alga.SHARED_REF_LOCATION_ID, - alga.SHARED_ALIAS_ID) - .from(al).join(alga).on(al.LOCATION_ID.eq(alga.LOCATION_ID)) - .where(alga.DB_OFFICE_ID.eq(officeId) - .and(alga.CATEGORY_ID.eq(categoryId) - .and(alga.GROUP_ID.eq(groupId)) - .and(al.UNIT_SYSTEM.eq(units)))) - .orderBy(alga.ATTRIBUTE); + alga.GROUP_ID, alga.ATTRIBUTE, alga.ALIAS_ID, alga.SHARED_REF_LOCATION_ID, + alga.SHARED_ALIAS_ID) + .from(al).join(alga).on(al.LOCATION_ID.eq(alga.LOCATION_ID)) + .where(alga.DB_OFFICE_ID.eq(officeId) + .and(alga.CATEGORY_OFFICE_ID.eq()) + .and(alga.GROUP_OFFICE_ID.eq()) + .and(alga.CATEGORY_ID.eq(categoryId) + .and(alga.GROUP_ID.eq(groupId)) + .and(al.UNIT_SYSTEM.eq(units)))) + .orderBy(alga.ATTRIBUTE); List features = select.stream() diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesGroupDao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesGroupDao.java index 3c06b9682..4ed6a1ad4 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesGroupDao.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesGroupDao.java @@ -112,22 +112,19 @@ private List getTimeSeriesGroupsWhere(Condition whereCond) { return new Pair<>(group, loc); }; - SelectOnConditionStep selectOn = dsl.select(catGrp.CAT_DB_OFFICE_ID, + SelectSeekStep1 query = dsl.select(catGrp.CAT_DB_OFFICE_ID, catGrp.TS_CATEGORY_ID, catGrp.TS_CATEGORY_DESC, catGrp.GRP_DB_OFFICE_ID, catGrp.TS_GROUP_ID, catGrp.TS_GROUP_DESC, catGrp.SHARED_TS_ALIAS_ID, catGrp.SHARED_REF_TS_ID, grpAssgn.CATEGORY_ID, grpAssgn.DB_OFFICE_ID, grpAssgn.GROUP_ID, grpAssgn.TS_ID, grpAssgn.TS_CODE, grpAssgn.ATTRIBUTE, - grpAssgn.ALIAS_ID, grpAssgn.REF_TS_ID) + grpAssgn.ALIAS_ID, grpAssgn.REF_TS_ID, grpAssgn.CATEGORY_OFFICE_ID, grpAssgn.GROUP_OFFICE_ID) .from(catGrp).leftJoin(grpAssgn) .on(catGrp.TS_CATEGORY_ID.eq(grpAssgn.CATEGORY_ID) - .and(catGrp.TS_GROUP_ID.eq(grpAssgn.GROUP_ID))); - - SelectOrderByStep select = selectOn; - if (whereCond != null) { - select = selectOn.where(whereCond); - } - - final SelectSeekStep1 query = select.orderBy(grpAssgn.ATTRIBUTE); + .and(catGrp.TS_GROUP_ID.eq(grpAssgn.GROUP_ID))) + .where(whereCond) + .and(grpAssgn.CATEGORY_OFFICE_ID.eq()) + .and(grpAssgn.GROUP_OFFICE_ID.eq()) + .orderBy(grpAssgn.ATTRIBUTE); logger.fine(() -> query.getSQL(ParamType.INLINED)); diff --git a/cwms-data-api/src/test/java/fixtures/CwmsDataApiSetupCallback.java b/cwms-data-api/src/test/java/fixtures/CwmsDataApiSetupCallback.java index 519eac93f..abce0b0ee 100644 --- a/cwms-data-api/src/test/java/fixtures/CwmsDataApiSetupCallback.java +++ b/cwms-data-api/src/test/java/fixtures/CwmsDataApiSetupCallback.java @@ -30,6 +30,7 @@ import io.restassured.response.ValidatableResponse; import javax.servlet.http.HttpServletResponse; +import org.testcontainers.images.PullPolicy; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.is; @@ -45,7 +46,7 @@ public class CwmsDataApiSetupCallback implements BeforeAllCallback,AfterAllCallb private static final String ORACLE_IMAGE = System.getProperty("CDA.oracle.database.image",System.getProperty("RADAR.oracle.database.image", CwmsDatabaseContainer.ORACLE_19C)); private static final String ORACLE_VOLUME = System.getProperty("CDA.oracle.database.volume",System.getProperty("RADAR.oracle.database.volume", "cwmsdb_data_api_volume")); - static final String CWMS_DB_IMAGE = System.getProperty("CDA.cwms.database.image",System.getProperty("RADAR.cwms.database.image", "registry.hecdev.net/cwms/schema_installer:99.99.99.2-CDA_STAGING")); + static final String CWMS_DB_IMAGE = System.getProperty("CDA.cwms.database.image",System.getProperty("RADAR.cwms.database.image", "registry.hecdev.net/cwms/schema_installer:99.99.99.8-CDA_STAGING")); private static String webUser = null; @@ -66,6 +67,7 @@ public void beforeAll(ExtensionContext context) throws Exception { .withOfficeId("HQ") .withVolumeName(TeamCityUtilities.cleanupBranchName(ORACLE_VOLUME)) .withSchemaImage(CWMS_DB_IMAGE); + cwmsDb.withImagePullPolicy(PullPolicy.alwaysPull()); cwmsDb.start(); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5e8c5f20c..37e0d1fa2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] jaxb-api = "2.3.1" jaxb-impl = "3.0.2" -jooq-codegen = "99.99.99.3-CDA_STAGING" +jooq-codegen = "99.99.99.8-CDA_STAGING" jooq = "3.18.7-jdk8" hec-data-access = "9.8.0" slf4j = "1.7.36" From 835c5c1e3acfbc18790af866e6d6a94a17024c3d Mon Sep 17 00:00:00 2001 From: zack-rma Date: Wed, 13 Nov 2024 13:01:59 -0800 Subject: [PATCH 2/6] Updated LocationGroupDao and TimeSeriesGroupDao with group and category office id parameters --- .../main/java/cwms/cda/api/Controllers.java | 2 + .../cwms/cda/api/LocationGroupController.java | 20 ++++-- .../cda/api/TimeSeriesGroupController.java | 19 +++++- .../cwms/cda/data/dao/LocationGroupDao.java | 23 ++++--- .../cwms/cda/data/dao/TimeSeriesGroupDao.java | 68 +++++++++++-------- .../api/LocationGroupControllerTestIT.java | 22 ++++++ .../cda/data/dao/LocationGroupDaoTest.java | 4 +- 7 files changed, 105 insertions(+), 53 deletions(-) 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 154f83849..ade0e474a 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 @@ -63,6 +63,8 @@ public final class Controllers { public static final String SIZE = "size"; public static final String OFFICE = "office"; + public static final String CATEGORY_OFFICE_ID = "category-office-id"; + public static final String GROUP_OFFICE_ID = "group-office-id"; public static final String UNIT = "unit"; public static final String COUNT = "count"; public static final String TIME = "time"; diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java index 6d39437c5..8f678ebdd 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java @@ -135,15 +135,20 @@ Boolean.class, false, metrics, name(LocationGroupController.class.getName(), @OpenApi( pathParams = { @OpenApiParam(name = GROUP_ID, required = true, description = "Specifies " - + "the location_group whose data is to be included in the response") + + "the location_group whose data is to be included in the response") }, queryParams = { @OpenApiParam(name = OFFICE, required = true, description = "Specifies the " - + "owning office of the location group whose data is to be included " - + "in the response."), + + "owning office of the location group whose data is to be included " + + "in the response."), + @OpenApiParam(name = GROUP_OFFICE_ID, required = true, description = "Specifies the " + + "owning office of the location group whose data is to be included in the response."), + @OpenApiParam(name = CATEGORY_OFFICE_ID, required = true, description = "Specifies the " + + "owning office of the category the location group belongs to " + + "whose data is to be included in the response."), @OpenApiParam(name = CATEGORY_ID, required = true, description = "Specifies" - + " the category containing the location group whose data is to be " - + "included in the response."), + + " the category containing the location group whose data is to be " + + "included in the response."), }, responses = { @OpenApiResponse(status = STATUS_200, content = { @@ -161,14 +166,15 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { LocationGroupDao cdm = new LocationGroupDao(dsl); String office = requiredParam(ctx, OFFICE); String categoryId = requiredParam(ctx, CATEGORY_ID); - + String groupOfficeId = requiredParam(ctx, GROUP_OFFICE_ID); + String categoryOfficeId = requiredParam(ctx, CATEGORY_OFFICE_ID); String formatHeader = ctx.header(Header.ACCEPT); String result; ContentType contentType; if (formatHeader != null && formatHeader.contains(Formats.GEOJSON)) { contentType = new ContentType(Formats.GEOJSON); FeatureCollection fc = cdm.buildFeatureCollectionForLocationGroup(office, - categoryId, groupId, "EN"); + groupOfficeId, categoryOfficeId, categoryId, groupId, "EN"); ObjectMapper mapper = ctx.appAttribute("ObjectMapper"); result = mapper.writeValueAsString(fc); } else { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java index 495183dbf..8066047e8 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java @@ -82,6 +82,10 @@ private Timer.Context markAndTime(String subject) { + " the assigned timeseries in the returned timeseries groups. (default: true)"), @OpenApiParam(name = TIMESERIES_CATEGORY_LIKE, description = "Posix regular expression " + "matching against the timeseries category id"), + @OpenApiParam(name = CATEGORY_OFFICE_ID, description = "Specifies the owning office of the " + + "timeseries group category"), + @OpenApiParam(name = GROUP_OFFICE_ID, description = "Specifies the owning office of the " + + "timeseries group"), @OpenApiParam(name = TIMESERIES_GROUP_LIKE, description = "Posix regular expression " + "matching against the timeseries group id") }, @@ -102,6 +106,8 @@ public void getAll(@NotNull Context ctx) { TimeSeriesGroupDao dao = new TimeSeriesGroupDao(dsl); String office = ctx.queryParam(OFFICE); + String categoryOffice = ctx.queryParam(CATEGORY_OFFICE_ID); + String groupOffice = ctx.queryParam(GROUP_OFFICE_ID); boolean includeAssigned = queryParamAsClass(ctx, new String[]{INCLUDE_ASSIGNED}, Boolean.class, true, metrics, name(TimeSeriesGroupController.class.getName(), @@ -111,7 +117,8 @@ Boolean.class, true, metrics, name(TimeSeriesGroupController.class.getName(), String tsGroupLike = queryParamAsClass(ctx, new String[]{TIMESERIES_GROUP_LIKE}, String.class, null, metrics, name(TimeSeriesGroupController.class.getName(), GET_ALL)); - List grps = dao.getTimeSeriesGroups(office, includeAssigned, tsCategoryLike, tsGroupLike); + List grps = dao.getTimeSeriesGroups(office, categoryOffice, groupOffice, + includeAssigned, tsCategoryLike, tsGroupLike); if (grps.isEmpty()) { CdaError re = new CdaError("No data found for The provided office"); logger.info(() -> re + " for request " + ctx.fullUrl()); @@ -140,6 +147,10 @@ Boolean.class, true, metrics, name(TimeSeriesGroupController.class.getName(), @OpenApiParam(name = OFFICE, required = true, description = "Specifies the " + "owning office of the timeseries group whose data is to be included" + " in the response."), + @OpenApiParam(name = CATEGORY_OFFICE_ID, description = "Specifies the owning office of the " + + "timeseries group category"), + @OpenApiParam(name = GROUP_OFFICE_ID, description = "Specifies the owning office of the " + + "timeseries group"), @OpenApiParam(name = CATEGORY_ID, required = true, description = "Specifies" + " the category containing the timeseries group whose data is to be " + "included in the response."), @@ -158,13 +169,15 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { TimeSeriesGroupDao dao = new TimeSeriesGroupDao(dsl); String office = ctx.queryParam(OFFICE); String categoryId = ctx.queryParam(CATEGORY_ID); + String groupOffice = ctx.queryParam(GROUP_OFFICE_ID); + String categoryOffice = ctx.queryParam(CATEGORY_OFFICE_ID); String formatHeader = ctx.header(Header.ACCEPT); ContentType contentType = Formats.parseHeader(formatHeader, TimeSeriesGroup.class); TimeSeriesGroup group = null; - List timeSeriesGroups = dao.getTimeSeriesGroups(office, categoryId, - groupId); + List timeSeriesGroups = dao.getTimeSeriesGroups(office, groupOffice, categoryOffice, + categoryId, groupId); if (timeSeriesGroups != null && !timeSeriesGroups.isEmpty()) { if (timeSeriesGroups.size() == 1) { group = timeSeriesGroups.get(0); diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationGroupDao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationGroupDao.java index e0fe44a23..82266c16f 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationGroupDao.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/LocationGroupDao.java @@ -218,9 +218,9 @@ public List getLocationGroups(@Nullable String officeId, /** * Get all location groups for a given office and category, * as well as a where clause to filter the shared_ref_location_id. - * @Param officeId The office id to use for the query. - * @Param locCategoryLike A regex to use to filter the location categories. May be null. - * @Param sharedRefLocLike A where clause to filter the shared_loc_alias_id. May be null. + * @param officeId The office id to use for the query. + * @param locCategoryLike A regex to use to filter the location categories. May be null. + * @param sharedRefLocLike A where clause to filter the shared_loc_alias_id. May be null. * @return A list of all location groups for the given parameters. */ @@ -432,7 +432,8 @@ public Feature buildFeatureFromAvLocRecordWithLocGroup(Record avLocRecord) { return feature; } - public FeatureCollection buildFeatureCollectionForLocationGroup(String officeId, + public FeatureCollection buildFeatureCollectionForLocationGroup(String locationOfficeId, String groupOfficeId, + String categoryOfficeId, String categoryId, String groupId, String units) { AV_LOC_GRP_ASSGN alga = AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN; @@ -442,9 +443,9 @@ public FeatureCollection buildFeatureCollectionForLocationGroup(String officeId, alga.GROUP_ID, alga.ATTRIBUTE, alga.ALIAS_ID, alga.SHARED_REF_LOCATION_ID, alga.SHARED_ALIAS_ID) .from(al).join(alga).on(al.LOCATION_ID.eq(alga.LOCATION_ID)) - .where(alga.DB_OFFICE_ID.eq(officeId) - .and(alga.CATEGORY_OFFICE_ID.eq()) - .and(alga.GROUP_OFFICE_ID.eq()) + .where(alga.DB_OFFICE_ID.eq(locationOfficeId) + .and(alga.CATEGORY_OFFICE_ID.eq(categoryOfficeId)) + .and(alga.GROUP_OFFICE_ID.eq(groupOfficeId)) .and(alga.CATEGORY_ID.eq(categoryId) .and(alga.GROUP_ID.eq(groupId)) .and(al.UNIT_SYSTEM.eq(units)))) @@ -533,8 +534,8 @@ public void assignLocs(LocationGroup group, String office) { /** * Used when an appropriate context already exists to avoid opening a second connection. * @param dslContext a dslContext that is assumed to be fully prepared for use in this operation - * @param group - * @param office + * @param group the location group to assign locations to + * @param office the office to use for the operation */ public void assignLocs(DSLContext dslContext, LocationGroup group, String office) { List assignedLocations = group.getAssignedLocations(); @@ -544,8 +545,8 @@ public void assignLocs(DSLContext dslContext, LocationGroup group, String office .collect(toList()); LOC_ALIAS_ARRAY3 assignedLocs = new LOC_ALIAS_ARRAY3(collect); LocationCategory cat = group.getLocationCategory(); - CWMS_LOC_PACKAGE.call_ASSIGN_LOC_GROUPS3(dslContext.configuration(), - cat.getId(), group.getId(), assignedLocs, office); + CWMS_LOC_PACKAGE.call_ASSIGN_LOC_GROUPS3(dslContext.configuration(), + cat.getId(), group.getId(), assignedLocs, office); } } } diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesGroupDao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesGroupDao.java index 4ed6a1ad4..9a2224c55 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesGroupDao.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesGroupDao.java @@ -24,9 +24,17 @@ package cwms.cda.data.dao; +import static java.util.stream.Collectors.toList; + import cwms.cda.data.dto.AssignedTimeSeries; import cwms.cda.data.dto.TimeSeriesCategory; import cwms.cda.data.dto.TimeSeriesGroup; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; import kotlin.Pair; import org.jetbrains.annotations.NotNull; import org.jooq.*; @@ -38,14 +46,6 @@ import usace.cwms.db.jooq.codegen.udt.records.TS_ALIAS_T; import usace.cwms.db.jooq.codegen.udt.records.TS_ALIAS_TAB_T; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import static java.util.stream.Collectors.toList; public class TimeSeriesGroupDao extends JooqDao { private static final Logger logger = Logger.getLogger(TimeSeriesGroupDao.class.getName()); @@ -56,19 +56,20 @@ public TimeSeriesGroupDao(DSLContext dsl) { } public List getTimeSeriesGroups() { - return getTimeSeriesGroups(null); + return getTimeSeriesGroups(null, null, null); } - public List getTimeSeriesGroups(String officeId) { + public List getTimeSeriesGroups(String officeId, String groupOfficeId, String categoryOfficeId) { Condition whereCond = DSL.noCondition(); if (officeId != null) { whereCond = AV_TS_CAT_GRP.AV_TS_CAT_GRP.GRP_DB_OFFICE_ID.eq(officeId); } - return getTimeSeriesGroupsWhere(whereCond); + return getTimeSeriesGroupsWhere(whereCond, categoryOfficeId, groupOfficeId); } - public List getTimeSeriesGroups(String officeId, boolean includeAssigned, String tsCategoryLike, String tsGroupLike) { + public List getTimeSeriesGroups(String officeId, String groupOfficeId, String categoryOfficeId, + boolean includeAssigned, String tsCategoryLike, String tsGroupLike) { Condition whereCond = DSL.noCondition(); if (officeId != null) { @@ -85,8 +86,8 @@ public List getTimeSeriesGroups(String officeId, boolean includ whereCond = whereCond.and(AV_TS_CAT_GRP.AV_TS_CAT_GRP.TS_GROUP_ID.isNotNull()); } - if(includeAssigned){ - return getTimeSeriesGroupsWhere(whereCond); + if (includeAssigned) { + return getTimeSeriesGroupsWhere(whereCond, categoryOfficeId, groupOfficeId); } else { return getTimeSeriesGroupsWithoutAssigned(whereCond); } @@ -94,13 +95,13 @@ public List getTimeSeriesGroups(String officeId, boolean includ } - public List getTimeSeriesGroups(String officeId, String categoryId, String groupId) { - return getTimeSeriesGroupsWhere(buildWhereCondition(officeId, categoryId, groupId)); + public List getTimeSeriesGroups(String officeId, String groupOfficeId, String categoryOfficeId, + String categoryId, String groupId) { + return getTimeSeriesGroupsWhere(buildWhereCondition(officeId, categoryId, groupId), categoryOfficeId, groupOfficeId); } @NotNull - private List getTimeSeriesGroupsWhere(Condition whereCond) { - List retval = new ArrayList<>(); + private List getTimeSeriesGroupsWhere(Condition whereCond, String categoryOfficeId, String groupOfficeId) { AV_TS_CAT_GRP catGrp = AV_TS_CAT_GRP.AV_TS_CAT_GRP; AV_TS_GRP_ASSGN grpAssgn = AV_TS_GRP_ASSGN.AV_TS_GRP_ASSGN; @@ -112,6 +113,15 @@ private List getTimeSeriesGroupsWhere(Condition whereCond) { return new Pair<>(group, loc); }; + Condition whereCondGrpCat = DSL.noCondition(); + if (categoryOfficeId != null) { + whereCondGrpCat = whereCondGrpCat.and(grpAssgn.CATEGORY_OFFICE_ID.eq(categoryOfficeId)) + .and(grpAssgn.GROUP_OFFICE_ID.eq(groupOfficeId)); + } + if (groupOfficeId != null) { + whereCondGrpCat = whereCondGrpCat.and(grpAssgn.GROUP_OFFICE_ID.eq(groupOfficeId)); + } + SelectSeekStep1 query = dsl.select(catGrp.CAT_DB_OFFICE_ID, catGrp.TS_CATEGORY_ID, catGrp.TS_CATEGORY_DESC, catGrp.GRP_DB_OFFICE_ID, catGrp.TS_GROUP_ID, catGrp.TS_GROUP_DESC, catGrp.SHARED_TS_ALIAS_ID, @@ -122,8 +132,7 @@ private List getTimeSeriesGroupsWhere(Condition whereCond) { .on(catGrp.TS_CATEGORY_ID.eq(grpAssgn.CATEGORY_ID) .and(catGrp.TS_GROUP_ID.eq(grpAssgn.GROUP_ID))) .where(whereCond) - .and(grpAssgn.CATEGORY_OFFICE_ID.eq()) - .and(grpAssgn.GROUP_OFFICE_ID.eq()) + .and(whereCondGrpCat) .orderBy(grpAssgn.ATTRIBUTE); logger.fine(() -> query.getSQL(ParamType.INLINED)); @@ -141,6 +150,7 @@ private List getTimeSeriesGroupsWhere(Condition whereCond) { } } + List retval = new ArrayList<>(); for (final Map.Entry> entry : map.entrySet()) { List assigned = entry.getValue(); retval.add(new TimeSeriesGroup(entry.getKey(), assigned)); @@ -243,22 +253,20 @@ public void delete(String categoryId, String groupId, String office) { } public void create(TimeSeriesGroup group, boolean failIfExists) { - connection(dsl, c-> { + connection(dsl, c -> { Configuration configuration = getDslContext(c,group.getOfficeId()).configuration(); String categoryId = group.getTimeSeriesCategory().getId(); CWMS_TS_PACKAGE.call_STORE_TS_GROUP(configuration, categoryId, - group.getId(), group.getDescription(), formatBool(failIfExists), - "T", group.getSharedAliasId(), - group.getSharedRefTsId(), group.getOfficeId()); + group.getId(), group.getDescription(), formatBool(failIfExists), + "T", group.getSharedAliasId(), + group.getSharedRefTsId(), group.getOfficeId()); assignTs(configuration,group, group.getOfficeId()); }); - } private void assignTs(Configuration configuration,TimeSeriesGroup group, String office) { List assignedTimeSeries = group.getAssignedTimeSeries(); - if(assignedTimeSeries != null) - { + if (assignedTimeSeries != null) { List collect = assignedTimeSeries.stream() .map(TimeSeriesGroupDao::convertToTsAliasType) .collect(toList()); @@ -269,7 +277,7 @@ private void assignTs(Configuration configuration,TimeSeriesGroup group, String } public void assignTs(TimeSeriesGroup group, String office) { - connection(dsl, c->assignTs(getDslContext(c, office).configuration(),group, office)); + connection(dsl, c -> assignTs(getDslContext(c, office).configuration(),group, office)); } private static TS_ALIAS_T convertToTsAliasType(AssignedTimeSeries assignedTimeSeries) { @@ -279,9 +287,9 @@ private static TS_ALIAS_T convertToTsAliasType(AssignedTimeSeries assignedTimeSe } public void renameTimeSeriesGroup(String oldGroupId, TimeSeriesGroup group) { - connection(dsl, c-> + connection(dsl, c -> CWMS_TS_PACKAGE.call_RENAME_TS_GROUP( - getDslContext(c,group.getOfficeId()).configuration(), + getDslContext(c, group.getOfficeId()).configuration(), group.getTimeSeriesCategory().getId(), oldGroupId, group.getId(), group.getOfficeId()) ); diff --git a/cwms-data-api/src/test/java/cwms/cda/api/LocationGroupControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/LocationGroupControllerTestIT.java index 61b385c59..ef4ff9838 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/LocationGroupControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/LocationGroupControllerTestIT.java @@ -228,6 +228,8 @@ void test_create_read_delete() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, officeId) .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) .when() .redirects().follow(true) .redirects().max(3) @@ -267,6 +269,8 @@ void test_create_read_delete() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, officeId) .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) .when() .redirects().follow(true) .redirects().max(3) @@ -365,6 +369,8 @@ void test_rename_group() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, officeId) .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) .when() .redirects().follow(true) .redirects().max(3) @@ -474,6 +480,8 @@ void test_add_assigned_locs() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, officeId) .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) .when() .redirects().follow(true) .redirects().max(3) @@ -585,6 +593,8 @@ void test_district_permissions() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, officeId) .queryParam(CATEGORY_ID, newLocGroup.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) .when() .redirects().follow(true) .redirects().max(3) @@ -626,6 +636,8 @@ void test_CWMS_permissions() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, CWMS_OFFICE) .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, CWMS_OFFICE) .when() .redirects().follow(true) .redirects().max(3) @@ -663,6 +675,8 @@ void test_CWMS_permissions() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, CWMS_OFFICE) .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, CWMS_OFFICE) .when() .redirects().follow(true) .redirects().max(3) @@ -713,6 +727,8 @@ void test_CWMS_permissions() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, CWMS_OFFICE) .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, CWMS_OFFICE) .when() .redirects().follow(true) .redirects().max(3) @@ -749,6 +765,8 @@ void test_CWMS_permissions_with_replacement() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, CWMS_OFFICE) .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, CWMS_OFFICE) .when() .redirects().follow(true) .redirects().max(3) @@ -786,6 +804,8 @@ void test_CWMS_permissions_with_replacement() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, CWMS_OFFICE) .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, CWMS_OFFICE) .when() .redirects().follow(true) .redirects().max(3) @@ -836,6 +856,8 @@ void test_CWMS_permissions_with_replacement() throws Exception { .contentType(Formats.JSON) .queryParam(OFFICE, CWMS_OFFICE) .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, CWMS_OFFICE) .when() .redirects().follow(true) .redirects().max(3) diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dao/LocationGroupDaoTest.java b/cwms-data-api/src/test/java/cwms/cda/data/dao/LocationGroupDaoTest.java index 0afbd1cbc..d8e174d70 100644 --- a/cwms-data-api/src/test/java/cwms/cda/data/dao/LocationGroupDaoTest.java +++ b/cwms-data-api/src/test/java/cwms/cda/data/dao/LocationGroupDaoTest.java @@ -104,8 +104,8 @@ public static boolean isSorted(List attributes) { void getLocationGroupAsGeojson() throws SQLException, JsonProcessingException { DSLContext lrl = getDslContext(getConnection(), "LRL"); LocationGroupDao dao = new LocationGroupDao(lrl); - FeatureCollection fc = dao.buildFeatureCollectionForLocationGroup("LRL", "Basin", - "Green River Basin", "EN"); + FeatureCollection fc = dao.buildFeatureCollectionForLocationGroup("LRL", + "LRL", "CWMS", "Basin", "Green River Basin", "EN"); assertNotNull(fc); ObjectWriter ow = new ObjectMapper().writerWithDefaultPrettyPrinter(); From e24464ef6cfbd1c95defae1f06b25e2c587c8729 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Thu, 14 Nov 2024 14:51:43 -0800 Subject: [PATCH 3/6] Updated test cases: expanded coverage; ts storage error in progress --- .../cwms/cda/api/LocationGroupController.java | 10 + .../cda/api/TimeSeriesGroupController.java | 10 + .../api/LocationCategoryControllerTestIT.java | 184 +++++- .../api/LocationGroupControllerTestIT.java | 557 ++++++++++++++++++ .../TimeSeriesCategoryControllerTestIT.java | 184 +++++- .../api/TimeSeriesGroupControllerTestIT.java | 419 ++++++++++++- 6 files changed, 1333 insertions(+), 31 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java index 8f678ebdd..05f66840f 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java @@ -223,6 +223,16 @@ public void create(@NotNull Context ctx) { String body = ctx.body(); ContentType contentType = Formats.parseHeader(formatHeader, LocationGroup.class); LocationGroup deserialize = Formats.parseContent(contentType, body, LocationGroup.class); + + if (!deserialize.getLocationCategory().getOfficeId().equalsIgnoreCase(CWMS_OFFICE) + && (!deserialize.getOfficeId().equalsIgnoreCase(deserialize.getLocationCategory().getOfficeId()) + || deserialize.getOfficeId().equalsIgnoreCase(CWMS_OFFICE))) { + CdaError re = new CdaError("Office ID cannot be CWMS and must match the location category office ID"); + logger.info(() -> re + System.lineSeparator() + "for request " + ctx.fullUrl()); + ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(re); + return; + } + LocationGroupDao dao = new LocationGroupDao(dsl); dao.create(deserialize); ctx.status(HttpServletResponse.SC_CREATED); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java index 8066047e8..a9691a753 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java @@ -233,6 +233,16 @@ public void create(@NotNull Context ctx) { String body = ctx.body(); ContentType contentType = Formats.parseHeader(formatHeader, TimeSeriesGroup.class); TimeSeriesGroup deserialize = Formats.parseContent(contentType, body, TimeSeriesGroup.class); + + if (!deserialize.getTimeSeriesCategory().getOfficeId().equalsIgnoreCase(CWMS_OFFICE) + && (!deserialize.getOfficeId().equalsIgnoreCase(deserialize.getTimeSeriesCategory().getOfficeId()) + || deserialize.getOfficeId().equalsIgnoreCase(CWMS_OFFICE))) { + CdaError re = new CdaError("Office ID cannot be CWMS and must match the TimeSeries category office ID"); + logger.info(() -> re + System.lineSeparator() + "for request " + ctx.fullUrl()); + ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(re); + return; + } + boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); TimeSeriesGroupDao dao = new TimeSeriesGroupDao(dsl); dao.create(deserialize, failIfExists); diff --git a/cwms-data-api/src/test/java/cwms/cda/api/LocationCategoryControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/LocationCategoryControllerTestIT.java index a5848cc44..117a5723d 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/LocationCategoryControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/LocationCategoryControllerTestIT.java @@ -35,7 +35,6 @@ import javax.servlet.http.HttpServletResponse; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -44,12 +43,13 @@ import cwms.cda.formatters.Formats; @Tag("integration") -@Disabled // tests failing for reasons other than office id switcharound. class LocationCategoryControllerTestIT extends DataApiTestIT { + TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + TestAccounts.KeyUser user2 = TestAccounts.KeyUser.SWT_NORMAL; + @Test - void test_create_read_delete() throws Exception { - String officeId = "SPK"; - TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + void test_create_read_delete() { + String officeId = user.getOperatingOffice(); LocationCategory cat = new LocationCategory(officeId, LocationCategoryControllerTestIT.class.getSimpleName(), "IntegrationTesting"); ContentType contentType = Formats.parseHeader(Formats.JSON, LocationCategory.class); @@ -119,4 +119,178 @@ void test_create_read_delete() throws Exception { .log().ifValidationFails(LogDetail.ALL,true) .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); } + + @Test + void test_create_already_existing_CWMS_category() { + String officeId = user.getOperatingOffice(); + LocationCategory cat = new LocationCategory(officeId, "Default", "Default"); + ContentType contentType = Formats.parseHeader(Formats.JSON, LocationCategory.class); + String xml = Formats.format(contentType, cat); + //Attempt to Create Category, should fail + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(xml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CONFLICT)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam("office", officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/category/" + cat.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } + + @Test + void test_create_read_delete_same_category_different_office() { + String officeId = user.getOperatingOffice(); + String officeId2 = user2.getOperatingOffice(); + LocationCategory cat = new LocationCategory(officeId, "test_create_read_delete", "IntegrationTesting"); + LocationCategory cat2 = new LocationCategory(officeId2, "test_create_read_delete", "IntegrationTesting"); + ContentType contentType = Formats.parseHeader(Formats.JSON, LocationCategory.class); + registerCategory(cat); + registerCategory(cat2); + //Create Category + String xml = Formats.format(contentType, cat); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(xml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Create second Category + xml = Formats.format(contentType, cat2); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(xml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/category/" + cat.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(cat.getOfficeId())) + .body("id", equalTo(cat.getId())) + .body("description", equalTo(cat.getDescription())); + // Read second category + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/category/" + cat2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(cat2.getOfficeId())) + .body("id", equalTo(cat2.getId())) + .body("description", equalTo(cat2.getDescription())); + //Delete + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/location/category/" + cat.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Delete seocond category + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId2) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/location/category/" + cat2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam("office", officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/category/" + cat.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + //Read second Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam("office", officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/category/" + cat2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } } diff --git a/cwms-data-api/src/test/java/cwms/cda/api/LocationGroupControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/LocationGroupControllerTestIT.java index ef4ff9838..7d489ef6b 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/LocationGroupControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/LocationGroupControllerTestIT.java @@ -66,6 +66,7 @@ class LocationGroupControllerTestIT extends DataApiTestIT { private List groupsToCleanup = new ArrayList<>(); private List categoriesToCleanup = new ArrayList<>(); TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + TestAccounts.KeyUser user2 = TestAccounts.KeyUser.SWT_NORMAL; @AfterEach void tearDown() throws Exception { @@ -297,6 +298,562 @@ void test_create_read_delete() throws Exception { .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); } + @Test + void test_create_read_delete_agency_aliases_same_name() throws Exception { + // Create two location groups of the same name with an agency alias category + String officeId = user.getOperatingOffice(); + String officeId2 = user2.getOperatingOffice(); + String locationId = "LocationGroupTest"; + createLocation(locationId, true, officeId); + createLocation(locationId, true, officeId2); + LocationCategory cat = new LocationCategory(CWMS_OFFICE, "Default", "Default"); + AssignedLocation assignLoc = new AssignedLocation(locationId, officeId, "AliasId", 1, locationId); + AssignedLocation assignLoc2 = new AssignedLocation(locationId, officeId2, "AliasId1", 1, locationId); + LocationGroup group = new LocationGroup(new LocationGroup(cat, officeId, LocationGroupControllerTestIT.class.getSimpleName(), "IntegrationTesting", + "sharedLocAliasId", locationId, 123), Collections.singletonList(assignLoc)); + LocationGroup group2 = new LocationGroup(new LocationGroup(cat, officeId2, LocationGroupControllerTestIT.class.getSimpleName() + "2", "IntegrationTesting", + "sharedLocAliasId", locationId, 123), Collections.singletonList(assignLoc2)); + ContentType contentType = Formats.parseHeader(Formats.JSON, LocationCategory.class); + String groupXml = Formats.format(contentType, group); + groupsToCleanup.add(group); + groupsToCleanup.add(group2); + //Create Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Create Group 2 + groupXml = Formats.format(contentType, group2); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user2.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/group") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group.getOfficeId())) + .body("id", equalTo(group.getId())) + .body("description", equalTo(group.getDescription())) + .body("assigned-locations[0].location-id", equalTo(locationId)) + .body("assigned-locations[0].alias-id", equalTo("AliasId")) + .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, group2.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group2.getOfficeId())) + .body("id", equalTo(group2.getId())) + .body("description", equalTo(group2.getDescription())) + .body("assigned-locations[0].location-id", equalTo(locationId)) + .body("assigned-locations[0].alias-id", equalTo("AliasId1")) + .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user2.toHeaderValue()) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, group2.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID,CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } + + @Test + void test_create_read_delete_same_names_different_offices() throws Exception { + // Create two location groups of the same name with an agency alias category + String officeId = user.getOperatingOffice(); + String officeId2 = user2.getOperatingOffice(); + String locationId = "LocationGroupTest"; + createLocation(locationId, true, officeId); + createLocation(locationId, true, officeId2); + LocationCategory cat = new LocationCategory(officeId, "TestCategory2", "IntegrationTesting"); + LocationCategory cat2 = new LocationCategory(officeId2, "TestCategory2", "IntegrationTesting"); + AssignedLocation assignLoc = new AssignedLocation(locationId, officeId, "AliasId", 1, locationId); + AssignedLocation assignLoc2 = new AssignedLocation(locationId, officeId, "AliasId2", 1, locationId); + LocationGroup group = new LocationGroup(new LocationGroup(cat, officeId, LocationGroupControllerTestIT.class.getSimpleName(), "IntegrationTesting", + "sharedLocAliasId", locationId, 123), Collections.singletonList(assignLoc)); + LocationGroup group2 = new LocationGroup(new LocationGroup(cat2, officeId2, LocationGroupControllerTestIT.class.getSimpleName(), "IntegrationTesting", + "sharedLocAliasId1", locationId, 123), Collections.singletonList(assignLoc2)); + ContentType contentType = Formats.parseHeader(Formats.JSON, LocationCategory.class); + String groupXml = Formats.format(contentType, group); + groupsToCleanup.add(group); + String categoryXml = Formats.format(contentType, cat); + categoriesToCleanup.add(cat); + categoriesToCleanup.add(cat2); + registerCategory(cat); + registerCategory(cat2); + //Create Category + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(categoryXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + categoryXml = Formats.format(contentType, cat2); + // Create Category 2 + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(categoryXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + + //Create Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Create Group 2 + groupXml = Formats.format(contentType, group2); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user2.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group.getOfficeId())) + .body("id", equalTo(group.getId())) + .body("description", equalTo(group.getDescription())) + .body("assigned-locations[0].location-id", equalTo(locationId)) + .body("assigned-locations[0].alias-id", equalTo("AliasId")) + .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, group2.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId2) + .queryParam(GROUP_OFFICE_ID, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group2.getOfficeId())) + .body("id", equalTo(group2.getId())) + .body("description", equalTo(group2.getDescription())) + .body("assigned-locations[0].location-id", equalTo(locationId)) + .body("assigned-locations[0].alias-id", equalTo("AliasId2")) + .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, cat2.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, group2.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId2) + .queryParam(GROUP_OFFICE_ID, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } + + @Test + void test_create_read_delete_office_combinations() throws Exception { + // Test creating, storing and deleting location groups with different offices for category and group (CWMS cat), + // and different offices for category and group (non-CWMS cat) + String districtOffice = user.getOperatingOffice(); + String locationId = "LocationGroupTest"; + createLocation(locationId, true, districtOffice); + LocationCategory cat = new LocationCategory(CWMS_OFFICE, "Default", "Default"); + LocationCategory cat2 = new LocationCategory(districtOffice, "TestCategory2", "IntegrationTesting"); + AssignedLocation assignLoc = new AssignedLocation(locationId, districtOffice, "AliasId", 1, locationId); + LocationGroup group = new LocationGroup(new LocationGroup(cat, districtOffice, LocationGroupControllerTestIT.class.getSimpleName(), "IntegrationTesting", + "sharedLocAliasId", locationId, 123), Collections.singletonList(assignLoc)); + LocationGroup group2 = new LocationGroup(new LocationGroup(cat2, districtOffice, LocationGroupControllerTestIT.class.getSimpleName(), "IntegrationTesting", + "sharedLocAliasId", locationId, 123), Collections.singletonList(assignLoc)); + ContentType contentType = Formats.parseHeader(Formats.JSON, LocationCategory.class); + String groupXml = Formats.format(contentType, group); + groupsToCleanup.add(group); + groupsToCleanup.add(group2); + String categoryXml = Formats.format(contentType, cat2); + categoriesToCleanup.add(cat2); + // Create Category 2 + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(categoryXml) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, districtOffice) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + + //Create Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Create Group 2 + groupXml = Formats.format(contentType, group2); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/location/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, districtOffice) + .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, districtOffice) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group.getOfficeId())) + .body("id", equalTo(group.getId())) + .body("description", equalTo(group.getDescription())) + .body("assigned-locations[0].location-id", equalTo(locationId)) + .body("assigned-locations[0].alias-id", equalTo("AliasId")) + .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, districtOffice) + .queryParam(CATEGORY_ID, group2.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, districtOffice) + .queryParam(GROUP_OFFICE_ID, districtOffice) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group2.getOfficeId())) + .body("id", equalTo(group2.getId())) + .body("description", equalTo(group2.getDescription())) + .body("assigned-locations[0].location-id", equalTo(locationId)) + .body("assigned-locations[0].alias-id", equalTo("AliasId")) + .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, districtOffice) + .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, districtOffice) + .queryParam(CATEGORY_ID, cat2.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, districtOffice) + .queryParam(CATEGORY_ID, group.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, districtOffice) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, districtOffice) + .queryParam(CATEGORY_ID, group2.getLocationCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, districtOffice) + .queryParam(GROUP_OFFICE_ID, districtOffice) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/location/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } + @Test void test_rename_group() throws Exception { String officeId = user.getOperatingOffice(); diff --git a/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesCategoryControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesCategoryControllerTestIT.java index c681cb668..0d9f5f037 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesCategoryControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesCategoryControllerTestIT.java @@ -27,7 +27,6 @@ import fixtures.TestAccounts; import io.restassured.filter.log.LogDetail; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -44,14 +43,14 @@ import static org.hamcrest.Matchers.is; @Tag("integration") -@Disabled // issue with groups and categories not affecting current changes with office class TimeSeriesCategoryControllerTestIT extends DataApiTestIT { + TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + TestAccounts.KeyUser user2 = TestAccounts.KeyUser.SWT_NORMAL; @Test - void test_create_read_delete() throws Exception { - String officeId = "SPK"; - TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + void test_create_read_delete() { + String officeId = user.getOperatingOffice(); TimeSeriesCategory cat = new TimeSeriesCategory(officeId, "test_create_read_delete", "IntegrationTesting"); ContentType contentType = Formats.parseHeader(Formats.JSON, TimeSeriesCategory.class); String xml = Formats.format(contentType, cat); @@ -119,4 +118,179 @@ void test_create_read_delete() throws Exception { .log().ifValidationFails(LogDetail.ALL,true) .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); } + + @Test + void test_create_already_existing_CWMS_category() { + String officeId = user.getOperatingOffice(); + TimeSeriesCategory cat = new TimeSeriesCategory(officeId, "Default", "Default"); + ContentType contentType = Formats.parseHeader(Formats.JSON, TimeSeriesCategory.class); + String xml = Formats.format(contentType, cat); + //Attempt to Create Category, should fail + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(xml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CONFLICT)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam("office", officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/category/" + cat.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } + + @Test + void test_create_read_delete_same_category_different_office() throws Exception { + String officeId = user.getOperatingOffice(); + String officeId2 = user2.getOperatingOffice(); + String timeSeriesId = "Alder Springs.Precip-Cumulative.Inst.15Minutes.0.raw-cda"; + createLocation(timeSeriesId.split("\\.")[0],true, officeId); + createTimeseries(officeId,timeSeriesId); + TimeSeriesCategory cat = new TimeSeriesCategory(officeId, "test_create_read_delete1", "IntegrationTesting"); + TimeSeriesCategory cat2 = new TimeSeriesCategory(officeId2, "test_create_read_delete1", "IntegrationTesting"); + ContentType contentType = Formats.parseHeader(Formats.JSON, TimeSeriesCategory.class); + String xml = Formats.format(contentType, cat); + //Create Category + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(xml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + xml = Formats.format(contentType, cat2); + //Create Category 2 + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(xml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/category/" + cat.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(cat.getOfficeId())) + .body("id", equalTo(cat.getId())) + .body("description", equalTo(cat.getDescription())); + // Read second category + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/category/" + cat2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(cat2.getOfficeId())) + .body("id", equalTo(cat2.getId())) + .body("description", equalTo(cat2.getDescription())); + //Delete + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/timeseries/category/" + cat.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Delete second category + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user2.toHeaderValue()) + .queryParam(OFFICE, officeId2) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/timeseries/category/" + cat2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam("office", officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/category/" + cat.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + //Read second Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam("office", officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/category/" + cat2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } } diff --git a/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesGroupControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesGroupControllerTestIT.java index 3304137a3..0bb3c70d6 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesGroupControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesGroupControllerTestIT.java @@ -30,12 +30,29 @@ import cwms.cda.data.dao.TimeSeriesCategoryDao; import cwms.cda.data.dao.TimeSeriesDaoImpl; import cwms.cda.data.dao.TimeSeriesGroupDao; +import cwms.cda.data.dto.AssignedTimeSeries; +import cwms.cda.data.dto.LocationCategory; import cwms.cda.data.dto.TimeSeries; +import cwms.cda.data.dto.TimeSeriesCategory; +import cwms.cda.data.dto.TimeSeriesGroup; +import cwms.cda.formatters.ContentType; +import cwms.cda.formatters.Formats; import fixtures.CwmsDataApiSetupCallback; import fixtures.TestAccounts; import io.restassured.filter.log.LogDetail; import io.restassured.path.json.JsonPath; import io.restassured.response.Response; +import java.io.InputStream; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.servlet.http.HttpServletResponse; import mil.army.usace.hec.test.database.CwmsDatabaseContainer; import org.apache.commons.io.IOUtils; import org.hamcrest.Matchers; @@ -47,27 +64,9 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; - -import cwms.cda.data.dto.AssignedTimeSeries; -import cwms.cda.data.dto.TimeSeriesCategory; -import cwms.cda.data.dto.TimeSeriesGroup; -import cwms.cda.formatters.ContentType; -import cwms.cda.formatters.Formats; import usace.cwms.db.jooq.codegen.packages.CWMS_TS_PACKAGE; import usace.cwms.db.jooq.codegen.packages.CWMS_UTIL_PACKAGE; -import javax.servlet.http.HttpServletResponse; -import java.io.InputStream; -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - import static cwms.cda.api.Controllers.*; import static cwms.cda.data.dao.JooqDao.formatBool; import static io.restassured.RestAssured.given; @@ -84,6 +83,7 @@ class TimeSeriesGroupControllerTestIT extends DataApiTestIT { private List timeSeriesToCleanup = new ArrayList<>(); private static final Logger LOGGER = Logger.getLogger(TimeSeriesGroupControllerTestIT.class.getName()); TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + TestAccounts.KeyUser user2 = TestAccounts.KeyUser.SWT_NORMAL; @BeforeAll public static void load_data() throws Exception { @@ -353,6 +353,371 @@ void test_create_read_delete() throws Exception { .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); } + @Test + void test_create_read_delete_agency_aliases_same_name() throws Exception { + // Create two location groups of the same name with an agency alias category + String officeId = user.getOperatingOffice(); + String officeId2 = user2.getOperatingOffice(); + String timeSeriesId = "Alder Springs.Precip-Cumulative.Inst.15Minutes.0.raw-cda"; + String locationId = timeSeriesId.split("\\.")[0]; + createLocation(locationId,true,officeId); + createTimeseries(officeId,timeSeriesId); + createTimeseries(officeId2,timeSeriesId); + TimeSeriesCategory cat = new TimeSeriesCategory(CWMS_OFFICE, "Agency Aliases", "Time series aliases for various agencies"); + TimeSeriesGroup group = new TimeSeriesGroup(cat, officeId, "test_create_read_delete", "IntegrationTesting", + "sharedTsAliasId", timeSeriesId); + TimeSeriesGroup group2 = new TimeSeriesGroup(cat, officeId2, "test_create_read_delete", "IntegrationTesting", + "sharedTsAliasId", timeSeriesId); + List assignedTimeSeries = group.getAssignedTimeSeries(); + + BigDecimal tsCode = getTsCode(officeId, timeSeriesId); + assignedTimeSeries.add(new AssignedTimeSeries(officeId,timeSeriesId, tsCode, "AliasId", timeSeriesId, 1)); + ContentType contentType = Formats.parseHeader(Formats.JSON, TimeSeriesCategory.class); + String groupXml = Formats.format(contentType, group); + groupsToCleanup.add(group); + //Create Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Create Group 2 + groupXml = Formats.format(contentType, group2); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, group.getTimeSeriesCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group.getOfficeId())) + .body("id", equalTo(group.getId())) + .body("description", equalTo(group.getDescription())) + .body("assigned-locations[0].location-id", equalTo(locationId)) + .body("assigned-locations[0].alias-id", equalTo("AliasId")) + .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, group2.getTimeSeriesCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group2.getOfficeId())) + .body("id", equalTo(group2.getId())) + .body("description", equalTo(group2.getDescription())) + .body("assigned-locations[0].location-id", equalTo(locationId)) + .body("assigned-locations[0].alias-id", equalTo("AliasId")) + .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/timeseries/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/timeseries/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, group.getTimeSeriesCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, group2.getTimeSeriesCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID,CWMS_OFFICE) + .queryParam(GROUP_OFFICE_ID, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } + + @Test + void test_create_read_delete_same_names_different_offices() throws Exception { + // Create two location groups of the same name with an agency alias category + String officeId = user.getOperatingOffice(); + String officeId2 = user2.getOperatingOffice(); + String timeSeriesId = "Alder Springs.Precip-Cumulative.Inst.15Minutes.0.raw-cda"; + String locationId = timeSeriesId.split("\\.")[0]; + createLocation(locationId,true, officeId); + createLocation(locationId,true, officeId2); + createTimeseries(officeId, timeSeriesId); + createTimeseries(officeId2, timeSeriesId); + TimeSeriesCategory cat = new TimeSeriesCategory(officeId, "TestCategory2", "IntegrationTesting"); + TimeSeriesCategory cat2 = new TimeSeriesCategory(officeId2, "TestCategory2", "IntegrationTesting"); + TimeSeriesGroup group = new TimeSeriesGroup(cat, officeId, "test_create_read_delete", "IntegrationTesting", + "sharedTsAliasId", timeSeriesId); + TimeSeriesGroup group2 = new TimeSeriesGroup(cat2, officeId2, "test_create_read_delete", "IntegrationTesting", + "sharedTsAliasId", timeSeriesId); + ContentType contentType = Formats.parseHeader(Formats.JSON, LocationCategory.class); + String groupXml = Formats.format(contentType, group); + groupsToCleanup.add(group); + String categoryXml = Formats.format(contentType, cat); + categoriesToCleanup.add(cat); + categoriesToCleanup.add(cat2); + //Create Category + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(categoryXml) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + categoryXml = Formats.format(contentType, cat2); + // Create Category 2 + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(categoryXml) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/category") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + + //Create Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Create Group 2 + groupXml = Formats.format(contentType, group2); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/timeseries/group") + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, group.getTimeSeriesCategory().getId()) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group.getOfficeId())) + .body("id", equalTo(group.getId())) + .body("description", equalTo(group.getDescription())); + //Read + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, group2.getTimeSeriesCategory().getId()) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group2.getOfficeId())) + .body("id", equalTo(group2.getId())) + .body("description", equalTo(group2.getDescription())); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, cat.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/timeseries/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + //Delete Group + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, cat2.getId()) + .queryParam(CASCADE_DELETE, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .delete("/timeseries/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); + + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_ID, group.getTimeSeriesCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + //Read Empty + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId2) + .queryParam(CATEGORY_ID, group2.getTimeSeriesCategory().getId()) + .queryParam(CATEGORY_OFFICE_ID, officeId2) + .queryParam(GROUP_OFFICE_ID, officeId2) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group2.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); + } + private static BigDecimal getTsCode(String officeId, String timeSeriesId) throws SQLException { CwmsDatabaseContainer db = CwmsDataApiSetupCallback.getDatabaseLink(); return db.connection(c -> { @@ -666,7 +1031,11 @@ void test_patch_permissions_CWMS() throws Exception { JsonNode ts = mapper.readTree(tsData); String location = ts.get("name").asText().split("\\.")[0]; String officeId = ts.get("office-id").asText(); - createLocation(location, true, officeId); + try { + createLocation(location, true, officeId); + } catch (RuntimeException e) { + // Location already exists + } // inserting the time series given() @@ -770,7 +1139,11 @@ void test_patch_permissions_CWMS_with_replacement() throws Exception { JsonNode ts2 = mapper.readTree(tsData2); String location = ts.get("name").asText().split("\\.")[0]; String officeId = ts.get("office-id").asText(); - createLocation(location, true, officeId); + try { + createLocation(location, true, officeId); + } catch (RuntimeException e) { + // Location already exists + } // inserting the time series given() @@ -871,7 +1244,11 @@ void test_patch_district_permission() throws Exception { JsonNode ts = mapper.readTree(tsData); String location = ts.get("name").asText().split("\\.")[0]; String officeId = ts.get("office-id").asText(); - createLocation(location, true, officeId); + try { + createLocation(location, true, officeId); + } catch (RuntimeException e) { + // Location already exists + } String tsId = ts.get("name").asText(); TimeSeriesCategory category = new TimeSeriesCategory(CWMS_OFFICE, "Default", "Default"); From a5aab9c2946d09f436fa791440dbe63c147bb53a Mon Sep 17 00:00:00 2001 From: zack-rma Date: Thu, 14 Nov 2024 16:00:08 -0800 Subject: [PATCH 4/6] Updated test case with fix for ts group storage error --- .../api/TimeSeriesGroupControllerTestIT.java | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesGroupControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesGroupControllerTestIT.java index 0bb3c70d6..00578c954 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesGroupControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesGroupControllerTestIT.java @@ -366,10 +366,11 @@ void test_create_read_delete_agency_aliases_same_name() throws Exception { TimeSeriesCategory cat = new TimeSeriesCategory(CWMS_OFFICE, "Agency Aliases", "Time series aliases for various agencies"); TimeSeriesGroup group = new TimeSeriesGroup(cat, officeId, "test_create_read_delete", "IntegrationTesting", "sharedTsAliasId", timeSeriesId); + TimeSeriesGroup group3 = new TimeSeriesGroup(group, null); TimeSeriesGroup group2 = new TimeSeriesGroup(cat, officeId2, "test_create_read_delete", "IntegrationTesting", "sharedTsAliasId", timeSeriesId); + TimeSeriesGroup group4 = new TimeSeriesGroup(group, null); List assignedTimeSeries = group.getAssignedTimeSeries(); - BigDecimal tsCode = getTsCode(officeId, timeSeriesId); assignedTimeSeries.add(new AssignedTimeSeries(officeId,timeSeriesId, tsCode, "AliasId", timeSeriesId, 1)); ContentType contentType = Formats.parseHeader(Formats.JSON, TimeSeriesCategory.class); @@ -406,7 +407,7 @@ void test_create_read_delete_agency_aliases_same_name() throws Exception { .log().ifValidationFails(LogDetail.ALL,true) .assertThat() .statusCode(is(HttpServletResponse.SC_CREATED)); - //Read + // Read given() .log().ifValidationFails(LogDetail.ALL,true) .accept(Formats.JSON) @@ -425,10 +426,7 @@ void test_create_read_delete_agency_aliases_same_name() throws Exception { .statusCode(is(HttpServletResponse.SC_OK)) .body("office-id", equalTo(group.getOfficeId())) .body("id", equalTo(group.getId())) - .body("description", equalTo(group.getDescription())) - .body("assigned-locations[0].location-id", equalTo(locationId)) - .body("assigned-locations[0].alias-id", equalTo("AliasId")) - .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + .body("description", equalTo(group.getDescription())); //Read given() .log().ifValidationFails(LogDetail.ALL,true) @@ -448,10 +446,43 @@ void test_create_read_delete_agency_aliases_same_name() throws Exception { .statusCode(is(HttpServletResponse.SC_OK)) .body("office-id", equalTo(group2.getOfficeId())) .body("id", equalTo(group2.getId())) - .body("description", equalTo(group2.getDescription())) - .body("assigned-locations[0].location-id", equalTo(locationId)) - .body("assigned-locations[0].alias-id", equalTo("AliasId")) - .body("assigned-locations[0].ref-location-id", equalTo(locationId)); + .body("description", equalTo(group2.getDescription())); + // update group to unassign all time series + groupXml = Formats.format(contentType, group3); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, group3.getOfficeId()) + .queryParam(REPLACE_ASSIGNED_TS, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .patch("/timeseries/group/" + group3.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)); + // update group to unassign all time series + groupXml = Formats.format(contentType, group4); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(groupXml) + .header("Authorization", user.toHeaderValue()) + .queryParam(OFFICE, group4.getOfficeId()) + .queryParam(REPLACE_ASSIGNED_TS, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .patch("/timeseries/group/" + group4.getId()) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)); //Delete Group given() .log().ifValidationFails(LogDetail.ALL,true) From cdbd69f6d905651a4a3c8acb1da274635fd345e3 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Fri, 15 Nov 2024 08:54:41 -0800 Subject: [PATCH 5/6] Updates to tests and error handling following feedback --- .../cwms/cda/api/LocationGroupController.java | 7 ++-- .../cda/api/TimeSeriesGroupController.java | 33 +++++++++++++++---- .../api/LocationCategoryControllerTestIT.java | 14 -------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java index 05f66840f..e2f292dac 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java @@ -227,10 +227,9 @@ public void create(@NotNull Context ctx) { if (!deserialize.getLocationCategory().getOfficeId().equalsIgnoreCase(CWMS_OFFICE) && (!deserialize.getOfficeId().equalsIgnoreCase(deserialize.getLocationCategory().getOfficeId()) || deserialize.getOfficeId().equalsIgnoreCase(CWMS_OFFICE))) { - CdaError re = new CdaError("Office ID cannot be CWMS and must match the location category office ID"); - logger.info(() -> re + System.lineSeparator() + "for request " + ctx.fullUrl()); - ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(re); - return; + CdaError re = new CdaError("Location Group office ID cannot be CWMS and must match the " + + "Location Category office ID"); + throw new IllegalArgumentException(re.toString()); } LocationGroupDao dao = new LocationGroupDao(dsl); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java index a9691a753..91606e973 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java @@ -25,7 +25,28 @@ package cwms.cda.api; import static com.codahale.metrics.MetricRegistry.name; -import static cwms.cda.api.Controllers.*; +import static cwms.cda.api.Controllers.CATEGORY_ID; +import static cwms.cda.api.Controllers.CATEGORY_OFFICE_ID; +import static cwms.cda.api.Controllers.CREATE; +import static cwms.cda.api.Controllers.CWMS_OFFICE; +import static cwms.cda.api.Controllers.FAIL_IF_EXISTS; +import static cwms.cda.api.Controllers.GET_ALL; +import static cwms.cda.api.Controllers.GET_ONE; +import static cwms.cda.api.Controllers.GROUP_ID; +import static cwms.cda.api.Controllers.GROUP_OFFICE_ID; +import static cwms.cda.api.Controllers.INCLUDE_ASSIGNED; +import static cwms.cda.api.Controllers.OFFICE; +import static cwms.cda.api.Controllers.REPLACE_ASSIGNED_TS; +import static cwms.cda.api.Controllers.RESULTS; +import static cwms.cda.api.Controllers.SIZE; +import static cwms.cda.api.Controllers.STATUS_200; +import static cwms.cda.api.Controllers.STATUS_404; +import static cwms.cda.api.Controllers.STATUS_501; +import static cwms.cda.api.Controllers.TIMESERIES_CATEGORY_LIKE; +import static cwms.cda.api.Controllers.TIMESERIES_GROUP_LIKE; +import static cwms.cda.api.Controllers.UPDATE; +import static cwms.cda.api.Controllers.queryParamAsClass; +import static cwms.cda.api.Controllers.requiredParam; import static cwms.cda.data.dao.JooqDao.getDslContext; import com.codahale.metrics.Histogram; @@ -237,10 +258,9 @@ public void create(@NotNull Context ctx) { if (!deserialize.getTimeSeriesCategory().getOfficeId().equalsIgnoreCase(CWMS_OFFICE) && (!deserialize.getOfficeId().equalsIgnoreCase(deserialize.getTimeSeriesCategory().getOfficeId()) || deserialize.getOfficeId().equalsIgnoreCase(CWMS_OFFICE))) { - CdaError re = new CdaError("Office ID cannot be CWMS and must match the TimeSeries category office ID"); - logger.info(() -> re + System.lineSeparator() + "for request " + ctx.fullUrl()); - ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(re); - return; + CdaError re = new CdaError("TimeSeries Group office ID cannot be CWMS and must match the " + + "TimeSeries Category office ID"); + throw new IllegalArgumentException(re.toString()); } boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); @@ -264,7 +284,8 @@ public void create(@NotNull Context ctx) { + "Default: false"), @OpenApiParam(name = OFFICE, required = true, description = "Specifies the " + "office of the user making the request. This is the office that the timeseries, group, and category " - + "belong to. If the group and/or category belong to the CWMS office, this only identifies the timeseries."), + + "belong to. If the group and/or category belong to the CWMS office, " + + "this only identifies the timeseries."), }, method = HttpMethod.PATCH, tags = {TAG} diff --git a/cwms-data-api/src/test/java/cwms/cda/api/LocationCategoryControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/LocationCategoryControllerTestIT.java index 117a5723d..5d6887564 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/LocationCategoryControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/LocationCategoryControllerTestIT.java @@ -141,20 +141,6 @@ void test_create_already_existing_CWMS_category() { .log().ifValidationFails(LogDetail.ALL,true) .assertThat() .statusCode(is(HttpServletResponse.SC_CONFLICT)); - //Read Empty - given() - .log().ifValidationFails(LogDetail.ALL,true) - .accept(Formats.JSON) - .contentType(Formats.JSON) - .queryParam("office", officeId) - .when() - .redirects().follow(true) - .redirects().max(3) - .get("/location/category/" + cat.getId()) - .then() - .log().ifValidationFails(LogDetail.ALL,true) - .assertThat() - .statusCode(is(HttpServletResponse.SC_NOT_FOUND)); } @Test From 28dd11abecc7b351223df17c9c9c62d125f245c8 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Fri, 15 Nov 2024 09:49:28 -0800 Subject: [PATCH 6/6] Updated error messages --- .../src/main/java/cwms/cda/api/LocationGroupController.java | 5 ++--- .../main/java/cwms/cda/api/TimeSeriesGroupController.java | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java index e2f292dac..9acf4e1c6 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java @@ -227,9 +227,8 @@ public void create(@NotNull Context ctx) { if (!deserialize.getLocationCategory().getOfficeId().equalsIgnoreCase(CWMS_OFFICE) && (!deserialize.getOfficeId().equalsIgnoreCase(deserialize.getLocationCategory().getOfficeId()) || deserialize.getOfficeId().equalsIgnoreCase(CWMS_OFFICE))) { - CdaError re = new CdaError("Location Group office ID cannot be CWMS and must match the " - + "Location Category office ID"); - throw new IllegalArgumentException(re.toString()); + throw new IllegalArgumentException("Location Group office ID cannot be CWMS and must match the " + + "Location Category office ID"); } LocationGroupDao dao = new LocationGroupDao(dsl); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java index 91606e973..eb06d9f33 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesGroupController.java @@ -258,9 +258,8 @@ public void create(@NotNull Context ctx) { if (!deserialize.getTimeSeriesCategory().getOfficeId().equalsIgnoreCase(CWMS_OFFICE) && (!deserialize.getOfficeId().equalsIgnoreCase(deserialize.getTimeSeriesCategory().getOfficeId()) || deserialize.getOfficeId().equalsIgnoreCase(CWMS_OFFICE))) { - CdaError re = new CdaError("TimeSeries Group office ID cannot be CWMS and must match the " + throw new IllegalArgumentException("TimeSeries Group office ID cannot be CWMS and must match the " + "TimeSeries Category office ID"); - throw new IllegalArgumentException(re.toString()); } boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true);