/cda2fhir

CDA to FHIR Transformer Library

Primary LanguageJavaApache License 2.0Apache-2.0

cda2fhir

License Info Jenkins CI

cda2fhir is a Java library to transform HL7 CDA R2 instances to HL7 FHIR resources. More specifically, cda2fhir enables automatic transformation of Consolidated CDA (C-CDA) Release 2.1 compliant document instances to the corresponding FHIR STU3 resources. For this purpose, cda2fhir provides extensible document transformers, resource transformers, data type transformers and value set transformers. The current implementation provides a document transformer for Continuity of Care Document (CCD), but further document transformers, e.g. for Discharge Summary or Referral Note, can be easily introduced by reusing the already existing section and entry transformers. Although the cda2fhir library expects C-CDA R2.1 compliant documents/entries, it has been tested as well with several older document instances compliant with earlier releases of C-CDA. The HAPI FHIR Validator is also integrated for automated validation of the generated FHIR resources.

All the mappings implemented between CDA artifacts and FHIR resources, data types and value sets are documented in this sheet: CDA to STU3 Mapping

Model Driven Health Tools (MDHT) is used for CDA manipulation and HAPI is used for FHIR manipulation. The current implementation produces STU3 resources.

Installation

Apache Maven is required to build cda2fhir. Please visit http://maven.apache.org/ in order to install Maven on your system.

Under the root directory of the cda2fhir project run the following:

$ cda2fhir> mvn install

In order to make a clean install run the following:

$ cda2fhir> mvn clean install

These will build the cda2fhir library and also run a number of test cases, which will transform some C-CDA Continuity of Care Document (CCD) instances, and some manually crafted CDA artifacts (e.g. entry class instances) and datatype instances to corresponding FHIR resources, wherever possible using the DAF profile.

This project incrementally builds and releases files for use in maven projects, using the instructions provided here. To use, add the repository and dependency to your pom.xml like so, replacing the X.Y.Z with a version number.

<repository>
  <id>amida-github</id>
  <name>github</name>
  <url>https://github.com/amida-tech/cda2fhir/raw/release</url>
</repository>
...
<dependency> 
  <artifactId>cda2fhir</artifactId>
  <groupId>tr.com.srdc</groupId>
  <version>X.Y.Z</version>	        
</dependency>

Transforming a CDA document to a Bundle of corresponding FHIR resources

// Load MDHT CDA packages. Otherwise ContinuityOfCareDocument and similar documents will not be recognised.
// This has to be called before loading the document; otherwise will have no effect.
CDAUtil.loadPackages();

// Read a Continuity of Care Document (CCD) instance, which is the official sample CCD instance
// distributed with C-CDA 2.1 specs, with a few extensions for having a more complete document
FileInputStream fis = new FileInputStream("src/test/resources/C-CDA_R2-1_CCD.xml");
ClinicalDocument cda = CDAUtil.load(fis);

// Init an object of CCDTransformerImpl class, which implements the generic ICDATransformer interface.
// FHIR resource id generator can be either an incremental counter, or a UUID generator.
// The default is UUID; here it is set as COUNTER.
ICDATransformer ccdTransformer = new CCDTransformerImpl(IdGeneratorEnum.COUNTER);

// By default, FHIR DSTU2 resources are generated by setting the appropriate DAF profile URLs
// in meta.profile attribute of resources. This is configurable through the statically (i.e. globally)
// managed Config class, and can be turned on or off.
Config.setGenerateDafProfileMetadata(true);

// By default, html formatted narratives are generated in text.div attributes of FHIR DSTU2 resources,
// thanks to the automated narrative generation capability of HAPI that is enabled via thymeleaf library.
// This is configurable through the statically managed Config class, and can be turned on or off.
Config.setGenerateNarrative(true);

// Finally, the CCD document instance is transformed to a FHIR Bundle, where the first entry is
// the Composition corresponding to the ClinicalDocument, and further entries are the ones referenced
// from the Composition.
Bundle bundle = ccdTransformer.transformDocument(cda);

// Through HAPI library, the Bundle can easily be printed in JSON or XML format.
FHIRUtil.printJSON(bundle, "src/test/resources/output/C-CDA_R2-1_CCD-w-daf.json");

Further code examples can be found in CCDTransformerTest class. The outcome of the above transformation operation for the CCD instance available in the C-CDA 2.1 specification is available here: https://github.com/srdc/cda2fhir/blob/master/src/test/resources/C-CDA_R2-1_CCD-w-daf.json

Transforming a CDA artifact (e.g. an entry class) to the corresponding FHIR resource(s)

// Init an object of ResourceTransformerImpl class, which implements the IResourceTransformer
// interface. When instantiated separately from the CDATransformer context, FHIR resources are
// generated with UUID ids, and a default patient reference is added as "Patient/0"
IResourceTransformer resTransformer = new ResourceTransformerImpl();

// Configuration of DAF profile URL creation in meta.profile and narrative generation in text.div is
// again configurable through the statically managed Config class.
Config.setGenerateDafProfileMetadata(true);
Config.setGenerateNarrative(false);

// Assume we already have a CCD instance in the ccd object below (skipping CDA artifact creation from scratch)
// Traverse all the sections of the CCD instance
for(Section cdaSec: ccd.getSections()) {
    // Transform a CDA section to a FHIR Composition.Section backbone resource
    Composition.Section fhirSec = resTransformer.tSection2Section(cdaSec);

    // if a CDA section is instance of a Family History Section (as identified through its templateId)
    if(cdaSec instanceof FamilyHistorySection) {
        // cast the section to FamilyHistorySection
        FamilyHistorySection famSec = (FamilyHistorySection) cdaSec;
        // traverse the Family History Organizers within the Family History Section
        for(FamilyHistoryOrganizer fhOrganizer : famSec.getFamilyHistories()) {
            // Transform each C-CDA FamilyHistoryOrganizer instance to FHIR (DAF) FamilyMemberHistory instance
            FamilyMemberHistory fmh = resTransformer.tFamilyHistoryOrganizer2FamilyMemberHistory(fhOrganizer);
        }
    }
}

// Again, any FHIR resource can be printed through FHIRUtil methods.
FHIRUtil.printXML(fmh, "src/test/resources/output/family-member-history.xml");

It should be noted that most of the time, IResourceTransformer methods return a FHIR Bundle composed of a few FHIR resources, instead of a single FHIR resource as in the example above. For example, tProblemObservation2Condition method returns a Bundle that contains the corresponding Condition as the first entry, which can also include other referenced resources such as Encounter, Practitioner.

Further examples can be found in ResourceTransformerTest class and CCDTransformerImpl class.

Validating generated FHIR resources

We have also integrated the HAPI FHIR Validator and have implemented a wrapper interface and a class on top of this validator: IValidator and ValidatorImpl. A resource can be validated individually, or a Bundle containing several resources as in the case of CDA transformation outcome can be validated at once. When (DAF) profile metadata is provided within the resources' meta.profile attribute, validation takes into account this profile as well. Validation outcome is provided as HTML within an OutputStream.

// Init an object of ValidatorImpl class, which implements the IValidator interface.
IValidator validator = new ValidatorImpl();

// Assume we already have a Bundle object to be validated at hand. Call the validateBundle method
// of the validator and get the validation outcome as HTML in a ByteArrayOutputStream.
ByteArrayOutputStream valOutcomeOs = (ByteArrayOutputStream) validator.validateBundle(bundle);

// The HTML can be printed to a file.
FileOutputStream fos = new FileOutputStream(new File("src/test/resources/output/validation-result-w-profile-for-C-CDA_R2-1_CCD.html"));
valOutcomeOs.writeTo(fos);

// Close the streams
valOutcomeOs.close();
fos.close();

Further examples can be found in ValidatorTest class

Jolt Based Tests and Automated Field Mapping

An extensive set of testing is provided based on Jolt templates. In essence the field mapping accomplished in Java code is replicated in Jolt templates. Jolt templates are located here. The tests based on Jolt templates are located here and make sure results generated by cda2fhir are in sync with Jolt templates.

Based on Jolt templates we generate reports that detail CDA field to FHIR field mapping. Currently these reports reside in test gold files in which a README is provided. A stand alone report generating unit test is part of our testing suite and can be used to generate all the reports to the output directory.

Acknowledgement

This research has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement No 689181, C3-Cloud Project (A Federated Collaborative Care Cure Cloud Architecture for Addressing the Needs of Multi-morbidity and Managing Poly-pharmacy).

This research has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement No 689444, POWER2DM Project (Predictive model-based decision support for diabetes patient empowerment).