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 43f937582b..a2cbf7bf2d 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,12 +25,36 @@ package cwms.cda.api; import static com.codahale.metrics.MetricRegistry.name; -import static cwms.cda.api.Controllers.*; +import static cwms.cda.api.Controllers.CASCADE_DELETE; +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.IGNORE_NULLS; +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; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; +import com.google.common.flogger.FluentLogger; import cwms.cda.api.errors.CdaError; import cwms.cda.data.dao.TimeSeriesGroupDao; import cwms.cda.data.dto.TimeSeriesGroup; @@ -47,7 +71,6 @@ import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; import io.javalin.plugin.openapi.annotations.OpenApiResponse; import java.util.List; -import com.google.common.flogger.FluentLogger; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -281,17 +304,32 @@ public void update(@NotNull Context ctx, @NotNull String oldGroupId) { boolean replaceAssignedTs = ctx.queryParamAsClass(REPLACE_ASSIGNED_TS, Boolean.class) .getOrDefault(false); TimeSeriesGroupDao timeSeriesGroupDao = new TimeSeriesGroupDao(dsl); + TimeSeriesGroup existingGroup = timeSeriesGroupDao.getTimeSeriesGroup(office, null, + null, group.getTimeSeriesCategory().getId(), oldGroupId); + if (!existingGroup.getDescription().equalsIgnoreCase(group.getDescription())) { + existingGroup = updateClearedFields(group, existingGroup); + timeSeriesGroupDao.create(existingGroup, false, false); + } if (!office.equalsIgnoreCase(CWMS_OFFICE) && !oldGroupId.equals(group.getId())) { timeSeriesGroupDao.renameTimeSeriesGroup(oldGroupId, group); } if (replaceAssignedTs) { - timeSeriesGroupDao.unassignForOffice(group.getTimeSeriesCategory().getId(), group.getId(), group.getOfficeId(), office); + timeSeriesGroupDao.unassignForOffice(group.getTimeSeriesCategory().getId(), group.getId(), + group.getOfficeId(), office); } timeSeriesGroupDao.assignTs(group, office); ctx.status(HttpServletResponse.SC_OK); } } + private TimeSeriesGroup updateClearedFields(TimeSeriesGroup groupBody, + TimeSeriesGroup existingTimeSeriesGroup) { + return new TimeSeriesGroup(new TimeSeriesGroup(existingTimeSeriesGroup.getTimeSeriesCategory(), + existingTimeSeriesGroup.getOfficeId(), existingTimeSeriesGroup.getId(), groupBody.getDescription(), + existingTimeSeriesGroup.getSharedAliasId(), existingTimeSeriesGroup.getSharedRefTsId()), + existingTimeSeriesGroup.getAssignedTimeSeries()); + } + @OpenApi( description = "Deletes requested time series group", pathParams = { @@ -303,7 +341,8 @@ public void update(@NotNull Context ctx, @NotNull String oldGroupId) { @OpenApiParam(name = OFFICE, required = true, description = "Specifies the " + "owning office of the time series group to be deleted"), @OpenApiParam(name = CASCADE_DELETE, type = Boolean.class, - description = "Specifies whether to unassign time series in this group before deleting. Default: false"), + description = "Specifies whether to unassign time series in this group before deleting. " + + "Default: false"), }, method = HttpMethod.DELETE, tags = {TAG} 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 7f455b48f8..e582b09c08 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 @@ -373,9 +373,9 @@ private void deleteViaUnassign(DSLContext dslContext, String categoryId, String public void unassignAll(String categoryId, String groupId, String office) { - dsl.transaction((Configuration config) -> { - unassignAll(config, categoryId, groupId, office); - }); + dsl.transaction((Configuration config) -> + unassignAll(config, categoryId, groupId, office) + ); } // This may not be that useful in practice. Typically groups either below to an office like SPK or to CWMS. @@ -402,12 +402,13 @@ private void unassignAll(Configuration config, String categoryId, String groupId public void unassignForOffice( String categoryId, String groupId, String office, String assignmentOffice) { connection(dsl, conn -> { - DSLContext dslContext = getDslContext(conn, office); + DSLContext dslContext = getDslContext(conn, assignmentOffice); unassignForOffice(dslContext.configuration(), categoryId, groupId, office, assignmentOffice); }); } - public static void unassignForOffice(Configuration config, String categoryId, String groupId, String office, String assignmentOffice) { + public static void unassignForOffice(Configuration config, String categoryId, String groupId, + String office, String assignmentOffice) { if (office != null && !"CWMS".equals(office)) { CWMS_ENV_PACKAGE.call_SET_SESSION_OFFICE_ID(config, assignmentOffice); } 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 f37adda9ab..9ffd611348 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 @@ -145,7 +145,7 @@ void clear_data() throws Exception { } catch (NotFoundException e) { LOGGER.atConfig().withCause(e).log("Group not found"); } catch (DataAccessException e) { - LOGGER.atInfo().withCause(e).log("Failed to unassign ts from %s that are in group owned by:%s", assignOffice, group.getOfficeId()); + LOGGER.atInfo().withCause(e).log("Failed to unassign ts from %s that are in group owned by %s", assignOffice, group.getOfficeId()); } } cwmsgroupsToSPKUnassign.clear(); @@ -1010,7 +1010,7 @@ void test_rename_group(String format) throws Exception { .log().ifValidationFails(LogDetail.ALL,true) .statusCode(is(HttpServletResponse.SC_CREATED)); - TimeSeriesGroup newGroup = new TimeSeriesGroup(cat, officeId, "test_rename_group_new", "IntegrationTesting", + TimeSeriesGroup newGroup = new TimeSeriesGroup(cat, officeId, "test_rename_group_new", "Test group rename", "sharedTsAliasId2", timeSeriesId); String newGroupXml = Formats.format(contentType, newGroup); //Rename Group @@ -1051,7 +1051,7 @@ void test_rename_group(String format) throws Exception { .statusCode(is(HttpServletResponse.SC_OK)) .body("office-id", equalTo(newGroup.getOfficeId())) .body("id", equalTo(newGroup.getId())) - .body("description", equalTo(newGroup.getDescription())) + .body("description", equalTo("Test group rename")) .body("assigned-time-series[0].timeseries-id", equalTo(timeSeriesId)) .body("assigned-time-series[0].alias-id", equalTo("AliasId")) .body("assigned-time-series[0].ref-ts-id", equalTo(timeSeriesId)); @@ -1222,6 +1222,26 @@ void test_add_assigned_locs(String format) { .assertThat() .log().ifValidationFails(LogDetail.ALL,true) .statusCode(is(HttpServletResponse.SC_OK)); + given() + .log().ifValidationFails(LogDetail.ALL,true) + .accept(format) + .contentType(Formats.JSON) + .queryParam(OFFICE, officeId) + .queryParam(CATEGORY_OFFICE_ID, officeId) + .queryParam(GROUP_OFFICE_ID, officeId) + .queryParam(CATEGORY_ID, group.getTimeSeriesCategory().getId()) + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/timeseries/group/" + group.getId()) + .then() + .assertThat() + .log().ifValidationFails(LogDetail.ALL,true) + .statusCode(is(HttpServletResponse.SC_OK)) + .body("office-id", equalTo(group.getOfficeId())) + .body("id", equalTo(group.getId())) + .body("description", equalTo(group.getDescription())) + .body("assigned-time-series.size()", equalTo(0)); //Delete Group given() .log().ifValidationFails(LogDetail.ALL,true) @@ -1519,16 +1539,18 @@ void test_patch_district_permission(String format) throws Exception { // Create Category given() - .log().ifValidationFails(LogDetail.ALL, true) - .accept(Formats.JSON) - .contentType(Formats.JSON) - .body(json) - .header("Authorization", user.toHeaderValue()) - .when() - .post("/timeseries/category") - .then() - .statusCode(anyOf(is(HttpServletResponse.SC_CREATED), is(HttpServletResponse.SC_CONFLICT))) - ; + .log().ifValidationFails(LogDetail.ALL, true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(json) + .header("Authorization", user.toHeaderValue()) + .when() + .post("/timeseries/category") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(anyOf(is(HttpServletResponse.SC_CREATED), is(HttpServletResponse.SC_CONFLICT))) + ; TimeSeriesGroup districtGroup = new TimeSeriesGroup(category, CWMS_OFFICE, "Default", "All Time Series", null, null); @@ -1539,15 +1561,17 @@ void test_patch_district_permission(String format) throws Exception { // Create Group given() - .log().ifValidationFails(LogDetail.ALL, true) - .accept(Formats.JSON) - .contentType(Formats.JSON) - .body(json1) - .header("Authorization", user.toHeaderValue()) - .when() - .post("/timeseries/group") - .then() - .statusCode(anyOf(is(HttpServletResponse.SC_CREATED), is(HttpServletResponse.SC_CONFLICT))) + .log().ifValidationFails(LogDetail.ALL, true) + .accept(Formats.JSON) + .contentType(Formats.JSON) + .body(json1) + .header("Authorization", user.toHeaderValue()) + .when() + .post("/timeseries/group") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(anyOf(is(HttpServletResponse.SC_CREATED), is(HttpServletResponse.SC_CONFLICT))) ; AssignedTimeSeries assignedTimeSeries = new AssignedTimeSeries(officeId, tsId, null, null, null);