use of org.hl7.fhir.r4.model.Attachment in project nia-patient-switching-standard-adaptor by NHSDigital.
the class COPCMessageHandler method checkAndMergeFileParts.
public void checkAndMergeFileParts(InboundMessage inboundMessage, String conversationId) throws SAXException, AttachmentLogException, ValidationException, InlineAttachmentProcessingException {
Document ebXmlDocument = xPathService.parseDocumentFromXml(inboundMessage.getEbXML());
var inboundMessageId = xPathService.getNodeValue(ebXmlDocument, MESSAGE_ID_PATH);
var currentAttachmentLog = patientAttachmentLogService.findAttachmentLog(inboundMessageId, conversationId);
if (currentAttachmentLog == null) {
throw new AttachmentLogException("Given COPC message is missing an attachment log");
}
// if a message has arrived early, it will not have a parent ID so we can cancel early.
if (currentAttachmentLog.getParentMid() == null) {
return;
}
var conversationAttachmentLogs = patientAttachmentLogService.findAttachmentLogs(conversationId);
var attachmentLogFragments = conversationAttachmentLogs.stream().sorted(Comparator.comparingInt(PatientAttachmentLog::getOrderNum)).filter(log -> !(log.getParentMid() == null) && log.getParentMid().equals(currentAttachmentLog.getParentMid())).toList();
var parentLogMessageId = attachmentLogFragments.size() == 1 ? currentAttachmentLog.getMid() : currentAttachmentLog.getParentMid();
attachmentLogFragments = conversationAttachmentLogs.stream().sorted(Comparator.comparingInt(PatientAttachmentLog::getOrderNum)).filter(log -> !(log.getParentMid() == null) && log.getParentMid().equals(parentLogMessageId)).toList();
var allFragmentsHaveUploaded = attachmentLogFragments.stream().allMatch(PatientAttachmentLog::getUploaded);
if (allFragmentsHaveUploaded) {
String payload = attachmentHandlerService.buildSingleFileStringFromPatientAttachmentLogs(attachmentLogFragments, conversationId);
var parentLogFile = conversationAttachmentLogs.stream().filter(log -> log.getMid().equals(parentLogMessageId)).findAny().orElse(null);
var mergedLargeAttachment = createNewLargeAttachmentInList(parentLogFile, payload);
attachmentHandlerService.storeAttachments(mergedLargeAttachment, conversationId);
var updatedLog = PatientAttachmentLog.builder().mid(parentLogFile.getMid()).uploaded(true).build();
patientAttachmentLogService.updateAttachmentLog(updatedLog, conversationId);
attachmentLogFragments.forEach((PatientAttachmentLog log) -> {
attachmentHandlerService.removeAttachment(log.getFilename(), conversationId);
patientAttachmentLogService.deleteAttachmentLog(log.getMid(), conversationId);
});
}
}
use of org.hl7.fhir.r4.model.Attachment in project nia-patient-switching-standard-adaptor by NHSDigital.
the class EhrExtractMessageHandler method handleMessage.
public void handleMessage(InboundMessage inboundMessage, String conversationId) throws JAXBException, JsonProcessingException, InlineAttachmentProcessingException, BundleMappingException, AttachmentNotFoundException, ParseException, SAXException {
RCMRIN030000UK06Message payload = unmarshallString(inboundMessage.getPayload(), RCMRIN030000UK06Message.class);
PatientMigrationRequest migrationRequest = migrationRequestDao.getMigrationRequest(conversationId);
MigrationStatusLog migrationStatusLog = migrationStatusLogService.getLatestMigrationStatusLog(conversationId);
migrationStatusLogService.addMigrationStatusLog(EHR_EXTRACT_RECEIVED, conversationId);
try {
Document ebXmlDocument = getEbXmlDocument(inboundMessage);
String messageId = xPathService.getNodeValue(ebXmlDocument, MESSAGE_ID_PATH);
boolean hasExternalAttachment = !(inboundMessage.getExternalAttachments() == null || inboundMessage.getExternalAttachments().isEmpty());
// Manage attachments against the EHR message
var attachments = inboundMessage.getAttachments();
if (attachments != null) {
attachmentHandlerService.storeAttachments(attachments, conversationId);
for (var i = 0; i < attachments.size(); i++) {
var attachment = attachments.get(i);
PatientAttachmentLog newAttachmentLog = buildPatientAttachmentLogFromAttachment(messageId, migrationRequest, attachment);
patientAttachmentLogService.addAttachmentLog(newAttachmentLog);
}
}
if (!hasExternalAttachment) {
var fileUpdatedPayload = attachmentReferenceUpdaterService.updateReferenceToAttachment(inboundMessage.getAttachments(), conversationId, inboundMessage.getPayload());
inboundMessage.setPayload(fileUpdatedPayload);
payload = unmarshallString(inboundMessage.getPayload(), RCMRIN030000UK06Message.class);
var bundle = bundleMapperService.mapToBundle(payload, migrationRequest.getLosingPracticeOdsCode());
migrationStatusLogService.updatePatientMigrationRequestAndAddMigrationStatusLog(conversationId, fhirParser.encodeToJson(bundle), objectMapper.writeValueAsString(inboundMessage), EHR_EXTRACT_TRANSLATED);
nackAckPreparationService.sendAckMessage(payload, conversationId);
}
// sending continue message
if (hasExternalAttachment) {
String patientNhsNumber = XmlParseUtilService.parseNhsNumber(payload);
for (InboundMessage.ExternalAttachment externalAttachment : inboundMessage.getExternalAttachments()) {
PatientAttachmentLog patientAttachmentLog;
// save COPC_UK01 messages
patientAttachmentLog = buildPatientAttachmentLogFromExternalAttachment(migrationRequest, externalAttachment);
patientAttachmentLogService.addAttachmentLog(patientAttachmentLog);
}
migrationStatusLogService.updatePatientMigrationRequestAndAddMigrationStatusLog(conversationId, null, objectMapper.writeValueAsString(inboundMessage), EHR_EXTRACT_TRANSLATED);
sendContinueRequest(payload, conversationId, patientNhsNumber, migrationRequest.getWinningPracticeOdsCode(), migrationStatusLog.getDate().toInstant());
}
} catch (BundleMappingException | DataFormatException | JsonProcessingException | InlineAttachmentProcessingException | AttachmentNotFoundException | SAXException | StorageException ex) {
nackAckPreparationService.sendNackMessage(EHR_EXTRACT_CANNOT_BE_PROCESSED, payload, conversationId);
throw ex;
} catch (ParseException ex) {
throw ex;
}
}
use of org.hl7.fhir.r4.model.Attachment in project MobileAccessGateway by i4mi.
the class Iti67ResponseConverter method translateToFhir.
@Override
public List<DocumentReference> translateToFhir(QueryResponse input, Map<String, Object> parameters) {
ArrayList<DocumentReference> list = new ArrayList<DocumentReference>();
if (input != null && Status.SUCCESS.equals(input.getStatus())) {
// process relationship association
Map<String, List<DocumentReferenceRelatesToComponent>> relatesToMapping = new HashMap<String, List<DocumentReferenceRelatesToComponent>>();
for (Association association : input.getAssociations()) {
// Relationship type -> relatesTo.code code [1..1]
// relationship reference -> relatesTo.target Reference(DocumentReference)
String source = association.getSourceUuid();
String target = association.getTargetUuid();
AssociationType type = association.getAssociationType();
DocumentReferenceRelatesToComponent relatesTo = new DocumentReferenceRelatesToComponent();
if (type != null)
switch(type) {
case APPEND:
relatesTo.setCode(DocumentRelationshipType.APPENDS);
break;
case REPLACE:
relatesTo.setCode(DocumentRelationshipType.REPLACES);
break;
case TRANSFORM:
relatesTo.setCode(DocumentRelationshipType.TRANSFORMS);
break;
case SIGNS:
relatesTo.setCode(DocumentRelationshipType.SIGNS);
break;
}
relatesTo.setTarget(new Reference().setReference("urn:oid:" + target));
if (!relatesToMapping.containsKey(source))
relatesToMapping.put(source, new ArrayList<DocumentReferenceRelatesToComponent>());
relatesToMapping.get(source).add(relatesTo);
}
if (input.getDocumentEntries() != null) {
for (DocumentEntry documentEntry : input.getDocumentEntries()) {
DocumentReference documentReference = new DocumentReference();
// FIXME do we need to cache this id in
documentReference.setId(noUuidPrefix(documentEntry.getEntryUuid()));
// relation to the DocumentManifest itself
// for
list.add(documentReference);
// limitedMetadata -> meta.profile canonical [0..*]
if (documentEntry.isLimitedMetadata()) {
documentReference.getMeta().addProfile("http://ihe.net/fhir/StructureDefinition/IHE_MHD_Query_Comprehensive_DocumentReference");
} else {
documentReference.getMeta().addProfile("http://ihe.net/fhir/StructureDefinition/IHE_MHD_Comprehensive_DocumentManifest");
}
// uniqueId -> masterIdentifier Identifier [0..1] [1..1]
if (documentEntry.getUniqueId() != null) {
documentReference.setMasterIdentifier((new Identifier().setValue("urn:oid:" + documentEntry.getUniqueId())));
}
// DocumentReference.identifier. use shall be ‘official’
if (documentEntry.getEntryUuid() != null) {
documentReference.addIdentifier((new Identifier().setSystem("urn:ietf:rfc:3986").setValue(asUuid(documentEntry.getEntryUuid()))).setUse(IdentifierUse.OFFICIAL));
}
// Other status values are allowed but are not defined in this mapping to XDS.
if (AvailabilityStatus.APPROVED.equals(documentEntry.getAvailabilityStatus())) {
documentReference.setStatus(DocumentReferenceStatus.CURRENT);
}
if (AvailabilityStatus.DEPRECATED.equals(documentEntry.getAvailabilityStatus())) {
documentReference.setStatus(DocumentReferenceStatus.SUPERSEDED);
}
// contentTypeCode -> type CodeableConcept [0..1]
if (documentEntry.getTypeCode() != null) {
documentReference.setType(transform(documentEntry.getTypeCode()));
}
// classCode -> category CodeableConcept [0..*]
if (documentEntry.getClassCode() != null) {
documentReference.addCategory((transform(documentEntry.getClassCode())));
}
// representing the XDS Affinity Domain Patient.
if (documentEntry.getPatientId() != null) {
Identifiable patient = documentEntry.getPatientId();
documentReference.setSubject(transformPatient(patient));
}
// creationTime -> date instant [0..1]
if (documentEntry.getCreationTime() != null) {
documentReference.setDate(Date.from(documentEntry.getCreationTime().getDateTime().toInstant()));
}
// PractitionerRole| Organization| Device| Patient| RelatedPerson) [0..*]
if (documentEntry.getAuthors() != null) {
for (Author author : documentEntry.getAuthors()) {
documentReference.addAuthor(transformAuthor(author));
}
}
// legalAuthenticator -> authenticator Note 1
// Reference(Practitioner|Practition erRole|Organization [0..1]
Person person = documentEntry.getLegalAuthenticator();
if (person != null) {
Practitioner practitioner = transformPractitioner(person);
documentReference.setAuthenticator((Reference) new Reference().setResource(practitioner));
}
// Relationship Association -> relatesTo [0..*]
// [1..1]
documentReference.setRelatesTo(relatesToMapping.get(documentEntry.getEntryUuid()));
// title -> description string [0..1]
if (documentEntry.getTitle() != null) {
documentReference.setDescription(documentEntry.getTitle().getValue());
}
// DocumentReference itself.
if (documentEntry.getConfidentialityCodes() != null) {
documentReference.addSecurityLabel(transform(documentEntry.getConfidentialityCodes()));
}
DocumentReferenceContentComponent content = documentReference.addContent();
Attachment attachment = new Attachment();
content.setAttachment(attachment);
// mimeType -> content.attachment.contentType [1..1] code [0..1]
if (documentEntry.getMimeType() != null) {
attachment.setContentType(documentEntry.getMimeType());
}
// languageCode -> content.attachment.language code [0..1]
if (documentEntry.getLanguageCode() != null) {
attachment.setLanguage(documentEntry.getLanguageCode());
}
// retrievable location of the document -> content.attachment.url uri
// [0..1] [1..1
// has to defined, for the PoC we define
// $host:port/camel/$repositoryid/$uniqueid
attachment.setUrl(config.getUriMagXdsRetrieve() + "?uniqueId=" + documentEntry.getUniqueId() + "&repositoryUniqueId=" + documentEntry.getRepositoryUniqueId());
// size -> content.attachment.size integer [0..1] The size is calculated
if (documentEntry.getSize() != null) {
attachment.setSize(documentEntry.getSize().intValue());
}
// on the data prior to base64 encoding, if the data is base64 encoded.
if (documentEntry.getHash() != null) {
attachment.setHash(Hex.fromHex(documentEntry.getHash()));
}
// comments -> content.attachment.title string [0..1]
if (documentEntry.getComments() != null) {
attachment.setTitle(documentEntry.getComments().getValue());
}
// TcreationTime -> content.attachment.creation dateTime [0..1]
if (documentEntry.getCreationTime() != null) {
attachment.setCreation(Date.from(documentEntry.getCreationTime().getDateTime().toInstant()));
}
// formatCode -> content.format Coding [0..1]
if (documentEntry.getFormatCode() != null) {
content.setFormat(transform(documentEntry.getFormatCode()).getCodingFirstRep());
}
DocumentReferenceContextComponent context = new DocumentReferenceContextComponent();
documentReference.setContext(context);
// referenceIdList -> context.encounter Reference(Encounter) [0..*] When
// referenceIdList contains an encounter, and a FHIR Encounter is available, it
// may be referenced.
// Map to context.related
List<ReferenceId> refIds = documentEntry.getReferenceIdList();
if (refIds != null) {
for (ReferenceId refId : refIds) {
context.getRelated().add(transform(refId));
}
}
// eventCodeList -> context.event CodeableConcept [0..*]
if (documentEntry.getEventCodeList() != null) {
documentReference.getContext().setEvent(transformMultiple(documentEntry.getEventCodeList()));
}
// serviceStartTime serviceStopTime -> context.period Period [0..1]
if (documentEntry.getServiceStartTime() != null || documentEntry.getServiceStopTime() != null) {
Period period = new Period();
period.setStartElement(transform(documentEntry.getServiceStartTime()));
period.setEndElement(transform(documentEntry.getServiceStopTime()));
documentReference.getContext().setPeriod(period);
}
// [0..1]
if (documentEntry.getHealthcareFacilityTypeCode() != null) {
context.setFacilityType(transform(documentEntry.getHealthcareFacilityTypeCode()));
}
// practiceSettingCode -> context.practiceSetting CodeableConcept [0..1]
if (documentEntry.getPracticeSettingCode() != null) {
context.setPracticeSetting(transform(documentEntry.getPracticeSettingCode()));
}
// sourcePatientId and sourcePatientInfo -> context.sourcePatientInfo
// Reference(Patient) [0..1] Contained Patient Resource with
// Patient.identifier.use element set to ‘usual’.
Identifiable sourcePatientId = documentEntry.getSourcePatientId();
PatientInfo sourcePatientInfo = documentEntry.getSourcePatientInfo();
Patient sourcePatient = new Patient();
if (sourcePatientId != null) {
sourcePatient.addIdentifier((new Identifier().setSystem("urn:oid:" + sourcePatientId.getAssigningAuthority().getUniversalId()).setValue(sourcePatientId.getId())).setUse(IdentifierUse.OFFICIAL));
}
if (sourcePatientInfo != null) {
sourcePatient.setBirthDateElement(transformToDate(sourcePatientInfo.getDateOfBirth()));
String gender = sourcePatientInfo.getGender();
if (gender != null) {
switch(gender) {
case "F":
sourcePatient.setGender(Enumerations.AdministrativeGender.FEMALE);
break;
case "M":
sourcePatient.setGender(Enumerations.AdministrativeGender.MALE);
break;
case "U":
sourcePatient.setGender(Enumerations.AdministrativeGender.UNKNOWN);
break;
case "A":
sourcePatient.setGender(Enumerations.AdministrativeGender.OTHER);
break;
}
}
ListIterator<Name> names = sourcePatientInfo.getNames();
while (names.hasNext()) {
Name name = names.next();
sourcePatient.addName(transform(name));
}
ListIterator<Address> addresses = sourcePatientInfo.getAddresses();
while (addresses.hasNext()) {
Address address = addresses.next();
if (address != null)
sourcePatient.addAddress(transform(address));
}
}
if (sourcePatientId != null || sourcePatientInfo != null) {
context.getSourcePatientInfo().setResource(sourcePatient);
}
}
}
} else {
processError(input);
}
return list;
}
use of org.hl7.fhir.r4.model.Attachment in project synthea by synthetichealth.
the class FhirR4 method convertToFHIR.
/**
* Convert the given Person into a FHIR Bundle of the Patient and the
* associated entries from their health record.
*
* @param person Person to generate the FHIR JSON for
* @param stopTime Time the simulation ended
* @return FHIR Bundle containing the Person's health record
*/
public static Bundle convertToFHIR(Person person, long stopTime) {
Bundle bundle = new Bundle();
if (TRANSACTION_BUNDLE) {
bundle.setType(BundleType.TRANSACTION);
} else {
bundle.setType(BundleType.COLLECTION);
}
BundleEntryComponent personEntry = basicInfo(person, bundle, stopTime);
for (Encounter encounter : person.record.encounters) {
BundleEntryComponent encounterEntry = encounter(person, personEntry, bundle, encounter);
for (HealthRecord.Entry condition : encounter.conditions) {
condition(person, personEntry, bundle, encounterEntry, condition);
}
for (HealthRecord.Allergy allergy : encounter.allergies) {
allergy(person, personEntry, bundle, encounterEntry, allergy);
}
for (Observation observation : encounter.observations) {
// Observation resources in v4 don't support Attachments
if (observation.value instanceof Attachment) {
media(person, personEntry, bundle, encounterEntry, observation);
} else {
observation(person, personEntry, bundle, encounterEntry, observation);
}
}
for (Procedure procedure : encounter.procedures) {
procedure(person, personEntry, bundle, encounterEntry, procedure);
}
for (HealthRecord.Device device : encounter.devices) {
device(person, personEntry, bundle, device);
}
for (HealthRecord.Supply supply : encounter.supplies) {
supplyDelivery(person, personEntry, bundle, supply, encounter);
}
for (Medication medication : encounter.medications) {
medicationRequest(person, personEntry, bundle, encounterEntry, medication);
}
for (HealthRecord.Entry immunization : encounter.immunizations) {
immunization(person, personEntry, bundle, encounterEntry, immunization);
}
for (Report report : encounter.reports) {
report(person, personEntry, bundle, encounterEntry, report);
}
for (CarePlan careplan : encounter.careplans) {
BundleEntryComponent careTeamEntry = careTeam(person, personEntry, bundle, encounterEntry, careplan);
carePlan(person, personEntry, bundle, encounterEntry, encounter.provider, careTeamEntry, careplan);
}
for (ImagingStudy imagingStudy : encounter.imagingStudies) {
imagingStudy(person, personEntry, bundle, encounterEntry, imagingStudy);
}
if (USE_US_CORE_IG) {
String clinicalNoteText = ClinicalNoteExporter.export(person, encounter);
boolean lastNote = (encounter == person.record.encounters.get(person.record.encounters.size() - 1));
clinicalNote(person, personEntry, bundle, encounterEntry, clinicalNoteText, lastNote);
}
// one claim per encounter
BundleEntryComponent encounterClaim = encounterClaim(person, personEntry, bundle, encounterEntry, encounter.claim);
explanationOfBenefit(personEntry, bundle, encounterEntry, person, encounterClaim, encounter);
}
if (USE_US_CORE_IG) {
// Add Provenance to the Bundle
provenance(bundle, person, stopTime);
}
return bundle;
}
use of org.hl7.fhir.r4.model.Attachment in project synthea by synthetichealth.
the class FhirR4 method media.
/**
* Map the given Observation with attachment element to a FHIR Media resource, and add it to the
* given Bundle.
*
* @param rand Source of randomness to use when generating ids etc
* @param personEntry The Entry for the Person
* @param bundle Bundle to add the Media to
* @param encounterEntry Current Encounter entry
* @param obs The Observation to map to FHIR and add to the bundle
* @return The added Entry
*/
private static BundleEntryComponent media(RandomNumberGenerator rand, BundleEntryComponent personEntry, Bundle bundle, BundleEntryComponent encounterEntry, Observation obs) {
org.hl7.fhir.r4.model.Media mediaResource = new org.hl7.fhir.r4.model.Media();
// Hard code as Image since we don't anticipate using video or audio any time soon
Code mediaType = new Code("http://terminology.hl7.org/CodeSystem/media-type", "image", "Image");
if (obs.codes != null && obs.codes.size() > 0) {
List<CodeableConcept> reasonList = obs.codes.stream().map(code -> mapCodeToCodeableConcept(code, SNOMED_URI)).collect(Collectors.toList());
mediaResource.setReasonCode(reasonList);
}
mediaResource.setType(mapCodeToCodeableConcept(mediaType, MEDIA_TYPE_URI));
mediaResource.setStatus(MediaStatus.COMPLETED);
mediaResource.setSubject(new Reference(personEntry.getFullUrl()));
mediaResource.setEncounter(new Reference(encounterEntry.getFullUrl()));
Attachment content = (Attachment) obs.value;
org.hl7.fhir.r4.model.Attachment contentResource = new org.hl7.fhir.r4.model.Attachment();
contentResource.setContentType(content.contentType);
contentResource.setLanguage(content.language);
if (content.data != null) {
contentResource.setDataElement(new org.hl7.fhir.r4.model.Base64BinaryType(content.data));
} else {
contentResource.setSize(content.size);
}
contentResource.setUrl(content.url);
contentResource.setTitle(content.title);
if (content.hash != null) {
contentResource.setHashElement(new org.hl7.fhir.r4.model.Base64BinaryType(content.hash));
}
mediaResource.setWidth(content.width);
mediaResource.setHeight(content.height);
mediaResource.setContent(contentResource);
return newEntry(rand, bundle, mediaResource);
}
Aggregations