Skip to content

Commit

Permalink
FM2-347:Add support for _has and _has:...:not for ServiceRequest and …
Browse files Browse the repository at this point in the history
…Observation
  • Loading branch information
gitcliff committed Mar 21, 2021
1 parent 976880c commit d3f2ae4
Show file tree
Hide file tree
Showing 22 changed files with 445 additions and 262 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class FhirConstants {
+ "/condition-ver-status";

public static final String CLINICAL_FINDINGS_SYSTEM_URI = HL7_FHIR_CODE_SYSTEM_PREFIX + "/clinical-findings";

public static final String TASK_STATUS_VALUE_SET_URI = "http://hl7.org/fhir/task-status";

public static final String OBSERVATION_REFERENCE_RANGE_SYSTEM_URI = HL7_FHIR_CODE_SYSTEM_PREFIX
Expand Down Expand Up @@ -255,6 +255,8 @@ public class FhirConstants {

public static final String COMMON_SEARCH_HANDLER = "common.search.handler";

public static final String HAS_SEARCH_HANDLER = "_has";

public static final String ID_PROPERTY = "_id.property";

public static final String LAST_UPDATED_PROPERTY = "_lastUpdated.property";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public interface FhirObservationService extends FhirService<Observation> {
Observation get(@Nonnull String uuid);

IBundleProvider searchForObservations(ReferenceAndListParam encounterReference, ReferenceAndListParam patientReference,
ReferenceAndListParam hasMemberReference, TokenAndListParam valueConcept, DateRangeParam valueDateParam,
QuantityAndListParam valueQuantityParam, StringAndListParam valueStringParam, DateRangeParam date,
TokenAndListParam code, TokenAndListParam category, TokenAndListParam id, DateRangeParam lastUpdated,
SortSpec sort, HashSet<Include> includes, HashSet<Include> revIncludes);
ReferenceAndListParam hasMemberReference, ReferenceAndListParam basedOnReference, TokenAndListParam valueConcept,
DateRangeParam valueDateParam, QuantityAndListParam valueQuantityParam, StringAndListParam valueStringParam,
DateRangeParam date, TokenAndListParam code, TokenAndListParam category, TokenAndListParam id,
DateRangeParam lastUpdated, SortSpec sort, HashSet<Include> includes, HashSet<Include> revIncludes);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import org.hl7.fhir.r4.model.ServiceRequest;

public interface FhirServiceRequestService extends FhirService<ServiceRequest> {

IBundleProvider searchForServiceRequests(ReferenceAndListParam patientReference, TokenAndListParam code,
IBundleProvider searchForServiceRequests(ReferenceAndListParam patientReference, TokenAndListParam code, HasParam has,
ReferenceAndListParam encounterReference, ReferenceAndListParam participantReference, DateRangeParam occurrence,
TokenAndListParam uuid, DateRangeParam lastUpdated, HashSet<Include> includes);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ public class FhirObservationServiceImpl extends BaseFhirService<Observation, org
@Override
@Transactional(readOnly = true)
public IBundleProvider searchForObservations(ReferenceAndListParam encounterReference,
ReferenceAndListParam patientReference, ReferenceAndListParam hasMemberReference, TokenAndListParam valueConcept,
DateRangeParam valueDateParam, QuantityAndListParam valueQuantityParam, StringAndListParam valueStringParam,
DateRangeParam date, TokenAndListParam code, TokenAndListParam category, TokenAndListParam id,
DateRangeParam lastUpdated, SortSpec sort, HashSet<Include> includes, HashSet<Include> revIncludes) {
ReferenceAndListParam patientReference, ReferenceAndListParam hasMemberReference,
ReferenceAndListParam basedOnReference, TokenAndListParam valueConcept, DateRangeParam valueDateParam,
QuantityAndListParam valueQuantityParam, StringAndListParam valueStringParam, DateRangeParam date,
TokenAndListParam code, TokenAndListParam category, TokenAndListParam id, DateRangeParam lastUpdated,
SortSpec sort, HashSet<Include> includes, HashSet<Include> revIncludes) {

SearchParameterMap theParams = new SearchParameterMap()
.addParameter(FhirConstants.ENCOUNTER_REFERENCE_SEARCH_HANDLER, encounterReference)
Expand All @@ -68,6 +69,7 @@ public IBundleProvider searchForObservations(ReferenceAndListParam encounterRefe
.addParameter(FhirConstants.CATEGORY_SEARCH_HANDLER, category)
.addParameter(FhirConstants.VALUE_CODED_SEARCH_HANDLER, valueConcept)
.addParameter(FhirConstants.HAS_MEMBER_SEARCH_HANDLER, hasMemberReference)
.addParameter(FhirConstants.BASED_ON_REFERENCE_SEARCH_HANDLER, basedOnReference)
.addParameter(FhirConstants.VALUE_STRING_SEARCH_HANDLER, "valueText", valueStringParam)
.addParameter(FhirConstants.QUANTITY_SEARCH_HANDLER, "valueNumeric", valueQuantityParam)
.addParameter(FhirConstants.DATE_RANGE_SEARCH_HANDLER, "obsDatetime", date)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import lombok.AccessLevel;
Expand Down Expand Up @@ -52,12 +53,12 @@ public class FhirServiceRequestServiceImpl extends BaseFhirService<ServiceReques

@Override
public IBundleProvider searchForServiceRequests(ReferenceAndListParam patientReference, TokenAndListParam code,
ReferenceAndListParam encounterReference, ReferenceAndListParam participantReference, DateRangeParam occurrence,
TokenAndListParam uuid, DateRangeParam lastUpdated, HashSet<Include> includes) {
HasParam has, ReferenceAndListParam encounterReference, ReferenceAndListParam participantReference,
DateRangeParam occurrence, TokenAndListParam uuid, DateRangeParam lastUpdated, HashSet<Include> includes) {

SearchParameterMap theParams = new SearchParameterMap()
.addParameter(FhirConstants.PATIENT_REFERENCE_SEARCH_HANDLER, patientReference)
.addParameter(FhirConstants.CODED_SEARCH_HANDLER, code)
.addParameter(FhirConstants.CODED_SEARCH_HANDLER, code).addParameter(FhirConstants.HAS_SEARCH_HANDLER, has)
.addParameter(FhirConstants.ENCOUNTER_REFERENCE_SEARCH_HANDLER, encounterReference)
.addParameter(FhirConstants.PARTICIPANT_REFERENCE_SEARCH_HANDLER, participantReference)
.addParameter(FhirConstants.DATE_RANGE_SEARCH_HANDLER, occurrence)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ private IBundleProvider handleObservationReverseInclude(ReferenceAndListParam pa
switch (targetType) {
case FhirConstants.OBSERVATION:
return observationService.searchForObservations(null, null, params, null, null, null, null, null, null, null,
null, null, null, null, null);
null, null, null, null, null, null);
case FhirConstants.DIAGNOSTIC_REPORT:
return diagnosticReportService.searchForDiagnosticReports(null, null, null, null, params, null, null, null,
null);
Expand All @@ -228,7 +228,8 @@ private IBundleProvider handlePractitionerReverseInclude(ReferenceAndListParam p
null);
case FhirConstants.PROCEDURE_REQUEST:
case FhirConstants.SERVICE_REQUEST:
return serviceRequestService.searchForServiceRequests(null, null, null, params, null, null, null, null);
return serviceRequestService.searchForServiceRequests(null, null, null, null, params, null, null, null,
null);
}

return null;
Expand All @@ -238,7 +239,7 @@ private IBundleProvider handleEncounterReverseInclude(ReferenceAndListParam para
switch (targetType) {
case FhirConstants.OBSERVATION:
return observationService.searchForObservations(params, null, null, null, null, null, null, null, null, null,
null, null, null, null, null);
null, null, null, null, null, null);
case FhirConstants.DIAGNOSTIC_REPORT:
return diagnosticReportService.searchForDiagnosticReports(params, null, null, null, null, null, null, null,
null);
Expand All @@ -247,7 +248,8 @@ private IBundleProvider handleEncounterReverseInclude(ReferenceAndListParam para
null);
case FhirConstants.PROCEDURE_REQUEST:
case FhirConstants.SERVICE_REQUEST:
return serviceRequestService.searchForServiceRequests(null, null, params, null, null, null, null, null);
return serviceRequestService.searchForServiceRequests(null, null, null, params, null, null, null, null,
null);
}

return null;
Expand All @@ -267,7 +269,7 @@ private IBundleProvider handlePatientReverseInclude(ReferenceAndListParam params
switch (targetType) {
case FhirConstants.OBSERVATION:
return observationService.searchForObservations(null, params, null, null, null, null, null, null, null, null,
null, null, null, null, null);
null, null, null, null, null, null);
case FhirConstants.DIAGNOSTIC_REPORT:
return diagnosticReportService.searchForDiagnosticReports(null, params, null, null, null, null, null, null,
null);
Expand All @@ -281,7 +283,8 @@ private IBundleProvider handlePatientReverseInclude(ReferenceAndListParam params
null);
case FhirConstants.SERVICE_REQUEST:
case FhirConstants.PROCEDURE_REQUEST:
return serviceRequestService.searchForServiceRequests(params, null, null, null, null, null, null, null);
return serviceRequestService.searchForServiceRequests(params, null, null, null, null, null, null, null,
null);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.ServiceRequest;
import org.openmrs.module.fhir2.api.FhirObservationService;
import org.openmrs.module.fhir2.api.search.SearchQueryBundleProviderR3Wrapper;
import org.openmrs.module.fhir2.providers.util.FhirProviderUtils;
Expand Down Expand Up @@ -112,6 +113,8 @@ public IBundleProvider searchObservations(
Patient.SP_FAMILY, Patient.SP_NAME }, targetTypes = Patient.class) ReferenceAndListParam patientParam,
@OptionalParam(name = Observation.SP_RELATED_TYPE, chainWhitelist = { "",
Observation.SP_CODE }, targetTypes = Observation.class) ReferenceAndListParam hasMemberReference,
@OptionalParam(name = Observation.SP_BASED_ON, chainWhitelist = { "",
ServiceRequest.SP_IDENTIFIER }, targetTypes = ServiceRequest.class) ReferenceAndListParam basedOnReference,
@OptionalParam(name = Observation.SP_VALUE_CONCEPT) TokenAndListParam valueConcept,
@OptionalParam(name = Observation.SP_VALUE_DATE) DateRangeParam valueDateParam,
@OptionalParam(name = Observation.SP_VALUE_QUANTITY) QuantityAndListParam valueQuantityParam,
Expand All @@ -138,8 +141,8 @@ public IBundleProvider searchObservations(
}

return new SearchQueryBundleProviderR3Wrapper(observationService.searchForObservations(encounterReference,
patientReference, hasMemberReference, valueConcept, valueDateParam, valueQuantityParam, valueStringParam, date,
code, category, id, lastUpdated, sort, includes, revIncludes));
patientReference, basedOnReference, hasMemberReference, valueConcept, valueDateParam, valueQuantityParam,
valueStringParam, date, code, category, id, lastUpdated, sort, includes, revIncludes));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.server.IResourceProvider;
Expand Down Expand Up @@ -113,7 +114,7 @@ public IBundleProvider searchForProcedureRequests(
Practitioner.SP_NAME }, targetTypes = Practitioner.class) ReferenceAndListParam participantReference,
@OptionalParam(name = ProcedureRequest.SP_OCCURRENCE) DateRangeParam occurrence,
@OptionalParam(name = ProcedureRequest.SP_RES_ID) TokenAndListParam uuid,
@OptionalParam(name = "_lastUpdated") DateRangeParam lastUpdated,
@OptionalParam(name = "_lastUpdated") DateRangeParam lastUpdated, @OptionalParam(name = "_has") HasParam has,
@IncludeParam(allow = { "ProcedureRequest:" + ProcedureRequest.SP_PATIENT,
"ProcedureRequest:" + ProcedureRequest.SP_REQUESTER,
"ProcedureRequest:" + ProcedureRequest.SP_ENCOUNTER }) HashSet<Include> includes) {
Expand All @@ -126,6 +127,6 @@ public IBundleProvider searchForProcedureRequests(
}

return new SearchQueryBundleProviderR3Wrapper(serviceRequestService.searchForServiceRequests(patientReference, code,
encounterReference, participantReference, occurrence, uuid, lastUpdated, includes));
has, encounterReference, participantReference, occurrence, uuid, lastUpdated, includes));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.hl7.fhir.r4.model.OperationOutcome;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.ServiceRequest;
import org.openmrs.module.fhir2.api.FhirObservationService;
import org.openmrs.module.fhir2.providers.util.FhirProviderUtils;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -108,6 +109,8 @@ public IBundleProvider searchObservations(
Patient.SP_NAME }, targetTypes = Patient.class) ReferenceAndListParam patientReference,
@OptionalParam(name = Observation.SP_HAS_MEMBER, chainWhitelist = { "",
Observation.SP_CODE }, targetTypes = Observation.class) ReferenceAndListParam hasMemberReference,
@OptionalParam(name = Observation.SP_BASED_ON, chainWhitelist = { "",
ServiceRequest.SP_IDENTIFIER }, targetTypes = ServiceRequest.class) ReferenceAndListParam basedOnReference,
@OptionalParam(name = Observation.SP_VALUE_CONCEPT) TokenAndListParam valueConcept,
@OptionalParam(name = Observation.SP_VALUE_DATE) DateRangeParam valueDateParam,
@OptionalParam(name = Observation.SP_VALUE_QUANTITY) QuantityAndListParam valueQuantityParam,
Expand Down Expand Up @@ -136,7 +139,7 @@ public IBundleProvider searchObservations(
}

return observationService.searchForObservations(encounterReference, patientReference, hasMemberReference,
valueConcept, valueDateParam, valueQuantityParam, valueStringParam, date, code, category, id, lastUpdated, sort,
includes, revIncludes);
basedOnReference, valueConcept, valueDateParam, valueQuantityParam, valueStringParam, date, code, category, id,
lastUpdated, sort, includes, revIncludes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@

import javax.annotation.Nonnull;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.IncludeParam;
Expand All @@ -21,23 +25,28 @@
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import com.google.common.collect.Lists;
import lombok.AccessLevel;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Encounter;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.OperationOutcome;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Practitioner;
import org.hl7.fhir.r4.model.ServiceRequest;
import org.openmrs.module.fhir2.FhirConstants;
import org.openmrs.module.fhir2.api.FhirServiceRequestService;
import org.openmrs.module.fhir2.providers.util.FhirProviderUtils;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -49,6 +58,8 @@
@Setter(AccessLevel.PACKAGE)
public class ServiceRequestFhirResourceProvider implements IResourceProvider {

private final FhirContext cntxt = FhirContext.forR4();

@Autowired
private FhirServiceRequestService serviceRequestService;

Expand Down Expand Up @@ -108,8 +119,9 @@ public IBundleProvider searchForServiceRequests(
Practitioner.SP_GIVEN, Practitioner.SP_FAMILY,
Practitioner.SP_NAME }, targetTypes = Practitioner.class) ReferenceAndListParam participantReference,
@OptionalParam(name = ServiceRequest.SP_OCCURRENCE) DateRangeParam occurrence,

@OptionalParam(name = ServiceRequest.SP_RES_ID) TokenAndListParam uuid,
@OptionalParam(name = "_lastUpdated") DateRangeParam lastUpdated,
@OptionalParam(name = "_lastUpdated") DateRangeParam lastUpdated, @OptionalParam(name = "_has") HasParam has,
@IncludeParam(allow = { "ServiceRequest:" + ServiceRequest.SP_PATIENT,
"ServiceRequest:" + ServiceRequest.SP_REQUESTER,
"ServiceRequest:" + ServiceRequest.SP_ENCOUNTER }) HashSet<Include> includes) {
Expand All @@ -121,7 +133,45 @@ public IBundleProvider searchForServiceRequests(
includes = null;
}

return serviceRequestService.searchForServiceRequests(patientReference, code, encounterReference,
hasParameter(has);

return serviceRequestService.searchForServiceRequests(patientReference, code, has, encounterReference,
participantReference, occurrence, uuid, lastUpdated, includes);
}

private void hasParameter(HasParam has) {
List<List<IQueryParameterType>> theHasParameters = Lists.newArrayList();
for (List<? extends IQueryParameterType> nextOrList : theHasParameters) {
String targetResourceType = null;
String paramReference = null;
String parameterName = null;

String paramName = null;
List<QualifiedParamList> parameters = new ArrayList<>();
for (IQueryParameterType nextParam : nextOrList) {
has = (HasParam) nextParam;
targetResourceType = has.getTargetResourceType();

if (targetResourceType.getClass().equals(Observation.class)) {
paramReference = has.getReferenceFieldName();
parameterName = has.getParameterName();
paramName = parameterName.replaceAll("\\..*", "");
parameters.add(QualifiedParamList.singleton(null, has.getValueAsQueryToken(cntxt)));
} else {
return;
}
}
if (paramName == null) {
continue;
}
ArrayList<IQueryParameterType> orValues = Lists.newArrayList();
String qualifier = ":not";
for (IQueryParameterType next : nextOrList) {
has.setValueAsQueryToken(cntxt, FhirConstants.HAS_SEARCH_HANDLER, qualifier,
next.getValueAsQueryToken(cntxt));
orValues.add(has);
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public void searchForObservations_shouldReturnObservationsByParameters() {
when(translator.toFhirResource(obs)).thenReturn(observation);

IBundleProvider results = fhirObservationService.searchForObservations(null, patientReference, null, null, null,
null, null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null, null);

assertThat(results, notNullValue());
assertThat(results.size(), equalTo(1));
Expand Down
Loading

0 comments on commit d3f2ae4

Please sign in to comment.