The zsegment module
Contents
We’re going to create a new shared module called zsegment. From the project files pane of the Translator click on Add…
This dialog will come up. Enter zsegment in the Create a new module textbox:
Then click on the Create button.
The new module will be appear in the Project Files pane:
Click on zsegment and then copy-paste the following code into the module:
zsegment = {} local function trace(a,b,c,d) return end function zsegment.extractZSegment(Msg) local Segments = Msg:split('\r') local ZSegments = {} for i = 1, #Segments do if Segments[i]:sub(1,1) == 'Z' then trace('Found '..Segments[i]) ZSegments[i] = Segments[i] end end return ZSegments end function zsegment.copyZSegments(Orig, Copy) -- enforce correct return character Copy = Copy:gsub('\r?\n','\r') Orig = Orig:gsub('\r?\n','\r') -- and strip return(s) from end of string -- '$' anchors matching to end of string Copy = Copy:gsub('\r+$','') local ZSegments = zsegment.extractZSegment(Orig) local SegmentList = Copy:split('\r') trace(SegmentList) for K,V in pairs(ZSegments) do table.insert(SegmentList, V) end trace(SegmentList) local Result = '' for i = 1, #SegmentList do Result = Result..SegmentList[i]..'\r' end return Result end
The beauty of the Translator is that:
- One can implement sophisticated logic
- Other people in your team can easily see what you have done
Do take the time to step through and look through the annotations of the zsegment module to understand it. It’s simple. This is how it works:
- The
extractZSegment()
function:- Slices the segments apart by splitting on the carriage return ‘\r’ character.
- Creates an array of those segments which start with Z, i.e., Z-segments.
- The main
copyZSegments()
routine takes the HL7 message without Z-segments and does the folowing:- Ensures the correct return character is used.
- Removes any returns from the end of the message.
- Slices it into segments also by splitting on the \r character.
- Then appends the Z-segments.
The Translator makes writing reusable modules like this easy. It’s one of the many things that makes Iguana so fun and productive.
Now go back to the main module and insert two require statements at the top:
require 'split' require 'zsegment'
Then add these lines to the main module:
Notice how we still have our error. If we look at the two extra trace lines we added earlier in the ‘Escaped Text’ mode we immediately see the culprit: there is a trailing carriage return in the copied data.
The new version of the message has a trailing \r. We can trim that \r using a helpful string extension we can write:
function string.StripLastReturns(S) -- strip return(s) "\r" & "\n" from the end of a string local i = #S while S:byte(i) == 10 or S:byte(i) == 13 do i = i - 1 end return S:sub(1,i) end
That means we can apply
to any string and it will strip one or more \r or \n off the end.:StripLastReturns()
This function uses
- # operator – returns the number of characters in the string
byte(N)
– returns the byte at the Nth place.
– returns the substring at the indexes given.sub(Start, End)
These are part of the standard Lua string library.
So we make things work by altering the code to the following:
Notice how I used Data:StripLastReturns()
as well to ensure there are no unwanted returns on the Data or the Copy.
You can really start to appreciate the visibility and power the Translator environment gives.
If you need to ensure your code is up-to-date then copy-paste this in:
require 'split' require 'zsegment' local function trace(a,b,c,d) return end function main(Data) local Orig = hl7.parse {vmd = 'transform.vmd', data = Data} local Out = hl7.message{vmd = 'transform.vmd', name = Orig:nodeName()} Out:mapTree(Orig) local Copy = zsegment.copyZSegments(Data, Out:S()) CheckTransform(Data, Copy:StripLastReturns()) Out.MSH[3][1] = 'Acme' Out.MSH[4][1] = 'Lab' trace(Out) local DataOut = Out:S() DataOut = zsegment.copyZSegments(Data, DataOut) DataOut = DataOut:StripLastReturns() trace(DataOut) queue.push{data = DataOut} end function CheckTransform(Orig, Copy) if Orig ~= Copy then trace(Orig) trace(Copy) error('Copy of HL7 message does not match the original') end end function string.StripLastReturns(S) -- strip return(s) "\r" & "\n" from the end of a string local i = #S while S:byte(i) == 10 or S:byte(i) == 13 do i = i - 1 end return S:sub(1,i) end
We still have one major difference to overcome with how we are handling ORM messages, but we will use that as an opportunity to show how Iguana can handle runtime errors.