Typically, when working with FHIR the right way to provide your own extensions is to work with existing resource types and simply ass your own extensions and/or constrain out fields you don't need.

This process is described on the Profiles & Extensions page.

There are situations however when you might want to create an entirely custom resource type. This feature should be used only if there is no other option, since it means you are creating a resource type that will not be interoperable with other FHIR implementations.

This is an advanced features and isn't needed for most uses of HAPI-FHIR. Feel free to skip this page.

Custom Resource Structure

The following example shows a custom resource structure class:

import java.util.ArrayList;
import java.util.List;

import org.hl7.fhir.dstu3.model.DomainResource;
import org.hl7.fhir.dstu3.model.ResourceType;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.Type;

import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.util.ElementUtil;

/**
 * This is an example of a custom resource that also uses a custom
 * datatype.
 * 
 * Note that we are extensing DomainResource for an STU3
 * resource. For DSTU2 it would be BaseResource. 
 */
@ResourceDef(name = "CustomResource", profile = "http://hl7.org/fhir/profiles/custom-resource")
public class CustomResource extends DomainResource {

	private static final long serialVersionUID = 1L;

	/**
	 * We give the resource a field with name "television". This field has no
	 * specific type, so it's a choice[x] field for any type.
	 */
	@Child(name="television", min=1, max=Child.MAX_UNLIMITED, order=0)
	private List<Type> myTelevision;

	/**
	 * We'll give it one more field called "dogs"
	 */
   @Child(name = "dogs", min=0, max=1, order=1)
	private StringType myDogs;
	
	@Override
	public CustomResource copy() {
		CustomResource retVal = new CustomResource();
		super.copyValues(retVal);
		retVal.myTelevision = myTelevision;
      retVal.myDogs = myDogs;
		return retVal;
	}

   public List<Type> getTelevision() {
	   if (myTelevision == null) {
	      myTelevision = new ArrayList<Type>();
	   }
		return myTelevision;
	}

   public StringType getDogs() {
      return myDogs;
   }

	@Override
	public ResourceType getResourceType() {
		return null;
	}

	@Override
	public FhirVersionEnum getStructureFhirVersionEnum() {
		return FhirVersionEnum.DSTU3;
	}

	@Override
	public boolean isEmpty() {
		return ElementUtil.isEmpty(myTelevision, myDogs);
	}

	public void setTelevision(List<Type> theValue) {
		this.myTelevision = theValue;
	}

	public void setDogs(StringType theDogs) {
      myDogs = theDogs;
   }

}

Custom Datatype Structure

The following example shows a custom datatype structure class:

import org.hl7.fhir.dstu3.model.DateTimeType;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.Type;
import org.hl7.fhir.instance.model.api.ICompositeType;

import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.util.ElementUtil;

/**
 * This is an example of a custom datatype. 
 * 
 * This is an STU3 example so it extends Type and implements ICompositeType. For
 * DSTU2 it would extend BaseIdentifiableElement and implement ICompositeDatatype.
 */
@DatatypeDef(name="CustomDatatype")
public class CustomDatatype extends Type implements ICompositeType {

	private static final long serialVersionUID = 1L;
	
	@Child(name = "date", order = 0, min = 1, max = 1)
	private DateTimeType myDate;

   @Child(name = "kittens", order = 1, min = 1, max = 1)
   private StringType myKittens;

	public DateTimeType getDate() {
		if (myDate == null)
			myDate = new DateTimeType();
		return myDate;
	}

   public StringType getKittens() {
      return myKittens;
   }

   @Override
	public boolean isEmpty() {
		return ElementUtil.isEmpty(myDate, myKittens);
	}

	public CustomDatatype setDate(DateTimeType theValue) {
		myDate = theValue;
		return this;
	}

	public CustomDatatype setKittens(StringType theKittens) {
      myKittens = theKittens;
      return this;
   }

	@Override
	protected CustomDatatype typedCopy() {
		CustomDatatype retVal = new CustomDatatype();
		super.copyValues(retVal);
		retVal.myDate = myDate;
		return retVal;
	}
}

Using the Custom Structure

And now let's try the custom structure out:

// Create a context. Note that we declare the custom types we'll be using
// on the context before actually using them
FhirContext ctx = FhirContext.forDstu3();
ctx.registerCustomType(CustomResource.class);
ctx.registerCustomType(CustomDatatype.class);

// Now let's create an instance of our custom resource type
// and populate it with some data
CustomResource res = new CustomResource();

// Add some values, including our custom datatype
DateType value0 = new DateType("2015-01-01");
res.getTelevision().add(value0);

CustomDatatype value1 = new CustomDatatype();
value1.setDate(new DateTimeType(new Date()));
value1.setKittens(new StringType("FOO"));
res.getTelevision().add(value1);

res.setDogs(new StringType("Some Dogs"));

// Now let's serialize our instance
String output = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res);
System.out.println(output);

This produces the following output (some spacing has been added for readability):

<CustomResource xmlns="http://hl7.org/fhir">
   <meta>
      <profile value="http://hl7.org/fhir/profiles/custom-resource"/>
   </meta>
   
   <televisionDate value="2015-01-01"/>
   <televisionCustomDatatype>
      <date value="2016-05-22T08:30:36-04:00"/>
      <kittens value="FOO"/>
   </televisionCustomDatatype>
   
   <dogs value="Some Dogs"/>
   
</CustomResource>

Back to top

Reflow Maven skin by Andrius Velykis.