You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ma...@apache.org on 2016/10/11 19:01:17 UTC

nifi git commit: Fixed HL7 segment index bug for order control codes, more testing

Repository: nifi
Updated Branches:
  refs/heads/master ee14ae8af -> 6d5f4777c


Fixed HL7 segment index bug for order control codes, more testing

Signed-off-by: Matt Burgess <ma...@apache.org>

Added NOTICE entries for test data and fixed checkstyle violations

Signed-off-by: Matt Burgess <ma...@apache.org>

This closes #1123


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/6d5f4777
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/6d5f4777
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/6d5f4777

Branch: refs/heads/master
Commit: 6d5f4777c5ce2e7e361dd0d794d6bdd706222c82
Parents: ee14ae8
Author: Joey Frazee <jo...@icloud.com>
Authored: Tue Oct 11 10:10:43 2016 -0500
Committer: Matt Burgess <ma...@apache.org>
Committed: Tue Oct 11 14:57:40 2016 -0400

----------------------------------------------------------------------
 NOTICE                                          |   6 +
 .../processors/hl7/ExtractHL7Attributes.java    |  26 +-
 .../src/main/resources/META-INF/NOTICE          |  15 +
 .../hl7/TestExtractHL7Attributes.java           | 459 +++++++++++++------
 4 files changed, 350 insertions(+), 156 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/6d5f4777/NOTICE
----------------------------------------------------------------------
diff --git a/NOTICE b/NOTICE
index c2026ba..b71bba0 100644
--- a/NOTICE
+++ b/NOTICE
@@ -27,3 +27,9 @@ Copyright 2008-2016 The Apache Software Foundation
 The derived work is adapted from
   release-1.2.1/ql/src/java/org/apache/hadoop/hive/ql/io/orc/WriterImpl.java
 and can be found in the org.apache.hadoop.hive.ql.io.orc package
+
+This includes derived works from the HAPI (MPL 1.1) project (http://hl7api.sourceforge.net/):
+Copyright 2012 University Health Network
+The derived work is adapted from ca.uhn.hapi:hapi-test:2.2 and
+ca.uhn.hapi:hapi-osgi-tests:2.2 and can be found in
+nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/test/java/org/apache/nifi/processors/hl7/TestExtractHL7Attributes.java

http://git-wip-us.apache.org/repos/asf/nifi/blob/6d5f4777/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/java/org/apache/nifi/processors/hl7/ExtractHL7Attributes.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/java/org/apache/nifi/processors/hl7/ExtractHL7Attributes.java b/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/java/org/apache/nifi/processors/hl7/ExtractHL7Attributes.java
index ac5b18e..40a7cf9 100644
--- a/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/java/org/apache/nifi/processors/hl7/ExtractHL7Attributes.java
+++ b/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/java/org/apache/nifi/processors/hl7/ExtractHL7Attributes.java
@@ -20,6 +20,8 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -239,34 +241,32 @@ public class ExtractHL7Attributes extends AbstractProcessor {
 
     private static Map<String, Segment> getAllSegments(final Group group) throws HL7Exception {
         final Map<String, Segment> segments = new TreeMap<>();
-        addSegments(group, segments);
-        return segments;
+        addSegments(group, segments, new HashMap<String, Integer>());
+        return Collections.unmodifiableMap(segments);
     }
 
-    private static void addSegments(final Group group, final Map<String, Segment> segments) throws HL7Exception {
+    private static void addSegments(final Group group, final Map<String, Segment> segments, final Map<String, Integer> segmentIndexes) throws HL7Exception {
         if (!isEmpty(group)) {
             for (final String name : group.getNames()) {
                 for (final Structure structure : group.getAll(name)) {
                     if (group.isGroup(name) && structure instanceof Group) {
-                        addSegments((Group) structure, segments);
+                        addSegments((Group) structure, segments, segmentIndexes);
                     } else if (structure instanceof Segment) {
-                        addSegments((Segment) structure, segments);
+                        addSegments((Segment) structure, segments, segmentIndexes);
                     }
                 }
+                segmentIndexes.put(name, segmentIndexes.getOrDefault(name, 1) + 1);
             }
         }
     }
 
-    private static void addSegments(final Segment segment, final Map<String, Segment> segments) throws HL7Exception {
+    private static void addSegments(final Segment segment, final Map<String, Segment> segments, final Map<String, Integer> segmentIndexes) throws HL7Exception {
         if (!isEmpty(segment)) {
-            final StringBuilder sb = new StringBuilder().append(segment.getName());
+            final String segmentName = segment.getName();
+            final StringBuilder sb = new StringBuilder().append(segmentName);
             if (isRepeating(segment)) {
-                final Type field = segment.getField(1, 0);
-                if (!isEmpty(field)) {
-                    final String fieldValue = field.encode();
-                    final int segmentIndex = StringUtils.isEmpty(fieldValue) ? 1 : Integer.parseInt(fieldValue);
-                    sb.append("_").append(segmentIndex);
-                }
+                final int segmentIndex = segmentIndexes.getOrDefault(segmentName, 1);
+                sb.append("_").append(segmentIndex);
             }
             final String segmentKey = sb.toString();
             segments.put(segmentKey, segment);

http://git-wip-us.apache.org/repos/asf/nifi/blob/6d5f4777/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/resources/META-INF/NOTICE
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/resources/META-INF/NOTICE b/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/resources/META-INF/NOTICE
new file mode 100644
index 0000000..cae5644
--- /dev/null
+++ b/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/main/resources/META-INF/NOTICE
@@ -0,0 +1,15 @@
+nifi-hl7-processors
+Copyright 2015-2016 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+*****************
+Mozilla Public License v1.1
+*****************
+
+src/test/java/org/apache/nifi/processors/hl7/TestExtractHL7Attributes.java
+contains test data and examples from HAPI (http://hl7api.sourceforge.net/):
+
+  (MPL 1.1) (ca.uhn.hapi:hapi-test:2.2 - http://hl7api.sourceforge.net/)
+  (MPL 1.1) (ca.uhn.hapi:hapi-osgi-tests:2.2 - http://hl7api.sourceforge.net/)

http://git-wip-us.apache.org/repos/asf/nifi/blob/6d5f4777/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/test/java/org/apache/nifi/processors/hl7/TestExtractHL7Attributes.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/test/java/org/apache/nifi/processors/hl7/TestExtractHL7Attributes.java b/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/test/java/org/apache/nifi/processors/hl7/TestExtractHL7Attributes.java
index cec8551..be72017 100644
--- a/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/test/java/org/apache/nifi/processors/hl7/TestExtractHL7Attributes.java
+++ b/nifi-nar-bundles/nifi-hl7-bundle/nifi-hl7-processors/src/test/java/org/apache/nifi/processors/hl7/TestExtractHL7Attributes.java
@@ -19,7 +19,8 @@ package org.apache.nifi.processors.hl7;
 import org.apache.nifi.util.MockFlowFile;
 import org.apache.nifi.util.TestRunner;
 import org.apache.nifi.util.TestRunners;
-import org.junit.Assert;
+
+import static org.junit.Assert.assertEquals;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -35,18 +36,73 @@ public class TestExtractHL7Attributes {
         "MSH|^~\\&|XXXXXXXX||HealthProvider||||ORU^R01|Q1111111111111111111|P|2.3|\r\n" +
         "PID|||12345^^^XYZ^MR||SMITH^JOHN||19700100|M||||||||||111111111111|123456789|\r\n" +
         "PD1||||1234567890^LAST^FIRST^M^^^^^NPI|\r\n" +
+        "ORC|NW|987654321^EPC|123456789^EPC||||||20161003000000|||SMITH\r\n" +
         "OBR|1|341856649^HNAM_ORDERID|000000000000000000|648088^Basic Metabolic Panel|||20150101000000|||||||||1620^Johnson^Corey^A||||||20150101000000|||F|||||||||||20150101000000|\r\n" +
         "OBX|1|NM|GLU^Glucose Lvl|59|mg/dL|65-99^65^99|L|||F|||20150102000000|\r\n";
 
+    private void runTests(final String message, final Map<String, String> expectedAttributes, final boolean useSegmentNames, final boolean parseSegmentFields) {
+        final TestRunner runner = TestRunners.newTestRunner(ExtractHL7Attributes.class);
+        runner.setProperty(ExtractHL7Attributes.USE_SEGMENT_NAMES, String.valueOf(useSegmentNames));
+        runner.setProperty(ExtractHL7Attributes.PARSE_SEGMENT_FIELDS, String.valueOf(parseSegmentFields));
+        runner.enqueue(message.getBytes(StandardCharsets.UTF_8));
+
+        runner.run();
+        runner.assertAllFlowFilesTransferred(ExtractHL7Attributes.REL_SUCCESS, 1);
+
+        final MockFlowFile flowFile = runner.getFlowFilesForRelationship(ExtractHL7Attributes.REL_SUCCESS).get(0);
+
+        final SortedMap<String, String> actualAttributes = new TreeMap<>(flowFile.getAttributes());
+        final SortedMap<String, Integer> actualSegments = new TreeMap<>();
+        final SortedMap<String, Integer> expectedSegments = new TreeMap<>();
+
+        // Get map of actual segment counts
+        for (final Map.Entry<String, String> entry : actualAttributes.entrySet()) {
+            final String key = entry.getKey();
+            if (!(key.equals("filename") || key.equals("path") || key.equals("uuid"))) {
+                final String segment = key.replaceAll("^([^\\.]+)\\.\\d+", "$1");
+                actualSegments.put(segment, actualSegments.getOrDefault(segment, 0) + 1);
+            }
+        }
+
+        // Get map of expected segment counts
+        for (final Map.Entry<String, String> entry : expectedAttributes.entrySet()) {
+            final String key = entry.getKey();
+            final String segment = key.replaceAll("^([^\\.]+)\\.\\d+", "$1");
+            expectedSegments.put(segment, expectedSegments.getOrDefault(segment, 0) + 1);
+        }
+
+        // First, check whether the actual and expected segment counts are the same
+        assertEquals("Segment counts do not match", expectedSegments, actualSegments);
+
+        // Check whether the actual and expected segment field values are the same
+        for (final Map.Entry<String, String> entry : expectedAttributes.entrySet()) {
+            final String key = entry.getKey();
+            final String expected = entry.getValue();
+            final String actual = actualAttributes.get(key);
+            assertEquals(key + " segment value does not match", expected, actual);
+        }
+    }
+
+    private void runTests(final String message, final Map<String, String> expectedAttributes) {
+        runTests(message, expectedAttributes, false, false);
+    }
+
     @BeforeClass
     public static void setup() {
         System.setProperty("org.slf4j.simpleLogger.log.org.apache.nifi", "DEBUG");
     }
 
     @Test
-    public void testExtract() throws IOException {
+    public void testExtract() {
+        final String message = "MSH|^~\\&|XXXXXXXX||HealthProvider||||ORU^R01|Q1111111111111111111|P|2.3|\r\n" +
+            "PID|||12345^^^XYZ^MR||SMITH^JOHN||19700100|M||||||||||111111111111|123456789|\r\n" +
+            "PD1||||1234567890^LAST^FIRST^M^^^^^NPI|\r\n" +
+            "ORC|NW|987654321^EPC|123456789^EPC||||||20161003000000|||SMITH\r\n" +
+            "OBR|1|341856649^HNAM_ORDERID|000000000000000000|648088^Basic Metabolic Panel|||20150101000000|||||||||1620^Johnson^Corey^A||||||20150101000000|||F|||||||||||20150101000000|\r\n" +
+            "OBX|1|NM|GLU^Glucose Lvl|59|mg/dL|65-99^65^99|L|||F|||20150102000000|\r\n";
+
         final SortedMap<String, String> expectedAttributes = new TreeMap<>();
-        // MSH.1 and MSH.2 could be escaped, but it's not clear which is right
+
         expectedAttributes.put("MSH.1", "|");
         expectedAttributes.put("MSH.2", "^~\\&");
         expectedAttributes.put("MSH.3", "XXXXXXXX");
@@ -55,6 +111,13 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("MSH.10", "Q1111111111111111111");
         expectedAttributes.put("MSH.11", "P");
         expectedAttributes.put("MSH.12", "2.3");
+
+        expectedAttributes.put("ORC_1.1", "NW");
+        expectedAttributes.put("ORC_1.2", "987654321^EPC");
+        expectedAttributes.put("ORC_1.3", "123456789^EPC");
+        expectedAttributes.put("ORC_1.9", "20161003000000");
+        expectedAttributes.put("ORC_1.12", "SMITH");
+
         expectedAttributes.put("OBR_1.1", "1");
         expectedAttributes.put("OBR_1.2", "341856649^HNAM_ORDERID");
         expectedAttributes.put("OBR_1.3", "000000000000000000");
@@ -64,6 +127,7 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("OBR_1.22", "20150101000000");
         expectedAttributes.put("OBR_1.25", "F");
         expectedAttributes.put("OBR_1.36", "20150101000000");
+
         expectedAttributes.put("OBX_1.1", "1");
         expectedAttributes.put("OBX_1.2", "NM");
         expectedAttributes.put("OBX_1.3", "GLU^Glucose Lvl");
@@ -73,7 +137,9 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("OBX_1.7", "L");
         expectedAttributes.put("OBX_1.10", "F");
         expectedAttributes.put("OBX_1.13", "20150102000000");
+
         expectedAttributes.put("PD1.4", "1234567890^LAST^FIRST^M^^^^^NPI");
+
         expectedAttributes.put("PID.3", "12345^^^XYZ^MR");
         expectedAttributes.put("PID.5", "SMITH^JOHN");
         expectedAttributes.put("PID.7", "19700100");
@@ -81,58 +147,20 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("PID.18", "111111111111");
         expectedAttributes.put("PID.19", "123456789");
 
-        final TestRunner runner = TestRunners.newTestRunner(ExtractHL7Attributes.class);
-        runner.enqueue(TEST_INPUT_RECORD.getBytes(StandardCharsets.UTF_8));
-
-        runner.run();
-        runner.assertAllFlowFilesTransferred(ExtractHL7Attributes.REL_SUCCESS, 1);
-
-        final MockFlowFile out = runner.getFlowFilesForRelationship(ExtractHL7Attributes.REL_SUCCESS).get(0);
-        final SortedMap<String, String> sortedAttrs = new TreeMap<>(out.getAttributes());
-
-        for (final Map.Entry<String, String> entry : expectedAttributes.entrySet()) {
-            final String key = entry.getKey();
-            final String expected = entry.getValue();
-            final String actual = sortedAttrs.get(key);
-            Assert.assertEquals(key + " segment values do not match", expected, actual);
-        }
-
-        int mshSegmentCount = 0;
-        int obrSegmentCount = 0;
-        int obxSegmentCount = 0;
-        int pd1SegmentCount = 0;
-        int pidSegmentCount = 0;
-
-        for (final Map.Entry<String, String> entry : sortedAttrs.entrySet()) {
-            final String entryKey = entry.getKey();
-            if (entryKey.startsWith("MSH")) {
-                mshSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("OBR")) {
-                obrSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("OBX")) {
-                obxSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("PD1")) {
-                pd1SegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("PID")) {
-                pidSegmentCount++;
-                continue;
-            }
-        }
-
-        Assert.assertEquals("Did not have the proper number of MSH segments", 8, mshSegmentCount);
-        Assert.assertEquals("Did not have the proper number of OBR segments", 9, obrSegmentCount);
-        Assert.assertEquals("Did not have the proper number of OBX segments", 9, obxSegmentCount);
-        Assert.assertEquals("Did not have the proper number of PD1 segments", 1, pd1SegmentCount);
-        Assert.assertEquals("Did not have the proper number of PID segments", 6, pidSegmentCount);
+        runTests(message, expectedAttributes);
     }
 
     @Test
     public void testExtractWithSegmentNames() throws IOException {
+        final String message = "MSH|^~\\&|XXXXXXXX||HealthProvider||||ORU^R01|Q1111111111111111111|P|2.3|\r\n" +
+            "PID|||12345^^^XYZ^MR||SMITH^JOHN||19700100|M||||||||||111111111111|123456789|\r\n" +
+            "PD1||||1234567890^LAST^FIRST^M^^^^^NPI|\r\n" +
+            "ORC|NW|987654321^EPC|123456789^EPC||||||20161003000000|||SMITH\r\n" +
+            "OBR|1|341856649^HNAM_ORDERID|000000000000000000|648088^Basic Metabolic Panel|||20150101000000|||||||||1620^Johnson^Corey^A||||||20150101000000|||F|||||||||||20150101000000|\r\n" +
+            "OBX|1|NM|GLU^Glucose Lvl|59|mg/dL|65-99^65^99|L|||F|||20150102000000|\r\n";
+
         final SortedMap<String, String> expectedAttributes = new TreeMap<>();
+
         expectedAttributes.put("MSH.FieldSeparator", "|");
         expectedAttributes.put("MSH.EncodingCharacters", "^~\\&");
         expectedAttributes.put("MSH.SendingApplication", "XXXXXXXX");
@@ -141,6 +169,13 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("MSH.MessageControlID", "Q1111111111111111111");
         expectedAttributes.put("MSH.ProcessingID", "P");
         expectedAttributes.put("MSH.VersionID", "2.3");
+
+        expectedAttributes.put("ORC_1.OrderControl", "NW");
+        expectedAttributes.put("ORC_1.PlacerOrderNumber", "987654321^EPC");
+        expectedAttributes.put("ORC_1.FillerOrderNumber", "123456789^EPC");
+        expectedAttributes.put("ORC_1.DateTimeOfTransaction", "20161003000000");
+        expectedAttributes.put("ORC_1.OrderingProvider", "SMITH");
+
         expectedAttributes.put("OBR_1.SetIDObservationRequest", "1");
         expectedAttributes.put("OBR_1.PlacerOrderNumber", "341856649^HNAM_ORDERID");
         expectedAttributes.put("OBR_1.FillerOrderNumber", "000000000000000000");
@@ -150,6 +185,7 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("OBR_1.ResultsRptStatusChngDateTime", "20150101000000");
         expectedAttributes.put("OBR_1.ResultStatus", "F");
         expectedAttributes.put("OBR_1.ScheduledDateTime", "20150101000000");
+
         expectedAttributes.put("OBX_1.SetIDOBX", "1");
         expectedAttributes.put("OBX_1.ValueType", "NM");
         expectedAttributes.put("OBX_1.ObservationIdentifier", "GLU^Glucose Lvl");
@@ -159,7 +195,9 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("OBX_1.ReferencesRange", "L");
         expectedAttributes.put("OBX_1.NatureOfAbnormalTest", "F");
         expectedAttributes.put("OBX_1.UserDefinedAccessChecks", "20150102000000");
+
         expectedAttributes.put("PD1.PatientPrimaryCareProviderNameIDNo", "1234567890^LAST^FIRST^M^^^^^NPI");
+
         expectedAttributes.put("PID.PatientIDInternalID", "12345^^^XYZ^MR");
         expectedAttributes.put("PID.PatientName", "SMITH^JOHN");
         expectedAttributes.put("PID.DateOfBirth", "19700100");
@@ -167,59 +205,20 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("PID.PatientAccountNumber", "111111111111");
         expectedAttributes.put("PID.SSNNumberPatient", "123456789");
 
-        final TestRunner runner = TestRunners.newTestRunner(ExtractHL7Attributes.class);
-        runner.setProperty(ExtractHL7Attributes.USE_SEGMENT_NAMES, "true");
-        runner.enqueue(TEST_INPUT_RECORD.getBytes(StandardCharsets.UTF_8));
-
-        runner.run();
-        runner.assertAllFlowFilesTransferred(ExtractHL7Attributes.REL_SUCCESS, 1);
-
-        final MockFlowFile out = runner.getFlowFilesForRelationship(ExtractHL7Attributes.REL_SUCCESS).get(0);
-        final SortedMap<String, String> sortedAttrs = new TreeMap<>(out.getAttributes());
-
-        for (final Map.Entry<String, String> entry : expectedAttributes.entrySet()) {
-            final String key = entry.getKey();
-            final String expected = entry.getValue();
-            final String actual = sortedAttrs.get(key);
-            Assert.assertEquals(key + " segment values do not match", expected, actual);
-        }
-
-        int mshSegmentCount = 0;
-        int obrSegmentCount = 0;
-        int obxSegmentCount = 0;
-        int pd1SegmentCount = 0;
-        int pidSegmentCount = 0;
-
-        for (final Map.Entry<String, String> entry : sortedAttrs.entrySet()) {
-            final String entryKey = entry.getKey();
-            if (entryKey.startsWith("MSH")) {
-                mshSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("OBR")) {
-                obrSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("OBX")) {
-                obxSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("PD1")) {
-                pd1SegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("PID")) {
-                pidSegmentCount++;
-                continue;
-            }
-        }
-
-        Assert.assertEquals("Did not have the proper number of MSH segments", 8, mshSegmentCount);
-        Assert.assertEquals("Did not have the proper number of OBR segments", 9, obrSegmentCount);
-        Assert.assertEquals("Did not have the proper number of OBX segments", 9, obxSegmentCount);
-        Assert.assertEquals("Did not have the proper number of PD1 segments", 1, pd1SegmentCount);
-        Assert.assertEquals("Did not have the proper number of PID segments", 6, pidSegmentCount);
+        runTests(message, expectedAttributes, true, false);
     }
 
     @Test
     public void testExtractWithSegmentNamesAndFields() throws IOException {
+        final String message = "MSH|^~\\&|XXXXXXXX||HealthProvider||||ORU^R01|Q1111111111111111111|P|2.3|\r\n" +
+            "PID|||12345^^^XYZ^MR||SMITH^JOHN||19700100|M||||||||||111111111111|123456789|\r\n" +
+            "PD1||||1234567890^LAST^FIRST^M^^^^^NPI|\r\n" +
+            "ORC|NW|987654321^EPC|123456789^EPC||||||20161003000000|||SMITH\r\n" +
+            "OBR|1|341856649^HNAM_ORDERID|000000000000000000|648088^Basic Metabolic Panel|||20150101000000|||||||||1620^Johnson^Corey^A||||||20150101000000|||F|||||||||||20150101000000|\r\n" +
+            "OBX|1|NM|GLU^Glucose Lvl|59|mg/dL|65-99^65^99|L|||F|||20150102000000|\r\n";
+
         final SortedMap<String, String> expectedAttributes = new TreeMap<>();
+
         expectedAttributes.put("MSH.FieldSeparator", "|");
         expectedAttributes.put("MSH.EncodingCharacters", "^~\\&");
         expectedAttributes.put("MSH.SendingApplication.HD.1", "XXXXXXXX");
@@ -229,6 +228,15 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("MSH.MessageControlID", "Q1111111111111111111");
         expectedAttributes.put("MSH.ProcessingID.PT.1", "P");
         expectedAttributes.put("MSH.VersionID", "2.3");
+
+        expectedAttributes.put("ORC_1.OrderControl", "NW");
+        expectedAttributes.put("ORC_1.PlacerOrderNumber.EI.1", "987654321");
+        expectedAttributes.put("ORC_1.PlacerOrderNumber.EI.2", "EPC");
+        expectedAttributes.put("ORC_1.FillerOrderNumber.EI.1", "123456789");
+        expectedAttributes.put("ORC_1.FillerOrderNumber.EI.2", "EPC");
+        expectedAttributes.put("ORC_1.DateTimeOfTransaction", "20161003000000");
+        expectedAttributes.put("ORC_1.OrderingProvider.XCN.1", "SMITH");
+
         expectedAttributes.put("OBR_1.SetIDObservationRequest", "1");
         expectedAttributes.put("OBR_1.PlacerOrderNumber.EI.1", "341856649");
         expectedAttributes.put("OBR_1.PlacerOrderNumber.EI.2", "HNAM_ORDERID");
@@ -243,6 +251,7 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("OBR_1.ResultsRptStatusChngDateTime", "20150101000000");
         expectedAttributes.put("OBR_1.ResultStatus", "F");
         expectedAttributes.put("OBR_1.ScheduledDateTime", "20150101000000");
+
         expectedAttributes.put("OBX_1.SetIDOBX", "1");
         expectedAttributes.put("OBX_1.ValueType", "NM");
         expectedAttributes.put("OBX_1.ObservationIdentifier.CE.1", "GLU");
@@ -250,16 +259,18 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("OBX_1.ObservationSubID", "59");
         expectedAttributes.put("OBX_1.ObservationValue", "mg/dL");
         expectedAttributes.put("OBX_1.Units.CE.1", "65-99");
-        expectedAttributes.put("OBX_1.Units.CE.3", "65");
+        expectedAttributes.put("OBX_1.Units.CE.2", "65");
         expectedAttributes.put("OBX_1.Units.CE.3", "99");
         expectedAttributes.put("OBX_1.ReferencesRange", "L");
         expectedAttributes.put("OBX_1.NatureOfAbnormalTest", "F");
         expectedAttributes.put("OBX_1.UserDefinedAccessChecks", "20150102000000");
+
         expectedAttributes.put("PD1.PatientPrimaryCareProviderNameIDNo.XCN.1", "1234567890");
         expectedAttributes.put("PD1.PatientPrimaryCareProviderNameIDNo.XCN.2", "LAST");
         expectedAttributes.put("PD1.PatientPrimaryCareProviderNameIDNo.XCN.3", "FIRST");
         expectedAttributes.put("PD1.PatientPrimaryCareProviderNameIDNo.XCN.4", "M");
         expectedAttributes.put("PD1.PatientPrimaryCareProviderNameIDNo.XCN.9", "NPI");
+
         expectedAttributes.put("PID.PatientIDInternalID.CX.1", "12345");
         expectedAttributes.put("PID.PatientIDInternalID.CX.4", "XYZ");
         expectedAttributes.put("PID.PatientIDInternalID.CX.5", "MR");
@@ -270,55 +281,217 @@ public class TestExtractHL7Attributes {
         expectedAttributes.put("PID.PatientAccountNumber.CX.1", "111111111111");
         expectedAttributes.put("PID.SSNNumberPatient", "123456789");
 
-        final TestRunner runner = TestRunners.newTestRunner(ExtractHL7Attributes.class);
-        runner.setProperty(ExtractHL7Attributes.USE_SEGMENT_NAMES, "true");
-        runner.setProperty(ExtractHL7Attributes.PARSE_SEGMENT_FIELDS, "true");
-        runner.enqueue(TEST_INPUT_RECORD.getBytes(StandardCharsets.UTF_8));
+        runTests(message, expectedAttributes, true, true);
+    }
 
-        runner.run();
-        runner.assertAllFlowFilesTransferred(ExtractHL7Attributes.REL_SUCCESS, 1);
+    @Test
+    public void test1714219() {
+        // Message from http://hl7api.sourceforge.net hapi-test/src/test/java/ca/uhn/hl7v2/parser/ParserTest.java
+        final String message = "MSH|^~\\&|Send App|Send Fac|Rec App|Rec Fac|20070504141816||ORM^O01||P|2.2\r" +
+            "PID|||12345678||Lastname^^INI^^PREFIX||19340207|F|||Street 15^^S GRAVENHAGE^^2551HL^NEDERLAND|||||||||||||||NL\r" +
+            "ORC|NW|8100088345^ORDERNR||LN1||C|^^^20070504080000||20070504141816|||0^Doctor\r" +
+            "OBR|1|8100088345^ORDERNR||ADR^Something||||||||||||0^Doctor\r" +
+            "OBX|1|ST|ADR^Something||item1^item2^item3^^item5||||||F\r";
+
+        final SortedMap<String, String> expectedAttributes = new TreeMap<>();
 
-        final MockFlowFile out = runner.getFlowFilesForRelationship(ExtractHL7Attributes.REL_SUCCESS).get(0);
-        final SortedMap<String, String> sortedAttrs = new TreeMap<>(out.getAttributes());
+        expectedAttributes.put("MSH.1", "|");
+        expectedAttributes.put("MSH.2", "^~\\&");
+        expectedAttributes.put("MSH.3", "Send App");
+        expectedAttributes.put("MSH.4", "Send Fac");
+        expectedAttributes.put("MSH.5", "Rec App");
+        expectedAttributes.put("MSH.6", "Rec Fac");
+        expectedAttributes.put("MSH.7", "20070504141816");
+        expectedAttributes.put("MSH.9", "ORM^O01");
+        expectedAttributes.put("MSH.11", "P");
+        expectedAttributes.put("MSH.12", "2.2");
 
-        for (final Map.Entry<String, String> entry : expectedAttributes.entrySet()) {
-            final String key = entry.getKey();
-            final String expected = entry.getValue();
-            final String actual = sortedAttrs.get(key);
-            Assert.assertEquals(key + " segment values do not match", expected, actual);
-        }
+        expectedAttributes.put("PID.3", "12345678");
+        expectedAttributes.put("PID.5", "Lastname^^INI^^PREFIX");
+        expectedAttributes.put("PID.7", "19340207");
+        expectedAttributes.put("PID.8", "F");
+        expectedAttributes.put("PID.11", "Street 15^^S GRAVENHAGE^^2551HL^NEDERLAND");
+        expectedAttributes.put("PID.26", "NL");
 
-        int mshSegmentCount = 0;
-        int obrSegmentCount = 0;
-        int obxSegmentCount = 0;
-        int pd1SegmentCount = 0;
-        int pidSegmentCount = 0;
-
-        for (final Map.Entry<String, String> entry : sortedAttrs.entrySet()) {
-            final String entryKey = entry.getKey();
-            if (entryKey.startsWith("MSH")) {
-                mshSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("OBR")) {
-                obrSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("OBX")) {
-                obxSegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("PD1")) {
-                pd1SegmentCount++;
-                continue;
-            } else if (entryKey.startsWith("PID")) {
-                pidSegmentCount++;
-                continue;
-            }
-        }
+        expectedAttributes.put("ORC_1.1", "NW");
+        expectedAttributes.put("ORC_1.2", "8100088345^ORDERNR");
+        expectedAttributes.put("ORC_1.4", "LN1");
+        expectedAttributes.put("ORC_1.6", "C");
+        expectedAttributes.put("ORC_1.7", "^^^20070504080000");
+        expectedAttributes.put("ORC_1.9", "20070504141816");
+        expectedAttributes.put("ORC_1.12", "0^Doctor");
+
+        expectedAttributes.put("OBR.1", "1");
+        expectedAttributes.put("OBR.2", "8100088345^ORDERNR");
+        expectedAttributes.put("OBR.4", "ADR^Something");
+        expectedAttributes.put("OBR.16", "0^Doctor");
+
+        expectedAttributes.put("OBX.1", "1");
+        expectedAttributes.put("OBX.2", "ST");
+        expectedAttributes.put("OBX.3", "ADR^Something");
+        expectedAttributes.put("OBX.5", "item1^item2^item3^^item5");
+        expectedAttributes.put("OBX.11", "F");
+
+        runTests(message, expectedAttributes);
+    }
+
+    @Test
+    public void testNPACExample() {
+        // Message from http://hl7api.sourceforge.net hapi-osgi-test/src/test/resources/ca/uhn/hl7v2/util/messages.txt
+        final String message = "MSH|^~\\&|RADIS1||DMCRES||1994050216163360||ORU^R01|1994050216163360|D|2.2|964||AL|AL\r" +
+            "MSA|AA|msgCtrlId\r" +
+            "PID|||N00803||RADIOLOGY^INPATIENT^SIX||19520606|F||A||||||||003555||\r" +
+            "PV1||I|N77^7714^01|||||||OB|\r" +
+            "OBR|1|003555.0015.001^DMCRES|0000000566^RADIS1|37953^CT CHEST^L|||199405021545|||||||||||||0000763||||A999|P||||||R/O TUMOR|202300^BAKER^MARK^E|||01^LOCHLEAR, JUDY|\r" +
+            "OBX||TX|FIND^FINDINGS^L|1|This is a test on 05/02/94.|\r" +
+            "OBX||TX|FIND^FINDINGS^L|2|This is a test for the CRR.|\r" +
+            "OBX||TX|FIND^FINDINGS^L|3|This is a test result to generate multiple obr's to check the cost|\r" +
+            "OBX||TX|FIND^FINDINGS^L|4|display for multiple exams.|\r" +
+            "OBX||TX|FIND^FINDINGS^L|5|APPROVING MD:|\r" +
+            "OBR|2|^DMCRES|0000000567^RADIS1|37956^CT ABDOMEN^L|||199405021550|||||||||||||0000763|||||P||||||R/O TUMOR|202300^BAKER^MARK^E|||01^LOCHLEAR, JUDY|\r" +
+            "OBR|3|^DMCRES|0000000568^RADIS1|37881^CT PELVIS (LIMITED)^L|||199405021551|||||||||||||0000763|||||P||||||R/O TUMOR|202300^BAKER^MARK^E|||01^LOCHLEAR, JUDY|";
 
-        Assert.assertEquals("Did not have the proper number of MSH segments", 9, mshSegmentCount);
-        Assert.assertEquals("Did not have the proper number of OBR segments", 14, obrSegmentCount);
-        Assert.assertEquals("Did not have the proper number of OBX segments", 12, obxSegmentCount);
-        Assert.assertEquals("Did not have the proper number of PD1 segments", 5, pd1SegmentCount);
-        Assert.assertEquals("Did not have the proper number of PID segments", 9, pidSegmentCount);
+        final SortedMap<String, String> expectedAttributes = new TreeMap<>();
+
+        expectedAttributes.put("MSH.1", "|");
+        expectedAttributes.put("MSH.2", "^~\\&");
+        expectedAttributes.put("MSH.3", "RADIS1");
+        expectedAttributes.put("MSH.5", "DMCRES");
+        expectedAttributes.put("MSH.7", "1994050216163360");
+        expectedAttributes.put("MSH.9", "ORU^R01");
+        expectedAttributes.put("MSH.10", "1994050216163360");
+        expectedAttributes.put("MSH.11", "D");
+        expectedAttributes.put("MSH.12", "2.2");
+        expectedAttributes.put("MSH.13", "964");
+        expectedAttributes.put("MSH.15", "AL");
+        expectedAttributes.put("MSH.16", "AL");
+
+        expectedAttributes.put("MSA.1", "AA");
+        expectedAttributes.put("MSA.2", "msgCtrlId");
+
+        expectedAttributes.put("PID.3", "N00803");
+        expectedAttributes.put("PID.5", "RADIOLOGY^INPATIENT^SIX");
+        expectedAttributes.put("PID.7", "19520606");
+        expectedAttributes.put("PID.8", "F");
+        expectedAttributes.put("PID.10", "A");
+        expectedAttributes.put("PID.18", "003555");
+
+        expectedAttributes.put("PV1.2", "I");
+        expectedAttributes.put("PV1.3", "N77^7714^01");
+        expectedAttributes.put("PV1.10", "OB");
+
+        expectedAttributes.put("OBR_1.1", "1");
+        expectedAttributes.put("OBR_1.2", "003555.0015.001^DMCRES");
+        expectedAttributes.put("OBR_1.3", "0000000566^RADIS1");
+        expectedAttributes.put("OBR_1.4", "37953^CT CHEST^L");
+        expectedAttributes.put("OBR_1.7", "199405021545");
+        expectedAttributes.put("OBR_1.20", "0000763");
+        expectedAttributes.put("OBR_1.24", "A999");
+        expectedAttributes.put("OBR_1.25", "P");
+        expectedAttributes.put("OBR_1.31", "R/O TUMOR");
+        expectedAttributes.put("OBR_1.32", "202300^BAKER^MARK^E");
+        expectedAttributes.put("OBR_1.35", "01^LOCHLEAR, JUDY");
+
+        expectedAttributes.put("OBX_1.2", "TX");
+        expectedAttributes.put("OBX_1.3", "FIND^FINDINGS^L");
+        expectedAttributes.put("OBX_1.4", "1");
+        expectedAttributes.put("OBX_1.5", "This is a test on 05/02/94.");
+
+        expectedAttributes.put("OBX_2.2", "TX");
+        expectedAttributes.put("OBX_2.3", "FIND^FINDINGS^L");
+        expectedAttributes.put("OBX_2.4", "2");
+        expectedAttributes.put("OBX_2.5", "This is a test for the CRR.");
+
+        expectedAttributes.put("OBX_3.2", "TX");
+        expectedAttributes.put("OBX_3.3", "FIND^FINDINGS^L");
+        expectedAttributes.put("OBX_3.4", "3");
+        expectedAttributes.put("OBX_3.5", "This is a test result to generate multiple obr's to check the cost");
+
+        expectedAttributes.put("OBX_4.2", "TX");
+        expectedAttributes.put("OBX_4.3", "FIND^FINDINGS^L");
+        expectedAttributes.put("OBX_4.4", "4");
+        expectedAttributes.put("OBX_4.5", "display for multiple exams.");
+
+        expectedAttributes.put("OBX_5.2", "TX");
+        expectedAttributes.put("OBX_5.3", "FIND^FINDINGS^L");
+        expectedAttributes.put("OBX_5.4", "5");
+        expectedAttributes.put("OBX_5.5", "APPROVING MD:");
+
+        expectedAttributes.put("OBR_2.1", "2");
+        expectedAttributes.put("OBR_2.2", "^DMCRES");
+        expectedAttributes.put("OBR_2.3", "0000000567^RADIS1");
+        expectedAttributes.put("OBR_2.4", "37956^CT ABDOMEN^L");
+        expectedAttributes.put("OBR_2.7", "199405021550");
+        expectedAttributes.put("OBR_2.20", "0000763");
+        expectedAttributes.put("OBR_2.25", "P");
+        expectedAttributes.put("OBR_2.31", "R/O TUMOR");
+        expectedAttributes.put("OBR_2.32", "202300^BAKER^MARK^E");
+        expectedAttributes.put("OBR_2.35", "01^LOCHLEAR, JUDY");
+
+        expectedAttributes.put("OBR_3.1", "3");
+        expectedAttributes.put("OBR_3.2", "^DMCRES");
+        expectedAttributes.put("OBR_3.3", "0000000568^RADIS1");
+        expectedAttributes.put("OBR_3.4", "37881^CT PELVIS (LIMITED)^L");
+        expectedAttributes.put("OBR_3.7", "199405021551");
+        expectedAttributes.put("OBR_3.20", "0000763");
+        expectedAttributes.put("OBR_3.25", "P");
+        expectedAttributes.put("OBR_3.31", "R/O TUMOR");
+        expectedAttributes.put("OBR_3.32", "202300^BAKER^MARK^E");
+        expectedAttributes.put("OBR_3.35", "01^LOCHLEAR, JUDY");
+
+        runTests(message, expectedAttributes);
     }
 
+    @Test
+    public void testADT() {
+        // Message from http://hl7api.sourceforge.net hapi-osgi-test/src/test/resources/ca/uhn/hl7v2/parser/tests/adt_a03.txt
+        final String message = "MSH|^~\\&|IRIS|SANTER|AMB_R|SANTER|200803051508||ADT^A03|263206|P|2.5\r" +
+            "EVN||200803051509||||200803031508\r" +
+            "PID|||5520255^^^PK^PK~ZZZZZZ83M64Z148R^^^CF^CF~ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103^99991231~^^^^TEAM||ZZZ^ZZZ||19830824|F||||||||||||||||||||||N\r" +
+            "PV1||I|6402DH^^^^^^^^MED. 1 - ONCOLOGIA^^OSPEDALE MAGGIORE DI LODI&LODI|||^^^^^^^^^^OSPEDALE MAGGIORE DI LODI&LODI|13936^TEST^TEST" +
+                "||||||||||5068^TEST2^TEST2||2008003369||||||||||||||||||||||||||200803031508\r" +
+            "PR1|1||1111^Mastoplastica|Protesi|20090224|02|";
+
+        final SortedMap<String, String> expectedAttributes = new TreeMap<>();
+
+        expectedAttributes.put("MSH.1", "|");
+        expectedAttributes.put("MSH.2", "^~\\&");
+        expectedAttributes.put("MSH.3", "IRIS");
+        expectedAttributes.put("MSH.4", "SANTER");
+        expectedAttributes.put("MSH.5", "AMB_R");
+        expectedAttributes.put("MSH.6", "SANTER");
+        expectedAttributes.put("MSH.7", "200803051508");
+        expectedAttributes.put("MSH.9", "ADT^A03");
+        expectedAttributes.put("MSH.10", "263206");
+        expectedAttributes.put("MSH.11", "P");
+        expectedAttributes.put("MSH.12", "2.5");
+
+        expectedAttributes.put("EVN.2", "200803051509");
+        expectedAttributes.put("EVN.6", "200803031508");
+
+        // NOTE: PID.3 should be the following but there's a long-standing bug where additional fields don't get rendered here
+        //expectedAttributes.put("PID.3", "5520255^^^PK^PK~ZZZZZZ83M64Z148R^^^CF^CF~ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103^99991231~^^^^TEAM");
+
+        expectedAttributes.put("PID.3", "5520255^^^PK^PK");
+        expectedAttributes.put("PID.5", "ZZZ^ZZZ");
+        expectedAttributes.put("PID.7", "19830824");
+        expectedAttributes.put("PID.8", "F");
+        expectedAttributes.put("PID.30", "N");
+
+        expectedAttributes.put("PV1.2", "I");
+        expectedAttributes.put("PV1.3", "6402DH^^^^^^^^MED. 1 - ONCOLOGIA^^OSPEDALE MAGGIORE DI LODI&LODI");
+        expectedAttributes.put("PV1.6", "^^^^^^^^^^OSPEDALE MAGGIORE DI LODI&LODI");
+        expectedAttributes.put("PV1.7", "13936^TEST^TEST");
+        expectedAttributes.put("PV1.17", "5068^TEST2^TEST2");
+        expectedAttributes.put("PV1.19", "2008003369");
+        expectedAttributes.put("PV1.45", "200803031508");
+
+        expectedAttributes.put("PR1_1.1", "1");
+        expectedAttributes.put("PR1_1.3", "1111^Mastoplastica");
+        expectedAttributes.put("PR1_1.4", "Protesi");
+        expectedAttributes.put("PR1_1.5", "20090224");
+        expectedAttributes.put("PR1_1.6", "02");
+
+        runTests(message, expectedAttributes);
+    }
 }