Search in sources :

Example 11 with Bundle

use of org.hl7.fhir.dstu3.model.Bundle in project loinc2hpo by monarch-initiative.

the class FhirResourceRetriever method retrievePatientFromServer.

/**
 * Retrieve a patient from the reference field of an observation
 * @param subject
 * @return
 */
public static Patient retrievePatientFromServer(Reference subject) throws SubjectNotFoundException, AmbiguousSubjectException {
    List<Patient> patients = new ArrayList<>();
    if (subject.hasReference()) {
        String ref = subject.getReference();
        if (!ref.startsWith(BASEURL) && ref.startsWith("Patient")) {
            ref = BASEURL + "/" + ref;
        }
        Bundle patientBundle = client.search().byUrl(ref).returnBundle(Bundle.class).execute();
        while (true) {
            patientBundle.getEntry().forEach(p -> patients.add((Patient) p.getResource()));
            if (patientBundle.getLink(IBaseBundle.LINK_NEXT) != null) {
                patientBundle = client.loadPage().next(patientBundle).execute();
            } else {
                break;
            }
        }
    } else if (subject.hasIdentifier()) {
        Identifier identifier = subject.getIdentifier();
    // TODO: find patient through the identifier
    }
    if (patients.size() == 1) {
        return patients.iterator().next();
    } else if (patients.isEmpty()) {
        throw new SubjectNotFoundException("Expect one subject, but found none");
    } else {
        throw new AmbiguousSubjectException("Except one subject, but found multiple");
    }
}
Also used : SubjectNotFoundException(org.monarchinitiative.loinc2hpo.exception.SubjectNotFoundException) AmbiguousSubjectException(org.monarchinitiative.loinc2hpo.exception.AmbiguousSubjectException) IBaseBundle(org.hl7.fhir.instance.model.api.IBaseBundle) ArrayList(java.util.ArrayList)

Example 12 with Bundle

use of org.hl7.fhir.dstu3.model.Bundle in project loinc2hpo by monarch-initiative.

the class FhirResourceRetriever method retrieveObservationFromServer.

/**
 * @TODO: implement it
 * retrieve a patient's observations from FHIR server
 * @param patient
 * @return
 */
public static List<Observation> retrieveObservationFromServer(Patient patient) {
    List<Observation> observationList = new ArrayList<>();
    String id = patient.getId();
    if (id != null) {
        Bundle observationBundle = client.search().forResource(Observation.class).where(new ReferenceClientParam("subject").hasId(id)).prettyPrint().returnBundle(Bundle.class).execute();
        while (true) {
            observationBundle.getEntry().forEach(p -> observationList.add((Observation) p.getResource()));
            if (observationBundle.getLink(IBaseBundle.LINK_NEXT) != null) {
                observationBundle = client.loadPage().next(observationBundle).execute();
            } else {
                break;
            }
        }
    }
    return observationList;
}
Also used : IBaseBundle(org.hl7.fhir.instance.model.api.IBaseBundle) ArrayList(java.util.ArrayList) ReferenceClientParam(ca.uhn.fhir.rest.gclient.ReferenceClientParam)

Example 13 with Bundle

use of org.hl7.fhir.dstu3.model.Bundle in project gpconnect-demonstrator by nhsconnect.

the class PatientResourceProvider method addWarningIssue.

/**
 * see
 * https://gpconnect-1-2-4.netlify.com/accessrecord_structured_development_version_compatibility.html
 * add an issue to the OperationOutcome to be returned in a successful
 * response bundle this is for forward compatibility as specified in 1.2.4
 *
 * @param param
 * @param paramPart
 * @param issueType
 * @param details lower level details to be added to the text element
 */
private void addWarningIssue(ParametersParameterComponent param, ParametersParameterComponent paramPart, IssueType issueType, String details) {
    if (operationOutcome == null) {
        createOperationOutcome();
    }
    OperationOutcomeIssueComponent issue = new OperationOutcomeIssueComponent();
    issue.setSeverity(OperationOutcome.IssueSeverity.WARNING);
    CodeableConcept codeableConcept = new CodeableConcept();
    Coding coding = new Coding();
    coding.setSystem(VS_GPC_ERROR_WARNING_CODE);
    switch(issueType) {
        case NOTSUPPORTED:
            issue.setCode(issueType);
            coding.setCode(SystemCode.NOT_IMPLEMENTED);
            coding.setDisplay("Not implemented");
            break;
        case REQUIRED:
            issue.setCode(issueType);
            coding.setCode(SystemCode.PARAMETER_NOT_FOUND);
            coding.setDisplay("Parameter not found");
            break;
        case INVALID:
            issue.setCode(issueType);
            coding.setCode(SystemCode.INVALID_PARAMETER);
            coding.setDisplay("Invalid Parameter");
            break;
    }
    codeableConcept.addCoding(coding);
    issue.setDetails(codeableConcept);
    String locus = paramPart != null ? "." + paramPart.getName() : "";
    issue.setDiagnostics(param.getName() + locus);
    if (details == null) {
        // mod to remove more informative text which was off spec
        codeableConcept.setText(param.getName() + locus + " is an unrecognised parameter");
    } else {
        codeableConcept.setText(details);
    }
    operationOutcome.addIssue(issue);
}
Also used : OperationOutcomeIssueComponent(org.hl7.fhir.dstu3.model.OperationOutcome.OperationOutcomeIssueComponent)

Example 14 with Bundle

use of org.hl7.fhir.dstu3.model.Bundle in project gpconnect-demonstrator by nhsconnect.

the class PopulateSlotBundle method populateBundle.

/**
 * @param bundle Bundle resource to populate
 * @param operationOutcome
 * @param planningHorizonStart Date
 * @param planningHorizonEnd Date
 * @param actorPractitioner boolean
 * @param actorLocation boolean
 * @param managingOrganisation boolean
 * @param bookingOdsCode String
 * @param bookingOrgType String eg "urgent-care"
 */
public void populateBundle(Bundle bundle, OperationOutcome operationOutcome, Date planningHorizonStart, Date planningHorizonEnd, boolean actorPractitioner, boolean actorLocation, boolean managingOrganisation, String bookingOdsCode, String bookingOrgType) {
    bundle.getMeta().addProfile(SystemURL.SD_GPC_SRCHSET_BUNDLE);
    // TODO remove hard coding pick up from providerRouting.json ?
    final String OUR_ODS_CODE = "A20047";
    // find all locations for this ODS practice code and construct Resources for them
    // #144 generalise to handle 1..n locations for a practice
    HashMap<String, BundleEntryComponent> locationEntries = new HashMap<>();
    for (LocationDetails aLocationDetail : locationSearch.findAllLocations()) {
        if (aLocationDetail.getOrgOdsCode().equals(OUR_ODS_CODE)) {
            Location aLocationResource = locationResourceProvider.getLocationById(new IdType(aLocationDetail.getId()));
            BundleEntryComponent locationEntry = new BundleEntryComponent();
            locationEntry.setResource(aLocationResource);
            // #202 use full urls
            // #215 full url removed completely
            // locationEntry.setFullUrl(serverBaseUrl + "Location/" + aLocationResource.getIdElement().getIdPart());
            locationEntries.put(aLocationResource.getIdElement().getIdPart(), locationEntry);
        }
    }
    // find the provider organization from the ods code
    List<OrganizationDetails> ourOrganizationsDetails = organizationSearch.findOrganizationDetailsByOrgODSCode(OUR_ODS_CODE);
    OrganizationDetails ourOrganizationDetails = null;
    if (!ourOrganizationsDetails.isEmpty()) {
        // at 1.2.2 these are added regardless of the status of the relevant parameter
        // Just picks the first organization. There should only be one.
        ourOrganizationDetails = ourOrganizationsDetails.get(0);
    } else {
    // do something here .. should never happen
    }
    // find the bookng organization from the ods code
    List<OrganizationDetails> bookingOrganizationsDetails = organizationSearch.findOrganizationDetailsByOrgODSCode(bookingOdsCode);
    OrganizationDetails bookingOrganizationDetails = null;
    if (!bookingOrganizationsDetails.isEmpty()) {
        // at 1.2.2 these are added regardless of the status of the relevant parameter
        // Just picks the first organization. There should only be one.
        bookingOrganizationDetails = bookingOrganizationsDetails.get(0);
    }
    HashSet<BundleEntryComponent> addedSchedule = new HashSet<>();
    HashSet<BundleEntryComponent> addedLocation = new HashSet<>();
    HashSet<String> addedPractitioner = new HashSet<>();
    HashSet<String> addedOrganization = new HashSet<>();
    // issue #165 don't add duplicate slots, hashSet contains slot id as String
    HashSet<String> addedSlot = new HashSet<>();
    // #144 process all locations
    for (String locationId : locationEntries.keySet()) {
        // process the schedules
        for (Schedule schedule : scheduleResourceProvider.getSchedulesForLocationId(locationId, planningHorizonStart, planningHorizonEnd)) {
            boolean slotsAdded = false;
            schedule.getMeta().addProfile(SystemURL.SD_GPC_SCHEDULE);
            BundleEntryComponent scheduleEntry = new BundleEntryComponent();
            scheduleEntry.setResource(schedule);
            // #202 use full urls
            // #215 full url removed completely
            // scheduleEntry.setFullUrl(serverBaseUrl + "Schedule/" + schedule.getIdElement().getIdPart());
            // This Set does not work as expected because Slot does not implement hashCode
            // so the second set call to getSlots returns different objects with the same slot id
            Set<Slot> slots = new HashSet<>();
            // 
            if (bookingOrgType.isEmpty() && bookingOdsCode.isEmpty()) {
                // OPTION 1 get slots Specfying  neither org type nor org code
                slots.addAll(slotResourceProvider.getSlotsForScheduleIdNoOrganizationTypeOrODS(schedule.getIdElement().getIdPart(), planningHorizonStart, planningHorizonEnd));
            } else if (!bookingOrgType.isEmpty() && bookingOdsCode.isEmpty()) {
                // OPTION 2 organisation type only
                for (Slot slot : slotResourceProvider.getSlotsForScheduleId(schedule.getIdElement().getIdPart(), planningHorizonStart, planningHorizonEnd)) {
                    SlotDetail slotDetail = slotSearch.findSlotByID(Long.parseLong(slot.getId()));
                    if (slotDetail.getOrganizationIds().isEmpty() && (slotDetail.getOrganizationTypes().isEmpty() || slotDetail.getOrganizationTypes().contains(bookingOrgType))) {
                        slots.add(slot);
                    }
                }
            } else if (!bookingOdsCode.isEmpty() && bookingOrgType.isEmpty()) {
                // OPTION 3 org code only
                for (Slot slot : slotResourceProvider.getSlotsForScheduleId(schedule.getIdElement().getIdPart(), planningHorizonStart, planningHorizonEnd)) {
                    SlotDetail slotDetail = slotSearch.findSlotByID(Long.parseLong(slot.getId()));
                    if (slotDetail.getOrganizationTypes().isEmpty() && (slotDetail.getOrganizationIds().isEmpty() || bookingOrganizationDetails != null && slotDetail.getOrganizationIds().contains(bookingOrganizationDetails.getId()))) {
                        slots.add(slot);
                    }
                }
            } else if (!bookingOrgType.isEmpty() && !bookingOdsCode.isEmpty()) {
                // OPTION 4 both org code and org type
                for (Slot slot : slotResourceProvider.getSlotsForScheduleId(schedule.getIdElement().getIdPart(), planningHorizonStart, planningHorizonEnd)) {
                    SlotDetail slotDetail = slotSearch.findSlotByID(Long.parseLong(slot.getId()));
                    if (((slotDetail.getOrganizationTypes().isEmpty() || slotDetail.getOrganizationTypes().contains(bookingOrgType))) && (slotDetail.getOrganizationIds().isEmpty() || bookingOrganizationDetails != null && slotDetail.getOrganizationIds().contains(bookingOrganizationDetails.getId()))) {
                        slots.add(slot);
                    }
                }
            }
            // added at 1.2.2 add the organisation but only if there are some slots available
            if (slots.size() > 0 && ourOrganizationDetails != null && !addedOrganization.contains(ourOrganizationDetails.getOrgCode())) {
                addOrganisation(ourOrganizationDetails, bundle);
                addedOrganization.add(ourOrganizationDetails.getOrgCode());
            }
            String freeBusyType = "FREE";
            // process all the slots to be returned
            for (Slot slot : slots) {
                if (freeBusyType.equalsIgnoreCase(slot.getStatus().toString())) {
                    String slotId = slot.getIdElement().getIdPart();
                    if (!addedSlot.contains(slotId)) {
                        BundleEntryComponent slotEntry = new BundleEntryComponent();
                        slotEntry.setResource(slot);
                        // #202 use full urls
                        // #215 full url removed completely
                        // slotEntry.setFullUrl(serverBaseUrl + "Slot/" + slotId);
                        bundle.addEntry(slotEntry);
                        addedSlot.add(slotId);
                        slotsAdded = true;
                    }
                    if (!addedSchedule.contains(scheduleEntry)) {
                        // only add a schedule if there's a reference to it and only add it once
                        bundle.addEntry(scheduleEntry);
                        addedSchedule.add(scheduleEntry);
                    }
                    if (actorLocation == true) {
                        // only add a unique location once
                        if (!addedLocation.contains(locationEntries.get(locationId))) {
                            bundle.addEntry(locationEntries.get(locationId));
                            addedLocation.add(locationEntries.get(locationId));
                        }
                    }
                }
            // if free/busy status matches
            }
            // # 193 for each schedule only add a practitioner if there have been some slots added.
            if (slotsAdded) {
                // practitioners for this schedule
                List<Reference> practitionerActors = scheduleResourceProvider.getPractitionerReferences(schedule);
                if (!practitionerActors.isEmpty()) {
                    for (Reference practitionerActor : practitionerActors) {
                        Practitioner practitioner = practitionerResourceProvider.getPractitionerById((IdType) practitionerActor.getReferenceElement());
                        if (practitioner == null) {
                            Coding errorCoding = new Coding().setSystem(SystemURL.VS_GPC_ERROR_WARNING_CODE).setCode(SystemCode.REFERENCE_NOT_FOUND);
                            CodeableConcept errorCodableConcept = new CodeableConcept().addCoding(errorCoding);
                            errorCodableConcept.setText("Invalid Reference");
                            operationOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setCode(IssueType.NOTFOUND).setDetails(errorCodableConcept);
                            throw new ResourceNotFoundException("Practitioner Reference returning null");
                        }
                        if (actorPractitioner) {
                            if (!addedPractitioner.contains(practitioner.getIdElement().getIdPart())) {
                                addPractitioner(practitioner, bundle);
                                addedPractitioner.add(practitioner.getIdElement().getIdPart());
                            }
                        }
                    }
                // for practitioner
                }
            // if non empty practitioner list
            }
        // if slots added
        }
    // for schedules
    }
// for location
}
Also used : HashMap(java.util.HashMap) LocationDetails(uk.gov.hscic.model.location.LocationDetails) Reference(org.hl7.fhir.dstu3.model.Reference) OrganizationDetails(uk.gov.hscic.model.organization.OrganizationDetails) IdType(org.hl7.fhir.dstu3.model.IdType) Practitioner(org.hl7.fhir.dstu3.model.Practitioner) BundleEntryComponent(org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent) Coding(org.hl7.fhir.dstu3.model.Coding) Schedule(org.hl7.fhir.dstu3.model.Schedule) Slot(org.hl7.fhir.dstu3.model.Slot) ResourceNotFoundException(ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException) SlotDetail(uk.gov.hscic.model.appointment.SlotDetail) Location(org.hl7.fhir.dstu3.model.Location) HashSet(java.util.HashSet) CodeableConcept(org.hl7.fhir.dstu3.model.CodeableConcept)

Example 15 with Bundle

use of org.hl7.fhir.dstu3.model.Bundle in project gpconnect-demonstrator by nhsconnect.

the class PopulateSlotBundle method addPractitioner.

// populateBundle
/**
 * Add practitioner to Bundle
 *
 * @param practitioner
 * @param bundle
 */
private void addPractitioner(Practitioner practitioner, Bundle bundle) {
    BundleEntryComponent practionerEntry = new BundleEntryComponent();
    practionerEntry.setResource(practitioner);
    // #202 use full urls
    // #215 full url removed completely
    // practionerEntry.setFullUrl(serverBaseUrl + "Practitioner/" + practitioner.getIdElement().getIdPart());
    bundle.addEntry(practionerEntry);
}
Also used : BundleEntryComponent(org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent)

Aggregations

IBaseBundle (org.hl7.fhir.instance.model.api.IBaseBundle)5 ArrayList (java.util.ArrayList)4 Bundle (org.hl7.fhir.dstu3.model.Bundle)4 BundleEntryComponent (org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent)4 UnprocessableEntityException (ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException)3 OrganizationDetails (uk.gov.hscic.model.organization.OrganizationDetails)3 ResourceNotFoundException (ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException)2 FHIRException (org.hl7.fhir.exceptions.FHIRException)2 PopulateMedicationBundle (uk.gov.hscic.medications.PopulateMedicationBundle)2 PatientDetails (uk.gov.hscic.model.patient.PatientDetails)2 Include (ca.uhn.fhir.model.api.Include)1 Search (ca.uhn.fhir.rest.annotation.Search)1 ReferenceClientParam (ca.uhn.fhir.rest.gclient.ReferenceClientParam)1 StringClientParam (ca.uhn.fhir.rest.gclient.StringClientParam)1 TokenClientParam (ca.uhn.fhir.rest.gclient.TokenClientParam)1 TokenOrListParam (ca.uhn.fhir.rest.param.TokenOrListParam)1 TokenParam (ca.uhn.fhir.rest.param.TokenParam)1 ForbiddenOperationException (ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException)1 InternalErrorException (ca.uhn.fhir.rest.server.exceptions.InternalErrorException)1 InvalidRequestException (ca.uhn.fhir.rest.server.exceptions.InvalidRequestException)1