From 1d0cddb5d4711f36defb8385623e1035ec3ec6b5 Mon Sep 17 00:00:00 2001 From: zack-rma Date: Wed, 20 Nov 2024 08:25:08 -0800 Subject: [PATCH] CWMSVue 594 - Added location office parameter to LocationGroup getAll (#954) Added location office parameter to LocationGroup getAll --- .../cwms/cda/api/LocationGroupController.java | 30 ++-- .../cwms/cda/data/dao/LocationGroupDao.java | 163 ++++++++++-------- .../cda/data/dao/LocationGroupDaoTestIT.java | 8 +- 3 files changed, 111 insertions(+), 90 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 bc90519d0..d6083bf62 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 @@ -59,6 +59,7 @@ public class LocationGroupController implements CrudHandler { public static final Logger logger = Logger.getLogger(LocationGroupController.class.getName()); + private static final String LOCATION_OFFICE_ID = "location-office-id"; public static final String TAG = "Location Groups"; private final MetricRegistry metrics; @@ -76,9 +77,10 @@ private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); } - @OpenApi(queryParams = { + @OpenApi( + queryParams = { @OpenApiParam(name = OFFICE, description = "Specifies the owning office of the " - + "location group(s) whose data is to be included in the response. If this " + + "location group whose data is to be included in the response. If this " + "field is not specified, matching location groups information from all " + "offices shall be returned."), @OpenApiParam(name = INCLUDE_ASSIGNED, type = Boolean.class, description = "Include" @@ -87,7 +89,9 @@ private Timer.Context markAndTime(String subject) { + "matching against the location category id"), @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.") + + "whose data is to be included in the response."), + @OpenApiParam(name = LOCATION_OFFICE_ID, required = true, description = "Specifies the " + + "owning office of the location assigned to the location group whose data is to be included in the response."), }, responses = { @OpenApiResponse(status = STATUS_200, @@ -96,7 +100,8 @@ private Timer.Context markAndTime(String subject) { @OpenApiContent(isArray = true, from = CsvV1LocationGroup.class, type = Formats.CSV) }) }, - description = "Returns CWMS Location Groups Data", tags = {TAG}) + description = "Returns CWMS Location Groups Data", tags = {TAG} + ) @Override public void getAll(@NotNull Context ctx) { @@ -106,6 +111,7 @@ public void getAll(@NotNull Context ctx) { String groupOfficeId = requiredParam(ctx, OFFICE); String categoryOfficeId = requiredParam(ctx, CATEGORY_OFFICE_ID); + String locationOfficeId = ctx.queryParam(LOCATION_OFFICE_ID); boolean includeAssigned = queryParamAsClass(ctx, new String[]{INCLUDE_ASSIGNED}, Boolean.class, false, metrics, name(LocationGroupController.class.getName(), @@ -114,7 +120,7 @@ Boolean.class, false, metrics, name(LocationGroupController.class.getName(), String locCategoryLike = queryParamAsClass(ctx, new String[]{LOCATION_CATEGORY_LIKE}, String.class, null, metrics, name(LocationGroupController.class.getName(), GET_ALL)); - List grps = cdm.getLocationGroups(groupOfficeId, categoryOfficeId, + List grps = cdm.getLocationGroups(locationOfficeId, groupOfficeId, categoryOfficeId, includeAssigned, locCategoryLike); if (!grps.isEmpty()) { @@ -163,14 +169,15 @@ Boolean.class, false, metrics, name(LocationGroupController.class.getName(), @OpenApiContent(type = Formats.GEOJSON) }) }, - description = "Retrieves requested Location Group", tags = {TAG}) + description = "Retrieves requested Location Group", tags = {TAG} + ) @Override public void getOne(@NotNull Context ctx, @NotNull String groupId) { try (final Timer.Context ignored = markAndTime(GET_ONE)) { DSLContext dsl = getDslContext(ctx); LocationGroupDao cdm = new LocationGroupDao(dsl); - String office = requiredParam(ctx, OFFICE); + String locationOfficeId = requiredParam(ctx, OFFICE); String categoryId = requiredParam(ctx, CATEGORY_ID); // Not marked as required to maintain backwards compatibility with existing clients @@ -182,13 +189,13 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { ContentType contentType; if (formatHeader != null && formatHeader.contains(Formats.GEOJSON)) { contentType = new ContentType(Formats.GEOJSON); - FeatureCollection fc = cdm.buildFeatureCollectionForLocationGroup(office, + FeatureCollection fc = cdm.buildFeatureCollectionForLocationGroup(locationOfficeId, groupOfficeId, categoryOfficeId, categoryId, groupId, "EN"); ObjectMapper mapper = ctx.appAttribute("ObjectMapper"); result = mapper.writeValueAsString(fc); } else { contentType = Formats.parseHeader(formatHeader, LocationGroup.class); - Optional grp = cdm.getLocationGroup(office, categoryId, groupId); + Optional grp = cdm.getLocationGroup(locationOfficeId, categoryId, groupId); if (grp.isPresent()) { result = Formats.format(contentType, grp.get()); } else { @@ -300,9 +307,8 @@ public void update(@NotNull Context ctx, @NotNull String oldGroupId) { + "location category of the location group to be deleted"), @OpenApiParam(name = OFFICE, required = true, description = "Specifies the " + "owning office of the location group to be deleted"), - @OpenApiParam(name = CASCADE_DELETE, type = Boolean.class, - description = "Specifies whether to specifies whether to unassign any " - + "location assignments. Default: false"), + @OpenApiParam(name = CASCADE_DELETE, type = Boolean.class, description = "Specifies whether " + + "to unassign any location assignments. Default: false"), }, method = HttpMethod.DELETE, tags = {TAG} 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 efdb7f543..f59b1fef0 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 @@ -100,28 +100,28 @@ public Optional getLocationGroup(@NotNull String officeId, @NotNu } List> assignments = dsl.select( - alcg.CAT_DB_OFFICE_ID, - alcg.LOC_CATEGORY_ID, - alcg.LOC_CATEGORY_DESC, - alcg.GRP_DB_OFFICE_ID, - alcg.LOC_GROUP_ID, - alcg.LOC_GROUP_DESC, - alcg.LOC_GROUP_ATTRIBUTE, - alcg.SHARED_LOC_ALIAS_ID, - alcg.SHARED_REF_LOCATION_ID, - alga.DB_OFFICE_ID, - alga.LOCATION_ID, - alga.ALIAS_ID, - alga.ATTRIBUTE, - alga.REF_LOCATION_ID) + alcg.CAT_DB_OFFICE_ID, + alcg.LOC_CATEGORY_ID, + alcg.LOC_CATEGORY_DESC, + alcg.GRP_DB_OFFICE_ID, + alcg.LOC_GROUP_ID, + alcg.LOC_GROUP_DESC, + alcg.LOC_GROUP_ATTRIBUTE, + alcg.SHARED_LOC_ALIAS_ID, + alcg.SHARED_REF_LOCATION_ID, + alga.DB_OFFICE_ID, + alga.LOCATION_ID, + alga.ALIAS_ID, + alga.ATTRIBUTE, + alga.REF_LOCATION_ID) .from(alcg).leftJoin(alga) .on(alcg.LOC_CATEGORY_ID.eq(alga.CATEGORY_ID) - .and(alcg.LOC_GROUP_ID.eq(alga.GROUP_ID))) + .and(alcg.LOC_GROUP_ID.eq(alga.GROUP_ID))) .where(alcg.LOC_CATEGORY_ID.eq(categoryId) - .and(alcg.LOC_GROUP_ID.eq(groupId)) - .and(alcg.GRP_DB_OFFICE_ID.in(CWMS, officeId)) - .and(alcg.CAT_DB_OFFICE_ID.in(CWMS, officeId)) - .and(assignmentOffice) + .and(alcg.LOC_GROUP_ID.eq(groupId)) + .and(alcg.GRP_DB_OFFICE_ID.in(CWMS, officeId)) + .and(alcg.CAT_DB_OFFICE_ID.in(CWMS, officeId)) + .and(assignmentOffice) ) .orderBy(alga.ATTRIBUTE).fetchSize(1000).fetch(mapper); @@ -186,7 +186,7 @@ private LocationCategory buildLocationCategory(Record resultRecord) { * @return A list of all location groups. */ public List getLocationGroups() { - return getLocationGroups(null, null, null); + return getLocationGroups(null, null, null, null); } /** @@ -195,7 +195,11 @@ public List getLocationGroups() { * @return A list of all location groups for the given office. */ public List getLocationGroups(String officeId) { - return getLocationGroups(officeId, null, null); + return getLocationGroups(officeId, null, null, null); + } + + public List getLocationGroups(String officeId, String categoryOfficeId, String locCategoryLike) { + return getLocationGroups(officeId, null, categoryOfficeId, locCategoryLike); } /** @@ -205,11 +209,11 @@ public List getLocationGroups(String officeId) { * @param locCategoryLike A regex to use to filter the location categories. May be null. * @return A list of all location groups for the given office and category. */ - public List getLocationGroups(@Nullable String officeId, + public List getLocationGroups(@Nullable String officeId, String groupOfficeId, String categoryOfficeId, boolean includeAssigned, @Nullable String locCategoryLike) { if (includeAssigned) { - return getLocationGroups(officeId, categoryOfficeId, locCategoryLike); + return getLocationGroups(officeId, groupOfficeId, categoryOfficeId, locCategoryLike); } else { return getGroupsWithoutAssignedLocations(officeId, categoryOfficeId, locCategoryLike); } @@ -218,16 +222,15 @@ 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 locationOfficeId The office id to use for the query. * @param groupOfficeId 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. */ - public List getLocationGroups(String groupOfficeId, String categoryOfficeId, String locCategoryLike, - String sharedRefLocLike) { - AV_LOC_GRP_ASSGN alga = AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN; - AV_LOC_CAT_GRP alcg = AV_LOC_CAT_GRP.AV_LOC_CAT_GRP; + public List getLocationGroups(String locationOfficeId, String groupOfficeId, String categoryOfficeId, + String locCategoryLike, String sharedRefLocLike) { final RecordMapper> mapper = grpRecord -> { LocationCategory category = buildLocationCategory(grpRecord); @@ -238,6 +241,9 @@ public List getLocationGroups(String groupOfficeId, String catego return new Pair<>(group, loc); }; + AV_LOC_GRP_ASSGN alga = AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN; + AV_LOC_CAT_GRP alcg = AV_LOC_CAT_GRP.AV_LOC_CAT_GRP; + Condition condition = noCondition(); if (locCategoryLike != null && !locCategoryLike.isEmpty()) { condition = caseInsensitiveLikeRegex(alcg.LOC_CATEGORY_ID, locCategoryLike); @@ -255,30 +261,32 @@ public List getLocationGroups(String groupOfficeId, String catego SelectConnectByStep connectBy; SelectOnConditionStep onStep = dsl.select( - alcg.CAT_DB_OFFICE_ID, - alcg.LOC_CATEGORY_ID, - alcg.LOC_CATEGORY_DESC, - alcg.GRP_DB_OFFICE_ID, - alcg.LOC_GROUP_ID, - alcg.LOC_GROUP_DESC, - alcg.LOC_GROUP_ATTRIBUTE, - alcg.SHARED_LOC_ALIAS_ID, - alcg.SHARED_REF_LOCATION_ID, - alga.DB_OFFICE_ID, - alga.LOCATION_ID, - alga.ALIAS_ID, - alga.ATTRIBUTE, - alga.REF_LOCATION_ID) - .from(alcg).leftJoin(alga) - .on(alcg.LOC_CATEGORY_ID.eq(alga.CATEGORY_ID) - .and(alcg.LOC_GROUP_ID.eq(alga.GROUP_ID))); + alcg.CAT_DB_OFFICE_ID, + alcg.LOC_CATEGORY_ID, + alcg.LOC_CATEGORY_DESC, + alcg.GRP_DB_OFFICE_ID, + alcg.LOC_GROUP_ID, + alcg.LOC_GROUP_DESC, + alcg.LOC_GROUP_ATTRIBUTE, + alcg.SHARED_LOC_ALIAS_ID, + alcg.SHARED_REF_LOCATION_ID, + alga.DB_OFFICE_ID, + alga.LOCATION_ID, + alga.ALIAS_ID, + alga.ATTRIBUTE, + alga.REF_LOCATION_ID) + .from(alcg).leftJoin(alga) + .on(alcg.LOC_CATEGORY_ID.eq(alga.CATEGORY_ID) + .and(alcg.LOC_GROUP_ID.eq(alga.GROUP_ID))); if (groupOfficeId != null) { - connectBy = onStep.where(DSL.upper(alcg.GRP_DB_OFFICE_ID).eq(groupOfficeId.toUpperCase()).and(condition)); - } else { - connectBy = onStep.where(condition); + condition = condition.and(DSL.upper(alcg.GRP_DB_OFFICE_ID).eq(groupOfficeId.toUpperCase())); + } else if (locationOfficeId != null) { + condition = condition.and(DSL.upper(alga.DB_OFFICE_ID).eq(locationOfficeId.toUpperCase())); } + connectBy = onStep.where(condition); + Map> map = new LinkedHashMap<>(); connectBy.orderBy(alcg.LOC_CATEGORY_ID, alcg.LOC_GROUP_ID, alga.ATTRIBUTE) @@ -301,12 +309,13 @@ public List getLocationGroups(String groupOfficeId, String catego /** * Get all location groups for a given office and category. + * @param locationOfficeId The group office id to use for the query. * @param groupOfficeId The group office id to use for the query. * @param categoryOfficeId The category office id to use for the query. * @param locCategoryLike A regex to use to filter the location categories. May be null. * @return A list of all location groups for the given office and category. */ - public List getLocationGroups(String groupOfficeId, + public List getLocationGroups(String locationOfficeId, String groupOfficeId, String categoryOfficeId, String locCategoryLike) { AV_LOC_GRP_ASSGN alga = AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN; AV_LOC_CAT_GRP alcg = AV_LOC_CAT_GRP.AV_LOC_CAT_GRP; @@ -339,8 +348,8 @@ public List getLocationGroups(String groupOfficeId, alga.ATTRIBUTE, alga.REF_LOCATION_ID) .from(alcg).leftJoin(alga) - .on(alcg.LOC_CATEGORY_ID.eq(alga.CATEGORY_ID) - .and(alcg.LOC_GROUP_ID.eq(alga.GROUP_ID))); + .on(alcg.LOC_CATEGORY_ID.eq(alga.CATEGORY_ID) + .and(alcg.LOC_GROUP_ID.eq(alga.GROUP_ID))); Condition condition = noCondition(); @@ -352,18 +361,24 @@ public List getLocationGroups(String groupOfficeId, condition = condition.and(alcg.CAT_DB_OFFICE_ID.eq(categoryOfficeId.toUpperCase())); } - if (groupOfficeId != null) { - if (CWMS.equalsIgnoreCase(groupOfficeId)) { + if (locationOfficeId != null) { + if (CWMS.equalsIgnoreCase(locationOfficeId)) { connectBy = onStep.where(alcg.CAT_DB_OFFICE_ID.eq(CWMS) .and(alcg.GRP_DB_OFFICE_ID.eq(CWMS)) .and(condition) ); } else { - connectBy = onStep.where(alcg.CAT_DB_OFFICE_ID.in(CWMS, groupOfficeId) - .and(alcg.GRP_DB_OFFICE_ID.in(CWMS, groupOfficeId)) - .and(alga.DB_OFFICE_ID.isNull().or(alga.DB_OFFICE_ID.eq(groupOfficeId))) - .and(condition) - ); + if (groupOfficeId != null) { + connectBy = onStep.where(alcg.CAT_DB_OFFICE_ID.in(CWMS, locationOfficeId) + .and(alcg.GRP_DB_OFFICE_ID.in(CWMS, groupOfficeId)) + .and(alga.DB_OFFICE_ID.isNull().or(alga.DB_OFFICE_ID.eq(locationOfficeId))) + .and(condition) + ); + } else { + connectBy = onStep.where(alcg.CAT_DB_OFFICE_ID.in(CWMS, locationOfficeId) + .and(alga.DB_OFFICE_ID.isNull().or(alga.DB_OFFICE_ID.eq(locationOfficeId))) + .and(condition)); + } } } else { connectBy = onStep.where(alcg.LOC_GROUP_ID.isNotNull()); @@ -449,23 +464,23 @@ public Feature buildFeatureFromAvLocRecordWithLocGroup(Record avLocRecord) { } public FeatureCollection buildFeatureCollectionForLocationGroup(String locationOfficeId, String groupOfficeId, - String categoryOfficeId, - String categoryId, - String groupId, String units) { + String categoryOfficeId, + String categoryId, + String groupId, String units) { AV_LOC_GRP_ASSGN alga = AV_LOC_GRP_ASSGN.AV_LOC_GRP_ASSGN; 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(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)))) - .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(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)))) + .orderBy(alga.ATTRIBUTE); List features = select.stream() @@ -513,7 +528,7 @@ public void create(LocationGroup group) { private static LOC_ALIAS_TYPE3 convertToLocAliasType(AssignedLocation a) { BigDecimal attribute = toBigDecimal(a.getAttribute()); return new LOC_ALIAS_TYPE3(a.getLocationId(), - attribute, a.getAliasId(), a.getRefLocationId()); + attribute, a.getAliasId(), a.getRefLocationId()); } /** @@ -557,10 +572,10 @@ public void assignLocs(DSLContext dslContext, LocationGroup group, String office List assignedLocations = group.getAssignedLocations(); if (assignedLocations != null) { List collect = assignedLocations.stream() - .map(LocationGroupDao::convertToLocAliasType) - .collect(toList()); + .map(LocationGroupDao::convertToLocAliasType) + .collect(toList()); LOC_ALIAS_ARRAY3 assignedLocs = new LOC_ALIAS_ARRAY3(collect); - LocationCategory cat = group.getLocationCategory(); + LocationCategory cat = group.getLocationCategory(); CWMS_LOC_PACKAGE.call_ASSIGN_LOC_GROUPS3(dslContext.configuration(), cat.getId(), group.getId(), assignedLocs, office); } diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dao/LocationGroupDaoTestIT.java b/cwms-data-api/src/test/java/cwms/cda/data/dao/LocationGroupDaoTestIT.java index b6b03aa59..e07e87196 100644 --- a/cwms-data-api/src/test/java/cwms/cda/data/dao/LocationGroupDaoTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/data/dao/LocationGroupDaoTestIT.java @@ -39,8 +39,8 @@ void testGetAllWithoutAssignedLocations() throws Exception { LocationGroupDao dao = new LocationGroupDao(dslContext(c)); List groups = dao.getLocationGroups("SPK"); Optional group = groups.stream() - .filter(g -> "Test Group2".equals(g.getId())) - .findFirst(); + .filter(g -> "Test Group2".equals(g.getId())) + .findFirst(); assertTrue(group.isPresent()); } catch (Exception e) { throw new RuntimeException(e); @@ -96,7 +96,7 @@ void testGetAllWithCategoryRegexStarAndLocRefRegexStarFindsOne() throws Exceptio db.connection(c -> { try { LocationGroupDao dao = new LocationGroupDao(dslContext(c)); - List groups = dao.getLocationGroups("SPK", "SPK", "*Category4", "*Loc Ref"); + List groups = dao.getLocationGroups(null, "SPK", "SPK","*Category4", "*Loc Ref"); Optional group2 = groups.stream() .filter(g -> "Test Group2".equals(g.getId())) .findFirst(); @@ -114,7 +114,7 @@ void testGetAllWithCategoryRegexStarAndLocRefRegexStarFindsBoth() throws Excepti db.connection(c -> { try { LocationGroupDao dao = new LocationGroupDao(dslContext(c)); - List groups = dao.getLocationGroups("SPK", "SPK", "*Category*", "*Loc*"); + List groups = dao.getLocationGroups(null, "SPK", "SPK", "*Category*", "*Loc*"); Optional group2 = groups.stream() .filter(g -> "Test Group2".equals(g.getId())) .findFirst();