Every resource type defined by FHIR has a corresponding class, which contains a number of getters and setters for the basic properties of that resource.

HAPI tries to make populating objects easier, by providing lots of convenience methods. For example, the Observation resource has an "issued" property which is of the FHIR "instant" type (a system time with either seconds or milliseconds precision). There are methods to use the actual FHIR datatype, but also convenience methods which use built-in Java types.

      Observation obs = new Observation();

      // These are all equivalent
      obs.setIssued(new InstantDt(new Date()));
      obs.setIssued(new Date(), TemporalPrecisionEnum.MILLI);
      obs.setIssuedWithMillisPrecision(new Date());

      // The InstantDt also lets you work with the instant as a Java Date
      // object or as a FHIR String.
      Date date = obs.getIssuedElement().getValue(); // A date object
      String dateString = obs.getIssuedElement().getValueAsString(); // "2014-03-08T12:59:58.068-05:00"

Most HAPI structures provide getters that automatically create child objects on access. This means it is simple to navigate complex structures without needing to worry about instantiating child objects.

      Observation observation = new Observation();

      // None of these calls will not return null, but instead create their
      // respective
      // child elements.
      List<IdentifierDt> identifierList = observation.getIdentifier();
      CodeableConceptDt code = observation.getCode();
      StringDt textElement = observation.getCode().getTextElement();

      // DateTimeDt is a FHIR primitive however, so the following will return
      // null
      // unless a value has been placed there.
      Date active = observation.addIdentifier().getPeriod().getStartElement().getValue();

Coded/Enumerated Values

There are many places in the FHIR specification where a "coded" string is used. This means that a code must be chosen from a list of allowable values.

Closed Valuesets / Codes

The FHIR specification defines a number of "closed" ValueSets, such as the one used for Patient.gender (note that this field was not a closed ValueSet in DSTU1 but is as of DSTU2). These valuesets must either be empty, or be populated with a value drawn from the list of allowable values defined by FHIR. HAPI provides special typesafe Enums to help in dealing with these fields.

      Patient patient = new Patient();

      // You can set this code using a String if you want. Note that
      // for "closed" valuesets (such as the one used for Patient.gender)
      // you must use one of the strings defined by the FHIR specification.
      // You must not define your own.
      // HAPI also provides Java enumerated types which make it easier to
      // deal with coded values. This code achieves the exact same result
      // as the code above.
      // You can also retrieve coded values the same way
      String genderString = patient.getGenderElement().getValueAsString();
      AdministrativeGenderEnum genderEnum = patient.getGenderElement().getValueAsEnum();
      // The following is a shortcut to create

Open Valusets / CodeableConcepts

The FHIR specification also defines a number of "open" ValueSets, such as the one used for Patient.maritalStatus. These fields may define a set of allowable codes, but also allow you to use your own codes instead if none of the given codes matches your needs. This is called an incomplete binding. Some fields may even define a set of codes that serve as nothing more than an example as to the type of codes that would be used there. This is known as an example binding.

For these fields, a CodeableConcept datatype is generally used by the FHIR specification. This datatype allows multiple "codings", which are a code and codesystem pair, optionally with a display name as well. The following example shows how to interact with this type.

      Patient patient = new Patient();

      // Coded types can naturally be set using plain strings
      CodingDt statusCoding = patient.getMaritalStatus().addCoding();

      // You could add a second coding to the field if needed too. This
      // can be useful if you want to convey the concept using different
      // codesystems.
      CodingDt secondStatus = patient.getMaritalStatus().addCoding();
      secondStatus.setDisplay("Happily Married");
      // CodeableConcept also has a text field meant to convey 
      // a user readable version of the concepts it conveys.
      patient.getMaritalStatus().setText("Happily Married");
      // There are also accessors for retrieving values
      String firstCode  = patient.getMaritalStatus().getCoding().get(0).getCode();
      String secondCode = patient.getMaritalStatus().getCoding().get(1).getCode();

HAPI also provides typesafe enums to help in working with CodeableConcept fields.

      Patient patient = new Patient();
      // Set the CodeableConcept's first coding to use the code
      // and codesystem associated with the M value.
      // If you need to set other fields (such as the display name) after
      // using the Enum type, you may still do so.
      // You can use accessors to retrieve values from CodeableConcept fields
      // Returns "M"
      String code = patient.getMaritalStatus().getCodingFirstRep().getCode();

      // Returns "http://hl7.org/fhir/v3/MaritalStatus". This value was also
      // populated via the enum above.
      String codeSystem = patient.getMaritalStatus().getCodingFirstRep().getCode();
      // In many cases, Enum types can be used to retrieve values as well. Note that
      // the setter takes a single type, but the getter returns a Set, because the
      // field can technicaly contain more than one code and codesystem. BE CAREFUL
      // when using this method however, as no Enum will be returned in the case
      // that the field contains only a code other than the ones defined by the Enum. 
      Set<MaritalStatusCodesEnum> status = patient.getMaritalStatus().getValueAsEnum();

Convenience Methods

The FHIR data model is rich enough to meet common use cases, but sometimes that richness adds complexity. For example, a Patient may have multiple names (a preferred name, a nickname, etc.) and each of those names may have multiple last names, multiple prefixes, etc.

The example below shows populating a name entry for a Patient. Note the use of the StringDt type, which encapsulates a regular String, but allows for extensions to be added.

Patient patient = new Patient();
HumanNameDt name = patient.addName();
StringDt family = name.addFamily();
StringDt firstName = name.addGiven();
StringDt secondName = name.addGiven();

HAPI also provides for simple setters that use Java primitive types and can be chained, leading to much simpler code.

Patient patient = new Patient();


Populating an Observation Resource

The following example shows how to create an observation resource containing a numeric datatype.

// Create an Observation instance
Observation observation = new Observation();

// Give the observation a status

// Give the observation a code (what kind of observation is this)
CodingDt coding = observation.getCode().addCoding();
coding.setCode("29463-7").setSystem("http://loinc.org").setDisplay("Body Weight");

// Create a quantity datatype
QuantityDt value = new QuantityDt();

// Set the reference range
SimpleQuantityDt low = new SimpleQuantityDt();
SimpleQuantityDt high = new SimpleQuantityDt();

Back to top

Reflow Maven skin by Andrius Velykis.