Skip to content

Commit

Permalink
Merge pull request #23 from onaio/fix-gateway-plugin
Browse files Browse the repository at this point in the history
Various Enhancements and Fixes
  • Loading branch information
ndegwamartin authored Nov 24, 2023
2 parents bfbdad7 + d6b5abc commit d87244b
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 236 deletions.
3 changes: 2 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ Resolves [link to issue]
bug fixes
- [ ] I have run `mvn spotless:check` to check my code follows the project's
style guide
- [ ] I have run `mvn clean test jacoco:report` to confirm the coverage report was generated at `plugins/target/site/jacoco/index.html`
- [ ] I have run `mvn clean test jacoco:report` to confirm the coverage report
was generated at `plugins/target/site/jacoco/index.html`
- [ ] I ran `mvn clean package` right before creating this pull request.
11 changes: 2 additions & 9 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>1.0.1</version>
<version>1.0.2</version>
</parent>

<artifactId>exec</artifactId>
Expand Down Expand Up @@ -67,17 +67,10 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.smartregister</groupId>
<artifactId>fhir-common-utils</artifactId>
<version>0.0.9-SNAPSHOT</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>org.smartregister</groupId>
<artifactId>plugins</artifactId>
<version>1.0.1</version>
<version>1.0.2</version>
</dependency>

<dependency>
Expand Down
4 changes: 2 additions & 2 deletions 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>1.0.1</version>
<version>1.0.2</version>
</parent>

<artifactId>plugins</artifactId>
Expand Down Expand Up @@ -45,7 +45,7 @@
<dependency>
<groupId>org.smartregister</groupId>
<artifactId>fhir-common-utils</artifactId>
<version>0.0.10-SNAPSHOT</version>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.smartregister.fhir.gateway.plugins;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServlet;

import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Resource;

public abstract class BaseEndpoint extends HttpServlet {
public Bundle createBundle(List<Resource> resourceList) {
Bundle responseBundle = new Bundle();
List<Bundle.BundleEntryComponent> bundleEntryComponentList = new ArrayList<>();

for (Resource resource : resourceList) {
bundleEntryComponentList.add(new Bundle.BundleEntryComponent().setResource(resource));
}

responseBundle.setEntry(bundleEntryComponentList);
responseBundle.setTotal(bundleEntryComponentList.size());
return responseBundle;
}

public Bundle createEmptyBundle(String requestURL) {
Bundle responseBundle = new Bundle();
responseBundle.setId(UUID.randomUUID().toString());
Bundle.BundleLinkComponent linkComponent = new Bundle.BundleLinkComponent();
linkComponent.setRelation(Bundle.LINK_SELF);
linkComponent.setUrl(requestURL);
responseBundle.setLink(Collections.singletonList(linkComponent));
responseBundle.setType(Bundle.BundleType.SEARCHSET);
responseBundle.setTotal(0);
return responseBundle;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.r4.model.DomainResource;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
Expand All @@ -13,11 +14,18 @@ public enum CacheHelper {
INSTANCE;
Cache<String, Map<String, List<String>>> cache;

Cache<String, DomainResource> resourceCache;

CacheHelper() {
cache =
Caffeine.newBuilder()
.expireAfterWrite(getCacheExpiryDurationInSeconds(), TimeUnit.SECONDS)
.maximumSize(1_000)
.maximumSize(DEFAULT_CACHE_SIZE)
.build();
resourceCache =
Caffeine.newBuilder()
.expireAfterWrite(getCacheExpiryDurationInSeconds(), TimeUnit.SECONDS)
.maximumSize(DEFAULT_CACHE_SIZE)
.build();
}

Expand All @@ -29,5 +37,11 @@ private int getCacheExpiryDurationInSeconds() {
return 60;
}

public boolean skipCache() {
String duration = System.getenv(CacheHelper.OPENSRP_CACHE_EXPIRY_SECONDS);
return StringUtils.isNotBlank(duration) && "0".equals(duration.trim());
}

public static final String OPENSRP_CACHE_EXPIRY_SECONDS = "openrsp_cache_timeout_seconds";
private static final int DEFAULT_CACHE_SIZE = 1_000;
}
Original file line number Diff line number Diff line change
@@ -1,57 +1,59 @@
package org.smartregister.fhir.gateway.plugins;

import static org.smartregister.fhir.gateway.plugins.Constants.IDENTIFIER;

import java.io.IOException;
import java.util.Collections;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpStatus;
import org.smartregister.model.location.LocationHierarchy;

import com.google.fhir.gateway.FhirClientFactory;
import com.google.fhir.gateway.HttpFhirClient;
import com.google.fhir.gateway.TokenVerifier;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;

@WebServlet("/LocationHierarchy")
public class LocationHierarchyEndpoint extends HttpServlet {
public class LocationHierarchyEndpoint extends BaseEndpoint {
private final TokenVerifier tokenVerifier;

private final HttpFhirClient fhirClient;
String PROXY_TO_ENV = "PROXY_TO";

private FhirContext fhirR4Context = FhirContext.forR4();
private IGenericClient r4FHIRClient =
fhirR4Context.newRestfulGenericClient(System.getenv(PROXY_TO_ENV));

private IParser fhirR4JsonParser = fhirR4Context.newJsonParser().setPrettyPrint(true);

private LocationHierarchyEndpointHelper locationHierarchyEndpointHelper;
private final FhirContext fhirR4Context = FhirContext.forR4();
private final IParser fhirR4JsonParser = fhirR4Context.newJsonParser().setPrettyPrint(true);
private final LocationHierarchyEndpointHelper locationHierarchyEndpointHelper;

public LocationHierarchyEndpoint() throws IOException {
this.tokenVerifier = TokenVerifier.createFromEnvVars();
this.fhirClient = FhirClientFactory.createFhirClientFromEnvVars();
this.locationHierarchyEndpointHelper = new LocationHierarchyEndpointHelper(r4FHIRClient);
this.locationHierarchyEndpointHelper =
new LocationHierarchyEndpointHelper(
fhirR4Context.newRestfulGenericClient(
System.getenv(Constants.PROXY_TO_ENV)));
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
try {
RestUtils.checkAuthentication(request, tokenVerifier);
String identifier = request.getParameter(IDENTIFIER);
String identifier = request.getParameter(Constants.IDENTIFIER);

LocationHierarchy locationHierarchy =
locationHierarchyEndpointHelper.getLocationHierarchy(identifier);
String resultContent = fhirR4JsonParser.encodeResourceToString(locationHierarchy);
String resultContent;

if (org.smartregister.utils.Constants.LOCATION_RESOURCE_NOT_FOUND.equals(
locationHierarchy.getId())) {
resultContent =
fhirR4JsonParser.encodeResourceToString(
createEmptyBundle(
request.getRequestURL() + "?" + request.getQueryString()));
} else {
resultContent =
fhirR4JsonParser.encodeResourceToString(
createBundle(Collections.singletonList(locationHierarchy)));
}
response.setContentType("application/json");
response.getOutputStream().print(resultContent);
response.setStatus(HttpStatus.SC_OK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Location;
import org.hl7.fhir.r4.model.StringType;
Expand All @@ -20,14 +18,14 @@

import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.gclient.ReferenceClientParam;
import ca.uhn.fhir.rest.gclient.TokenClientParam;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;

public class LocationHierarchyEndpointHelper {

private static final Logger logger =
LoggerFactory.getLogger(LocationHierarchyEndpointHelper.class);

private IGenericClient r4FHIRClient;
private final IGenericClient r4FHIRClient;

public LocationHierarchyEndpointHelper(IGenericClient fhirClient) {
this.r4FHIRClient = fhirClient;
Expand All @@ -37,16 +35,26 @@ private IGenericClient getFhirClientForR4() {
return r4FHIRClient;
}

public LocationHierarchy getLocationHierarchy(String identifier) {
Location location = getLocationsByIdentifier(identifier);
String locationId = Constants.EMPTY_STRING;
if (location != null && location.getIdElement() != null) {
locationId = location.getIdElement().getIdPart();
public LocationHierarchy getLocationHierarchy(String locationId) {
LocationHierarchy locationHierarchy;

if (CacheHelper.INSTANCE.skipCache()) {
locationHierarchy = getLocationHierarchyCore(locationId);
} else {
locationHierarchy =
(LocationHierarchy)
CacheHelper.INSTANCE.resourceCache.get(
locationId, this::getLocationHierarchyCore);
}
return locationHierarchy;
}

public LocationHierarchy getLocationHierarchyCore(String locationId) {
Location location = getLocationById(locationId);

LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree();
LocationHierarchy locationHierarchy = new LocationHierarchy();
if (StringUtils.isNotBlank(locationId) && location != null) {
if (location != null) {
logger.info("Building Location Hierarchy of Location Id : " + locationId);
locationHierarchyTree.buildTreeFromList(getLocationHierarchy(locationId, location));
StringType locationIdString = new StringType().setId(locationId).getIdElement();
Expand All @@ -55,6 +63,7 @@ public LocationHierarchy getLocationHierarchy(String identifier) {

locationHierarchy.setLocationHierarchyTree(locationHierarchyTree);
} else {
logger.error("LocationHierarchy with identifier: " + locationId + " not found");
locationHierarchy.setId(LOCATION_RESOURCE_NOT_FOUND);
}
return locationHierarchy;
Expand All @@ -76,7 +85,7 @@ public List<Location> descendants(String locationId, Location parentLocation) {

List<Location> allLocations = new ArrayList<>();
if (parentLocation != null) {
allLocations.add((Location) parentLocation);
allLocations.add(parentLocation);
}

if (childLocationBundle != null) {
Expand All @@ -91,26 +100,15 @@ public List<Location> descendants(String locationId, Location parentLocation) {
return allLocations;
}

private @Nullable Location getLocationsByIdentifier(String identifier) {
Bundle locationsBundle =
getFhirClientForR4()
.search()
.forResource(Location.class)
.where(
new TokenClientParam(Location.SP_IDENTIFIER)
.exactly()
.identifier(identifier))
.returnBundle(Bundle.class)
.execute();

List<Location> locationsList = new ArrayList<>();
if (locationsBundle != null)
locationsList =
locationsBundle.getEntry().stream()
.map(
bundleEntryComponent ->
((Location) bundleEntryComponent.getResource()))
.collect(Collectors.toList());
return locationsList.size() > 0 ? locationsList.get(0) : new Location();
private @Nullable Location getLocationById(String locationId) {
Location location = null;
try {
location =
getFhirClientForR4()
.fetchResourceFromUrl(Location.class, "Location/" + locationId);
} catch (ResourceNotFoundException e) {
logger.error(e.getMessage());
}
return location;
}
}
Loading

0 comments on commit d87244b

Please sign in to comment.