From: Michael H. <mh...@st...> - 2003-05-27 21:29:55
|
Hi. I'm playing around with HAPI, assessing it's suitability for an experimental project our group is working on. So far I am impressed. But there is an issue that I'd like to ask about (and offer to contribute some hacking if there is interest). I'm writing handlers for different message types. I find it a bit cumbersome, though maybe I'm missing something obvious. Here's my issue. Suppose I want to process messages of type ADT_A01. Hapi, version 0.3, uses namespaces to segregate the v2.2, 2.3, 2.3.1 and 2.4 versions of classes of this type. They all have various helper functions like "getPV1()", but because the only commonality between the different versions of the class is that they all extend AbstractMessage, one can't really use these helper functions in a message handler if you want to handle messages of varying versions, unless you do an awful lot of ugly, non-object-oriented testing and casting. And the PV1 object they all return also has no overlap between versions; so repeat the above problem, all the way down to the primitive types. I could just do a bunch of calls like get("PV1"), but that results in a lot of ugly syntax too, because the "get" method always returns (and creates) what you ask for, whether it was in the message or not, so you have to really drill down to see if an optional segment (like PDA or PV2) actually was in the message or not. Furthermore, if I wanted to make generic handlers for segments like PDA, those have to be invoked lexically, not at the object level. Like, I do get("PDA"), then call my processPDA handler with that blind Segment, and hope I don't have a typo somewhere (like, mistakenly calling "blah=get("PDA")" then calling "processPV2(blah)", or whatever). Very un-object-oriented. How about this: the sourcegen module scans all versions for a particular message type, and constructs a superset of all segments and groups it contains, and spits out a generic class of that type.. say, an ADT_A01 class with getXXX methods for all possible segments and groups, all of which for that class return null. That class could extend AbstractMessage or whatever. Then, instead of having the different hl7 versions segregated by namespace, have sourcegen spit out classes like ADT_A01_V23 and so on, which extend the ADT_A01 superclass, and override the getXXX things as appropriate. Then do the same for segments, groups, compound and primitive datatypes. Then, my ADT_A01 handler could simply cast the incoming message to an ADT_A01 object, call getPDA(), and if it isn't there because the message is version 2.2 and hence isn't defined, I get a null and ignore that segment; if it's a message for version 2.4 but isn't in the message, I still get a null, and again ignore it. That way I don't have to care (unless I want to) what version the messages come from. Same procedure with processing groups, segments, and datatypes; have a generic PV1 class, with PV1_v23 subclasses, and so on. My handlers can then process segments like PV1 or PDA and have the bindings done by the compiler. I notice that the CVS repository for the newer versions does something like this already for the primitive types. Great start. How about turtles all the way down? I could take a stab at this, if there's interest. But the sourcegen module wants to connect to a database to draw out it's definitions. Is there a read-only instance of this DB somewhere that one could connect to? Or is it identical to what you get if you purchase the HL7 spec from hl7.org? In other words, how can I get my hands on the data definitions and geek around with sourcegen? Or is there a much more obvious and clean way to access the segments (and from there, datatypes) in a message processor that I'm missing? Thanks for any feedback, and apologies if these are silly questions/ideas. Dicom is my bread and butter; I'm a relative novice at hl7. Cheers, Mike Harm Stanford University School of Medicine mh...@st... ------------------------------------------------------------------------ ------ 'What should you do,' the author asked rhetorically, 'if you are in a situation where there is a strong wind, and a lee shore, and your boat doesn't have an auxiliary engine?' Reply: 'Look, JUST STAY OUT of situations where there's a strong wind and a lee shore and your boat doesn't have an auxiliary engine.' - Jerry Fodor, "The Elm and the Expert" |