From 1e2505b3a6b9ed17bb06a51ef16642d4613dc095 Mon Sep 17 00:00:00 2001 From: Priyanka-eGov Date: Mon, 27 Jan 2025 18:10:37 +0530 Subject: [PATCH 1/7] HCMPRE-2212 making facilityId in plan search a set for multiple drop down search, changes filterMap signature. --- .../src/main/java/digit/service/PlanEnricher.java | 14 +++++++------- .../java/digit/web/models/PlanSearchCriteria.java | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/health-services/plan-service/src/main/java/digit/service/PlanEnricher.java b/health-services/plan-service/src/main/java/digit/service/PlanEnricher.java index 1cff13076dc..7ab443a6f31 100644 --- a/health-services/plan-service/src/main/java/digit/service/PlanEnricher.java +++ b/health-services/plan-service/src/main/java/digit/service/PlanEnricher.java @@ -253,31 +253,31 @@ public void enrichSearchRequest(PlanSearchRequest planSearchRequest) { PlanSearchCriteria planSearchCriteria = planSearchRequest.getPlanSearchCriteria(); // Filter map for filtering plan metadata present in additional details - Map filtersMap = new LinkedHashMap<>(); + Map> filtersMap = new LinkedHashMap<>(); // Add facility id as a filter if present in search criteria - if (!ObjectUtils.isEmpty(planSearchCriteria.getFacilityId())) { - filtersMap.put(FACILITY_ID_SEARCH_PARAMETER_KEY, planSearchCriteria.getFacilityId()); + if (!ObjectUtils.isEmpty(planSearchCriteria.getFacilityIds())) { + filtersMap.put(FACILITY_ID_SEARCH_PARAMETER_KEY, planSearchCriteria.getFacilityIds()); } // Add terrain as a filter if present in search criteria if (!ObjectUtils.isEmpty(planSearchCriteria.getTerrain())) { - filtersMap.put(TERRAIN_CONDITION_SEARCH_PARAMETER_KEY, planSearchCriteria.getTerrain()); + filtersMap.put(TERRAIN_CONDITION_SEARCH_PARAMETER_KEY, Collections.singleton(planSearchCriteria.getTerrain())); } // Add onRoadCondition as a filter if present in search criteria if (!ObjectUtils.isEmpty(planSearchCriteria.getOnRoadCondition())) { - filtersMap.put(ROAD_CONDITION_SEARCH_PARAMETER_KEY, planSearchCriteria.getOnRoadCondition()); + filtersMap.put(ROAD_CONDITION_SEARCH_PARAMETER_KEY, Collections.singleton(planSearchCriteria.getOnRoadCondition())); } // Add securityQ1 as a filter if present in search criteria if (!ObjectUtils.isEmpty(planSearchCriteria.getSecurityQ1())) { - filtersMap.put(SECURITY_Q1_SEARCH_PARAMETER_KEY, planSearchCriteria.getSecurityQ1()); + filtersMap.put(SECURITY_Q1_SEARCH_PARAMETER_KEY, Collections.singleton(planSearchCriteria.getSecurityQ1())); } // Add securityQ2 as a filter if present in search criteria if (!ObjectUtils.isEmpty(planSearchCriteria.getSecurityQ2())) { - filtersMap.put(SECURITY_Q2_SEARCH_PARAMETER_KEY, planSearchCriteria.getSecurityQ2()); + filtersMap.put(SECURITY_Q2_SEARCH_PARAMETER_KEY, Collections.singleton(planSearchCriteria.getSecurityQ2())); } if(!CollectionUtils.isEmpty(filtersMap)) diff --git a/health-services/plan-service/src/main/java/digit/web/models/PlanSearchCriteria.java b/health-services/plan-service/src/main/java/digit/web/models/PlanSearchCriteria.java index f71cca497fc..f0b22e87d65 100644 --- a/health-services/plan-service/src/main/java/digit/web/models/PlanSearchCriteria.java +++ b/health-services/plan-service/src/main/java/digit/web/models/PlanSearchCriteria.java @@ -40,8 +40,8 @@ public class PlanSearchCriteria { @JsonProperty("planConfigurationId") private String planConfigurationId = null; - @JsonProperty("facilityId") - private String facilityId = null; + @JsonProperty("facilityIds") + private Set facilityIds = null; @JsonProperty("onRoadCondition") private String onRoadCondition = null; @@ -72,6 +72,6 @@ public class PlanSearchCriteria { private Integer limit = null; @JsonIgnore - private Map filtersMap = null; + private Map> filtersMap = null; } From b561a96710f48a38d7b4dda70a2afafe01614eee Mon Sep 17 00:00:00 2001 From: Priyanka-eGov Date: Mon, 27 Jan 2025 18:15:30 +0530 Subject: [PATCH 2/7] HCMPRE-2212 making facilityId in plan search a set for multiple drop down search, changes filterMap signature. --- .../src/main/java/digit/util/QueryUtil.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java index 070f442a897..3333400e3f0 100644 --- a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java +++ b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java @@ -102,7 +102,7 @@ public String addOrderByClause(String query, String orderByClause) { * @param filterMap * @return */ - public String preparePartialJsonStringFromFilterMap(Map filterMap) { + public String preparePartialJsonStringFromFilterMap(Map> filterMap) { Map queryMap = new HashMap<>(); filterMap.keySet().forEach(key -> { @@ -129,16 +129,16 @@ public String preparePartialJsonStringFromFilterMap(Map filterMa * @param index * @param nestedKeyArray * @param currentQueryMap - * @param value + * @param values */ - private void prepareNestedQueryMap(int index, String[] nestedKeyArray, Map currentQueryMap, String value) { + private void prepareNestedQueryMap(int index, String[] nestedKeyArray, Map currentQueryMap, Set values) { // Return when all levels have been reached. if (index == nestedKeyArray.length) return; // For the final level simply put the value in the map. else if (index == nestedKeyArray.length - 1) { - currentQueryMap.put(nestedKeyArray[index], value); + currentQueryMap.put(nestedKeyArray[index], values); return; } @@ -146,7 +146,7 @@ else if (index == nestedKeyArray.length - 1) { currentQueryMap.put(nestedKeyArray[index], new HashMap<>()); // Make a recursive call to enrich data in next level. - prepareNestedQueryMap(index + 1, nestedKeyArray, (Map) currentQueryMap.get(nestedKeyArray[index]), value); + prepareNestedQueryMap(index + 1, nestedKeyArray, (Map) currentQueryMap.get(nestedKeyArray[index]), values); } /** From fcce569226f3583f6a4fc6c76a2dc67435c2d2ce Mon Sep 17 00:00:00 2001 From: Priyanka-eGov Date: Mon, 27 Jan 2025 18:20:24 +0530 Subject: [PATCH 3/7] HCMPRE-2212 making facilityId in plan search a set for multiple drop down search, changes filterMap signature. --- .../java/digit/service/enrichment/PlanFacilityEnricher.java | 6 +++--- .../java/digit/web/models/PlanFacilitySearchCriteria.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java b/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java index fccb2de96df..c204f54c694 100644 --- a/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java +++ b/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java @@ -192,16 +192,16 @@ public void enrichSearchRequest(PlanFacilitySearchRequest planFacilitySearchRequ PlanFacilitySearchCriteria planFacilitySearchCriteria = planFacilitySearchRequest.getPlanFacilitySearchCriteria(); // Filter map for filtering facility meta data present in additional details - Map filtersMap = new LinkedHashMap<>(); + Map> filtersMap = new LinkedHashMap<>(); // Add facility status as a filter if present in search criteria if(!ObjectUtils.isEmpty(planFacilitySearchCriteria.getFacilityStatus())) { - filtersMap.put(FACILITY_STATUS_SEARCH_PARAMETER_KEY, planFacilitySearchCriteria.getFacilityStatus()); + filtersMap.put(FACILITY_STATUS_SEARCH_PARAMETER_KEY, Collections.singleton(planFacilitySearchCriteria.getFacilityStatus())); } // Add facility type as a filter if present in search criteria if(!ObjectUtils.isEmpty(planFacilitySearchCriteria.getFacilityType())) { - filtersMap.put(FACILITY_TYPE_SEARCH_PARAMETER_KEY, planFacilitySearchCriteria.getFacilityType()); + filtersMap.put(FACILITY_TYPE_SEARCH_PARAMETER_KEY, Collections.singleton(planFacilitySearchCriteria.getFacilityType())); } if(!CollectionUtils.isEmpty(filtersMap)) diff --git a/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java b/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java index a5a4e49c42c..bab8d1555f1 100644 --- a/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java +++ b/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java @@ -59,6 +59,6 @@ public class PlanFacilitySearchCriteria { private Integer limit = null; @JsonIgnore - private Map filtersMap = null; + private Map> filtersMap = null; } From 06f635d61e83302115203d2dbe14a6acfc02d506 Mon Sep 17 00:00:00 2001 From: Priyanka-eGov Date: Tue, 28 Jan 2025 13:54:38 +0530 Subject: [PATCH 4/7] HCMPRE-2212 making facilityId in plan search a set for multiple drop down search, changes filterMap signature. --- .../repository/impl/PlanRepositoryImpl.java | 1 + .../querybuilder/PlanQueryBuilder.java | 28 +++++---- .../enrichment/PlanFacilityEnricher.java | 6 +- .../src/main/java/digit/util/QueryUtil.java | 57 ++++++++++++++++--- .../models/PlanFacilitySearchCriteria.java | 2 +- 5 files changed, 70 insertions(+), 24 deletions(-) diff --git a/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java b/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java index 90cdb199bf8..d1e6ca25217 100644 --- a/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java +++ b/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java @@ -152,6 +152,7 @@ private List queryDatabaseForPlanIds(PlanSearchCriteria planSearchCriter List preparedStmtList = new ArrayList<>(); String query = planQueryBuilder.getPlanSearchQuery(planSearchCriteria, preparedStmtList); log.info("Plan search query: " + query); + log.info("PreparedStatment List " + preparedStmtList); return jdbcTemplate.query(query, new SingleColumnRowMapper<>(String.class), preparedStmtList.toArray()); } diff --git a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java index 27c53bb9ccb..892f87147ed 100644 --- a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java +++ b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java @@ -7,10 +7,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; +import java.util.*; @Component public class PlanQueryBuilder { @@ -172,13 +169,22 @@ private String buildPlanSearchQuery(PlanSearchCriteria planSearchCriteria, List< queryUtil.addToPreparedStatement(preparedStmtList, planSearchCriteria.getJurisdiction()); } - if(!CollectionUtils.isEmpty(planSearchCriteria.getFiltersMap())) { - queryUtil.addClauseIfRequired(builder, preparedStmtList); - builder.append(" additional_details @> CAST( ? AS jsonb )"); - String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap()); - preparedStmtList.add(partialQueryJsonString); + if (!CollectionUtils.isEmpty(planSearchCriteria.getFiltersMap())) { + Map> filtersMap = planSearchCriteria.getFiltersMap(); + for (String key : filtersMap.keySet()) { + if ("facilityId".equals(key)) { + String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList); + builder.append(partialQueryJsonString); + } else { + queryUtil.addClauseIfRequired(builder, preparedStmtList); + builder.append(" additional_details @> CAST( ? AS jsonb )"); + String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList); + preparedStmtList.add(partialQueryJsonString); + } + } } + StringBuilder countQuery = new StringBuilder(); if (isCount) { @@ -191,7 +197,7 @@ private String buildPlanSearchQuery(PlanSearchCriteria planSearchCriteria, List< if (isStatusCount) { return PLAN_STATUS_COUNT_QUERY.replace("{INTERNAL_QUERY}", builder); } - + System.out.println(preparedStmtList); return builder.toString(); } @@ -205,7 +211,7 @@ private String getPaginatedQuery(String query, PlanSearchCriteria planSearchCrit // Append limit paginatedQuery.append(" LIMIT ? "); preparedStmtList.add(ObjectUtils.isEmpty(planSearchCriteria.getLimit()) ? config.getDefaultLimit() : planSearchCriteria.getLimit()); - + System.out.println(preparedStmtList); return paginatedQuery.toString(); } diff --git a/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java b/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java index c204f54c694..fccb2de96df 100644 --- a/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java +++ b/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java @@ -192,16 +192,16 @@ public void enrichSearchRequest(PlanFacilitySearchRequest planFacilitySearchRequ PlanFacilitySearchCriteria planFacilitySearchCriteria = planFacilitySearchRequest.getPlanFacilitySearchCriteria(); // Filter map for filtering facility meta data present in additional details - Map> filtersMap = new LinkedHashMap<>(); + Map filtersMap = new LinkedHashMap<>(); // Add facility status as a filter if present in search criteria if(!ObjectUtils.isEmpty(planFacilitySearchCriteria.getFacilityStatus())) { - filtersMap.put(FACILITY_STATUS_SEARCH_PARAMETER_KEY, Collections.singleton(planFacilitySearchCriteria.getFacilityStatus())); + filtersMap.put(FACILITY_STATUS_SEARCH_PARAMETER_KEY, planFacilitySearchCriteria.getFacilityStatus()); } // Add facility type as a filter if present in search criteria if(!ObjectUtils.isEmpty(planFacilitySearchCriteria.getFacilityType())) { - filtersMap.put(FACILITY_TYPE_SEARCH_PARAMETER_KEY, Collections.singleton(planFacilitySearchCriteria.getFacilityType())); + filtersMap.put(FACILITY_TYPE_SEARCH_PARAMETER_KEY, planFacilitySearchCriteria.getFacilityType()); } if(!CollectionUtils.isEmpty(filtersMap)) diff --git a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java index 3333400e3f0..ecdc7c075ec 100644 --- a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java +++ b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java @@ -10,10 +10,7 @@ import org.springframework.util.ObjectUtils; import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.IntStream; import static digit.config.ServiceConstants.DOT_REGEX; @@ -102,7 +99,7 @@ public String addOrderByClause(String query, String orderByClause) { * @param filterMap * @return */ - public String preparePartialJsonStringFromFilterMap(Map> filterMap) { + public String preparePartialJsonStringFromFilterMap(Map filterMap) { Map queryMap = new HashMap<>(); filterMap.keySet().forEach(key -> { @@ -121,6 +118,48 @@ public String preparePartialJsonStringFromFilterMap(Map> fil return partialJsonQueryString; } + public String preparePartialJsonStringFromFilterMap(Map> filterMap, List preparedStmtList) { + Map queryMap = new HashMap<>(); + StringBuilder finalJsonQuery = new StringBuilder(); + + for (String key : filterMap.keySet()) { + // Handle nested keys (dot separator) + if (key.contains(DOT_SEPARATOR)) { + String[] keyArray = key.split(DOT_REGEX); + Map nestedQueryMap = new HashMap<>(); + prepareNestedQueryMap(0, keyArray, nestedQueryMap, String.valueOf(filterMap.get(key))); + queryMap.put(keyArray[0], nestedQueryMap.get(keyArray[0])); + return gson.toJson(queryMap); + } else if ("facilityId".equals(key)) { + Set values = filterMap.get(key); + if (values != null && !values.isEmpty()) { + StringBuilder orClauseBuilder = new StringBuilder(); + + // For each value, add an OR condition with a placeholder for the value + for (String value : values) { + if (orClauseBuilder.length() > 0) { + orClauseBuilder.append(" OR "); + } + // Add the condition for the key-value pair + orClauseBuilder.append("additional_details @> ?::jsonb"); + // Add the actual value in the format { "facilityId": "value" } + preparedStmtList.add("{\"" + key + "\": \"" + value + "\"}"); + } + + // Append the OR clause as part of the AND conditions + finalJsonQuery.append(" AND (").append(orClauseBuilder.toString()).append(") "); + return finalJsonQuery.toString(); // Return the query with OR conditions for facilityId + } + } else { + queryMap.put(key, filterMap.get(key).toString()); + } + } + + return gson.toJson(queryMap); + // Return the dynamically constructed query string + } + + /** * Tail recursive method to prepare n-level nested partial json for queries on nested data in * master data. For e.g. , if the key is in the format a.b.c, it will construct a nested json @@ -129,16 +168,16 @@ public String preparePartialJsonStringFromFilterMap(Map> fil * @param index * @param nestedKeyArray * @param currentQueryMap - * @param values + * @param value */ - private void prepareNestedQueryMap(int index, String[] nestedKeyArray, Map currentQueryMap, Set values) { + private void prepareNestedQueryMap(int index, String[] nestedKeyArray, Map currentQueryMap, String value) { // Return when all levels have been reached. if (index == nestedKeyArray.length) return; // For the final level simply put the value in the map. else if (index == nestedKeyArray.length - 1) { - currentQueryMap.put(nestedKeyArray[index], values); + currentQueryMap.put(nestedKeyArray[index], value); return; } @@ -146,7 +185,7 @@ else if (index == nestedKeyArray.length - 1) { currentQueryMap.put(nestedKeyArray[index], new HashMap<>()); // Make a recursive call to enrich data in next level. - prepareNestedQueryMap(index + 1, nestedKeyArray, (Map) currentQueryMap.get(nestedKeyArray[index]), values); + prepareNestedQueryMap(index + 1, nestedKeyArray, (Map) currentQueryMap.get(nestedKeyArray[index]), value); } /** diff --git a/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java b/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java index bab8d1555f1..a5a4e49c42c 100644 --- a/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java +++ b/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java @@ -59,6 +59,6 @@ public class PlanFacilitySearchCriteria { private Integer limit = null; @JsonIgnore - private Map> filtersMap = null; + private Map filtersMap = null; } From 3ff5addc97f166564866c89dd1ee2fff8c9e6419 Mon Sep 17 00:00:00 2001 From: Priyanka-eGov Date: Tue, 28 Jan 2025 13:56:06 +0530 Subject: [PATCH 5/7] HCMPRE-2212 making facilityId in plan search a set for multiple drop down search, changes filterMap signature. --- .../java/digit/repository/querybuilder/PlanQueryBuilder.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java index 892f87147ed..349d08fdacf 100644 --- a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java +++ b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java @@ -184,7 +184,6 @@ private String buildPlanSearchQuery(PlanSearchCriteria planSearchCriteria, List< } } - StringBuilder countQuery = new StringBuilder(); if (isCount) { @@ -197,7 +196,7 @@ private String buildPlanSearchQuery(PlanSearchCriteria planSearchCriteria, List< if (isStatusCount) { return PLAN_STATUS_COUNT_QUERY.replace("{INTERNAL_QUERY}", builder); } - System.out.println(preparedStmtList); + return builder.toString(); } @@ -211,7 +210,7 @@ private String getPaginatedQuery(String query, PlanSearchCriteria planSearchCrit // Append limit paginatedQuery.append(" LIMIT ? "); preparedStmtList.add(ObjectUtils.isEmpty(planSearchCriteria.getLimit()) ? config.getDefaultLimit() : planSearchCriteria.getLimit()); - System.out.println(preparedStmtList); + return paginatedQuery.toString(); } From 42cc2867eedd1dba1230131d08bb0b726efd3ad0 Mon Sep 17 00:00:00 2001 From: Priyanka-eGov Date: Tue, 28 Jan 2025 16:11:22 +0530 Subject: [PATCH 6/7] HCMPRE-2212 making facilityId in plan search a set for multiple drop down search, changes filterMap signature. --- .../java/digit/config/ServiceConstants.java | 7 +++ .../querybuilder/PlanQueryBuilder.java | 11 ++-- .../src/main/java/digit/util/QueryUtil.java | 63 +++++++++---------- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/health-services/plan-service/src/main/java/digit/config/ServiceConstants.java b/health-services/plan-service/src/main/java/digit/config/ServiceConstants.java index 69d0986f961..8597c1a2a5d 100644 --- a/health-services/plan-service/src/main/java/digit/config/ServiceConstants.java +++ b/health-services/plan-service/src/main/java/digit/config/ServiceConstants.java @@ -384,4 +384,11 @@ public class ServiceConstants { public static final String CONFIRMED_TARGET_POPULATION = "CONFIRMED_HCM_ADMIN_CONSOLE_TARGET_POPULATION"; + public static final String ADDITIONAL_DETAILS_QUERY = " additional_details @> CAST( ? AS jsonb )"; + + public static final String JSONB_QUERY_FORMAT = "additional_details @> ?::jsonb"; + + public static final String AND_CONDITION = " AND "; + + public static final String OR_CONDITION = " OR "; } diff --git a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java index 349d08fdacf..93c0f18ae8f 100644 --- a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java +++ b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java @@ -9,6 +9,9 @@ import java.util.*; +import static digit.config.ServiceConstants.ADDITIONAL_DETAILS_QUERY; +import static digit.config.ServiceConstants.FACILITY_ID_SEARCH_PARAMETER_KEY; + @Component public class PlanQueryBuilder { @@ -172,13 +175,13 @@ private String buildPlanSearchQuery(PlanSearchCriteria planSearchCriteria, List< if (!CollectionUtils.isEmpty(planSearchCriteria.getFiltersMap())) { Map> filtersMap = planSearchCriteria.getFiltersMap(); for (String key : filtersMap.keySet()) { - if ("facilityId".equals(key)) { - String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList); + if (FACILITY_ID_SEARCH_PARAMETER_KEY.equals(key)) { + String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList, key); builder.append(partialQueryJsonString); } else { queryUtil.addClauseIfRequired(builder, preparedStmtList); - builder.append(" additional_details @> CAST( ? AS jsonb )"); - String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList); + builder.append(ADDITIONAL_DETAILS_QUERY); + String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList, key); preparedStmtList.add(partialQueryJsonString); } } diff --git a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java index ecdc7c075ec..ff48890024a 100644 --- a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java +++ b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java @@ -13,8 +13,7 @@ import java.util.*; import java.util.stream.IntStream; -import static digit.config.ServiceConstants.DOT_REGEX; -import static digit.config.ServiceConstants.DOT_SEPARATOR; +import static digit.config.ServiceConstants.*; @Component public class QueryUtil { @@ -118,45 +117,43 @@ public String preparePartialJsonStringFromFilterMap(Map filterMa return partialJsonQueryString; } - public String preparePartialJsonStringFromFilterMap(Map> filterMap, List preparedStmtList) { + public String preparePartialJsonStringFromFilterMap(Map> filterMap, List preparedStmtList, String key) { Map queryMap = new HashMap<>(); StringBuilder finalJsonQuery = new StringBuilder(); - - for (String key : filterMap.keySet()) { - // Handle nested keys (dot separator) - if (key.contains(DOT_SEPARATOR)) { - String[] keyArray = key.split(DOT_REGEX); - Map nestedQueryMap = new HashMap<>(); - prepareNestedQueryMap(0, keyArray, nestedQueryMap, String.valueOf(filterMap.get(key))); - queryMap.put(keyArray[0], nestedQueryMap.get(keyArray[0])); - return gson.toJson(queryMap); - } else if ("facilityId".equals(key)) { - Set values = filterMap.get(key); - if (values != null && !values.isEmpty()) { - StringBuilder orClauseBuilder = new StringBuilder(); - - // For each value, add an OR condition with a placeholder for the value - for (String value : values) { - if (orClauseBuilder.length() > 0) { - orClauseBuilder.append(" OR "); - } - // Add the condition for the key-value pair - orClauseBuilder.append("additional_details @> ?::jsonb"); - // Add the actual value in the format { "facilityId": "value" } - preparedStmtList.add("{\"" + key + "\": \"" + value + "\"}"); + // Handle nested keys (dot separator) + if (key.contains(DOT_SEPARATOR)) { + String[] keyArray = key.split(DOT_REGEX); + Map nestedQueryMap = new HashMap<>(); + prepareNestedQueryMap(0, keyArray, nestedQueryMap, (String) filterMap.get(key).toArray()[0]); + queryMap.put(keyArray[0], nestedQueryMap.get(keyArray[0])); + return gson.toJson(queryMap); + } else if (FACILITY_ID_SEARCH_PARAMETER_KEY.equals(key)) { + Set values = filterMap.get(key); + if (values != null && !values.isEmpty()) { + StringBuilder orClauseBuilder = new StringBuilder(); + + // For each value, add an OR condition with a placeholder for the value + for (String value : values) { + if (orClauseBuilder.length() > 0) { + orClauseBuilder.append(OR_CONDITION); } - - // Append the OR clause as part of the AND conditions - finalJsonQuery.append(" AND (").append(orClauseBuilder.toString()).append(") "); - return finalJsonQuery.toString(); // Return the query with OR conditions for facilityId + // Add the condition for the key-value pair + orClauseBuilder.append(JSONB_QUERY_FORMAT); + // Add the actual value in the format { "facilityId": "value" } + preparedStmtList.add("{\"" + key + "\": \"" + value + "\"}"); } - } else { - queryMap.put(key, filterMap.get(key).toString()); + + // Append the OR clause as part of the AND conditions + finalJsonQuery.append(AND_CONDITION).append("(").append(orClauseBuilder.toString()).append(") "); + return finalJsonQuery.toString(); // Return the query with OR conditions for facilityId } + } else { + queryMap.put(key, (String) filterMap.get(key).toArray()[0]); } - return gson.toJson(queryMap); + // Return the dynamically constructed query string + return gson.toJson(queryMap); } From 6f2066cabbbb192e8d830dff0b4b056f730bc565 Mon Sep 17 00:00:00 2001 From: Priyanka-eGov Date: Tue, 28 Jan 2025 17:22:17 +0530 Subject: [PATCH 7/7] HCMPRE-2212 Adding comments --- .../repository/impl/PlanRepositoryImpl.java | 1 - .../querybuilder/PlanQueryBuilder.java | 2 ++ .../src/main/java/digit/util/QueryUtil.java | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java b/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java index d1e6ca25217..90cdb199bf8 100644 --- a/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java +++ b/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java @@ -152,7 +152,6 @@ private List queryDatabaseForPlanIds(PlanSearchCriteria planSearchCriter List preparedStmtList = new ArrayList<>(); String query = planQueryBuilder.getPlanSearchQuery(planSearchCriteria, preparedStmtList); log.info("Plan search query: " + query); - log.info("PreparedStatment List " + preparedStmtList); return jdbcTemplate.query(query, new SingleColumnRowMapper<>(String.class), preparedStmtList.toArray()); } diff --git a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java index 93c0f18ae8f..0b0c7347aa7 100644 --- a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java +++ b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java @@ -176,9 +176,11 @@ private String buildPlanSearchQuery(PlanSearchCriteria planSearchCriteria, List< Map> filtersMap = planSearchCriteria.getFiltersMap(); for (String key : filtersMap.keySet()) { if (FACILITY_ID_SEARCH_PARAMETER_KEY.equals(key)) { + // its for facility multi select then no need to add to preparedStmtList String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList, key); builder.append(partialQueryJsonString); } else { + // handle all other keys normally. queryUtil.addClauseIfRequired(builder, preparedStmtList); builder.append(ADDITIONAL_DETAILS_QUERY); String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList, key); diff --git a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java index ff48890024a..127dcd951a6 100644 --- a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java +++ b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java @@ -95,6 +95,8 @@ public String addOrderByClause(String query, String orderByClause) { /** * This method prepares partial json string from the filter map to query on jsonb column * + * - For nested keys (keys containing dot separators), a nested JSON structure is constructed. + * - For other keys, a simple key-value JSON structure is returned. * @param filterMap * @return */ @@ -117,6 +119,23 @@ public String preparePartialJsonStringFromFilterMap(Map filterMa return partialJsonQueryString; } + /** + * This is an overloaded function, to handle facility multi select for plan search specifically. + * Prepares a partial JSON query string based on the provided filter map, key, and prepared statement list. + * + * @param filterMap A map containing filter keys and their corresponding set of values. + * @param preparedStmtList A list to which placeholder values for prepared statements are added. + * @param key The key used to construct the partial query. + * @return A partial JSON query string or a query fragment with OR conditions. + * + * This method dynamically constructs a JSON query or query fragment based on the structure of the `key`: + * - For nested keys (keys containing dot separators), a nested JSON structure is constructed. + * - For the "facilityId" key, an OR condition is generated for all values in the set. + * - For other keys, a simple key-value JSON structure is returned. + * + * Notes: + * - When constructing the query for "facilityId", placeholders for each value are added to the `preparedStmtList`. + */ public String preparePartialJsonStringFromFilterMap(Map> filterMap, List preparedStmtList, String key) { Map queryMap = new HashMap<>(); StringBuilder finalJsonQuery = new StringBuilder();