From 6201727ab830bbc514b3fa2c83bd5a054aa5929a Mon Sep 17 00:00:00 2001 From: Mutesasira Moses Date: Thu, 24 Aug 2023 17:33:53 +0300 Subject: [PATCH] add support for Support FHIR Pagination when Pulling results (#38) --- .../labonfhir/api/dao/LabOnFhirDao.java | 14 +++ .../labonfhir/api/model/FailedTask.java | 1 + .../labonfhir/api/model/TaskRequest.java | 42 +++++++ .../api/scheduler/FetchTaskUpdates.java | 116 ++++++++++++------ .../api/service/LabOnFhirService.java | 21 +++- .../service/impl/LabOnFhirServiceImpl.java | 11 ++ api/src/main/resources/liquibase.xml | 25 ++++ 7 files changed, 192 insertions(+), 38 deletions(-) create mode 100644 api/src/main/java/org/openmrs/module/labonfhir/api/model/TaskRequest.java diff --git a/api/src/main/java/org/openmrs/module/labonfhir/api/dao/LabOnFhirDao.java b/api/src/main/java/org/openmrs/module/labonfhir/api/dao/LabOnFhirDao.java index 37e4a8e..76578cc 100644 --- a/api/src/main/java/org/openmrs/module/labonfhir/api/dao/LabOnFhirDao.java +++ b/api/src/main/java/org/openmrs/module/labonfhir/api/dao/LabOnFhirDao.java @@ -3,9 +3,11 @@ import java.util.List; import org.hibernate.criterion.Restrictions; +import org.openmrs.api.APIException; import org.openmrs.api.db.hibernate.DbSession; import org.openmrs.api.db.hibernate.DbSessionFactory; import org.openmrs.module.labonfhir.api.model.FailedTask; +import org.openmrs.module.labonfhir.api.model.TaskRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; @@ -35,5 +37,17 @@ public List getAllFailedTasks(Boolean isSent) { return getSession().createCriteria(FailedTask.class).list(); } } + + + public TaskRequest saveOrUpdateTaskRequest(TaskRequest taskRequest) throws APIException { + getSession().saveOrUpdate(taskRequest); + return taskRequest; + } + + public TaskRequest getLastTaskRequest() throws APIException { + String hql = "FROM TaskRequest tr WHERE tr.requestDate = (SELECT MAX(t.requestDate) FROM TaskRequest t)"; + return (TaskRequest)getSession().createQuery(hql).uniqueResult(); + } + } diff --git a/api/src/main/java/org/openmrs/module/labonfhir/api/model/FailedTask.java b/api/src/main/java/org/openmrs/module/labonfhir/api/model/FailedTask.java index 2628e89..d4dd356 100644 --- a/api/src/main/java/org/openmrs/module/labonfhir/api/model/FailedTask.java +++ b/api/src/main/java/org/openmrs/module/labonfhir/api/model/FailedTask.java @@ -31,6 +31,7 @@ public Integer getId() { } @Override public void setId(Integer id) { + this.id = id; } public String getError() { diff --git a/api/src/main/java/org/openmrs/module/labonfhir/api/model/TaskRequest.java b/api/src/main/java/org/openmrs/module/labonfhir/api/model/TaskRequest.java new file mode 100644 index 0000000..4dac9ad --- /dev/null +++ b/api/src/main/java/org/openmrs/module/labonfhir/api/model/TaskRequest.java @@ -0,0 +1,42 @@ +package org.openmrs.module.labonfhir.api.model; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.openmrs.BaseOpenmrsData; + +@Entity +@Table(name = "task_request") +public class TaskRequest extends BaseOpenmrsData { + + @Id + @GeneratedValue + @Column(name = "id") + private Integer id; + + @Column(name = "request_date") + private Date requestDate; + + @Override + public Integer getId() { + return id; + } + + @Override + public void setId(Integer id) { + this.id = id; + } + + public Date getRequestDate() { + return requestDate; + } + + public void setRequestDate(Date requestDate) { + this.requestDate = requestDate; + } +} diff --git a/api/src/main/java/org/openmrs/module/labonfhir/api/scheduler/FetchTaskUpdates.java b/api/src/main/java/org/openmrs/module/labonfhir/api/scheduler/FetchTaskUpdates.java index 8a68b19..13d4289 100644 --- a/api/src/main/java/org/openmrs/module/labonfhir/api/scheduler/FetchTaskUpdates.java +++ b/api/src/main/java/org/openmrs/module/labonfhir/api/scheduler/FetchTaskUpdates.java @@ -3,16 +3,20 @@ import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; import java.util.Iterator; import java.util.List; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.gclient.TokenClientParam; +import ca.uhn.fhir.rest.param.DateRangeParam; import lombok.AccessLevel; import lombok.Setter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.SessionFactory; +import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.DiagnosticReport; @@ -28,6 +32,8 @@ import org.openmrs.module.fhir2.api.dao.FhirObservationDao; import org.openmrs.module.fhir2.api.translators.ObservationReferenceTranslator; import org.openmrs.module.labonfhir.LabOnFhirConfig; +import org.openmrs.module.labonfhir.api.model.TaskRequest; +import org.openmrs.module.labonfhir.api.service.LabOnFhirService; import org.openmrs.scheduler.tasks.AbstractTask; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; @@ -35,6 +41,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; +import java.text.SimpleDateFormat; @Component @Setter(AccessLevel.PACKAGE) @@ -72,29 +79,63 @@ public class FetchTaskUpdates extends AbstractTask implements ApplicationContext @Qualifier("sessionFactory") SessionFactory sessionFactory; + @Autowired + private LabOnFhirService labOnFhirService; + @Override public void execute() { - + try { applicationContext.getAutowireCapableBeanFactory().autowireBean(this); - } catch (Exception e) { + } + catch (Exception e) { // return; } - + if (!config.isLisEnabled()) { return; } - + try { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + Date newDate = new Date(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(newDate); + calendar.add(Calendar.YEAR, -5); + Date fiveYearsAgo = calendar.getTime(); + + TaskRequest lastRequest = labOnFhirService.getLastTaskRequest(); + String lastRequstDate = dateFormat.format(fiveYearsAgo); + if (lastRequest != null) { + lastRequstDate = dateFormat.format(lastRequest.getRequestDate()); + } + + String currentTime = dateFormat.format(newDate); + DateRangeParam lastUpdated = new DateRangeParam().setLowerBound(lastRequstDate).setUpperBound(currentTime); + // Get List of Tasks that belong to this instance and update them - updateTasksInBundle(client.search().forResource(Task.class) - .where(Task.IDENTIFIER.hasSystemWithAnyCode(FhirConstants.OPENMRS_FHIR_EXT_TASK_IDENTIFIER)) - .where(Task.STATUS.exactly().code(TaskStatus.COMPLETED.toCode())).returnBundle(Bundle.class) - .execute()); - } catch (Exception e) { + Bundle taskBundle = client.search().forResource(Task.class) + .where(Task.IDENTIFIER.hasSystemWithAnyCode(FhirConstants.OPENMRS_FHIR_EXT_TASK_IDENTIFIER)) + .where(Task.STATUS.exactly().code(TaskStatus.COMPLETED.toCode())).lastUpdated(lastUpdated) + .returnBundle(Bundle.class).execute(); + + List taskBundles = new ArrayList<>(); + taskBundles.add(taskBundle); + //Support FHIR Server Pagination + while (taskBundle.getLink(IBaseBundle.LINK_NEXT) != null) { + taskBundle = client.loadPage().next(taskBundle).execute(); + taskBundles.add(taskBundle); + } + updateTasksInBundle(taskBundles); + + TaskRequest request = new TaskRequest(); + request.setRequestDate(newDate); + labOnFhirService.saveOrUpdateTaskRequest(request); + } + catch (Exception e) { log.error("ERROR executing FetchTaskUpdates : " + e.toString() + getStackTrace(e)); } - + super.startExecuting(); } @@ -105,35 +146,36 @@ public void shutdown() { this.stopExecuting(); } - private void updateTasksInBundle(Bundle taskBundle) { - - for (Iterator tasks = taskBundle.getEntry().iterator(); tasks.hasNext();) { - String openmrsTaskUuid = null; - - try { - // Read incoming LIS Task - Task openelisTask = (Task) ((Bundle.BundleEntryComponent) tasks.next()).getResource(); - openmrsTaskUuid = openelisTask.getIdentifierFirstRep().getValue(); - - // Find original openmrs task using Identifier - Task openmrsTask = taskService.get(openmrsTaskUuid); - - // Only update if matching OpenMRS Task found - if (openmrsTask != null) { - // Handle status - openmrsTask.setStatus(openelisTask.getStatus()); - - Boolean taskOutPutUpdated = false; - if (openelisTask.hasOutput()) { - // openmrsTask.setOutput(openelisTask.getOutput()); - taskOutPutUpdated = updateOutput(openelisTask.getOutput(), openmrsTask); - } - if (taskOutPutUpdated) { - taskService.update(openmrsTaskUuid, openmrsTask); + private void updateTasksInBundle(List taskBundles) { + for (Bundle bundle : taskBundles) { + for (Iterator tasks = bundle.getEntry().iterator(); tasks.hasNext();) { + String openmrsTaskUuid = null; + + try { + // Read incoming LIS Task + Task openelisTask = (Task) ((Bundle.BundleEntryComponent) tasks.next()).getResource(); + openmrsTaskUuid = openelisTask.getIdentifierFirstRep().getValue(); + // Find original openmrs task using Identifier + Task openmrsTask = taskService.get(openmrsTaskUuid); + + // Only update if matching OpenMRS Task found + if (openmrsTask != null) { + // Handle status + openmrsTask.setStatus(openelisTask.getStatus()); + + Boolean taskOutPutUpdated = false; + if (openelisTask.hasOutput()) { + // openmrsTask.setOutput(openelisTask.getOutput()); + taskOutPutUpdated = updateOutput(openelisTask.getOutput(), openmrsTask); + } + if (taskOutPutUpdated) { + taskService.update(openmrsTaskUuid, openmrsTask); + } } } - } catch (Exception e) { - log.error("Could not save task " + openmrsTaskUuid + ":" + e.toString() + getStackTrace(e)); + catch (Exception e) { + log.error("Could not save task " + openmrsTaskUuid + ":" + e.toString() + getStackTrace(e)); + } } } } diff --git a/api/src/main/java/org/openmrs/module/labonfhir/api/service/LabOnFhirService.java b/api/src/main/java/org/openmrs/module/labonfhir/api/service/LabOnFhirService.java index c83993d..f5258b6 100644 --- a/api/src/main/java/org/openmrs/module/labonfhir/api/service/LabOnFhirService.java +++ b/api/src/main/java/org/openmrs/module/labonfhir/api/service/LabOnFhirService.java @@ -2,6 +2,7 @@ import org.openmrs.api.OpenmrsService; import org.openmrs.module.labonfhir.api.model.FailedTask; +import org.openmrs.module.labonfhir.api.model.TaskRequest; import java.util.List; import org.openmrs.api.APIException; @@ -40,5 +41,23 @@ public interface LabOnFhirService extends OpenmrsService{ @Transactional List getAllFailedTasks(Boolean isSent) throws APIException; - + /** + * Saves an TaskRequest + * + * @param taskRequest + * @return TaskRequest + * @throws APIException + */ + @Transactional + TaskRequest saveOrUpdateTaskRequest(TaskRequest taskRequest) throws APIException; + + + /** + * Returns the Last Task Request + + * @throws APIException + */ + @Transactional(readOnly = true) + TaskRequest getLastTaskRequest() throws APIException; + } diff --git a/api/src/main/java/org/openmrs/module/labonfhir/api/service/impl/LabOnFhirServiceImpl.java b/api/src/main/java/org/openmrs/module/labonfhir/api/service/impl/LabOnFhirServiceImpl.java index 7c8fcef..e58398a 100644 --- a/api/src/main/java/org/openmrs/module/labonfhir/api/service/impl/LabOnFhirServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/labonfhir/api/service/impl/LabOnFhirServiceImpl.java @@ -5,6 +5,7 @@ import org.openmrs.api.APIException; import org.openmrs.module.labonfhir.api.dao.LabOnFhirDao; import org.openmrs.module.labonfhir.api.model.FailedTask; +import org.openmrs.module.labonfhir.api.model.TaskRequest; import org.openmrs.module.labonfhir.api.service.LabOnFhirService; import org.springframework.beans.factory.annotation.Autowired; @@ -43,5 +44,15 @@ public void onStartup() { public void onShutdown() { } + + @Override + public TaskRequest getLastTaskRequest() throws APIException { + return dao.getLastTaskRequest(); + } + + @Override + public TaskRequest saveOrUpdateTaskRequest(TaskRequest taskRequest) throws APIException { + return dao.saveOrUpdateTaskRequest(taskRequest); + } } diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 038e7e3..1d08962 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -86,6 +86,31 @@ + + + + + + Creating the task_request table + + + + + + + + + + + + + + + + + + +