HL7v4 FHIR notes

Russell Bateman
February 2020
last update:



Links


FHIR Patient resource

This is mostly for illustration and the legend that follows it.. I don't remember what version this was (probably DSTU3). For the latest version you should look at check out 8.1 Resource Patient - Content and scroll down.

FHIR Resource icons legend


Structure:

(folder icon) subsumes other resources including containers, complex resources and simple primitive data types.
(cube icon) defines a complex resource (that's a leaf node).
(rectangle icon) indicates a simple primitive data type like a Date or a simple code (a string identifier like "male").
(question-mark) is often ontological (like "is deceased").
(link) a reference that will turn up as an identifier in a (usually substantial) resource that's to be associated.

Flags:

Summary
Modifier, unsafe to ignore
Invariants, rules apply
Normative, content stable and locked

Cardinality signals whether and how many of something is mandatory. For example above , a patient may have zero or infinite identifiers associated with his record.

The Type given is usually a hyperlink you can click on that will take you to a page where the type of the resource for a patient is detailed.


The FHIR validator

The official FHIR validator is a useful JAR whose usage is explained at this hyperlink. The JAR is available at this link. All the details on use, and they are numerous and confusing, are available from that page. The validator JAR can be easily made accessible from the command line thus:

#!/bin/sh
if [ "$1" = "--help" ]; then
  echo "Usage: $0  [-output ]"
	exit 0
fi
VALIDATOR_PATH="/home/russ/dev/fhir-validator/validator_cli.jar"
java -jar $VALIDATOR_PATH -version 4.0 $*

Use is this way:

~/bin $ ./fhir-validator.sh --help
Usage: ./fhir-validator.sh  [-output ]
~/bin $ fhir-validator.sh FHIR-document validator-output
FHIR Validation tool Version 5.1.17 (Git# 44f7dca1c794). Built 2020-10-14T20:04:32.293Z (11 days old)
  Java:   1.8.0_265 from /usr/lib/jvm/java-8-openjdk-amd64/jre on amd64 (64bit). 3538MB available
  Paths:  Current = /home/russ/bin, Package Cache = /home/russ/.fhir/packages
  Params: -version 4.0 mds-extract
Loading
  Load FHIR v4.0 from hl7.fhir.r4.core#4.0.1 - 4575 resources (00:04.0220)
  Terminology server http://tx.fhir.org - Version 1.0.362 (00:01.0186)
  Get set...  go (00:00.0003)
Validating
  Validate mds-extract   ..Detect format for mds-extract
.
.
.

Some beginning steps...

Here are the Maven dependencies for the code about to come. (This isn't the whole pom.xml.) This was the latest version of HAPI-FHIR at the time I wrote this. In particular, I'm guided by HAPI-FHIR Documentation, specifically, the link Parsing and Serializing. All this HAPI-FHIR software was written by or under the ægis of James Agnew—huge kudos to him.

pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <properties>
    <hapi-fhir.version>4.2.0</hapi-fhir.version>
  </properties>

  <dependency>
    <groupId>ca.uhn.hapi.fhir</groupId>
    <artifactId>hapi-fhir-base</artifactId>
    <version>${hapi-fhir.version}</version>
  </dependency>
  <dependency>
    <groupId>ca.uhn.hapi.fhir</groupId>
    <artifactId>hapi-fhir-structures-dstu3</artifactId>
    <version>${hapi-fhir.version}</version>
  </dependency>
</project>
FhirContextTest.java:
package com.windofkeltia.fhir;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
import org.hl7.fhir.dstu3.model.Patient;

import com.windofkeltia.utilities.TestUtilities;

/**
 * Prime this pump: figure out how HAPI FHIR works from our direction: usually, consumers are,
 * unlike us, interested in the client-side or in FHIR servers set up to validate what they
 * produce. We're not here to produce FHIR (XML or JSON), but to parse it and turn it into
 * a meta- or interlingua for a search engine (not shown here).
 *
 * @author Russell Bateman
 * @since February 2020
 */
public class FhirContextTest
{
  // @formatter:off
  @Rule   public TestName name = new TestName();
  @Before public void setUp()  { TestUtilities.setUp( name ); }
  @After  public void tearDown() { }

  private static boolean VERBOSE = true;//TestUtilities.VERBOSE;

  /**
   * The purpose of this case is only to demonstrate the client side of things a little bit
   * (see {@link FhirContextTest} documentation), which isn't what interests us, but doing
   * this does give us an easy way to come up with the XML for a Patient. We could also
   * generate the JSON for a sample Patient. Whatever we made in here, we could use in one
   * of the more germane tests below.
   */
  @Ignore
  @Test
  public void testXmlSerialization()
  {
    FhirContext context = FhirContext.forDstu3();
    IParser     parser  = context.newXmlParser().setPrettyPrint( true );
    Patient     patient = new Patient();
    patient.addName().setFamily( "Simpson" ).addGiven( "James" );
    String serialized = parser.encodeResourceToString( patient );
    System.out.println( "  Patient (serialized):\n" + serialized );
  }

  @Test
  public void testXml()
  {
    FhirContext  context = FhirContext.forDstu3();
    final String INPUT   = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
                    + "<Patient xmlns=\"http://hl7.org/fhir\">\n"
                    + "  <name>\n"
                    + "    <family value=\"Simpson\" />\n"
                    + "    <given value=\"James\" />\n"
                    + "  </name>\n"
                    + "</Patient>";

    if( VERBOSE )
      System.out.println( "  Input:\n" + INPUT );

    IParser parser  = context.newXmlParser();
    Patient patient = parser.parseResource( Patient.class, INPUT );

    if( VERBOSE )
    {
      System.out.print(   "  " + patient.getName().get( 0 ).getFamily() );
      System.out.println( ", " + patient.getName().get( 0 ).getGiven() );
    }
  }

  @Test
  public void testJson()
  {
    FhirContext  context = FhirContext.forDstu3();
    final String INPUT   = "{"
                    + "  \"resourceType\" : \"Patient\","
                    + "  \"name\" :"
                    + "  ["
                    + "    {"
                    + "      \"family\": \"Simpson\""
                    + "    }"
                    + "  ]"
                    + "}";

    if( VERBOSE )
      System.out.println( "  Input:\n  " + INPUT );

    IParser parser  = context.newJsonParser();
    Patient patient = parser.parseResource( Patient.class, INPUT );

    if( VERBOSE )
    {
      System.out.print(   "  " + patient.getName().get( 0 ).getFamily() );
      System.out.println( ", " + patient.getName().get( 0 ).getGiven() );
    }
  }

  /**
   * Start out in XML, but switch to JSON for output (serialization).
   */
  @Test
  public void testXmlToJson()
  {
    FhirContext  context = FhirContext.forDstu3();
    final String INPUT   = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
                    + "<Patient xmlns=\"http://hl7.org/fhir\">"
                    + "  <name>"
                    + "    <family value=\"Simpson\" />"
                    + "    <given value=\"James\" />"
                    + "  </name>"
                    + "</Patient>";

    if( VERBOSE )
      System.out.println( "  Input:\n" + INPUT );

    IParser parser    = context.newXmlParser();
    Patient patient   = parser.parseResource( Patient.class, INPUT );
    parser            = context.newJsonParser().setPrettyPrint( true );
    String serialized = parser.encodeResourceToString( patient );

    if( VERBOSE )
      System.out.println( " Pretty-printed JSON output:\n" + serialized );
  }
}

Sample output from these tests

Test: testXml ----------------------------------------------------------------------------------
[main] INFO ca.uhn.fhir.util.VersionUtil - HAPI FHIR version 4.2.0 - Rev 8491707942
[main] INFO ca.uhn.fhir.context.FhirContext - Creating new FHIR context for FHIR version [DSTU3]
  Input:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Patient xmlns="http://hl7.org/fhir">
  <name>
    <family value="Simpson"/>
    <given value="James"/>
  </name>
</Patient>
  Simpson, [James]
Test: testJson ---------------------------------------------------------------------------------
[main] INFO ca.uhn.fhir.context.FhirContext - Creating new FHIR context for FHIR version [DSTU3]
  Input:
  {  "resourceType" : "Patient",  "name" :  [    {      "family": "Simpson"    }  ]}
  Simpson, []
Test: testXmlToJson ----------------------------------------------------------------------------
[main] INFO ca.uhn.fhir.context.FhirContext - Creating new FHIR context for FHIR version [DSTU3]
  Input:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><Patient xmlns="http://hl7.org/fhir"><name><family value="Simpson"/><given value="James"/></name></Patient>
  Pretty-printed JSON output:
{
  "resourceType": "Patient",
  "name": [
    {
      "family": "Simpson",
      "given": [
        "James"
      ]
    }
  ]
}