Consume CDA Content using MDHT API

Someone sends standard compliance document and you need to extract data and save to the system. You can use the MDHT API’s to extract specific information.

The first step in reading a CDA document is to initialize the runtime environment. MDHT extends the Eclipse Modeling Framework (EMF) XML serialization which enables the system to properly identify the appropriate Java classes to instantiate. So the first step is to let the system know which CDA runtime environments to use when opening the CDA XML document.

  1. Initialize Runtime Environment You can either implicitly or explicitly initialize the environment
    • Implicit Initialization uses the available CDA runtime in the class path and runs the initialzation code. This is the preffered approach to initializing the environment.

      // Implicit initialization
      CDAUtil.loadPackages();
                              
    • Explicit Initialization invokes the appropriate initialization using the corresponding ECore package for the CDA runtime

      // Explicit initialization
      CCDPackage.eINSTANCE.eClass();
                              
      Note: This line of code initializes the CCDPackage instance as well as its dependencies (e.g. CDA, HL7 Datatypes, etc.) In order to use another CDA runtime packages such as IHE or Consolidated, you will need to have a corresponding line for each. This option should be used when you want to control what is available at runtime.

Then we use the CDAUtil class to read the document in from a Java input stream. In this case, we are reading the SampleCCDDocument.xml file that comes with the CCD specification.

  1. Load CDA Document
    // load sample continuity of care document from file
    ContinuityOfCareDocument ccdDocument = (ContinuityOfCareDocument) CDAUtil.load(new FileInputStream("resources/SampleCCDDocument.xml"));
                        
    We can downcast to ContinuityOfCareDocument because we expect that type to be returned (as opposed to a generic instance of the ClinicalDocument class).

The domain-specific API that is generated contains getter methods for section and entry-level templates based on associations in the model. In the CCD model, we have an association between the ContinuityOfCareDocument class and the AlertsSection. Therefore a “getter” method is generated named getAlertsSection.

  1. Get Alerts Sections from Document
    // get the alerts section from the document using domain-specific "getter" method
    AlertsSection alertsSection = ccdDocument.getAlertsSection();
                        
    The method is a “query” method in that it is read-only and implemented using OCL.

The domain-specific method getProblemActs returns all Acts that are also ProblemActs per the CCD model. We want to loop through these problem acts and process their subordinate observation entries. Due to the structure of the CCD model, we do not have a method named getAlertObservation though this could be implemented manually at design-time. Instead we must iterate over all entry relationships and check to see which ones are Alert Observations using the Java instanceof operator.

  1. Get Problem Acts
    // for each enclosing problem act
    for (ProblemAct problemAct : alertsSection.getProblemActs()) {
        // look at subordinate observations
        //     we don't have a domain-specific "getter" method here so we use
        //     entry relationship
        for (EntryRelationship entryRelationship : problemAct.getEntryRelationships()) {
            // check for alert observation
            if (entryRelationship.getObservation() instanceof AlertObservation) {
                AlertObservation alertObservation = (AlertObservation) entryRelationship.getObservation();
                if (!alertObservation.getValues().isEmpty() & alertObservation.getValues().get(0) instanceof CD) {
                    CD value = (CD) alertObservation.getValues().get(0);
                    System.out.println("alert observation value: " + value.getCode() + ", " + value.getCodeSystem() + ", " + value.getDisplayName());
                }
            }
        }
    }
                        
    Once we have found an Alert Observation instance, we print the value out to the console. The values list is type ANY so it is appropriate to check to make sure it is non-empty and conforms to the correct CD data type. This allows us to downcast and access CD methods (e.g. getCode).

We can use a domain-specific method named getReactionObservations to get the reaction observations from an alert observation. Iterating over the reaction observations, we process the value ensuring that we test for non-empty and the expected data type (CD).

  1. Getting Reaction Observations
    // get reaction observations using domain-specific "getter" method
    for (ReactionObservation reactionObservation : alertObservation.getReactionObservations()) {
        if (!reactionObservation.getValues().isEmpty() & alertObservation.getValues().get(0) instanceof CD) {
            CD value = (CD) reactionObservation.getValues().get(0);
            System.out.println("reaction observation value: " + value.getCode() + ", " + value.getCodeSystem() + ", " + value.getDisplayName());
    }
                            
                        

We can use getAlertStatusObservation to get the current status of the allergy. This follows a similar pattern to the reaction observation example

  1. Getting Alert Status Observations
     
    // get alert status observation using domain-specific "getter" method
    AlertStatusObservation alertStatusObservation = alertObservation.getAlertStatusObservation();
    if (alertStatusObservation != null & !alertStatusObservation.getValues().isEmpty() 
        & alertObservation.getValues().get(0) instanceof CD) {
        CD value = (CD) alertStatusObservation.getValues().get(0);
        System.out.println("alert status observation value: " + value.getCode() + ", " + value.getCodeSystem() + ", " + value.getDisplayName());
    }