001package ca.cdr.api.consent;
002
003import ca.uhn.fhir.context.FhirContext;
004import org.hl7.fhir.instance.model.api.IBaseResource;
005import org.hl7.fhir.instance.model.api.IIdType;
006import org.slf4j.Logger;
007import org.slf4j.LoggerFactory;
008
009import java.util.ArrayList;
010import java.util.Collections;
011import java.util.List;
012import java.util.Objects;
013import java.util.Optional;
014import java.util.Set;
015import java.util.stream.Collectors;
016
017import static org.apache.commons.collections4.CollectionUtils.isEmpty;
018
019public class CompartmentUtil {
020        private static final Logger ourLog = LoggerFactory.getLogger(CompartmentUtil.class);
021        public static final String PATIENT = "Patient";
022
023        private CompartmentUtil() {
024                // utility class
025        }
026
027        public static Optional<IIdType> getPatientCompartmentForResource(
028                        FhirContext theFhirContext, IBaseResource theResource) {
029                List<IIdType> patientCompartments = getPatientCompartmentForResourceMultiple(theFhirContext, theResource);
030                if (isEmpty(patientCompartments)) {
031                        return Optional.empty();
032                }
033                if (patientCompartments.size() > 1) {
034                        String allIds = patientCompartments.stream().map(IIdType::getIdPart).collect(Collectors.joining(", "));
035                        ourLog.warn("Multiple patient compartments found: {}. Selecting first compartment.", allIds);
036                }
037                return Optional.of(patientCompartments.get(0));
038        }
039
040        public static List<IIdType> getPatientCompartmentForResourceMultiple(
041                        FhirContext theFhirContext, IBaseResource theResource) {
042
043                if (theResource == null) {
044                        return Collections.emptyList();
045                }
046
047                List<IIdType> retVal = new ArrayList<>();
048                try {
049                        if (isPatient(theResource)) {
050                                retVal.add(theResource.getIdElement());
051                        } else {
052                                List<IIdType> patientIds =
053                                                theFhirContext
054                                                                .newTerser()
055                                                                .getCompartmentOwnersForResource(PATIENT, theResource, Set.of())
056                                                                .stream()
057                                                                .map(id -> theFhirContext.getVersion().newIdType(id.getValue()))
058                                                                .filter(id -> Objects.equals(PATIENT, id.getResourceType()))
059                                                                .toList();
060                                retVal.addAll(patientIds);
061                        }
062                } catch (Exception e) {
063                        ourLog.warn(
064                                        "Error finding Patient compartment for: {}",
065                                        theResource.getIdElement().getValueAsString());
066                }
067
068                return retVal;
069        }
070
071        private static boolean isPatient(IBaseResource theResource) {
072                return theResource != null && PATIENT.equals(theResource.fhirType());
073        }
074}