Skip to content

Commit

Permalink
Merge branch 'openmrs:master' into FM2-584
Browse files Browse the repository at this point in the history
  • Loading branch information
mherman22 authored Jun 30, 2023
2 parents 370265b + f33535f commit 415b1e2
Show file tree
Hide file tree
Showing 25 changed files with 171 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ public Group.GroupMemberComponent toFhirResource(@Nonnull GroupMember member) {
@Override
public GroupMember toOpenmrsType(@Nonnull Group.GroupMemberComponent component) {
GroupMember member = new GroupMember();
member.setId(component.getId());

if (component.hasId()) {
member.setId(component.getId());
}

member.setEntity(component.getEntity());
member.setEntityTarget(component.getEntityTarget());
member.setInactive(component.getInactive());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ public Condition toOpenmrsType(@Nonnull Condition existingCondition,
notNull(existingCondition, "The existing Openmrs Condition object should not be null");
notNull(condition, "The Condition object should not be null");

existingCondition.setUuid(condition.getIdElement().getIdPart());
if (condition.hasId()) {
existingCondition.setUuid(condition.getIdElement().getIdPart());
}

existingCondition.setPatient(patientReferenceTranslator.toOpenmrsType(condition.getSubject()));
existingCondition.setClinicalStatus(clinicalStatusTranslator.toOpenmrsType(condition.getClinicalStatus()));
existingCondition
Expand Down
4 changes: 4 additions & 0 deletions api/src/main/java/org/openmrs/module/fhir2/FhirConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -346,4 +346,8 @@ private FhirConstants() {
public static final String RX_NORM_SYSTEM_URI = "http://www.nlm.nih.gov/research/umls/rxnorm";

public static final String UCUM_SYSTEM_URI = "http://unitsofmeasure.org";

public static final String EXACT_TOTAL_SEARCH_PARAMETER = "_exactTotal";

public static final String COUNT_QUERY_CACHE = "countQueryCache";
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.List;

import ca.uhn.fhir.rest.api.PatchTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IAnyResource;

public interface FhirService<T extends IAnyResource> {
Expand All @@ -27,7 +28,7 @@ public interface FhirService<T extends IAnyResource> {

T update(@Nonnull String uuid, @Nonnull T updatedResource);

T patch(@Nonnull String uuid, @Nonnull PatchTypeEnum patchType, @Nonnull String body);
T patch(@Nonnull String uuid, @Nonnull PatchTypeEnum patchType, @Nonnull String body, RequestDetails requestDetails);

void delete(@Nonnull String uuid);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import static org.hibernate.criterion.Restrictions.in;
import static org.hibernate.criterion.Restrictions.isNull;
import static org.hibernate.criterion.Restrictions.or;
import static org.openmrs.module.fhir2.FhirConstants.COUNT_QUERY_CACHE;
import static org.openmrs.module.fhir2.FhirConstants.EXACT_TOTAL_SEARCH_PARAMETER;

import javax.annotation.Nonnull;

Expand All @@ -31,6 +33,7 @@
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.SessionFactory;
Expand All @@ -50,6 +53,7 @@
import org.openmrs.api.handler.VoidHandler;
import org.openmrs.module.fhir2.FhirConstants;
import org.openmrs.module.fhir2.api.dao.FhirDao;
import org.openmrs.module.fhir2.api.search.param.PropParam;
import org.openmrs.module.fhir2.api.search.param.SearchParameterMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
Expand Down Expand Up @@ -179,13 +183,30 @@ public boolean hasDistinctResults() {
@Override
public int getSearchResultsCount(@Nonnull SearchParameterMap theParams) {
Criteria criteria = getSearchResultCriteria(theParams);

applyExactTotal(theParams, criteria);

if (hasDistinctResults()) {
return ((Long) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
} else {
return ((Long) criteria.setProjection(Projections.countDistinct("id")).uniqueResult()).intValue();
}
}

protected void applyExactTotal(SearchParameterMap theParams, Criteria criteria) {

List<PropParam<?>> exactTotal = theParams.getParameters(EXACT_TOTAL_SEARCH_PARAMETER);
if (!exactTotal.isEmpty()) {
PropParam<Boolean> propParam = (PropParam<Boolean>) exactTotal.get(0);
if (propParam.getParam()) {
criteria.setCacheMode(CacheMode.REFRESH);
}
} else {
criteria.setCacheable(true);
criteria.setCacheRegion(COUNT_QUERY_CACHE);
}
}

@Override
public List<T> getSearchResults(@Nonnull SearchParameterMap theParams) {
Criteria criteria = getSearchResultCriteria(theParams);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public List<Obs> getSearchResults(@Nonnull SearchParameterMap theParams) {
results.add(obs);
groupCount--;
}

if (results.size() >= theParams.getToIndex()) {
//Load only as many results as requested per page
break;
Expand Down Expand Up @@ -121,6 +121,7 @@ public int getSearchResultsCount(@Nonnull SearchParameterMap theParams) {
criteria.addOrder(Order.asc("concept")).addOrder(Order.desc("obsDatetime"));
criteria.setProjection(Projections.projectionList().add(Projections.groupProperty("concept.id"))
.add(Projections.groupProperty("obsDatetime")).add(Projections.rowCount()));
applyExactTotal(theParams, criteria);
List<Object[]> rows = criteria.list();
final int maxGroupCount = getMaxParameter(theParams);
int groupCount = maxGroupCount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import java.util.stream.Collectors;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.PatchTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
Expand Down Expand Up @@ -126,7 +128,8 @@ public T update(@Nonnull String uuid, @Nonnull T updatedResource) {
}

@Override
public T patch(@Nonnull String uuid, @Nonnull PatchTypeEnum patchType, @Nonnull String body) {
public T patch(@Nonnull String uuid, @Nonnull PatchTypeEnum patchType, @Nonnull String body,
RequestDetails requestDetails) {
if (uuid == null) {
throw new InvalidRequestException("id cannot be null");
}
Expand All @@ -144,12 +147,15 @@ public T patch(@Nonnull String uuid, @Nonnull PatchTypeEnum patchType, @Nonnull

switch (patchType) {
case JSON_PATCH:
// note that we are actually doing a JSON Merge Patch, not a JSON Patch, but FHIR doesn't seem to support this type
// see https://erosb.github.io/post/json-patch-vs-merge-patch/ for an example of the difference
updatedFhirObject = JsonPatchUtils.apply(fhirContext, existingFhirObject, body);
if (isJsonMergePatch(requestDetails)) {
updatedFhirObject = JsonPatchUtils.applyJsonMergePatch(fhirContext, existingFhirObject, body);
} else {
updatedFhirObject = JsonPatchUtils.applyJsonPatch(fhirContext, existingFhirObject, body);
}
break;
default:
throw new InvalidRequestException("only JSON patches currently supported");
throw new InvalidRequestException("only JSON-formatted patches are currently supported");

}
return applyUpdate(existingObject, updatedFhirObject);
}
Expand Down Expand Up @@ -236,6 +242,15 @@ protected void validateObject(U object) {
}
}

/**
* checks the Content-Type header of the request to determine if it corresponds to a merge json
* patch
*/
private Boolean isJsonMergePatch(RequestDetails requestDetails) {
String contentType = requestDetails.getHeader(Constants.HEADER_CONTENT_TYPE);
return contentType != null && contentType.equalsIgnoreCase("application/merge-patch+json");
}

protected ResourceNotFoundException resourceNotFound(String uuid) {
return new ResourceNotFoundException(
"Resource of type " + resourceClass.getSimpleName() + " with ID " + uuid + " is not known");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import ca.uhn.fhir.rest.api.PatchTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.SimpleBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import lombok.AccessLevel;
Expand Down Expand Up @@ -56,7 +57,8 @@ public MedicationDispense update(@Nonnull String uuid, @Nonnull MedicationDispen
}

@Override
public MedicationDispense patch(@Nonnull String uuid, @Nonnull PatchTypeEnum patchType, @Nonnull String body) {
public MedicationDispense patch(@Nonnull String uuid, @Nonnull PatchTypeEnum patchType, @Nonnull String body,
RequestDetails requestDetails) {
throw new UnsupportedOperationException("MedicationDispense is not available in OpenMRS versions < 2.6.0");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ protected final SearchParameterMap baseSearchParameterMap() {
return new SearchParameterMap().addParameter(FhirConstants.COMMON_SEARCH_HANDLER, FhirConstants.ID_PROPERTY, getId())
.addParameter(FhirConstants.COMMON_SEARCH_HANDLER, FhirConstants.LAST_UPDATED_PROPERTY, getLastUpdated())
.addParameter(FhirConstants.INCLUDE_SEARCH_HANDLER, getIncludes())
.addParameter(FhirConstants.REVERSE_INCLUDE_SEARCH_HANDLER, getRevIncludes()).setSortSpec(getSort());
.addParameter(FhirConstants.REVERSE_INCLUDE_SEARCH_HANDLER, getRevIncludes()).setSortSpec(getSort())
.addParameter(FhirConstants.EXACT_TOTAL_SEARCH_PARAMETER, Boolean.FALSE);
}

public abstract SearchParameterMap toSearchParameterMap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ public Allergy toOpenmrsType(@Nonnull Allergy allergy, @Nonnull AllergyIntoleran
notNull(allergy, "The existing Allergy should not be null");
notNull(fhirAllergy, "The AllergyIntolerance object should not be null");

if (fhirAllergy.getId() != null) {
allergy.setUuid(fhirAllergy.getId());
if (fhirAllergy.hasId()) {
allergy.setUuid(fhirAllergy.getIdElement().getIdPart());
}

if (fhirAllergy.hasCode()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public Cohort toOpenmrsType(@Nonnull Cohort existingCohort, @Nonnull Group group
notNull(existingCohort, "ExistingCohort object should not be null");

if (group.hasId()) {
existingCohort.setUuid(group.getId());
existingCohort.setUuid(group.getIdElement().getIdPart());
}

if (group.hasName()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ public Obs toOpenmrsType(@Nonnull org.hl7.fhir.r4.model.Condition condition) {
public Obs toOpenmrsType(@Nonnull Obs existingObsCondition, @Nonnull org.hl7.fhir.r4.model.Condition condition) {
notNull(existingObsCondition, "The existing Openmrs Obs Condition object should not be null");
notNull(condition, "The Condition object should not be null");
existingObsCondition.setUuid(condition.getIdElement().getIdPart());

if (condition.hasId()) {
existingObsCondition.setUuid(condition.getIdElement().getIdPart());
}

CodeableConcept codeableConcept = condition.getCode();
existingObsCondition.setValueCoded(conceptTranslator.toOpenmrsType(codeableConcept));
existingObsCondition.setPerson(patientReferenceTranslator.toOpenmrsType(condition.getSubject()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ public org.openmrs.Encounter toOpenmrsType(@Nonnull org.openmrs.Encounter existi
notNull(existingEncounter, "The existing Openmrs Encounter object should not be null");
notNull(encounter, "The Encounter object should not be null");

existingEncounter.setUuid(encounter.getId());
if (encounter.hasId()) {
existingEncounter.setUuid(encounter.getIdElement().getIdPart());
}

EncounterType encounterType = encounterTypeTranslator.toOpenmrsType(encounter.getType());
if (encounterType != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ public org.openmrs.Location toOpenmrsType(@Nonnull org.openmrs.Location openmrsL
notNull(openmrsLocation, "The existing Openmrs location should not be null");
notNull(fhirLocation, "The Location object should not be null");

openmrsLocation.setUuid(fhirLocation.getIdElement().getIdPart());
if (fhirLocation.hasId()) {
openmrsLocation.setUuid(fhirLocation.getIdElement().getIdPart());
}

openmrsLocation.setName(fhirLocation.getName());
openmrsLocation.setDescription(fhirLocation.getDescription());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ public Drug toOpenmrsType(@Nonnull Drug existingDrug, @Nonnull Medication medica
return null;
}

if (medication.getId() != null) {
existingDrug.setUuid(medication.getId());
if (medication.hasId()) {
existingDrug.setUuid(medication.getIdElement().getIdPart());
}

if (medication.hasCode()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ public org.openmrs.Patient toOpenmrsType(@Nonnull org.openmrs.Patient currentPat
notNull(currentPatient, "The existing Openmrs Patient object should not be null");
notNull(patient, "The Patient object should not be null");

currentPatient.setUuid(patient.getId());
if (patient.hasId()) {
currentPatient.setUuid(patient.getIdElement().getIdPart());
}

for (Identifier identifier : patient.getIdentifier()) {
PatientIdentifier omrsIdentifier = identifierTranslator.toOpenmrsType(identifier);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ public Person toOpenmrsType(@Nonnull Person openmrsPerson, @Nonnull org.hl7.fhir
notNull(openmrsPerson, "The existing Openmrs Person object should not be null");
notNull(person, "The Person object should not be null");

openmrsPerson.setUuid(person.getId());
if (person.hasId()) {
openmrsPerson.setUuid(person.getIdElement().getIdPart());
}

for (HumanName name : person.getName()) {
openmrsPerson.addName(nameTranslator.toOpenmrsType(name));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ public Provider toOpenmrsType(@Nonnull Provider existingProvider, @Nonnull Pract
return null;
}

existingProvider.setUuid(practitioner.getId());
if (practitioner.hasId()) {
existingProvider.setUuid(practitioner.getIdElement().getIdPart());
}

existingProvider.setIdentifier(practitioner.getIdentifierFirstRep().getValue());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ public User toOpenmrsType(@Nonnull User user, @Nonnull Practitioner practitioner
return null;
}

user.setUuid(practitioner.getId());
if (practitioner.hasId()) {
user.setUuid(practitioner.getIdElement().getIdPart());
}

setSystemId(practitioner, user);

if (practitioner.hasBirthDateElement()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ public Visit toOpenmrsType(@Nonnull Visit existingVisit, @Nonnull Encounter enco
notNull(existingVisit, "The existingVisit object should not be null");
notNull(encounter, "The Encounter object should not be null");

existingVisit.setUuid(encounter.getId());
if (encounter.hasId()) {
existingVisit.setUuid(encounter.getIdElement().getIdPart());
}

VisitType visitType = visitTypeTranslator.toOpenmrsType(encounter.getType());
if (visitType != null) {
Expand Down
Loading

0 comments on commit 415b1e2

Please sign in to comment.