From eae585b7c89b695dc5c58380758e003f14cfc998 Mon Sep 17 00:00:00 2001 From: "Crouzier, Nicolas (Assoc)" Date: Thu, 4 Jan 2018 10:04:12 -0500 Subject: [PATCH] Initial commit --- .gitignore | 15 +++ pom.xml | 46 +++++++++ .../hit/pcd/custom/CodedElementFormat.java | 72 ++++++++++++++ .../java/gov/nist/hit/pcd/custom/LOINC.java | 98 +++++++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/gov/nist/hit/pcd/custom/CodedElementFormat.java create mode 100644 src/main/java/gov/nist/hit/pcd/custom/LOINC.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2702ba4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +.settings/ +target/ + +# Windows +Thumbs.db +Desktop.ini + +# OSX +.DS_Store + +#Eclipse +.project +.metadata +.classpath +.settings/ \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b6f7b61 --- /dev/null +++ b/pom.xml @@ -0,0 +1,46 @@ + + 4.0.0 + gov.nist.healthcare.pcd.pcdtool + pcdtool-message-validation + 0.0.1-SNAPSHOT + + + + joda-time + joda-time + 2.7 + + + + junit + junit + 4.12 + test + + + + log4j + log4j + 1.2.17 + + + gov.nist.hit.core.hl7v2 + hit-core-hl7v2-api + ${hitcorehl7v2.version} + + + org.apache.commons + commons-lang3 + 3.4 + + + com.google.guava + guava + 18.0 + + + + 1.0.19 + + \ No newline at end of file diff --git a/src/main/java/gov/nist/hit/pcd/custom/CodedElementFormat.java b/src/main/java/gov/nist/hit/pcd/custom/CodedElementFormat.java new file mode 100644 index 0000000..9414868 --- /dev/null +++ b/src/main/java/gov/nist/hit/pcd/custom/CodedElementFormat.java @@ -0,0 +1,72 @@ +package gov.nist.hit.pcd.custom; + + +import hl7.v2.instance.Element; +import hl7.v2.instance.Query; +import hl7.v2.instance.Simple; +import scala.collection.Iterator; +import scala.collection.immutable.List; + +public abstract class CodedElementFormat { + + public boolean isValid(String code) { + return true; + } + + public abstract String getCodeSystemValue(); + + public boolean checkFirstTriplet(List elementList) { + if (elementList != null) { + Iterator it = elementList.iterator(); + while (it.hasNext()) { + Element element = it.next(); + // get 3rd component + List codeSystemList = Query.queryAsSimple(element, + "3[1]").get(); + String codeSystem = getValue(codeSystemList); + if (getCodeSystemValue().equals(codeSystem)) { + // get 1st component + List identifierList = Query.queryAsSimple(element, + "1[1]").get(); + String identifier = getValue(identifierList); + return isValid(identifier); + } + } + } + return true; + } + + public boolean checkSecondTriplet(List elementList) { + if (elementList != null) { + Iterator it = elementList.iterator(); + while (it.hasNext()) { + Element element = it.next(); + // get 3rd component + List codeSystemList = Query.queryAsSimple(element, + "6[1]").get(); + String codeSystem = getValue(codeSystemList); + if (getCodeSystemValue().equals(codeSystem)) { + // get 1st component + List identifierList = Query.queryAsSimple(element, + "4[1]").get(); + String identifier = getValue(identifierList); + return isValid(identifier); + } + } + } + return true; + } + + private static String getValue(List simpleElementList) { + if (simpleElementList.size() > 1) { + throw new IllegalArgumentException("Invalid List size : " + + simpleElementList.size()); + } + if (simpleElementList.size() == 0) { + return ""; + } + // only get first element + return simpleElementList.apply(0).value().raw(); + } + +} \ No newline at end of file diff --git a/src/main/java/gov/nist/hit/pcd/custom/LOINC.java b/src/main/java/gov/nist/hit/pcd/custom/LOINC.java new file mode 100644 index 0000000..f4dab2b --- /dev/null +++ b/src/main/java/gov/nist/hit/pcd/custom/LOINC.java @@ -0,0 +1,98 @@ +package gov.nist.hit.pcd.custom; + +import hl7.v2.instance.Simple; +import scala.collection.immutable.List; + +public class LOINC extends CodedElementFormat { + + private static String codeSystemValue = "LN"; + + public String getCodeSystemValue() { + return codeSystemValue; + } + + /** + * Check if a code is a valid LOINC + * + * @param code + * @return true if valid + */ + public boolean isValid(String code) { + if (!code.matches("\\d{1,5}-\\d")) { + return false; + } + String extract = code.substring(0, code.indexOf("-")); + String checkDigit = mod10(extract); + String loinc = String.format("%s-%s", extract, checkDigit); + return code.equals(loinc); + } + + /** + * Mod10 algorithm for LOINC + * + * @param code + * @return the mod10 String + */ + private static String mod10(String code) { + if (!code.matches("\\d+")) { + return null; + } + if (code.length() > 5) { + return null; + } + // if length < 5, add leading "0" + StringBuffer input = new StringBuffer(code); + while (input.length() < 5) { + input.insert(0, "0"); + } + + // 1. Using the number 12345, assign positions to the digits, from right + // to left. + + // 2. Take the odd digit positions counting from the right (1st, 3rd, + // 5th, etc.) + StringBuffer odd = new StringBuffer(); + for (int i = 0; 2 * i < input.length(); i++) { + odd.insert(0, input.charAt(2 * i)); + } + + // 3.Multiply by 2. + int odd2 = Integer.parseInt(odd.toString()) * 2; + + // 4. Take the even digit positions starting from the right (2nd, 4th, + // etc.). + StringBuffer even = new StringBuffer(); + for (int i = 0; 2 * i + 1 < input.length(); i++) { + even.insert(0, input.charAt(2 * i + 1)); + } + + // 5.Append (4) to the front of the results of (3). + even.append(odd2); + + // 6. Add the digits of (5) together. + double add = 0; + for (int i = 0; i < even.length(); i++) { + add = add + Integer.parseInt(even.substring(i, i + 1)); + } + + // 7. Find the next highest multiple of 10. + double multiple = Math.ceil(add / 10) * 10; + + // 8. Subtract (6) from (7). + Long result = Math.round(multiple - add); + + return result.toString(); + } + + private String getValue(List simpleElementList) { + if (simpleElementList.size() > 1) { + throw new IllegalArgumentException("Invalid List size : " + + simpleElementList.size()); + } + if (simpleElementList.size() == 0) { + return ""; + } + // only get first element + return simpleElementList.apply(0).value().raw(); + } +} \ No newline at end of file