HL7

HL7 is a combination of the data exchange formats and communication protocols used to connect health care applications.

Read more about HL7 here.

Integrator fully supports all existing HL7 formats and protocols, and is one of the best available HL7 interface engines.

In Integrator the HL7 messages can be send and received using one of the following connectors:

Supported HL7 formats:

Lab Order processing

Flow Description

Hospital sends HL7 2.3 message containing order via SFTP to their pre-defined vendor folder on the Data Exchange Server. Interface engine (Integrator) formats source message to AP Easy specification and moves it to the pre-defined client folder on the server. The client is a Lab, such as Quest Diagnostics.

Source HL7 message

MSH|^~\&|MM|MOD6078|AP Easy|MOD6078|20161216231442||ORM^O01|211072-20161216231442|P|2.3|
PID|1|12345678|123456||LastName^FirstName^MiddleName||19050925|M|||1000 PERSHING LN^^FORKED RIVER^NJ^08731||||||||11122333
IN1|1||12379|MEDICARE B-NJ: NOVITAS SOLUTIONS|PO BOX 1234^^MECHANICSBURG^PA^170551802||||||||||PRIMARY|LastName^FirstName^MiddleName|1|19050925|^^^^|||1||||||||||||||1504245123
IN1|2||61667|BCBS-NJ: HORIZON BCBS - OUT OF STATE - BLUE CARD (PPO)|PO BOX 11122^^NEPTUNE^NJ^077541301|||00865600002|||||||SECONDARY|LastName^FirstName^MiddleName|1|19050925|^^^^|||2||||||||||||||YHB3HZN64699555
ORC|NW|211072-A||211072|||||20161216231442|||^HAHN^JUSTENE^
OBR|1|211072-A|A|D48.5^Biopsy by Shave Method;H and E||20161216231442|20161216081131||||||Morphology:  erythematous scaly papule;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central parietal scalp;||^^^left central parietal scalp|^HAHN^JUSTENE^|||||||||F||^^^^^^^^||||
NTE|1|Specimen Label|shave bx
NTE|2|Specimen Source|A) left central parietal scalp
NTE|3|Morphology|erythematous scaly papule
NTE|4|Procedure Name|Biopsy by Shave Method
NTE|5|triangulation|from lt tragus 14.5cm up and 3cm rt
NTE|6|triangulation|0.6cm
DG1|1|I10|D48.5|Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis
ORC|NW|211072-B||211072|||||20161216231442|||^HAHN^JUSTENE^
OBR|1|211072-B|B|D48.5^Biopsy by Shave Method;H and E||20161216231442|20161216081049||||||Morphology: Erythematous scaling plaque;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central frontal scalp;||^^^left central frontal scalp|^HAHN^JUSTENE^|||||||||F||^^^^^^^^||||
NTE|1|Specimen Label|shave bx
NTE|2|Specimen Source|B) left central frontal scalp
NTE|3|Morphology|Erythematous scaling plaque
NTE|4|Procedure Name|Biopsy by Shave Method
NTE|5|triangulation|from lt tragus 14.5 cm up and 2cm rt
NTE|6|triangulation|1cm
DG1|1|I10|D48.5|Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis

Reformatted destination HL7 message

MSH|^~\&|Integrator|MOD6078|AP Easy|MOD6078|20161216231442||ORM^O01|211072-20161216231442|P|2.3
PID|1|12345678|123456||LastName^FirstName^MiddleName||19050925|M|||1000 PERSHING LN^^FORKED RIVER^NJ^08731||||||||11122333
PV1|1||^^^&MOD6078||||^HAHN^JUSTENE
IN1|1||12379|MEDICARE B-NJ: NOVITAS SOLUTIONS|PO BOX 1234^^MECHANICSBURG^PA^170551802||||||||||PRIMARY|LastName^FirstName^MiddleName|1|19050925||||1||||||||||||||1504245123
IN1|2||61667|BCBS-NJ: HORIZON BCBS - OUT OF STATE - BLUE CARD (PPO)|PO BOX 11122^^NEPTUNE^NJ^077541301|||00865600002|||||||SECONDARY|LastName^FirstName^MiddleName|1|19050925||||2||||||||||||||YHB3HZN64699555
ORC|NW|211072-A||211072|||||20161216231442|||^HAHN^JUSTENE
OBR|1|211072-A|A|D48.5^Biopsy by Shave Method;H and E||20161216231442|20161216081131||||||Morphology:  erythematous scaly papule;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central parietal scalp;||^^^left central parietal scalp|^HAHN^JUSTENE|||||||||F
OBX|1|FT|03^Clinical||Morphology:  erythematous scaly papule;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central parietal scalp;
OBX|2|FT|01^Site||A) left central parietal scalp
OBX|3|FT|02^Procedure||SHAVE
ORC|NW|211072-B||211072|||||20161216231442|||^HAHN^JUSTENE
OBR|1|211072-B|B|D48.5^Biopsy by Shave Method;H and E||20161216231442|20161216081049||||||Morphology: Erythematous scaling plaque;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central frontal scalp;||^^^left central frontal scalp|^HAHN^JUSTENE|||||||||F
OBX|1|FT|03^Clinical||Morphology: Erythematous scaling plaque;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central frontal scalp;
OBX|2|FT|01^Site||B) left central frontal scalp
OBX|3|FT|02^Procedure||SHAVE

Connections

Prerequisites

Before creating a flow, lets create all required folders on the Data Exchange Server:

source-orders
    processing
    failed
destination-orders

The Processing

  1. Hospital sends order via SFTP to the source-orders folder.
  2. Integrator moves order to the processing folder.
  3. Integrator reformats message to the AP Easy specification, which is understood by the Lab software and moves it to the destination-orders folder.
  4. If there is an error during step #3, Integrator moves original message to the failed folder.

Important: suggested approach is just one of the many. We want to make our flow processing as reliable as possible, hence all the file movements between the folders. Ultimately #3 does all the hard lifting, everything else is just an orchestration.

The Flow

Step 1. Create all required SFTP connections, one connection per-folder above:

hl7-vendor-client-order-connections

Important: when creating connections, set the following properties:

Step 2. Create HL7 format

When creating a format set HL7 Version to 2.3 and leave everything else default:

hl7-order-format

Step 3. Create a "reformat" flow.

This flow will reformat source message in the processing folder to AP Easy specification and will move it to the destination-orders folder.

For this flow we will need the following connections and formats:

1) Start creating a flow by clicking the Add flow button on the Flow Builder page.

2) Type in HL7 in the Search... box and select Read HL7 message, create different HL7 message

3) In the opened window select source (FROM) connection which points to the processing folder and destination (TO) connection which points to the destination-orders folder.

4) Select format created in step 2 for the FROM and TO formats.

5) Enter *.hl7 in the FROM and Vendor_Order_Destination.hl7 in the TO fields:

hl7-order-reformat

6) Click the mapping button and select Parameters tab.

7) Enter order in the Transformation Name field. It will be used in the reports and dashboard.

8) Select Ignore Empty Source. By doing this you will allow flow to finish even when there are no files in the processing folder.

9) Enter the following code in the Preprocessing field. This code does all the reformatting. Read more about using JavaScript when source is an HL7 message or destination is an HL7 message.

importPackage(Packages.ca.uhn.hl7v2.model.v23.message);
importPackage(Packages.ca.uhn.hl7v2.model.v23.segment);
importPackage(Packages.ca.uhn.hl7v2.model.v23.datatype);

var message = dataSet.getActualData();

// clone source message
var destMessage = ClassUtils.clone(message);

// change sender
destMessage.getMSH().getSendingApplication().getNamespaceID().setValue("Integrator");

var numOrders = destMessage.getORDERReps();

// add OBX segmentts, remove NTE and DG segments
for (num = 0; num < numOrders; num++) {
   var order = destMessage.getORDER(num);

   var detail = order.getORDER_DETAIL();

   var allNte = detail.getNTEAll();

   var maxId = 1;
   for (i = 0; i < allNte.length; i++) {
      // skip 1,3,5,6
      if (i == 0 || i == 2 || i == 4 || i == 5) {
          continue;
      }  

      maxId++;
   } 

   // obx 1
   var obx = detail.insertOBSERVATION(0).getOBX();
   obx.getObx1_SetIDOBX().setValue(1);
   // OBX-2 -> FT ?
   obx.getObx2_ValueType().setValue("FT");
   // OBX-3.1 -> max ID ?
   obx.getObx3_ObservationIdentifier().getIdentifier().setValue("0" + maxId);
   // OBX-3.2 -> Clinical ?
   obx.getObx3_ObservationIdentifier().getText().setValue("Clinical");
   // OBX-5 = OBR-13 in source message
   var ft = new FT(destMessage);
   ft.setValue(detail.getOBR().getObr13_RelevantClinicalInformation().getValue());
   obx.insertObservationValue(0).setData(ft);

   var index = 1;

   for (i = 0; i < allNte.length; i++) {
      var nte = allNte.get(i);

      // skip 1,3,5,6
      if (i == 0 || i == 2 || i == 4 || i == 5) {
          continue;
      }  

      var obx = detail.insertOBSERVATION(index++).getOBX();

      // OBX-1 -> index ? 
      obx.getObx1_SetIDOBX().setValue(index);
      // OBX-2 -> FT ?
      obx.getObx2_ValueType().setValue("FT");
      // OBX-3.1 -> index ?  
      obx.getObx3_ObservationIdentifier().getIdentifier().setValue("0" + (index - 1));

      // OBX-3.2 -> mapping, from NTE-2 ?  
      var qualifier = nte.getNte2_SourceOfComment().getValue().toLowerCase();
      obx.getObx3_ObservationIdentifier().getText().setValue(qualifier.contains("specimen") ? "Site" : "Procedure");

      // OBX-5 = mapping from NTE-3
      var obx5Value = nte.getNte3_Comment(0).getValue();
      var nte3 = obx5Value.toLowerCase();

      if (nte3.contains("biopsy by punch method")) {
         obx5Value = "PUNCH"; 
      } else if (nte3.contains("biopsy by shave method")) {
         obx5Value = "SHAVE"; 
      } else if (nte3.contains("shave removal")) {
         obx5Value = "SHAVE"; 
      } else if (nte3.contains("curettage and destruction with pathology")) {
         obx5Value = "SHAVE"; 
      } else if (nte3.contains("punch excision")) {
         obx5Value = "EXCISION"; 
      } else if (nte3.contains("excision")) {
         obx5Value = "EXCISION"; 
      }   

      var ft = new FT(destMessage);
      ft.setValue(obx5Value);
      obx.insertObservationValue(0).setData(ft);


   }  

   // remove NTE segments
   while (detail.getNTEReps() > 0) {
     detail.removeNTE(0);
   }  

   // remove DG1 segments
   while (detail.getDG1Reps() > 0) {
     detail.removeDG1(0);
   }  
}

// add segment PV1
var pv1 = destMessage.getPATIENT().getPATIENT_VISIT().getPV1();

// PV1-1: Patient Visit ID 
pv1.getPv11_SetIDPatientVisit().setValue("1");

// PV1-3 = MSH-4  
pv1.getAssignedPatientLocation().getFacility().getUniversalID().setValue(
  destMessage.getMSH().getMsh4_SendingFacility().getNamespaceID().getValue());

// XCN - attending doctor
var doctor = pv1.getAttendingDoctor(0);

if (message.getORDER().getORC().getOrc12_OrderingProviderReps() > 0) {
   var provider = message.getORDER().getORC().getOrc12_OrderingProvider(0);

  // PV1-7.1 = ORC-12.1 
   doctor.getIDNumber().setValue(provider.getXcn1_IDNumber().getValue());

   // PV1-7.2 = ORC-12.2 
   doctor.getFamilyName().setValue(provider.getFamilyName().getValue());

   // PV1-7.3 = ORC-12.3 
   doctor.getGivenName().setValue(provider.getGivenName().getValue());

  // PV1-7.4 = ORC-12.4 
   doctor.getMiddleInitialOrName().setValue(provider.getXcn4_MiddleInitialOrName().getValue());
}  

dataSet.setActualData(destMessage);

10) Save and test the flow.

Step 4. Create move files to processing flow.

This flow moves files from the source-orders folder to the processing folder.

For this flow we will need the following connections:

1) Start creating a flow by clicking the Add flow button on the Flow Builder page.

2) Type in files in the Search... box and select File Management

3) In the opened window select source (FROM) connection which points to the source-orders folder and destination (TO) connection which points to the processing folder.

hl7-order-to-processing

4) Click the mapping button and select Parameters tab.

5) Select Move for the Action. By selecting this action you will configure flow to move files from the source-orders to the processing.

6) Save and test the flow.

Step 5. Create clean up flow.

This flow deletes files from the processing folder or, if there is an error, moves files to the failed folder.

1) Start creating a flow by clicking the Add flow button on the Flow Builder page.

2) Type in files in the Search... box and select File Management

3) In the opened window add two transformations:

4) Save and test the flow.

Step 6. Put it all together.

In a previous 5 steps we created 3 flows which:

In order to put it all together we will need to create nested flow.

Add the following flows to the nested flow:

1) Flow created in Step 4.

2) Flow created in step 3.

3) Flow created in step 5.

hl7-order-nested-flow

Save and test the flow.

Step 7. Schedule the flow created in step 6 to be executed periodically.

Lab Results processing

Flow Description

Client sends HL7 2.3 message containing test results and PDF from AP Easy via SFTP to their pre-defined client folder on Data Exchange Server. Interface engine (Integrator) formats source message to vendor specifications, base x64 encodes the PDF into the HL7 message as a last OBX segment, and moves file to pre-defined vendor folder on the server. Vendor retrieves messages via SFTP. The client is a Lab, such as Quest Diagnostics.

Source HL7 message

MSH|^~\&|AP Easy|COMPASS||MOD6078|20161216140344||ORU^R01|C16-23271|P|2.2
PID|1|123456|Pt000123456||TEST^JACK^||191220|M|||123 N SMITH ROAD^^GALLOWAY^NJ^08205||||||||||
PV1|1||||||1902855349^Yanusz^Donna^^APN|^^^^|^^^^||||||||^^^^
ORC|RE|210915-A210915-B|C16-23271^AP Easy||CM||||201612150712
OBR|1|210915-A~210915-B~|C16-23271^AP Easy|Surgical Pathology|||201612140000|||||||201612150712||1902855349^Yanusz^Donna^^APN||||||201612160000||SP|F|||||||1093993263^Erickson^Christof^^MD|^^^^|^^^^
OBX|1|TX|Specimen(s) Received||A.  PUNCH.  right medial heel\\.br\\B.  PUNCH.  right medial heel\\.br\\||||||F|||||||
OBX|2|TX|Clinical Information||A.  Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister\\.br\\B.  Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister\\.br\\||||||F|||||||
OBX|3|TX|Gross Description||A.  A tan three piece aggregate 3x2x12 mm punch biopsy skin specimen was received in formalin. The larger piece was bisected and entirely submitted with one punch, as well as with the smaller piece in one cassette.\\.br\\B.  A tan two piece aggregate 3x2x8 mm punch biopsy skin specimen received in Michel's medium. One punch and the remaining piece were entirely submitted for frozen sectioning.\\.br\\||||||F|||||||
OBX|4|TX|Microscopic Description||A.  In thick skin there is subepidermal vesicular dermatitis with an infiltrate of lymphocytes, histiocytes and eosinophils in the papillary dermis beneath. A special stain, PAS, is negative for hyphae. \\.br\\B.  Frozen tissue examination was performed and shows vesicle formation with loss of the overlying epidermis.\\.br\\DIRECT IMMUNOFLUORESCENCE RESULTS:\\.br\\     IgG - negative\\.br\\     C3  - negative\\.br\\     IgA - negative\\.br\\     IgM - negative\\.br\\     Fibrinogen - negative\\.br\\Positive and negative controls were examined and showed appropriate staining. Intrinsic staining of patient tissue was appropriate.\\.br\\\\.br\\This test was developed and its performance characteristics determined by Compass Dermatopathology. It has not been cleared or approved by the U.S. Food and Drug Administration (USFDA). The USFDA has determined that such clearance or approval is not necessary. This test is used for clinical purposes and should not be regarded as investigational or for research. This laboratory is certified under the Clinical Laboratory Improvement Amendments (CLIA) as qualified to perform high complexity clinical laboratory testing.\\.br\\\\.br\\The CPT and ICD-10 codes are for information purposes only and are based on AMA guidelines without regard to specific payor requirements. \\.br\\||||||F|||||||
OBX|5|TX|Diagnosis||A.  SUBEPIDERMAL VESICULAR DERMATITIS WITH EOSINPHILS\\.br\\B.  NON-DIAGNOSTIC Direct ImmunofluorescencE\\.br\\\\.br\\||||||F|||||||
OBX|6|TX|Comments||A.  These changes may be seen in bullous pemphigoid. The histologic differential diagnosis includes a bullous hypersensitivity reaction and other immunobullous disorders. \\.br\\B.  The biopsy shows blister formation with loss of the epidermis which results in artifactual changes which render interpretation of immunofluorescence patterns problematic. Repeat perilesional biopsy for direct immunofluorescence is recommended.\\.br\\\\.br\\||||||F|||||||
OBR|2|210915-A~210915-B~|C16-23271^AP Easy|Surgical Pathology|||201612140000|||||||201612150712||1902855349^Yanusz^Donna^^APN||||||201612160000||SP|F|||||||1093993263^Erickson^Christof^^MD|^^^^|^^^^
OBX|1|TX|Specimen(s) Received_1||PUNCH.  RIGHT MEDIAL HEEL|||N|||F|||||||
OBX|2|TX|Specimen(s) Received_2||PUNCH.  RIGHT MEDIAL HEEL|||N|||F|||||||
OBX|3|TX|Clinical Information_1||Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister|||N|||F|||||||
OBX|4|TX|Clinical Information_2||Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister|||N|||F|||||||
OBX|5|TX|Gross Description_1||A tan three piece aggregate 3x2x12 mm punch biopsy skin specimen was received in formalin. The larger piece was bisected and entirely submitted with one punch, as well as with the smaller piece in one cassette.|||N|||F|||||||
OBX|6|TX|Gross Description_2||A tan two piece aggregate 3x2x8 mm punch biopsy skin specimen received in Michel's medium. One punch and the remaining piece were entirely submitted for frozen sectioning.|||N|||F|||||||
OBX|7|TX|Microscopic Description_1||In thick skin there is subepidermal vesicular dermatitis with an infiltrate of lymphocytes, histiocytes and eosinophils in the papillary dermis beneath. A special stain, PAS, is negative for hyphae. |||N|||F|||||||
OBX|8|TX|Microscopic Description_2||Frozen tissue examination was performed and shows vesicle formation with loss of the overlying epidermis.\\.br\\DIRECT IMMUNOFLUORESCENCE RESULTS:\\.br\\     IgG - negative\\.br\\     C3  - negative\\.br\\     IgA - negative\\.br\\     IgM - negative\\.br\\     Fibrinogen - negative\\.br\\Positive and negative controls were examined and showed appropriate staining. Intrinsic staining of patient tissue was appropriate.\\.br\\\\.br\\This test was developed and its performance characteristics determined by Compass Dermatopathology. It has not been cleared or approved by the U.S. Food and Drug Administration (USFDA). The USFDA has determined that such clearance or approval is not necessary. This test is used for clinical purposes and should not be regarded as investigational or for research. This laboratory is certified under the Clinical Laboratory Improvement Amendments (CLIA) as qualified to perform high complexity clinical laboratory testing.\\.br\\\\.br\\The CPT and ICD-10 codes are for information purposes only and are based on AMA guidelines without regard to specific payor requirements. |||N|||F|||||||
OBX|9|TX|Diagnosis_1||SUBEPIDERMAL VESICULAR DERMATITIS WITH EOSINPHILS|||N|||F|||||||
OBX|10|TX|Diagnosis_2||NON-DIAGNOSTIC DIRECT IMMUNOFLUORESCENCE^B|||N|||F|||||||
OBX|11|TX|Comments_1||THESE CHANGES MAY BE SEEN IN BULLOUS PEMPHIGOID. THE HISTOLOGIC DIFFERENTIAL DIAGNOSIS INCLUDES A BULLOUS HYPERSENSITIVITY REACTION AND OTHER IMMUNOBULLOUS DISORDERS. |||N|||F|||||||
OBX|12|TX|Comments_2||THE BIOPSY SHOWS BLISTER FORMATION WITH LOSS OF THE EPIDERMIS WHICH RESULTS IN ARTIFACTUAL CHANGES WHICH RENDER INTERPRETATION OF IMMUNOFLUORESCENCE PATTERNS PROBLEMATIC. REPEAT PERILESIONAL BIOPSY FOR DIRECT IMMUNOFLUORESCENCE IS RECOMMENDED.^B|||N|||F|||||||

Reformatted destination HL7 message

MSH|^~\\&|AP Easy|COMPASS||MOD6078|20161216140344||ORU^R01|C16-23271|P|2.2
PID|1|123456|Pt000123456||TEST^JACK^||191220|M|||123 N SMITH ROAD^^GALLOWAY^NJ^08205||||||||||
PV1|1||||||1902855349^Yanusz^Donna^^APN|^^^^|^^^^||||||||^^^^
ORC|RE|210915-A|C16-23271^AP Easy|210915|CM||||201612150712
OBR|1|210915-A|C16-23271^AP Easy|Surgical Pathology|||201612140000|||||||201612150712||1902855349^Yanusz^Donna^^APN||||||201612160000||SP|F|||||||1093993263^Erickson^Christof^^MD|^^^^|^^^^
OBX|1|TX|Specimen(s) Received||PUNCH.  RIGHT MEDIAL HEEL|||N|||F
OBX|2|TX|Clinical Information||Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister|||N|||F
OBX|3|TX|Gross Description||A tan three piece aggregate 3x2x12 mm punch biopsy skin specimen was received in formalin. The larger piece was bisected and entirely submitted with one punch, as well as with the smaller piece in one cassette.|||N|||F
OBX|4|TX|Microscopic Description||In thick skin there is subepidermal vesicular dermatitis with an infiltrate of lymphocytes, histiocytes and eosinophils in the papillary dermis beneath. A special stain, PAS, is negative for hyphae. |||N|||F
OBX|5|TX|Diagnosis||SUBEPIDERMAL VESICULAR DERMATITIS WITH EOSINPHILS|||N|||F
OBX|6|TX|Comments||THESE CHANGES MAY BE SEEN IN BULLOUS PEMPHIGOID. THE HISTOLOGIC DIFFERENTIAL DIAGNOSIS INCLUDES A BULLOUS HYPERSENSITIVITY REACTION AND OTHER IMMUNOBULLOUS DISORDERS. |||N|||F
ORC|RE|210915-B|C16-23271^AP Easy|210915|CM||||201612150712
OBR|2|210915-B|C16-23271^AP Easy|Surgical Pathology|||201612140000|||||||201612150712||1902855349^Yanusz^Donna^^APN||||||201612160000||SP|F|||||||1093993263^Erickson^Christof^^MD|^^^^|^^^^
OBX|7|TX|Specimen(s) Received||PUNCH.  RIGHT MEDIAL HEEL|||N|||F
OBX|8|TX|Clinical Information||Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister|||N|||F
OBX|9|TX|Gross Description||A tan two piece aggregate 3x2x8 mm punch biopsy skin specimen received in Michel's medium. One punch and the remaining piece were entirely submitted for frozen sectioning.|||N|||F
OBX|10|TX|Microscopic Description||Frozen tissue examination was performed and shows vesicle formation with loss of the overlying epidermis.\\.br\\DIRECT IMMUNOFLUORESCENCE RESULTS:\\.br\\     IgG - negative\\.br\\     C3  - negative\\.br\\     IgA - negative\\.br\\     IgM - negative\\.br\\     Fibrinogen - negative\\.br\\Positive and negative controls were examined and showed appropriate staining. Intrinsic staining of patient tissue was appropriate.\\.br\\\\.br\\This test was developed and its performance characteristics determined by Compass Dermatopathology. It has not been cleared or approved by the U.S. Food and Drug Administration (USFDA). The USFDA has determined that such clearance or approval is not necessary. This test is used for clinical purposes and should not be regarded as investigational or for research. This laboratory is certified under the Clinical Laboratory Improvement Amendments (CLIA) as qualified to perform high complexity clinical laboratory testing.\\.br\\\\.br\\The CPT and ICD-10 codes are for information purposes only and are based on AMA guidelines without regard to specific payor requirements. |||N|||F
OBX|11|TX|Diagnosis||NON-DIAGNOSTIC DIRECT IMMUNOFLUORESCENCE|||N|||F
OBX|12|TX|Comments||THE BIOPSY SHOWS BLISTER FORMATION WITH LOSS OF THE EPIDERMIS WHICH RESULTS IN ARTIFACTUAL CHANGES WHICH RENDER INTERPRETATION OF IMMUNOFLUORESCENCE PATTERNS PROBLEMATIC. REPEAT PERILESIONAL BIOPSY FOR DIRECT IMMUNOFLUORESCENCE IS RECOMMENDED.|||N|||F
OBX|13|ED|PDF^PDF BASE64|1|^^PDF^Base64^$\{ATTACH:44713897-7733-4c3c-812d-ce4424183c36\}

Connections

Prerequisites

Before creating a flow, lets create all required folders on the Data Exchange Server:

source-results
    processing (remote)
    failed
destination-results

To read and encode PDF file we will need to store it in the Integrator Home folder. Integrator Home folder is automatically created for each client, so user doesn't need to worry about creating it, but still need to have a connection, which points to this folder. Let's call this folder processing (local). It is going to be under the Integrator Home folder.

home
    processing (local)

The Processing

  1. Lab sends results via SFTP to the source-results folder.
  2. Integrator moves results and pdf to the processing (remote) and to the processing (local) folders. Files in the processing (remote) folder are used as a copy of the original message and pdf. If transformation fails, files from the processing (remote) will be copied to the failed folder.
  3. Using files in processing (local) folder, the Integrator reformats message from the AP Easy specification to the vendor specs, Base64 encodes PDF and attaches it in the last OBX segment, than moves message to the destination-results folder.
  4. If there is an error during step #3, Integrator moves original message and pdf from the processing (remote) to the failed folder. Otherwise it deletes files in the processing (remote) and processing (local) folders.

Important: suggested approach is just one of the many. We want to make our flow processing as reliable as possible, hence all the file movements between the folders. Ultimately #2 and #3 do all the hard lifting, everything else is just an orchestration.

The Flow

Step 1. Create all required SFTP connections, one connection per-folder above:

hl7-results-connections

Important: when creating connections, set the following properties:

Step 2. Create connection for the processing (local) folder. The Local Files connection type must be used.

Since you are locked to the Home folder as your root folder, you will need to use Files fields to point connection to the actual local folder under the Home.

hl7-results-local-connection

Step 3. If you don't have it already, create HL7 format

When creating a format set HL7 Version to 2.3 and leave everything else default:

hl7-order-format

Step 4. Create a "reformat" flow.

This flow will reformat source message in the processing (local) folder from AP Easy specification to the vendor specs, base x64 encode the PDF and attach it into the HL7 message in the last OBX segment. Than it will move reformatted message to the destination-results folder.

For this flow we will need the following connections and formats:

1) Start creating a flow by clicking the Add flow button on the Flow Builder page.

2) Type in HL7 in the Search... box and select Read HL7 message, create different HL7 message

3) In the opened window select source (FROM) connection which points to the processing (local) folder and destination (TO) connection which points to the destination-reults folder.

4) Select format created in step 2 for the FROM and TO formats.

5) Enter result.hl7 in the FROM and Vendor_Result_Destination.hl7 in the TO fields:

hl7-results-reformat

6) Click the mapping button and select Parameters tab.

7) Enter result in the Transformation Name field. It will be used in the reports and dashboard.

8) Select Ignore Empty Source. By doing this you will allow flow to finish even when there are no files in the processing (local) folder.

9) Enter the following code in the Preprocessing field. This code does all the reformatting. Read more about using JavaScript when source is an HL7 message or destination is an HL7 message.

importPackage(Packages.ca.uhn.hl7v2.model.v23.message);
importPackage(Packages.ca.uhn.hl7v2.model.v23.segment);
importPackage(Packages.ca.uhn.hl7v2.model.v23.datatype);
importPackage(Packages.ca.uhn.hl7v2.util);
importPackage(java.io);

var message = dataSet.getActualData();

var destMessage = new ORU_R01();

// copy MSH from the source
DeepCopy.copy(message.getMSH(), destMessage.getMSH());

// change sender
destMessage.getMSH().getSendingApplication().getNamespaceID().setValue("Integrator");

var responses = message.getRESPONSEAll();

for (resNum = 0; resNum < responses.length; resNum++) {
   var response = responses.get(resNum);

   var newResponse = destMessage.insertRESPONSE(resNum);

   // copy PID AND PV1 from the source 
   DeepCopy.copy(response.getPATIENT().getPID(), newResponse.getPATIENT().getPID());
   DeepCopy.copy(response.getPATIENT().getVISIT().getPV1(), newResponse.getPATIENT().getVISIT().getPV1());

   // Everything below and including OBR|2| in source message is not used.
   var orderObservation = response.getORDER_OBSERVATION();

   var sourceObr = orderObservation.getOBR();

   var orderNums = sourceObr.getPlacerOrderNumber();

   if (orderNums != null) {
        for (orNum = 0; orNum < orderNums.length; orNum++) {
            var or = orderNums[orNum];

            var destOrderObservation = newResponse.insertORDER_OBSERVATION(orNum);

            // copy ORC from the source and chnage ORC-2  
            DeepCopy.copy(orderObservation.getORC(), destOrderObservation.getORC());
            while (destOrderObservation.getORC().getOrc2_PlacerOrderNumberReps() > 1) destOrderObservation.getORC().removeOrc2_PlacerOrderNumber(1); 
            destOrderObservation.getORC().getOrc2_PlacerOrderNumber(0).getEntityIdentifier().setValue(or.getEntityIdentifier().getValue());

            // copy OBR from the source
            DeepCopy.copy(orderObservation.getOBR(), destOrderObservation.getOBR());
            while (destOrderObservation.getOBR().getObr2_PlacerOrderNumberReps() > 1) destOrderObservation.getOBR().removeObr2_PlacerOrderNumber(1); 
            destOrderObservation.getOBR().getObr2_PlacerOrderNumber(0).getEntityIdentifier().setValue(or.getEntityIdentifier().getValue());

            var observations = orderObservation.getOBSERVATIONAll();

            // copy source OBX to dest OBX
            for (index = 0; index < observations.length; index++) {
                 var observation = observations.get(index);

                 var newObservation = destOrderObservation.insertOBSERVATION(index);

                 DeepCopy.copy(observation.getOBX(), newObservation.getOBX());
            }

            // add pdf attachment as last obx 
            if (orNum == orderNums.length - 1) {
                var folder = FilenameUtils.getFullPath(etlConfig.getAliasesMap().get(task.getConnectionName()).getUrl()); 

                var file = folder + "result.pdf";

                if (FileUtils.fileExists(file)) {
                    var attachment = Base64.encodeBytes(FileUtils.getBytesFromFile(new File(file)), Base64.DONT_BREAK_LINES);

                    var newObservation = destOrderObservation.insertOBSERVATION(observations.length);

                    newObservation.getOBX().getObx1_SetIDOBX().setValue(observations.length + 1);
                    newObservation.getOBX().getObx2_ValueType().setValue("ED");
                    newObservation.getOBX().getObservationIdentifier().getCe1_Identifier().setValue("PDF");
                    newObservation.getOBX().getObservationIdentifier().getCe2_Text().setValue("PDF BASE64");
                    newObservation.getOBX().getObservationSubID().setValue(1);

                    var msg = "^^PDF^Base64^${ATTACH:" + attachment + "}";

                    newObservation.getOBX().insertObx5_ObservationValue(0).parse(msg);
                }   
            }    
        }  
    }  

}  

dataSet.setActualData(destMessage);

Important: the part of the code below is responsive for reading pdf from the processing (local) folder, base64 encoding it, and attaching to the reformatted message. The expected file name is result.pdf:

....
            // add pdf attachment as last obx 
            if (orNum == orderNums.length - 1) {
                var folder = FilenameUtils.getFullPath(etlConfig.getAliasesMap().get(task.getConnectionName()).getUrl()); 

                var file = folder + "result.pdf";

                if (FileUtils.fileExists(file)) {
                    var attachment = Base64.encodeBytes(FileUtils.getBytesFromFile(new File(file)), Base64.DONT_BREAK_LINES);

                    var newObservation = destOrderObservation.insertOBSERVATION(observations.length);

                    newObservation.getOBX().getObx1_SetIDOBX().setValue(observations.length + 1);
                    newObservation.getOBX().getObx2_ValueType().setValue("ED");
                    newObservation.getOBX().getObservationIdentifier().getCe1_Identifier().setValue("PDF");
                    newObservation.getOBX().getObservationIdentifier().getCe2_Text().setValue("PDF BASE64");
                    newObservation.getOBX().getObservationSubID().setValue(1);

                    var msg = "^^PDF^Base64^${ATTACH:" + attachment + "}";

                    newObservation.getOBX().insertObx5_ObservationValue(0).parse(msg);
                }   
            }    
....            

Important: please also keep in mind that, according to the hl7 specs, the size of the attachment in the OBX segment is limited to 65 Kb.

10) Save and test the flow.

Step 5. Create move files to processing flow.

This flow moves files from the source-results folder to the processing (local) and processing (remote) folders. Files in the processing (remote) folder have the same names as original files. Files in the processing (local) will be renamed to the result.*.

For this flow we will need the following connections:

1) Start creating a flow by clicking the Add flow button on the Flow Builder page.

2) Type in files in the Search... box and select File Management

3) In the opened window add 4 transformations:

hl7-results-copy-and-rename-files

4) Save and test the flow.

Step 6. Create clean up flow.

This flow deletes files from the both processing folders or, if there is an error, moves files to the failed folder.

1) Start creating a flow by clicking the Add flow button on the Flow Builder page.

2) Type in files in the Search... box and select File Management

3) In the opened window add 3 transformations:

4) Save and test the flow.

Step 7. Put it all together.

In a previous 6 steps we created 3 flows which:

In order to put it all together we will need to create nested flow.

Add the following flows to the nested flow:

1) Flow created in step 5.

2) Flow created in step 4.

3) Flow created in step 6.

hl7-results-nested

Save and test the flow.

Step 8. Schedule the flow created in step 7 to be executed periodically.

Sending messages over MLLP

Step 1. Create HL7 MLLP Sender connection.

Step 2. Create HL7 Format you are going to be using for the destination (TO).

Step 3. Start creating an HL7 flows in the Flow Builder page by clicking the + button and typing in hl7 in the search box.

Step 4. Depending on your source (FROM) choose either "Extract from files, create HL7 message" or "Read HL7 messages, create different HL7 messages".

Step 5. Continue by defining source (FROM) and destination (TO).

Step 6. For the destination (TO) use connection created in step 1 and format created in step 2.

Step 7. Continue by adding new transformations and defining parameters.

Receiving messages over MLLP

Step 1. Create HL7 MLLP Listener.

Important: when configuring HL7 MLLP Listener make sure that your are using unique port for each listener. If you are running Integrator on premise - make sure that ports configured for the listener are open. If you are using Integrator deployed on a cloud - please contact Etlworks supports.

Step 2. Create HL7 Format you are going to be using for the source (TO).

Step 3. Start creating an HL7 flows in the Flow Builder page by clicking the + button and typing in hl7 in the search box.

Step 4. Depending on your destination (TO) choose either "Read HL7 messages, create files", "Read HL7 messages, create different HL7 messages" or "Read HL7 messages, load data into the database".

Step 5. Continue by defining source (FROM) and destination (TO).

Step 6. For the source (FROM) use connection created in step 1 and format created in step 2.

Step 7. Continue by adding new transformations and defining parameters.

Step 8. Schedule event-driven flow.

Note: all messages received by MLLP listener can be found in Messages.

Sending messages over HTTP

Step 1. Create HTTP or HL7 HTTP Sender connection. The former is more generic and supports more options, the later is specific to HL7 but has some stability issues (hence the beta tag).

Step 2. Create HL7 Format you are going to be using for the destination (TO).

Step 3. Start creating an HL7 flows in the Flow Builder page by clicking the + button and typing in hl7 in the search box.

Step 4. Depending on your source (FROM) choose either "Extract from files, create HL7 message" or "Read HL7 messages, create different HL7 messages".

Step 5. Continue by defining source (FROM) and destination (TO).

Step 6. For the destination (TO) use connection created in step 1 and format created in step 2.

Step 7. Continue by adding new transformations and defining parameters.

Receiving messages over HTTP

Step 1. Create HTTP Listener.

Important: when configuring HTTP Listener make sure that your are using unique URL Ending for each listener.
Step 2. Create HL7 Format you are going to be using for the source (TO).

Step 3. Start creating an HL7 flows in the Flow Builder page by clicking the + button and typing in hl7 in the search box.

Step 4. Depending on your destination (TO) choose either "Read HL7 messages, create files", "Read HL7 messages, create different HL7 messages" or "Read HL7 messages, load data into the database".

Step 5. Continue by defining source (FROM) and destination (TO).

Step 6. For the source (FROM) use connection created in step 1 and format created in step 2.

Step 7. Continue by adding new transformations and defining parameters.

Step 8. Schedule event-driven flow.

Note: all messages received by MLLP listener can be found in Messages.

Important: read more how third-party application can send http requests to the Integrator.