Skip to content

Commit

Permalink
Merge pull request #76 from onaio/post_process_admin_level_filters
Browse files Browse the repository at this point in the history
Admin level filtering after fetch
  • Loading branch information
dubdabasoduba authored Aug 2, 2024
2 parents 8acb65e + 8b11812 commit efab847
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 28 deletions.
4 changes: 2 additions & 2 deletions exec/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.smartregister</groupId>
<artifactId>opensrp-gateway-plugin</artifactId>
<version>2.0.3</version>
<version>2.0.4</version>
</parent>

<artifactId>exec</artifactId>
Expand Down Expand Up @@ -70,7 +70,7 @@
<dependency>
<groupId>org.smartregister</groupId>
<artifactId>plugins</artifactId>
<version>2.0.3</version>
<version>2.0.4</version>
</dependency>

<dependency>
Expand Down
2 changes: 1 addition & 1 deletion plugins/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.smartregister</groupId>
<artifactId>opensrp-gateway-plugin</artifactId>
<version>2.0.3</version>
<version>2.0.4</version>
</parent>

<artifactId>plugins</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class Constants {
public static final String MIN_ADMIN_LEVEL = "administrativeLevelMin";
public static final String MAX_ADMIN_LEVEL = "administrativeLevelMax";
public static final int DEFAULT_MAX_ADMIN_LEVEL = 10;
public static final int DEFAULT_MIN_ADMIN_LEVEL = 0;
public static final String PAGINATION_PAGE_SIZE = "_count";
public static final String PAGINATION_PAGE_NUMBER = "_page";
public static final int PAGINATION_DEFAULT_PAGE_SIZE = 20;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.r4.model.Binary;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Composition;
import org.hl7.fhir.r4.model.Location;
import org.hl7.fhir.r4.model.Resource;
Expand Down Expand Up @@ -52,39 +54,56 @@ private IGenericClient getFhirClientForR4() {
return r4FHIRClient;
}

public LocationHierarchy getLocationHierarchy(String locationId, List<String> adminLevels) {
public LocationHierarchy getLocationHierarchy(
String locationId,
List<String> preFetchAdminLevels,
List<String> postFetchAdminLevels) {
LocationHierarchy locationHierarchy;

if (CacheHelper.INSTANCE.skipCache()) {
locationHierarchy = getLocationHierarchyCore(locationId, adminLevels);
locationHierarchy =
getLocationHierarchyCore(locationId, preFetchAdminLevels, postFetchAdminLevels);
} else {
locationHierarchy =
(LocationHierarchy)
CacheHelper.INSTANCE.resourceCache.get(
locationId,
key -> getLocationHierarchyCore(locationId, adminLevels));
key ->
getLocationHierarchyCore(
locationId,
preFetchAdminLevels,
postFetchAdminLevels));
}
return locationHierarchy;
}

public List<LocationHierarchy> getLocationHierarchies(
List<String> locationIds, List<String> adminLevels) {
List<String> locationIds,
List<String> preFetchAdminLevels,
List<String> postFetchAdminLevels) {
List<LocationHierarchy> locationHierarchies = new ArrayList<>();
for (String locationId : locationIds) {
locationHierarchies.add(getLocationHierarchy(locationId, adminLevels));
locationHierarchies.add(
getLocationHierarchy(locationId, preFetchAdminLevels, postFetchAdminLevels));
}
return locationHierarchies;
}

public LocationHierarchy getLocationHierarchyCore(String locationId, List<String> adminLevels) {
public LocationHierarchy getLocationHierarchyCore(
String locationId,
List<String> preFetchAdminLevels,
List<String> postFetchAdminLevels) {
Location location = getLocationById(locationId);

LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree();
LocationHierarchy locationHierarchy = new LocationHierarchy();
if (location != null) {
logger.info("Building Location Hierarchy of Location Id : " + locationId);

locationHierarchyTree.buildTreeFromList(
getDescendants(locationId, location, adminLevels));
filterLocationsByAdminLevels(
getDescendants(locationId, location, preFetchAdminLevels),
postFetchAdminLevels));
StringType locationIdString = new StringType().setId(locationId).getIdElement();
locationHierarchy.setLocationId(locationIdString);
locationHierarchy.setId(LOCATION_RESOURCE + locationId);
Expand All @@ -97,19 +116,22 @@ public LocationHierarchy getLocationHierarchyCore(String locationId, List<String
return locationHierarchy;
}

private List<Location> getLocationHierarchyLocations(
String locationId, Location parentLocation, List<String> adminLevels) {
public List<Location> getLocationHierarchyLocations(
String locationId,
Location parentLocation,
List<String> preFetchAdminLevels,
List<String> postFetchAdminLevels) {
List<Location> descendants;

if (CacheHelper.INSTANCE.skipCache()) {
descendants = getDescendants(locationId, parentLocation, adminLevels);
descendants = getDescendants(locationId, parentLocation, preFetchAdminLevels);
} else {
descendants =
CacheHelper.INSTANCE.locationListCache.get(
locationId,
key -> getDescendants(locationId, parentLocation, adminLevels));
key -> getDescendants(locationId, parentLocation, preFetchAdminLevels));
}
return descendants;
return filterLocationsByAdminLevels(descendants, postFetchAdminLevels);
}

public List<Location> getDescendants(
Expand Down Expand Up @@ -171,14 +193,18 @@ public List<Location> getDescendants(
public Bundle handleIdentifierRequest(HttpServletRequest request, String identifier) {
String administrativeLevelMin = request.getParameter(Constants.MIN_ADMIN_LEVEL);
String administrativeLevelMax = request.getParameter(Constants.MAX_ADMIN_LEVEL);
List<String> adminLevels =
List<String> preFetchAdminLevels =
generateAdminLevels(
String.valueOf(Constants.DEFAULT_MIN_ADMIN_LEVEL), administrativeLevelMax);
List<String> postFetchAdminLevels =
generateAdminLevels(administrativeLevelMin, administrativeLevelMax);
String mode = request.getParameter(Constants.MODE);
if (Constants.LIST.equals(mode)) {
List<String> locationIds = Collections.singletonList(identifier);
return getPaginatedLocations(request, locationIds);
} else {
LocationHierarchy locationHierarchy = getLocationHierarchy(identifier, adminLevels);
LocationHierarchy locationHierarchy =
getLocationHierarchy(identifier, preFetchAdminLevels, postFetchAdminLevels);
return Utils.createBundle(Collections.singletonList(locationHierarchy));
}
}
Expand All @@ -191,7 +217,10 @@ public Bundle handleNonIdentifierRequest(
String syncLocationsParam = request.getParameter(Constants.SYNC_LOCATIONS);
String administrativeLevelMin = request.getParameter(Constants.MIN_ADMIN_LEVEL);
String administrativeLevelMax = request.getParameter(Constants.MAX_ADMIN_LEVEL);
List<String> adminLevels =
List<String> preFetchAdminLevels =
generateAdminLevels(
String.valueOf(Constants.DEFAULT_MIN_ADMIN_LEVEL), administrativeLevelMax);
List<String> postFetchAdminLevels =
generateAdminLevels(administrativeLevelMin, administrativeLevelMax);
List<String> selectedSyncLocations = extractSyncLocations(syncLocationsParam);
String practitionerId = verifiedJwt.getSubject();
Expand Down Expand Up @@ -223,7 +252,8 @@ public Bundle handleNonIdentifierRequest(
&& userRoles.contains(Constants.ROLE_ALL_LOCATIONS)
&& !selectedSyncLocations.isEmpty()) {
List<LocationHierarchy> locationHierarchies =
getLocationHierarchies(selectedSyncLocations, adminLevels);
getLocationHierarchies(
selectedSyncLocations, preFetchAdminLevels, postFetchAdminLevels);
List<Resource> resourceList =
locationHierarchies.stream()
.map(locationHierarchy -> (Resource) locationHierarchy)
Expand Down Expand Up @@ -294,7 +324,10 @@ public Bundle getPaginatedLocations(HttpServletRequest request, List<String> loc
String pageNumber = request.getParameter(Constants.PAGINATION_PAGE_NUMBER);
String administrativeLevelMin = request.getParameter(Constants.MIN_ADMIN_LEVEL);
String administrativeLevelMax = request.getParameter(Constants.MAX_ADMIN_LEVEL);
List<String> adminLevels =
List<String> preFetchAdminLevels =
generateAdminLevels(
String.valueOf(Constants.DEFAULT_MIN_ADMIN_LEVEL), administrativeLevelMax);
List<String> postFetchAdminLevels =
generateAdminLevels(administrativeLevelMin, administrativeLevelMax);
Map<String, String[]> parameters = new HashMap<>(request.getParameterMap());

Expand All @@ -313,7 +346,8 @@ public Bundle getPaginatedLocations(HttpServletRequest request, List<String> loc
for (String identifier : locationIds) {
Location parentLocation = getLocationById(identifier);
List<Location> locations =
getLocationHierarchyLocations(identifier, parentLocation, adminLevels);
getLocationHierarchyLocations(
identifier, parentLocation, preFetchAdminLevels, postFetchAdminLevels);
resourceLocations.addAll(locations);
}
int totalEntries = resourceLocations.size();
Expand Down Expand Up @@ -374,4 +408,22 @@ public List<String> generateAdminLevels(

return adminLevels;
}

public List<Location> filterLocationsByAdminLevels(
List<Location> locations, List<String> postFetchAdminLevels) {
List<Location> allLocations = new ArrayList<>();
for (Location location : locations) {
for (CodeableConcept codeableConcept : location.getType()) {
List<Coding> codings = codeableConcept.getCoding();
for (Coding coding : codings) {
if (coding.getSystem().equals(Constants.DEFAULT_ADMIN_LEVEL_TYPE_URL)) {
if (postFetchAdminLevels.contains(coding.getCode())) {
allLocations.add(location);
}
}
}
}
}
return allLocations;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,8 @@ public static List<LocationHierarchy> getLocationsHierarchy(List<String> locatio
LocationHierarchy locationHierarchy;
for (String locationsIdentifier : locationsIdentifiers) {
locationHierarchy =
locationHierarchyEndpointHelper.getLocationHierarchy(locationsIdentifier, null);
locationHierarchyEndpointHelper.getLocationHierarchy(
locationsIdentifier, null, null);
if (!org.smartregister.utils.Constants.LOCATION_RESOURCE_NOT_FOUND.equals(
locationHierarchy.getId())) locationHierarchyList.add(locationHierarchy);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void testGetLocationHierarchyNotFound() {
.when(client)
.fetchResourceFromUrl(any(), any());
LocationHierarchy locationHierarchy =
locationHierarchyEndpointHelper.getLocationHierarchy("non-existent", null);
locationHierarchyEndpointHelper.getLocationHierarchy("non-existent", null, null);
assertEquals(
org.smartregister.utils.Constants.LOCATION_RESOURCE_NOT_FOUND,
locationHierarchy.getId());
Expand All @@ -69,7 +69,7 @@ public void testGetLocationHierarchyFound() {
.when(client)
.fetchResourceFromUrl(Location.class, "Location/12345");
LocationHierarchy locationHierarchy =
locationHierarchyEndpointHelper.getLocationHierarchy("12345", null);
locationHierarchyEndpointHelper.getLocationHierarchy("12345", null, null);
assertEquals("Location Resource : 12345", locationHierarchy.getId());
}

Expand Down Expand Up @@ -100,9 +100,12 @@ public void testGetPaginatedLocationsPaginatesLocations() {
Mockito.doCallRealMethod()
.when(mockLocationHierarchyEndpointHelper)
.getPaginatedLocations(request, locationIds);
Mockito.doCallRealMethod()
.when(mockLocationHierarchyEndpointHelper)
.filterLocationsByAdminLevels(locations, adminLevels);
Mockito.doReturn(locations)
.when(mockLocationHierarchyEndpointHelper)
.getDescendants("12345", null, adminLevels);
.getLocationHierarchyLocations("12345", null, adminLevels, adminLevels);

Bundle resultBundle =
mockLocationHierarchyEndpointHelper.getPaginatedLocations(request, locationIds);
Expand Down Expand Up @@ -144,6 +147,7 @@ public void testHandleNonIdentifierRequestListModePaginatesLocations() {
.getRequestURL();

Map<String, String[]> parameters = new HashMap<>();

parameters.put(Constants.MODE, new String[] {"list"});
parameters.put(Constants.SYNC_LOCATIONS, new String[] {"1,2,3,4"});
LocationHierarchyEndpointHelper mockLocationHierarchyEndpointHelper =
Expand All @@ -152,6 +156,7 @@ public void testHandleNonIdentifierRequestListModePaginatesLocations() {
mock(PractitionerDetailsEndpointHelper.class);
DecodedJWT mockDecodedJWT = mock(DecodedJWT.class);
MockedStatic<JwtUtils> mockJwtUtils = Mockito.mockStatic(JwtUtils.class);
List<String> adminLevels = new ArrayList<>();

List<Location> locations = createLocationList(4, false);
List<String> locationIds = List.of("1", "2", "3", "4");
Expand All @@ -168,9 +173,13 @@ public void testHandleNonIdentifierRequestListModePaginatesLocations() {
.when(mockLocationHierarchyEndpointHelper)
.handleNonIdentifierRequest(
request, mockPractitionerDetailsEndpointHelper, mockDecodedJWT);
Mockito.doCallRealMethod()
.when(mockLocationHierarchyEndpointHelper)
.filterLocationsByAdminLevels(locations, adminLevels);
Mockito.doReturn(locations)
.when(mockLocationHierarchyEndpointHelper)
.getDescendants(Mockito.anyString(), Mockito.any(), Mockito.any());
.getLocationHierarchyLocations(
Mockito.anyString(), Mockito.any(), Mockito.any(), Mockito.any());
Mockito.doReturn(Constants.SyncStrategy.RELATED_ENTITY_LOCATION)
.when(mockLocationHierarchyEndpointHelper)
.getSyncStrategyByAppId(Mockito.any());
Expand Down Expand Up @@ -232,7 +241,7 @@ public void testGenerateAdminLevelsWithInvalidRange() {
}

@Test
public void testGetDecendantsWithAdminLevelFiltersReturnsLocationsWithinAdminLevel() {
public void testGetDescendantsWithAdminLevelFiltersReturnsLocationsWithinAdminLevel() {
String locationId = "12345";
Location parentLocation = new Location();
parentLocation.setId(locationId);
Expand Down Expand Up @@ -276,6 +285,20 @@ public void testGetDecendantsWithAdminLevelFiltersReturnsLocationsWithinAdminLev
verify(queryMock, times(2)).execute();
}

@Test
public void testFilterLocationsByAdminLevelsBasic() {
List<Location> locations = createLocationList(5, true);
List<String> adminLevels = List.of("1", "3");

List<Location> filteredLocations =
locationHierarchyEndpointHelper.filterLocationsByAdminLevels(
locations, adminLevels);

Assert.assertEquals(2, filteredLocations.size());
Assert.assertEquals("1", filteredLocations.get(0).getId());
Assert.assertEquals("3", filteredLocations.get(1).getId());
}

private Bundle getLocationBundle() {
Bundle bundleLocation = new Bundle();
bundleLocation.setId("Location/1234");
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>org.smartregister</groupId>
<artifactId>opensrp-gateway-plugin</artifactId>
<version>2.0.3</version>
<version>2.0.4</version>
<packaging>pom</packaging>

<modules>
Expand Down

0 comments on commit efab847

Please sign in to comment.