This wiki has undergone a migration to Confluence found Here
<meta name="googlebot" content="noindex">

RIMBAA: Java based Reference Implementation

From HL7Wiki
Jump to navigation Jump to search
This page uses terminology as defined in this whitepaper.

Description

The HL7 RIMBAA group has created a Java based reference implementation. The architecture of this implementation is based on the RP-RO-MS cells.

Java Reference Implementation


The work product starts in RO and uses an object-relational mapping solution (Hibernate) for the transition to RP. When it comes to the RP cell the reference implementation uses the Table per Hierarchy strategy. All internal objects are completely RIM based. We use Hibernate to generate the Schema for the database, and it is also used to persist the RIM objects. The transition between RO to MS is supported using MIFs (the reference implementation contains a MIF parsing API). The direct transition from RO to MS is the most complex part of the API and at every step it is guided by the parsed MIF file. It works almost perfectly in the direction from MS to RO, it works almost perfectly between RP and RO using Hibernate, and it works fairly well in the direction of RO to MS. The V3 XML generated is 90% plus perfect but there are little quirks which require tweaking. The XML generated is so close to correct it can be mostly be tweaked using XSLT.

The advantage of using an object-relational mapping tool is the fact that database queries can be formulated using RIM classes/attributes. All SQL-details are hidden from the programmer. The following is an example of an SQL statement (RP style) that, based on the CDA model expressed in pure RIM terms, will pull all pulmonary function test results for patient 1234567 from the pure RIM based database:

SELECT  new list(i.extension, name.givenName, name.familyName, clinicalStatement.value, 
    clinicalStatement.value.unit,  clinicalStatement.code.displayName) 
   FROM PatientImpl patient 
   INNER JOIN patient.id AS i
   inner join patient.player as person
   inner join person.name as name
   inner join patient.participation as part
   inner join part.act as document
   inner join document.outboundRelationship as component
   inner join component.target as body
   inner join body.outboundRelationship as component2
   inner join component2.target as section
   inner join section.outboundRelationship as entry
   inner join entry.target as clinicalStatement
   where component.typeCode='COMP' 
     and i.extension='1234567'

Another example which pulls all of the "Glucose Level" (using its code 64544) values from the pure RIM based database:

   SELECT DISTINCT obs.Value_Number AS number, 'mg/dl' AS units,  
     SUBSTR(obs.Effectivetime_low,5,4) AS time, patientid.extension AS patientid 
   FROM ACT obs
   INNER JOIN PARTICIPATION participant ON(obs.internalId = participant.actInternalId)
   INNER JOIN Role_id patientid ON(patientid.roleInternalId = participant.roleInternalId)
   WHERE  obs.Code_code = '64544' 
      AND patientid.root ='2.16.840.1.113883.19.5'
      AND patientid.extension =  '12345'

Does the use of large numbers of Joins scale, without additional tuning of the database? Part of the answer is to automatically "conduct" a copy of certain data elements (e.g. the patient identifier) to an optional more proximal spot in memory before you do the query - the logic of adding/overriding context would be a nightmare to do in a query. That eliminates the majority of the joins. It takes some time in memory to do the context conduction when we are processing the message before we persist it. Once it's persisted we can get what we want with fewer joins. The above query examples are relatively simple, a production system would more likely retrieve lists of clinicalStatement objects (see first example) instead of a list of string and number values. The query language used allows you to query for any object.

For any given use case, you can create a one off database that would perform better, but then you need a different schema for each use case. One of the big advantages of a RIMBAA approach is that you use the same schema for everything. You might sacrifice some performance, but you'd avoid creating countless new schemas. So we might be willing to sacrifice some peformance for the saved costs of not having to create and maintain numerous database schemas though out the enterprise.

Generating messages is really not that hard to accomplish if you have the data. Using any one of a number of XML generating API's (RO to MS) you create the XML which can be sent. Receiving any data if it's in HL7 V3 format is also not complicated - if you have the corresponding MIF file it will "magically" be converted to RO objects and magically transition to RP cell.

Known Implementations