diff --git a/src/main/java/org/ehrbase/fhirbridge/camel/processor/ITI65Processor.java b/src/main/java/org/ehrbase/fhirbridge/camel/processor/ITI65Processor.java index b4d0932dd..55ced0693 100644 --- a/src/main/java/org/ehrbase/fhirbridge/camel/processor/ITI65Processor.java +++ b/src/main/java/org/ehrbase/fhirbridge/camel/processor/ITI65Processor.java @@ -7,9 +7,12 @@ import org.apache.camel.Processor; import org.ehrbase.fhirbridge.camel.CamelConstants; import org.ehrbase.fhirbridge.fhir.support.Bundles; +import org.ehrbase.fhirbridge.ihe.xds.ITITrace; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.DocumentManifest; +import org.hl7.fhir.r4.model.DocumentReference; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ResourceType; import org.springframework.stereotype.Component; @@ -27,6 +30,7 @@ public class ITI65Processor implements Processor { @Override public void process(Exchange exchange) throws Exception { Bundle bundle = (Bundle) exchange.getIn().getBody(Resource.class); + setSaveInput(exchange, bundle); for(Bundle.BundleEntryComponent entry: bundle.getEntry()){ if(entry.getResource().getResourceType().equals(ResourceType.Binary)){ Binary binary = (Binary) entry.getResource(); @@ -44,4 +48,18 @@ public void process(Exchange exchange) throws Exception { } } } + + private void setSaveInput(Exchange exchange, Bundle bundle) { + DocumentManifest documentManifest = null; // cant be null since fhir profile requires it + DocumentReference documentReference = null; // cant be null since fhir profile requires it + for(Bundle.BundleEntryComponent entry: bundle.getEntry()){ + if(entry.getResource().getResourceType().equals(ResourceType.DocumentManifest)){ + documentManifest = (DocumentManifest) entry.getResource(); + }else if(entry.getResource().getResourceType().equals(ResourceType.DocumentReference)){ + documentReference = (DocumentReference) entry.getResource(); + } + } + ITITrace itiTrace = new ITITrace(documentManifest, documentReference); + exchange.getIn().setHeader("iti65-trace", itiTrace); + } } diff --git a/src/main/java/org/ehrbase/fhirbridge/camel/route/TransactionRouteBuilder.java b/src/main/java/org/ehrbase/fhirbridge/camel/route/TransactionRouteBuilder.java index 2c3bdaa0a..13c9a8ec6 100644 --- a/src/main/java/org/ehrbase/fhirbridge/camel/route/TransactionRouteBuilder.java +++ b/src/main/java/org/ehrbase/fhirbridge/camel/route/TransactionRouteBuilder.java @@ -31,6 +31,7 @@ import org.ehrbase.fhirbridge.fhir.bundle.validator.AntiBodyPanelBundleValidator; import org.ehrbase.fhirbridge.fhir.bundle.validator.BloodGasPanelBundleValidator; import org.ehrbase.fhirbridge.fhir.bundle.validator.DiagnosticReportLabBundleValidator; +import org.ehrbase.fhirbridge.fhir.bundle.validator.Iti65BundleValidator; import org.ehrbase.fhirbridge.fhir.bundle.validator.UCCAppProDatenValidator; import org.ehrbase.fhirbridge.fhir.bundle.validator.UCCSensorDatenValidator; import org.ehrbase.fhirbridge.fhir.bundle.validator.VirologischerBefundBundleValidator; @@ -53,15 +54,24 @@ public class TransactionRouteBuilder extends AbstractRouteBuilder { public void configure() throws Exception { // @formatter:off from("bundle-provide:consumer?fhirContext=#fhirContext") - .setHeader(CamelConstants.PROFILE, method(Bundles.class, "getTransactionProfile")) - .choice() - .when(header(CamelConstants.PROFILE).isEqualTo(Profile.ITI65)) - .bean(ITI65Processor.class) - .choice() - .when(header(CamelConstants.PROFILE).isEqualTo(Optional.empty())) - .to("direct:provideResource") - .process(BundleResponseProcessor.BEAN_ID) + .setHeader(CamelConstants.PROFILE, method(Bundles.class, "getTransactionProfile")) + .choice() + .when(header(CamelConstants.PROFILE).isEqualTo(Profile.ITI65)) + .to("direct:processITI65") .otherwise() + .to("direct:process-bundle"); + + from("direct:processITI65") + .bean(ITI65Processor.class) + .bean(Iti65BundleValidator.class) + .choice() + .when(header(CamelConstants.PROFILE).isEqualTo(Optional.empty())) // If no Bundle is contained within MHD + .to("direct:provideResource") + .process(BundleResponseProcessor.BEAN_ID) + .otherwise() + .to("direct:process-bundle"); + + from("direct:process-bundle") .choice() .when(header(CamelConstants.PROFILE).isEqualTo(Profile.ANTI_BODY_PANEL)) .bean(AntiBodyPanelBundleValidator.class) @@ -71,33 +81,33 @@ public void configure() throws Exception { .bean(BloodGasPanelConverter.class, "convert") .when(header(CamelConstants.PROFILE).isEqualTo(Profile.DIAGNOSTIC_REPORT_LAB)) .bean(DiagnosticReportLabBundleValidator.class) - .bean(DiagnosticReportLabConverter.class,"convert") + .bean(DiagnosticReportLabConverter.class, "convert") .when(header(CamelConstants.PROFILE).isEqualTo(Profile.VIROLOGISCHER_BEFUND)) .bean(VirologischerBefundBundleValidator.class) - .bean(VirologischerBefundConverter.class,"convert") + .bean(VirologischerBefundConverter.class, "convert") .when(header(CamelConstants.PROFILE).isEqualTo(Profile.UCC_SENSORDATEN_STEPS)) .bean(UCCSensorDatenValidator.class) - .bean(UCCSensordatenActivityBundleConverter.class,"convert") + .bean(UCCSensordatenActivityBundleConverter.class, "convert") .when(header(CamelConstants.PROFILE).isEqualTo(Profile.UCC_SENSORDATEN_VITALSIGNS)) .bean(UCCSensorDatenValidator.class) - .bean(UCCSensordatenVitalSignsBundleConverter.class,"convert") + .bean(UCCSensordatenVitalSignsBundleConverter.class, "convert") .when(header(CamelConstants.PROFILE).isEqualTo(Profile.UCC_APP_PRO_DATEN)) .bean(UCCAppProDatenValidator.class) - .bean(UCCAppProDatenBundleConverter.class,"convert") + .bean(UCCAppProDatenBundleConverter.class, "convert") .otherwise() .throwException(new UnprocessableEntityException("Unsupported transaction: provided Bundle should have a resource that " + "uses on of the following profiles: " + Profile.BLOOD_GAS_PANEL.getUri() + ", " + Profile.DIAGNOSTIC_REPORT_LAB.getUri() + ", " + Profile.ANTI_BODY_PANEL.getUri() + - ", " +Profile.VIROLOGISCHER_BEFUND.getUri() + - ", " + Profile.UCC_SENSORDATEN_STEPS.getUri()+ + ", " + Profile.VIROLOGISCHER_BEFUND.getUri() + + ", " + Profile.UCC_SENSORDATEN_STEPS.getUri() + ", " + Profile.UCC_SENSORDATEN_VITALSIGNS.getUri() + ", " + Profile.UCC_APP_PRO_DATEN.getUri() )) - .end() - .to("direct:provideResource") - .process(BundleResponseProcessor.BEAN_ID); + .end() + .to("direct:provideResource") + .process(BundleResponseProcessor.BEAN_ID); // @formatter:on } } diff --git a/src/main/java/org/ehrbase/fhirbridge/config/ihe/xds/XdsConfiguration.java b/src/main/java/org/ehrbase/fhirbridge/config/ihe/xds/XdsConfiguration.java index 275e90e29..4bbaa0991 100644 --- a/src/main/java/org/ehrbase/fhirbridge/config/ihe/xds/XdsConfiguration.java +++ b/src/main/java/org/ehrbase/fhirbridge/config/ihe/xds/XdsConfiguration.java @@ -16,7 +16,7 @@ package org.ehrbase.fhirbridge.config.ihe.xds; -import org.ehrbase.fhirbridge.ihe.xds.Iti41Converter; +import org.ehrbase.fhirbridge.ihe.xds.converter.Iti41Converter; import org.ehrbase.fhirbridge.ihe.xds.XdsRouteBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/ehrbase/fhirbridge/fhir/bundle/validator/Iti65BundleValidator.java b/src/main/java/org/ehrbase/fhirbridge/fhir/bundle/validator/Iti65BundleValidator.java new file mode 100644 index 000000000..ad5a6a46b --- /dev/null +++ b/src/main/java/org/ehrbase/fhirbridge/fhir/bundle/validator/Iti65BundleValidator.java @@ -0,0 +1,34 @@ +package org.ehrbase.fhirbridge.fhir.bundle.validator; + +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.ResourceType; +import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionValidator; + +import java.util.Map; + +public class Iti65BundleValidator implements FhirTransactionValidator { + + @Override + public void validateRequest(Object payload, Map parameters) { + Bundle bundle = (Bundle) payload; + validateDocumentReference(bundle); + } + + private void validateDocumentReference(Bundle bundle) { + int count = 0; + for(Bundle.BundleEntryComponent entry :bundle.getEntry()){ + if(entry.getResource().getResourceType().equals(ResourceType.DocumentReference)){ + count ++; + } + } + if(count>1){ + throw new UnprocessableEntityException("Only one DocumentReference per MHD Bundle is supported!"); + } + } + + @Override + public void validateResponse(Object o, Map map) { + throw new UnsupportedOperationException("Response validation is not supported"); + } +} diff --git a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/ITI41Processor.java b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/ITI41Processor.java new file mode 100644 index 000000000..cf06dd9bf --- /dev/null +++ b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/ITI41Processor.java @@ -0,0 +1,17 @@ +package org.ehrbase.fhirbridge.ihe.xds; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.ehrbase.client.classgenerator.interfaces.CompositionEntity; + +public class ITI41Processor implements Processor { + + public static final String BEAN_ID = "iti41Processor"; + + @Override + public void process(Exchange exchange) throws Exception { + ITITrace iti41Trace = (ITITrace) exchange.getIn().getHeader("iti65-trace"); + iti41Trace.setCompositionEntity((CompositionEntity) exchange.getIn().getBody()); + exchange.getIn().setBody(iti41Trace); + } +} diff --git a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/ITITrace.java b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/ITITrace.java new file mode 100644 index 000000000..89936b230 --- /dev/null +++ b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/ITITrace.java @@ -0,0 +1,34 @@ +package org.ehrbase.fhirbridge.ihe.xds; + +import org.ehrbase.client.classgenerator.interfaces.CompositionEntity; +import org.hl7.fhir.r4.model.DocumentManifest; +import org.hl7.fhir.r4.model.DocumentReference; + +public class ITITrace { + private final DocumentManifest documentManifest; + private final DocumentReference documentReference; + private CompositionEntity compositionEntity; + + public ITITrace(DocumentManifest documentManifest, DocumentReference documentReference) { + this.documentManifest = documentManifest; + this.documentReference = documentReference; + } + + public CompositionEntity getCompositionEntity() { + return compositionEntity; + } + + public void setCompositionEntity(CompositionEntity compositionEntity) { + this.compositionEntity = compositionEntity; + } + + public DocumentManifest getDocumentManifest() { + return documentManifest; + } + + public DocumentReference getDocumentReference() { + return documentReference; + } +} + + diff --git a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/XDSValidator.java b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/XDSValidator.java new file mode 100644 index 000000000..268fe128e --- /dev/null +++ b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/XDSValidator.java @@ -0,0 +1,15 @@ +package org.ehrbase.fhirbridge.ihe.xds; + +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; + +public class XDSValidator implements Processor { + + @Override + public void process(Exchange exchange) throws Exception { + if(exchange.getIn().getHeader("iti65-trace")==null){ + throw new UnprocessableEntityException("ITI 41 is only supported, if the rsource instance was sent via ITI65."); + } + } +} diff --git a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/XdsRouteBuilder.java b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/XdsRouteBuilder.java index d27a835ac..0e49a6865 100644 --- a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/XdsRouteBuilder.java +++ b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/XdsRouteBuilder.java @@ -16,7 +16,13 @@ package org.ehrbase.fhirbridge.ihe.xds; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.util.ObjectHelper; +import org.ehrbase.client.classgenerator.interfaces.CompositionEntity; +import org.ehrbase.client.openehrclient.VersionUid; +import org.ehrbase.fhirbridge.camel.CamelConstants; +import org.ehrbase.fhirbridge.ehr.converter.ConversionException; import org.openehealth.ipf.commons.ihe.xds.core.requests.ProvideAndRegisterDocumentSet; /** @@ -31,11 +37,23 @@ public void configure() throws Exception { errorHandler(defaultErrorHandler().logExhaustedMessageHistory(false)); from("direct:send-to-cdr") - .routeId("sendToXdsCdr") - .setProperty("fhir_resource").body() - .convertBodyTo(ProvideAndRegisterDocumentSet.class) - .to("xds-iti41://{{fhir-bridge.xds.hostname}}:{{fhir-bridge.xds.port}}{{fhir-bridge.xds.context-path}}") - .setBody().exchangeProperty("fhir_resource"); + .routeId("sendToXdsCdr") + .bean(XDSValidator.class) + .doTry() + .to("bean:fhirResourceConversionService?method=convert(${headers.CamelFhirBridgeProfile}, ${body})") + .doCatch(ConversionException.class) + .throwException(UnprocessableEntityException.class, "${exception.message}") + .end() + .process(exchange -> { + if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(CamelConstants.COMPOSITION_ID))) { + String compositionId = exchange.getIn().getHeader(CamelConstants.COMPOSITION_ID, String.class); + exchange.getIn().getBody(CompositionEntity.class).setVersionUid(new VersionUid(compositionId)); + } + }) + .bean(ITI41Processor.class) + .convertBodyTo(ProvideAndRegisterDocumentSet.class) + .to("xds-iti41://{{fhir-bridge.xds.hostname}}:{{fhir-bridge.xds.port}}{{fhir-bridge.xds.context-path}}") + .setBody().exchangeProperty("fhir_resource"); // @formatter:on } } diff --git a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/DocumentConverter.java b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/DocumentConverter.java new file mode 100644 index 000000000..65b86ad07 --- /dev/null +++ b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/DocumentConverter.java @@ -0,0 +1,143 @@ +package org.ehrbase.fhirbridge.ihe.xds.converter; + +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import com.nedap.archie.rm.RMObject; +import com.nedap.archie.rm.composition.Composition; +import com.sun.istack.ByteArrayDataSource; +import org.apache.commons.codec.binary.Base64; +import org.ehrbase.client.classgenerator.interfaces.CompositionEntity; +import org.ehrbase.client.flattener.Unflattener; +import org.ehrbase.fhirbridge.ehr.ResourceTemplateProvider; +import org.ehrbase.serialisation.flatencoding.FlatFormat; +import org.ehrbase.serialisation.flatencoding.FlatJasonProvider; +import org.ehrbase.serialisation.jsonencoding.CanonicalJson; +import org.hl7.fhir.r4.model.Attachment; +import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.DocumentReference; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Code; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Document; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.DocumentEntry; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Identifiable; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.LocalizedString; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.PatientInfo; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Timestamp; + +import javax.activation.DataHandler; +import java.nio.charset.StandardCharsets; +import java.util.List; + +public class DocumentConverter { + + public static List convert(DocumentReference documentReference, CompositionEntity compositionEntity) { + Document document = new Document(); + document.setDocumentEntry(getDocumentEntry(documentReference)); + document.setDataHandler(getDataHandler(compositionEntity)); + return List.of(document); + } + + private static DataHandler getDataHandler(CompositionEntity compositionEntity) { + byte[] encodedBytes = Base64.encodeBase64(getFlattenedJson(compositionEntity).getBytes(StandardCharsets.UTF_8)); + ByteArrayDataSource compositionInBytes = new ByteArrayDataSource(encodedBytes, "application/xml"); + return new DataHandler(compositionInBytes); + } + + private static String getFlattenedJson(CompositionEntity compositionEntity) { + ResourceTemplateProvider resourceTemplateProvider = new ResourceTemplateProvider("classpath:/opt/"); + resourceTemplateProvider.afterPropertiesSet(); + Unflattener unflattener = new Unflattener(resourceTemplateProvider); + RMObject rmObject = unflattener.unflatten(compositionEntity); + CanonicalJson canonicalJson = new CanonicalJson(); + String compositionJson = canonicalJson.marshal(rmObject); //super dump but currently i dont see any other way + Composition composition = canonicalJson.unmarshal(compositionJson); + if(composition.getArchetypeDetails().getTemplateId() == null){ + throw new UnprocessableEntityException("No Template id could be found within the composition, therefore base64 is not possible"); + } + return new FlatJasonProvider(resourceTemplateProvider) + .buildFlatJson(FlatFormat.SIM_SDT, composition.getArchetypeDetails().getTemplateId().toString()) + .marshal(rmObject); + } + + private static DocumentEntry getDocumentEntry(DocumentReference documentReference) { + DocumentEntry documentEntry = new DocumentEntry(); + documentEntry.setUniqueId(documentReference.getIdentifier().get(0).getId()); + documentEntry.setTypeCode(getTypeCode(documentReference)); + documentEntry.setClassCode(getClassCode(documentReference)); + documentEntry.setPatientId(new Identifiable(documentReference.getSubject().getReference())); + documentEntry.getConfidentialityCodes().add(getConfidentialityCode(documentReference)); + documentEntry.setMimeType("application/xml"); + setDataFromContent(documentEntry, documentReference); + // documentEntry.setFormatCode(new Code(documentReference.getFo)); + setEventCodeList(documentEntry, documentReference); + return documentEntry; + } + + private static void setEventCodeList(DocumentEntry documentEntry, DocumentReference documentReference) { + setEventCodes(documentEntry, documentReference); + setFacilityTypeCode(documentEntry, documentReference); + setPracticeSettingCode(documentEntry, documentReference); + setSourcePatientId(documentEntry, documentReference); + } + + private static void setSourcePatientId(DocumentEntry documentEntry, DocumentReference documentReference) { + PatientInfo patientInfo = new PatientInfo(); + patientInfo.getIds().add(new Identifiable(documentReference.getContext().getSourcePatientInfo().getReference())); + documentEntry.setSourcePatientInfo(patientInfo); + } + + private static void setPracticeSettingCode(DocumentEntry documentEntry, DocumentReference documentReference) { + for(Coding coding : documentReference.getContext().getPracticeSetting().getCoding()){ + documentEntry.getEventCodeList().add(codingToCode(coding)); + } + } + + private static void setFacilityTypeCode(DocumentEntry documentEntry, DocumentReference documentReference) { + for(Coding coding : documentReference.getContext().getFacilityType().getCoding()){ + documentEntry.getEventCodeList().add(codingToCode(coding)); + } + } + + private static void setEventCodes(DocumentEntry documentEntry, DocumentReference documentReference) { + for(CodeableConcept event : documentReference.getContext().getEvent()){ + for(Coding coding : event.getCoding()){ + documentEntry.getEventCodeList().add(codingToCode(coding)); + } + } + } + + private static void setDataFromContent(DocumentEntry documentEntry, DocumentReference documentReference) { + Attachment content = documentReference.getContent().get(0).getAttachment(); + documentEntry.setLanguageCode(content.getLanguage()); + documentEntry.setTitle(new LocalizedString(content.getTitle(), content.getLanguage(), "UTF-8")); + Timestamp timestamp = new Timestamp(); + timestamp.setDateTime(content.getCreationElement().getValueAsCalendar().toZonedDateTime()); + documentEntry.setCreationTime(timestamp); + } + + private static Code getConfidentialityCode(DocumentReference documentReference) { + Coding coding = documentReference.getSecurityLabel().get(0).getCoding().get(0); + return new Code(coding.getCode(), new LocalizedString(coding.getDisplay()), coding.getSystem()); + } + + private static Code getTypeCode(DocumentReference documentReference) { + Coding coding = documentReference.getType().getCoding().get(0); + return new Code(coding.getCode(), new LocalizedString(coding.getDisplay()), coding.getSystem()); + } + + private static Code getClassCode(DocumentReference documentReference) { + Coding coding = documentReference.getCategory().get(0).getCoding().get(0); + return new Code(coding.getCode(), new LocalizedString(coding.getDisplay()), coding.getSystem()); + } + + private static Code codingToCode(Coding coding){ + Code code = new Code(); + code.setCode(coding.getCode()); + LocalizedString display = new LocalizedString(); + display.setLang("de-DE"); + display.setCharset("UTF-8"); + display.setValue(coding.getDisplay()); + code.setDisplayName(display); + code.setSchemeName(code.getSchemeName()); + return code; + } +} diff --git a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/Iti41Converter.java b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/Iti41Converter.java similarity index 58% rename from src/main/java/org/ehrbase/fhirbridge/ihe/xds/Iti41Converter.java rename to src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/Iti41Converter.java index 870a4bcd9..71e5878a7 100644 --- a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/Iti41Converter.java +++ b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/Iti41Converter.java @@ -14,48 +14,40 @@ * limitations under the License. */ -package org.ehrbase.fhirbridge.ihe.xds; +package org.ehrbase.fhirbridge.ihe.xds.converter; +import org.ehrbase.fhirbridge.ihe.xds.ITITrace; import org.openehealth.ipf.commons.ihe.xds.core.metadata.Association; import org.openehealth.ipf.commons.ihe.xds.core.metadata.Document; -import org.openehealth.ipf.commons.ihe.xds.core.metadata.DocumentEntry; import org.openehealth.ipf.commons.ihe.xds.core.metadata.Folder; import org.openehealth.ipf.commons.ihe.xds.core.metadata.SubmissionSet; -import org.openehealth.ipf.commons.ihe.xds.core.metadata.Timestamp; import org.openehealth.ipf.commons.ihe.xds.core.requests.ProvideAndRegisterDocumentSet; import org.openehealth.ipf.commons.ihe.xds.core.requests.builder.ProvideAndRegisterDocumentSetBuilder; import org.springframework.core.convert.converter.Converter; import org.springframework.lang.NonNull; -import javax.activation.DataHandler; -import java.time.OffsetDateTime; +import javax.xml.bind.JAXB; +import java.io.StringWriter; import java.util.List; /** * @author Renaud Subiger * @since 1.6 */ -// TODO: Check with @SevKohler, if the Exchange is required here. If yes, use TypeConverter from Camel -public class Iti41Converter implements Converter { +public class Iti41Converter implements Converter { @Override - public ProvideAndRegisterDocumentSet convert(@NonNull Object composition) { - SubmissionSet submissionSet = getSumissionSet(); + public ProvideAndRegisterDocumentSet convert(@NonNull ITITrace itiTrace) { + SubmissionSet submissionSet = SubmissionSetConverter.convert(itiTrace.getDocumentManifest()); List folders = getFolders(); - List documents = getDocuments(composition); - List< Association > associations = getAssociations(); + List documents = DocumentConverter.convert(itiTrace.getDocumentReference(), itiTrace.getCompositionEntity()); + List associations = getAssociations(); ProvideAndRegisterDocumentSetBuilder provideAndRegisterDocumentSetBuilder = new ProvideAndRegisterDocumentSetBuilder(true, new SubmissionSet()); ProvideAndRegisterDocumentSet provideAndRegisterDocumentSet = provideAndRegisterDocumentSetBuilder.doBuild(submissionSet, folders, documents, associations); + StringWriter sw = new StringWriter(); + JAXB.marshal(provideAndRegisterDocumentSet, sw); + System.out.println("HIER: "+sw.toString()); return provideAndRegisterDocumentSet; - - } - - private SubmissionSet getSumissionSet() { - SubmissionSet submissionSet = new SubmissionSet(); - Timestamp timestamp =new Timestamp(); - timestamp.setDateTime(OffsetDateTime.now().toZonedDateTime()); - submissionSet.setSubmissionTime(timestamp); - return submissionSet; } private List getAssociations() { @@ -63,17 +55,12 @@ private List getAssociations() { return List.of(association); } - private List getDocuments(Object source) { - Document document = new Document(); - DataHandler dataHandler = new DataHandler(source, "application/json"); - DocumentEntry documentEntry = new DocumentEntry(); - document.setDataHandler(dataHandler); - // document.setDocumentEntry(); - return List.of(document); - } - private List getFolders() { Folder folder = new Folder(); return List.of(folder); } } + +/* + + */ \ No newline at end of file diff --git a/src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/SubmissionSetConverter.java b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/SubmissionSetConverter.java new file mode 100644 index 000000000..c00d05db0 --- /dev/null +++ b/src/main/java/org/ehrbase/fhirbridge/ihe/xds/converter/SubmissionSetConverter.java @@ -0,0 +1,73 @@ +package org.ehrbase.fhirbridge.ihe.xds.converter; + +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.DocumentManifest; +import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.Reference; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Author; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Code; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Identifiable; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.LocalizedString; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Person; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.SubmissionSet; +import org.openehealth.ipf.commons.ihe.xds.core.metadata.Timestamp; + +import java.time.OffsetDateTime; +import java.util.List; +import java.util.Optional; + +public class SubmissionSetConverter { + + public static SubmissionSet convert(DocumentManifest documentManifest) { + SubmissionSet submissionSet = new SubmissionSet(); + Timestamp timestamp = new Timestamp(); + timestamp.setDateTime(OffsetDateTime.now().toZonedDateTime()); + submissionSet.setSubmissionTime(timestamp); + submissionSet.setAuthor(getAuthor(documentManifest.getAuthor())); + submissionSet.setUniqueId(documentManifest.getMasterIdentifier().getId()); + submissionSet.setEntryUuid(documentManifest.getIdentifier().get(0).getValue()); + submissionSet.setSourceId(documentManifest.getSource()); + submissionSet.setContentTypeCode(getContentType(documentManifest)); + submissionSet.setPatientId(new Identifiable(documentManifest.getSubject().getReference())); + return submissionSet; + } + + private static Code getContentType(DocumentManifest documentManifest) { + Coding coding = documentManifest.getType().getCoding().get(0); + return new Code(coding.getCode(), new LocalizedString(coding.getDisplay()), coding.getSystem()); + } + + private static Author getAuthor(List authors) { + for (Reference authorEntry : authors) { + Author author = new Author(); + authorEntry.getResource(); + author.setAuthorPerson(getPerson(authorEntry)); + return author; + } + throw new UnprocessableEntityException("no Author was defined in the MHD Bundle"); + } + + private static Person getPerson(Reference authorEntry) { + if (authorEntry.getResource().getClass().equals(PractitionerRole.class)) { + PractitionerRole practitionerRole = (PractitionerRole) authorEntry.getResource(); + Person person = new Person(); + Optional id = practitionerRole.getCode().stream().filter(CodeableConcept::hasCoding) + .flatMap(codeableConcept -> codeableConcept.getCoding().stream()) + .map(Coding::getCode) + .findFirst(); +/* Optional name = practitionerRole.getCode().stream().filter(CodeableConcept::hasCoding) + .flatMap(codeableConcept -> codeableConcept.getCoding().stream()) + .map(Coding::getDisplay) + .findFirst(); + person.setName(new Name(name.get()));*/ + person.setId(new Identifiable(id.get())); //Always present + return person; + } else { + throw new UnprocessableEntityException("Only PractionerRole is currently supported for DocumentManifest Author"); + } + } + + +}