Sunday, July 14, 2013

Extending Code Lists in Everest

Someone asked a really great question on the Everest forums. I am paraphrasing but the gist of the question was: “How do I add a code to an enumerated vocabulary?”. In order to answer the question I’ll dive a little into how Everest generates code lists.

When generating the RMIM assemblies, GPMR will parse the vocabulary MIF files and keep an internal representation of the value sets, code systems and concept domains that properties are bound to. When generating C# or Java GPMR will determine the best way of representing the value set in code.

  • If the Value Set or Code System is not complete (i.e. is marked partial) then any properties bound to said value set carry a type of CS<String>, CV<String>, etc.
  • If the property or Value Set is marked CWE (extensions allowed) then the the property is bound to String as well.
  • If the Value Set is made up of an expression and not all expression components can be found (i.e. intersect X and Y where Y is not available) then the property is bound to String
  • Otherwise, enumerate the literals in the value set and bind the property to an Enumeration (or IEnumeratedVocabulary in Java)

That last bit is usually the sticky point. Some jurisdictions ignore the CWE strength and add codes of their own (I have seen custom realm codes, custom null flavors, all kinds of weirdness in our travels).

In order to overcome this Everest (and jEverest) provide a relatively easy mechanism for assigning “non standard” codes to properties. For this example, let’s say we want to assign a custom ProcessingID of “Sample” (a bit contrived but it illustrates the process). To assign our ProcessingID of “S” we’d do this in .NET:

PRPA_IN101103CA sample = new PRPA_IN101103CA();
sample.ProcessingCode = Util.Convert<CS<ProcessingID>>("S");

In Java the process is a little easier as jEverest uses IEnumeratedVocabulary so we can just add the code:

PRPA_IN101103CA sample = new PRPA_IN101103CA();
sample.setProcessingCode(new ProcessingID("S", null));

The result is a (non standard) XML instance carrying our custom code:


<processingCode code=”S”/>

Saturday, July 6, 2013

Setting the Client Registry on FHIR–First impressions

I recently had an opportunity to explore HL7 FHIR in more detail (thanks to a lighter workload this week), and as a developer felt a need to actually write something.

Many of the FHIR implementations I’ve seen publicly hosted are greenfield reference implementations that demonstrate the resource based paradigms of this new messaging standard being developed by HL7. So, I did something novel, I tried to put FHIR atop an existing software implementation. But what to write? The answer was simple, I’d add FHIR to our client registry.

This post is just a rambling of some of the experiences I’ve had with FHIR as it pertains to our client registry reference implementation. I will share some opinions about how FHIR can be improved in a future blog post.

Getting Started

The first thing I did was reach out to http://hl7.org/fhir and download the C# reference classes for  FHIR. After opening the solution I found that they weren’t annotated with .NET serialization attributes, rather you had to use the supplied serializers provided in the class library. While this is great for getting started on the client side I had trouble figuring out a way to integrate them with the WCF REST stack (not a complaint, I have this same issue with Everest and extended WebServiceHost serialization formatters is not a trivial task).

So I decided instead of piggy-backing on the existing FHIR classes provided by HL7, I’d write some XmlSerializer annotated classes from scratch (I’m only supporting XML for the client registry). This was a good way for me to learn the resources and class models.

Case Based Design

One thing that immediately popped out at me about FHIR was the fact that it was case based software design. Each resource, although linked to common data types and other resources, is like an island and the style of data representation isn’t necessarily common between them. Some resources use “code” to identify themselves, other use “identifier” or “name”.  Coming from a v3 implementation background this was quite new to me.

For example, a Patient resource can have zero or more associations named “contact” with a  class named “Contact” describing a relationship. When implementing the Patient resource I created a class named “Contact” and assigned a property on Patient of that type. However, the Organization resource also has zero or more associations named “contact” with a class named “Contact” … Only the Contact class in the Patient resource and the Contact class in the Organization resources are different (well, almost the same). Of course, that should not be confused with the FHIR data type “Contact” which represents a telecommunications object.

There are lots of examples of this in FHIR where there are several classes, conveying similar concepts, yet they are completely different. Something that could’ve been solved easily using …

Inheritance

Another thing that bugs me about FHIR (from an implementation standpoint) is the lack of object inheritance. Admittedly this was abused in HL7v3 (supporting extension and restriction), but used properly it could be of benefit to FHIR. Take again, for example, the “Contact” class (from either Patient or Organization). Would it not make sense to have a common ancestor, say “Person” containing properties “name, telecom, address, gender” and then extend that for use in the “Patient” or “Organization” resources. Even Patient or Practitioner could extend “Person” as they too carry those attributes.

True, deep object hierarchies are a bad thing but some level of inheritance can do quite a bit of good. It is the equivalent to saying “operator overloads could be abused so we just don’t support them” .. True, but when not abused it is a very useful tool (apologies for the Java bash there).

Extensions

I used to hate extensions in FHIR, but after implementing FHIR on the client registry I see why they’re present. There are lots of times (especially on the CR) where data provided from a patient feed (either PIXv3, PIXv2, or the pan-Canadian HL7v3 implementation) can’t be appropriately mapped to FHIR, or where FHIR is too limited in some respect.

For example, consider a PIX feed (v2 or v3) where a mother’s information is provided (http://cr.marc-hi.ca:8080/fhir/0.09/Patient/@27423 provides an example where Edna Brown is Patricia Brown’s mother). In FHIR I can represent this relationship via a “contact” association and a “RelationshipKind” of “parent” however I’ve lost data fidelity (the real relationship is “Mother”, but might have been “Step Mother” in either case “parent” is an applicable mapping). FHIR handles this quite nicely as I can simply extend the RelationshipKind element to add the original relationship code (if you look at the source document you’ll see that).

Personally I would have liked to seen extensions take the form of the WS-* extensions (new namespace, and well defined element structure etc.) however because the FHIR standard supports JSON in addition to XML this isn’t possible, so I think they’ve come up with a flexible enough structure for resources.

Changes … Frequently

I understand that FHIR is an evolving standard, however it would be nice to have more structured changes being posted. For example, I started implemented FHIR 0.09 on June 26th, was nearly finished by July 2nd. At that time there was an association on the Patient resource named “Details” pointing to a class called “Demographics”. On July 3rd (or 4th I can’t recall) I was nearly ready to deploy my solution and was just cleaning up some code, verifying resources, etc. However when I got around to the Patient resource, the Details association was gone and there was no longer a class called “Demographics”. Wait a minute! Was I dreaming?! Did I just hallucinate an entirely new class?

Turns out I didn’t, although the spec still read “FHIR 0.09” the structure of some of the resources changed. This is more of a version management / tagging issue than anything but still should be something to beware of.

Paradigm Shift

This last one isn’t a complaint about FHIR, it is a REST based standard. This last point speaks more to the pains of putting a REST based interface on an RPC based system. It was however, the most challenging part of the project (it still isn’t complete). REST is a paradigm shift from the event based (read RPC) model on which our client registry is designed. This follows the paradigm that HLv3 and HLv2 use where an event is processed and stored (patient was admitted, patient was merged, etc.). For this project I had to somehow map those events to RESTful CRUD operations.

It isn’t too bad for querying and reading (the only operations currently supported) as we can simply pluck contents out of the patient table however we do lose some data fidelity and context (at least in our implementation). It will cause us some grief as I move to extend the FHIR interface to support creation, update, and merge operations.

For example, it is possible on an admit (or register in v3) to specify the “custodian” of the data, or the location where data was entered, etc. All of which are used by many facilities including business rule enforcement and auditing. The registry has some context as to the event that occurred which resulted in the new record being created, updated, etc. In FHIR this context is a little more difficult to attain. To the FHIR interface (as with any REST system) we’re stuck with CRUD operations on the resource (to be fair extensions and/or the Transaction resource can be used to facilitate this, but then we’re just stuck putting RPC atop REST).

Final Thoughts

All-in-all, the FHIR implementation for the CR wasn’t too bad. It took about a week of effort to get read, version read, version history and query on the ValueSet (another discussion on its own), Profile, and Patient resources. When I have more time I’ll get to work on the create and update operations.

The final product is quite impressive. Assuming I’ve interpreted the FHIR documentation correctly; we now have a PIX manager that can accept v2, and v3 patient identity feeds and allow clients to query using rest (you can try it here : http://cr.marc-hi.ca:8080/fhir/0.09). There are approximately 15,000 patients in the registry (all randomly generated of course).

To assist in your exploring, here are some patients of note:

  • Justin Fyfe (lots of versions as the result of Merge operations)
  • Patricia Brown (has a relationship with her mother)

I will post more about this adventure as it progresses.