use of org.hl7.fhir.dstu3.model.Reference in project loinc2hpo by monarch-initiative.
the class FhirObservationAnalyzer method getHPO4ObservationOutcome.
/**
* A core function that tries three ways to return a LabTestResultInHPO object:
* first, it tries to return the result through the interpretation field. If it fails,
* second, it tries to return the result through the quantative value, or
* third, it tries to return the retult through the coded value (ordinal Loinc)
* @param loinc2HPOannotationMap
* @param loincIds
* @return
*/
public static LabTestResultInHPO getHPO4ObservationOutcome(HashSet<LoincId> loincIds, Map<LoincId, UniversalLoinc2HPOAnnotation> loinc2HPOannotationMap) {
// first make sure the observation has a valid loinc code; otherwise, we cannot handle it
if (!hasValidLoincCode(loincIds)) {
// TODO: consider handling this as a future project
return null;
}
LoincId loincId = null;
try {
loincId = getLoincIdOfObservation();
} catch (MalformedLoincCodeException e) {
logger.error("malformed loinc code; should never happen");
return null;
} catch (LoincCodeNotFoundException e) {
logger.error("No loinc code was found in the observation; should never happen");
return null;
} catch (UnsupportedCodingSystemException e) {
logger.error("coding system not recognized");
return null;
}
if (!loinc2HPOannotationMap.containsKey(loincId)) {
return null;
}
if (observation.hasInterpretation()) {
logger.debug("enter analyzer using the interpretation field");
try {
// return getHPOFromInterpretation(observation.getInterpretation(), loinc2HPOannotationMap);
HpoTermId4LoincTest hpoterm = new ObservationAnalysisFromInterpretation(getLoincIdOfObservation(), observation.getInterpretation(), loinc2HPOannotationMap).getHPOforObservation();
return new BasicLabTestResultInHPO(hpoterm, null);
} catch (UnrecognizedCodeException e) {
// this means the interpretation code is not recognized
logger.info("The interpretation codes for this loinc code is not annotated; system will try using raw values");
} catch (MalformedLoincCodeException e1) {
// not going to happen
logger.error("malformed loinc code.");
return null;
} catch (LoincCodeNotFoundException e2) {
// not going to happen
logger.error("no loinc code is found in the observation");
return null;
} catch (UnsupportedCodingSystemException e3) {
// not going to happen
logger.error("The interpretation coding system cannot be recognized.");
return null;
} catch (AmbiguousResultsFoundException e) {
logger.error("The observation has conflicting interpretation codes.");
return null;
} catch (AnnotationNotFoundException e) {
logger.error("There is no annotation for the loinc code used in the observation");
}
}
// Qn will have a value field
if (observation.hasValueQuantity()) {
try {
HpoTermId4LoincTest hpoterm = new ObservationAnalysisFromQnValue(loincId, observation, loinc2HPOannotationMap).getHPOforObservation();
if (hpoterm != null)
return new BasicLabTestResultInHPO(hpoterm, null);
} catch (ReferenceNotFoundException e) {
// if there is no reference
logger.error("The observation has no reference field.");
// TODO: make a list of our own references
} catch (AmbiguousReferenceException e) {
logger.info("There are two reference ranges or more");
} catch (UnrecognizedCodeException e) {
logger.error("uncognized coding system");
}
}
// Ord will have a ValueCodeableConcept field
if (observation.hasValueCodeableConcept()) {
try {
HpoTermId4LoincTest hpoterm = null;
hpoterm = new ObservationAnalysisFromCodedValues(loincId, observation.getValueCodeableConcept(), loinc2HPOannotationMap).getHPOforObservation();
if (hpoterm != null)
return new BasicLabTestResultInHPO(hpoterm, null);
} catch (AmbiguousResultsFoundException e) {
logger.error("multiple results are found");
} catch (UnrecognizedCodeException e) {
logger.error("unrecognized codes");
} catch (FHIRException e) {
// not going to happen
logger.error("Could not get HPO term from coded value");
} catch (AnnotationNotFoundException e) {
logger.error("There is no annotation for the loinc code used in the observation");
}
}
// if all the above fails, we cannot do nothing
logger.error("Could not return HPO for observation: " + observation.getId());
return null;
}
use of org.hl7.fhir.dstu3.model.Reference 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");
}
}
use of org.hl7.fhir.dstu3.model.Reference in project gpconnect-demonstrator by nhsconnect.
the class LocationResourceProvider method locationDetailsToLocation.
/**
* convert locationDetails to fhir resource
* @param locationDetails
* @return Location resource
*/
private Location locationDetailsToLocation(LocationDetails locationDetails) {
Location location = new Location();
String resourceId = String.valueOf(locationDetails.getId());
String versionId = String.valueOf(locationDetails.getLastUpdated().getTime());
String resourceType = location.getResourceType().toString();
IdType id = new IdType(resourceType, resourceId, versionId);
location.setId(id);
location.getMeta().setVersionId(versionId);
location.getMeta().setLastUpdated(locationDetails.getLastUpdated());
location.getMeta().addProfile(SystemURL.SD_GPC_LOCATION);
location.setName(locationDetails.getName());
// #207 no site code
// location.setIdentifier(Collections.singletonList(new Identifier().setSystem(SystemURL.ID_ODS_SITE_CODE).setValue(locationDetails.getSiteOdsCode())));
// #246 remove type element
// Coding locationCommTypeCode = new Coding();
// locationCommTypeCode.setCode("COMM");
// locationCommTypeCode.setSystem(SystemURL.VS_CC_SER_DEL_LOCROLETYPE);
// locationCommTypeCode.setDisplay("Community Location");
//
// Coding locationGachTypeCode = new Coding();
// locationGachTypeCode.setCode("GACH");
// locationGachTypeCode.setSystem(SystemURL.VS_CC_SER_DEL_LOCROLETYPE);
// locationGachTypeCode.setDisplay("Hospitals; General Acute Care Hospital");
//
// @SuppressWarnings("deprecation")
// CodeableConcept locationType = new CodeableConcept();
// locationType.addCoding(locationCommTypeCode);
// locationType.addCoding(locationGachTypeCode);
// location.setType(locationType);
Organization orgz = FindOrganization(locationDetails.getOrgOdsCode());
if (orgz != null) {
Reference mngOrg = new Reference();
mngOrg.setReference(orgz.getId());
// #246 remove display element
// mngOrg.setDisplay(orgz.getName());
location.setManagingOrganization(mngOrg);
}
EnumSet<LocationStatus> statusList = EnumSet.allOf(LocationStatus.class);
LocationStatus locationStatus = null;
String status = locationDetails.getStatus();
if (status != null) {
for (LocationStatus statusItem : statusList) {
if (statusItem.toCode().equalsIgnoreCase(status)) {
locationStatus = statusItem;
break;
}
}
}
location.setAddress(createAddress(locationDetails));
location.setStatus(locationStatus);
return location;
}
use of org.hl7.fhir.dstu3.model.Reference in project gpconnect-demonstrator by nhsconnect.
the class MedicationStatementResourceProvider method getMedicationStatementResource.
public MedicationStatement getMedicationStatementResource(MedicationStatementDetail statementDetail) {
MedicationStatement medicationStatement = new MedicationStatement();
medicationStatement.setId(statementDetail.getId().toString());
List<Identifier> identifiers = new ArrayList<>();
Identifier identifier = new Identifier().setSystem("https://fhir.nhs.uk/Id/cross-care-setting-identifier").setValue(statementDetail.getGuid());
identifiers.add(identifier);
medicationStatement.setIdentifier(identifiers);
medicationStatement.setMeta(new Meta().addProfile(SystemURL.SD_GPC_MEDICATION_STATEMENT));
medicationStatement.addExtension(new Extension(SystemURL.SD_CC_EXT_MEDICATION_STATEMENT_LAST_ISSUE, new DateTimeType(statementDetail.getLastIssueDate(), TemporalPrecisionEnum.DAY)));
if (statementDetail.getMedicationRequestPlanId() != null) {
medicationStatement.addBasedOn(new Reference(new IdType("MedicationRequest", statementDetail.getMedicationRequestPlanId())));
}
try {
medicationStatement.setStatus(MedicationStatementStatus.fromCode(statementDetail.getStatusCode()));
} catch (FHIRException e) {
throw new UnprocessableEntityException(e.getMessage());
}
if (statementDetail.getMedicationId() != null) {
medicationStatement.setMedication(new Reference(new IdType("Medication", statementDetail.getMedicationId())));
}
medicationStatement.setEffective(new Period().setStart(statementDetail.getStartDate()).setEnd(statementDetail.getEndDate()));
medicationStatement.setDateAsserted(statementDetail.getDateAsserted());
if (statementDetail.getPatientId() != null)
medicationStatement.setSubject(new Reference(new IdType("Patient", statementDetail.getPatientId())));
try {
medicationStatement.setTaken(statementDetail.getTakenCode() != null ? MedicationStatementTaken.fromCode(statementDetail.getTakenCode()) : MedicationStatementTaken.UNK);
} catch (FHIRException e) {
throw new UnprocessableEntityException(e.getMessage());
}
setReasonCodes(medicationStatement, statementDetail);
setNotes(medicationStatement, statementDetail);
String dosageText = statementDetail.getDosageText();
medicationStatement.addDosage(new Dosage().setText(dosageText == null || dosageText.trim().isEmpty() ? NO_INFORMATION_AVAILABLE : dosageText).setPatientInstruction(statementDetail.getDosagePatientInstruction()));
String prescribingAgency = statementDetail.getPrescribingAgency();
if (prescribingAgency != null && !prescribingAgency.trim().isEmpty()) {
String prescribingAgencyDisplay = "";
if (prescribingAgency.equalsIgnoreCase("prescribed-at-gp-practice")) {
prescribingAgencyDisplay = "Prescribed at GP practice";
} else if (prescribingAgency.equalsIgnoreCase("prescribed-by-another-organisation")) {
prescribingAgencyDisplay = "Prescribed by another organisation";
}
Coding coding = new Coding(SystemURL.CS_CC_PRESCRIBING_AGENCY_STU3, prescribingAgency, prescribingAgencyDisplay);
CodeableConcept codeableConcept = new CodeableConcept().addCoding(coding);
medicationStatement.addExtension(new Extension(SystemURL.SD_EXTENSION_CC_PRESCRIBING_AGENCY, codeableConcept));
}
// #281 1.2.5 add dosageLastChanged
Date dosageLastChanged = statementDetail.getDosageLastChanged();
if (dosageLastChanged != null) {
medicationStatement.addExtension(new Extension(SystemURL.SD_EXTENSION_CC_DOSAGE_LAST_CHANGED, new DateTimeType(dosageLastChanged)));
}
return medicationStatement;
}
use of org.hl7.fhir.dstu3.model.Reference 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
}
Aggregations