190 likes | 394 Views
HL7 V3 API. What is happening behind the scenes…. Presentation Goals. Familiarize developers and other interested parties with various concepts and classes that formulate the API Walk through a Message parsing scenario
E N D
HL7 V3 API What is happening behind the scenes…
Presentation Goals • Familiarize developers and other interested parties with various concepts and classes that formulate the API • Walk through a Message parsing scenario • Describe at a high level what objects are instantiated and what notable behavior occurs. • Peel the “onion” a layer or two to get a feel for what is going on… but not enough to get overwhelmed (hopefully).
Before we get started… • RIM • HL7 Primitive Data Types • MIF • XML • Java Reflection and Java Generics • HL7 V3 API Java Doc
RIM • HL7 Reference Information Model • Static model of health and health care information • See /etc/Rim202.xml for more details. The file not only describes the Rim classes and relationships, but also provides useful documentation. Also, the Java doc for the rim package contains a subset of the xml file documentation. • Examples: Patient, Place, Diet, Role, Entity… • The rim classes are automatically generated via a transformation (JavaRim202.xsl) of Rim202.xml. This transformation is performed by the RimGenerator object. • org.hl7.rim and org.hl7.rim.impl • There is a rmi-map.properties file that maps logical RIM class names to the actual implementing java class. • Generated Rim classes should migrate to a jar file rather than the source tree.
HL7 Primitive Data Types • Some of these types should be somewhat familiar if you have encountered HL7 V2.X. • Rim classes contain attributes that have these primitive data types. • org.hl7.types and org.hl7.types.impl • Examples: CE (“Coded Element”), TS (“Timestamp”), AD (“Address”) • There are many “null flavor” types to help discern why a field might be null: NI, NA, UNK, NASK, ASKU NAV, OTH, PINF, NINF, MSK, NP. • Most type implementations will have a corresponding null flavor implementer as well. Example: ADimpl, ADNull. • These classes are NOT automatically generated. • There is a type-map.properties file that maps a primitive data type to a corresponding “presenter” in the org.hl7.xml package • HL7 V3 added more sophisticated types such as bags, lists, physical quantities, etc.
MIF • HL7 Model Interchange Format • XML based. • Contains actual message definitions. (Example: AdverseEvent) • Complex/Verbose/Explicit in nature. V3 reduces ambiguity and embraces industry accepted standards and infrastructure.
XML • In a nutshell • human readable • self documenting • can be validated • well suited for automated processing and translation • industry wide accepted standards and infrastructure/tools. • HL7 V3 API typically uses SAX parsers throughout various packages. • You should become familiar with the XML family of standards and tools as a HL7 V3 application developer [if you are not already]. • See w3schools for more information about the XML family of standards.
Java Reflection and Generics • Java provides a reflection API that allows code to examine and manipulate objects even if the names of the classes, fields, and methods are unknown until runtime. • See java reflection tutorial for more info. • The HL7 V3 API relies heavily on reflection to dynamically process messages. • Generics (as of V1.5) allow Java to “abstract over types”. • See java generics tutorial for more info. • The HL7 V3 API relies heavily on generics as well. Various Primitive Data Types are container oriented.
HL7 V3 API Java Doc • It may be useful to keep an open browser window with the HL7 V3 API Java Doc handy to peek at the various classes and packages mentioned in this presentation.
Walking Through a Scenario • The HL7 V3 API provides a Demo package that illustrates usage of the API. • Ant target = demoAdverseEventMif • Presentation will discuss important classes and processing steps that take place behind the curtain as we examine this demo. • Reminder: end goal is to understand at a high level what is going on.
DemoDriver.java • Main application entry for demo • For our scenario, using MIF format for the AdverseEventInvestigation message. • org.hl7.demo • Key steps: • MIF Schema Pre Processing via MifMessageTypeLoader in org.hl7.meta package. • Rim object graph creation via MessgeContentHandler in org.hl7.parser package. • Tranformation back to XML via Transformer (org.hl7.xml.transform) and RimGraphXMLSpeaker (org.hl7.xml.builder).
MIF Schema Pre Processing • Creates MessageTypeLoader passing in RIM and MIF XML file names utilizing classes in the org.hl7.meta package. • Creates a MessageType object for the input MIF message by calling MessageTypeLoader’s loadMessageType() method. • During the load process, the RIM file is parsed via the RimAssociationLookupsParser’s parse() method, resulting in a RimAssoaciationLookups mapping object. RIM class associations will be required by MIF schema parsing. • The MIF file (schema) is parsed by the MifMessageTypeLoader’s loadProcessRoot() method. As a result, the MessageType object contains a map of CloneClass objects. • The CloneClass class contains collections of Attributes and Associations (aka “Feature”). See CloneClassImpl, AttributeImpl, and AssociationImpl. • The Attribute class essentially contains the name, RIM data type, and cardinality of an attribute. • The Association class essentially contains the association short name, association, and the target clone class. • Underneath the covers, factories such as RimPropertiesBasedFactory and DatatypeMetadataFactory are called (from CloneClassImp and MifMessageTypeLoader) to create Rim and datatype classes on the fly. • The objects produced by the factories will be the repositories for actual message values when the message is later parsed. These objects also have behavior as well. • At this point, we have a roadmap (created dynamically by parsing schema) denoting the message element structure and relationships. We have not actually parsed the message contents yet!
Peeking into MIF Schema Pre Parsing • Example Schema definitions from the PORR_MT04001.xsd file in /data/schemas2002/schemas • DocumentationOf complexType • PrimarySourceReport complexType • Will match schema input against toString() output of MessageType. • Recursively shows collection of CloneClasses, Attributes, and Associations. • Attributes prefixed by ^^ in toString() output • Associations prefixed by – in toString() output
DocumentationOf Type • <xs:complexType name="PORR_MT040001.DocumentationOf"> • <xs:sequence> • <xs:element name="primarySourceReport" type="PORR_MT040001.PrimarySourceReport"/> • </xs:sequence> • <xs:attribute name="type" type="Classes" default="ActRelationship"/> • <xs:attribute name="typeCode" type="ActRelationshipType" use="optional" default="DOC"/> • <xs:attribute name="contextControlCode" type="ContextControl" use="optional"/> • <xs:attribute name="contextConductionInd" type="bl" use="optional"/> • <xs:attribute name="templateId" use="optional"> • <xs:simpleType> • <xs:list itemType="oid"/> • </xs:simpleType> • </xs:attribute> • <xs:attribute name="typeID" use="optional"> • <xs:simpleType> • <xs:list itemType="oid"/> • </xs:simpleType> • </xs:attribute> • <xs:attribute name="realmCode" use="optional"> • <xs:simpleType> • <xs:list itemType="cs"/> • </xs:simpleType> • </xs:attribute> • <xs:attribute name="nullFlavor" type="cs" use="optional"/> • </xs:complexType>
DocumentationOf subset of MessageType.toString() • Clone class DocumentationOf clones ActRelationship • ^^ templateId: SET<OID> // 0..* • ^^ realmCode: SET<CS> // 0..* • ^^ typeID: SET<OID> // 0..* • ^^ type: CS // 0..* • ^^ typeCode: CS // 1..1 • ^^ contextControlCode: CS // 0..1 • ^^ contextConductionInd: BL // 0..1 • -- primarySourceReport: target: PrimarySourceReport // 1..1
PrimarySourceReport type • <xs:complexType name="PORR_MT040001.PrimarySourceReport"> • <xs:sequence> • <xs:element name="id" type="II"/> • <xs:element name="code" type="CE"/> • <xs:element name="title" type="ST" minOccurs="0"/> • <xs:element name="text" type="ED" minOccurs="0"/> • <xs:element name="statusCode" type="CS" minOccurs="0"/> • <xs:element name="effectiveTime" type="IVL_TS" minOccurs="0"/> • <xs:element name="author" type="PORR_MT040001.Author2" minOccurs="0" maxOccurs="unbounded"/> • </xs:sequence> • <xs:attribute name="type" type="Classes" default="Observation"/> • <xs:attribute name="classCode" type="ActClass" use="optional" default="OBS"/> • <xs:attribute name="moodCode" type="ActMood" use="optional" default="EVN"/> • <xs:attribute name="templateId" use="optional"> • <xs:simpleType> • <xs:list itemType="oid"/> • </xs:simpleType> • </xs:attribute> • <xs:attribute name="typeID" use="optional"> • <xs:simpleType> • <xs:list itemType="oid"/> • </xs:simpleType> • </xs:attribute> • <xs:attribute name="realmCode" use="optional"> • <xs:simpleType> • <xs:list itemType="cs"/> • </xs:simpleType> • </xs:attribute> • <xs:attribute name="nullFlavor" type="cs" use="optional"/> • </xs:complexType>
PrimarySourceReport subset of MesageType.toString() • Clone class PrimarySourceReport clones Observation • ^^ templateId: SET<OID> // 0..* • ^^ realmCode: SET<CS> // 0..* • ^^ typeID: SET<OID> // 0..* • ^^ type: CS // 0..* • ^^ classCode: CS // 1..1 • ^^ moodCode: CS // 1..1 • ^^ id: II // 1..1 • ^^ code: CE // 1..1 • ^^ title: ST // 0..1 • ^^ text: ED // 0..1 • ^^ statusCode: CS // 0..1 • ^^ effectiveTime: IVL<TS> // 0..1 • -- author: participation: Author2 // 0..*
Schema Pre Processing Highlights • Attribute “type” denotes RIM class name. • DocumentationOf = ActRelationship • PrimarySourceReport = Observation • Schema Attributes and elements denote attributes in CloneClass. • Schema Complex type elements typically denote an association to another class for the CloneClass. • Rim Lookup map is used to “finalize” the association. How? TBD