Skip to main content

Data Map Nodes

A Data Map node converts each message it receives from one format to another. You draw the mapping in the Map view: link a source field to a destination field, pick how its value is converted, and the node generates readable Lua that does the work.

Source → Data Map (HL7 v2 ADT^A01 → FHIR Bundle) → Destination

It replaces hand-written mapping code for the common cases, without hiding anything. Everything the node runs is ordinary Lua in the node's files, which you can read, test, debug and commit like any other script.


What it converts​

A node reads one format and builds one format. Every combination below is supported except FHIR to FHIR:

ReadsBuilds
HL7 v2HL7 v2
FHIR R4, R4B, R5: resources or Bundles, JSON or XMLFHIR R4, R4B, R5: a Bundle or a single resource
X12 4010 and 5010X12 4010 and 5010
CDA R2 and C-CDA 5.0CDA R2 and C-CDA 5.0
Database rows, as JSONDatabase rows, as JSON
Your own JSON or XML documentsYour own JSON or XML documents

One node builds one output format: two output formats means two nodes. Within that format, a node can take and build as many message types as you like. For example, ADT^A01, ADT^A08 and ORU^R01 in, each mapped to its own FHIR Bundle.


Adding one​

  1. In the Workflow Builder, drag Data Map from the Transform group onto the canvas, and connect it between a source and a destination.
  2. Open the node's Scripting tab. It opens in the Map view, on a Create your first map card.
  3. Select + New map, or Import existing map to start from a map built in another node or saved to a file (see Moving maps between nodes). New map opens a short wizard that asks, one step at a time:
    1. Source message: the protocol and version it reads, and the message it takes (ADT_A01, Patient, 837P, a table, a structure).
    2. Sample data (optional): paste or upload one or more samples, so the board shows real values. For JSON and XML, the structure can be read from the first sample.
    3. Filters: the condition a message must meet for this map to take it. See Conditions.
    4. Destination message: the protocol and version it builds, the message it builds, how the output starts, and the map's name. A later map can start as a copy of an existing one.
  4. Link fields, or select Auto-map to add the standard mappings. See Building a Map.
  5. Run it on a sample. See Testing and Errors.

The first map decides the formats the node reads and builds. The node's later maps use the same formats. When the first map is ready, the node's files are committed for you, so later changes show as changes against that starting point.


Node settings​

Two fields in the node's configuration decide what happens when a message can't be mapped:

FieldOptionsDefault
On ErrorFor a rejected message (it can't be read, no map takes it, or it lacks a value a map requires): Stop the node: nothing more is processed until it is restarted. Skip the message: log the error and carry on with the next. Any other error, such as one in your own Lua or a message that can't be sent, always stops the nodeStop the node
Unknown MessagesFor a message no map takes: Treat as an error (then On Error applies), Skip the message, or Pass it through unchangedTreat as an error

A message is unknown when it matches none of the messages in the source schema, or when it matches one but meets none of its maps' conditions.


The node's files​

Your own code sits at the top of the node. Everything the Map view manages is in the mapping folder.

FileWhat it isEdited by
main.luaReads each message, hands it to its map, pushes the result, and applies the two settings aboveYou, if you need to
custom.luaYour own Lua functions, which the maps call by name (see Custom Lua)You. The Map view only adds an empty function for a name a map uses that isn't there yet
premap.luaPreMap, which runs on each message just before its mapYou
postmap.luaPostMap, which runs on what the map builtYou
source.json, destination.jsonThe source and destination schemasThe Map view and the Schema Editor
mapping/datamap.luaThe list of maps: name, the message each takes, its condition, and the formatsThe Map view (or by hand)
mapping/maps/<name>.map.luaOne map's rules, as a Lua tableThe Map view (or by hand)
mapping/init.lua, mapping/maps/<name>.luaThe code generated from the mapsGenerated: don't edit
mapping/helpers/*.luaConversion helpers the generated code uses (hl7v2.lua, fhir.lua, convert.lua, normalize.lua, …)Kept up to date by the Map view

Nodes made before the mapping folder existed are moved into it the first time they are opened, and any custom Lua inside their maps is moved into custom.lua as named functions. Nodes that called the destination the target have target.json renamed destination.json the same way. The change shows in Source Control: commit it when you're ready.

PreMap and PostMap​

For anything that applies to every message, rather than to one field, use premap.lua and postmap.lua. The PreMap and PostMap buttons in the Map view's toolbar open them.

-- premap.lua: runs once a map has been found for the message, just before it.
-- Change MsgIn, or return another message to map in its place.
function PreMap(MsgIn, MsgType)
end

-- postmap.lua: runs on what the map built (nil when it built nothing).
-- Change MsgOut, or return another message to send in its place.
function PostMap(MsgOut, MsgIn, MsgType)
end

The Map view never changes either file. main.lua is still there for anything else, such as an extra log line or a header on the outgoing message. The generated files say Do not edit by hand in their first lines. If one is edited anyway, see Hand edits to generated code.


In this section​

PageCovers
Building a MapThe Map view, links, functions, normalizing values, Auto-map, fixed values, custom Lua, schema changes, moving maps between nodes, undo and committing
ConditionsSeveral maps for one message type, and which one takes a message
FormatsWhat is particular to HL7 v2, FHIR, X12, CDA and C-CDA, database rows, JSON and XML
Testing and ErrorsSamples, runs, checks, generated code, and committing