Java tutorial
package ca.cgta.input.converter; import java.util.logging.Level; import static org.apache.commons.lang.StringUtils.*; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.bind.JAXBException; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ca.cgta.input.model.config.Code; import ca.cgta.input.model.config.Contributor; import ca.cgta.input.model.config.ContributorConfigFactory; import ca.cgta.input.model.config.SendingSystem; import ca.cgta.input.model.inner.AdverseReaction; import ca.cgta.input.model.inner.AssociatedParty; import ca.cgta.input.model.inner.Ce; import ca.cgta.input.model.inner.ClinicalDocumentData; import ca.cgta.input.model.inner.ClinicalDocumentSection; import ca.cgta.input.model.inner.ConfidentialityStatusEnum; import ca.cgta.input.model.inner.Cx; import ca.cgta.input.model.inner.Diagnosis; import ca.cgta.input.model.inner.Ei; import ca.cgta.input.model.inner.MedicationAdmin; import ca.cgta.input.model.inner.MedicationComponent; import ca.cgta.input.model.inner.MedicationOrder; import ca.cgta.input.model.inner.Mrg; import ca.cgta.input.model.inner.Note; import ca.cgta.input.model.inner.Patient; import ca.cgta.input.model.inner.PersonInRole; import ca.cgta.input.model.inner.Pl; import ca.cgta.input.model.inner.Tables; import ca.cgta.input.model.inner.Visit; import ca.cgta.input.model.inner.Xad; import ca.cgta.input.model.inner.Xcn; import ca.cgta.input.model.inner.Xpn; import ca.cgta.input.model.inner.Xtn; import ca.cgta.input.model.outer.ClinicalDocumentGroup; import ca.cgta.input.model.outer.MedicationOrderWithAdmins; import ca.cgta.input.model.outer.PatientWithVisits; import ca.uhn.hl7v2.HL7Exception; import ca.uhn.hl7v2.model.DataTypeException; import ca.uhn.hl7v2.model.GenericSegment; import ca.uhn.hl7v2.model.Primitive; import ca.uhn.hl7v2.model.Structure; import ca.uhn.hl7v2.model.primitive.AbstractTextPrimitive; import ca.uhn.hl7v2.model.v25.datatype.CE; import ca.uhn.hl7v2.model.v25.datatype.CNE; import ca.uhn.hl7v2.model.v25.datatype.CNN; import ca.uhn.hl7v2.model.v25.datatype.CX; import ca.uhn.hl7v2.model.v25.datatype.DT; import ca.uhn.hl7v2.model.v25.datatype.ED; import ca.uhn.hl7v2.model.v25.datatype.EI; import ca.uhn.hl7v2.model.v25.datatype.FT; import ca.uhn.hl7v2.model.v25.datatype.HD; import ca.uhn.hl7v2.model.v25.datatype.NDL; import ca.uhn.hl7v2.model.v25.datatype.NM; import ca.uhn.hl7v2.model.v25.datatype.PL; import ca.uhn.hl7v2.model.v25.datatype.PRL; import ca.uhn.hl7v2.model.v25.datatype.SN; import ca.uhn.hl7v2.model.v25.datatype.TM; import ca.uhn.hl7v2.model.v25.datatype.TS; import ca.uhn.hl7v2.model.v25.datatype.XAD; import ca.uhn.hl7v2.model.v25.datatype.XCN; import ca.uhn.hl7v2.model.v25.datatype.XPN; import ca.uhn.hl7v2.model.v25.datatype.XTN; import ca.uhn.hl7v2.model.v25.group.ORU_R01_OBSERVATION; import ca.uhn.hl7v2.model.v25.group.ORU_R01_ORDER_OBSERVATION; import ca.uhn.hl7v2.model.v25.group.ORU_R01_PATIENT_RESULT; import ca.uhn.hl7v2.model.v25.group.RAS_O17_ADMINISTRATION; import ca.uhn.hl7v2.model.v25.group.RAS_O17_ORDER; import ca.uhn.hl7v2.model.v25.group.RDE_O11_ORDER; import ca.uhn.hl7v2.model.v25.message.ADT_A01; import ca.uhn.hl7v2.model.v25.message.ORU_R01; import ca.uhn.hl7v2.model.v25.message.RAS_O17; import ca.uhn.hl7v2.model.v25.message.RDE_O11; import ca.uhn.hl7v2.model.v25.segment.DG1; import ca.uhn.hl7v2.model.v25.segment.IAM; import ca.uhn.hl7v2.model.v25.segment.MRG; import ca.uhn.hl7v2.model.v25.segment.MSH; import ca.uhn.hl7v2.model.v25.segment.NK1; import ca.uhn.hl7v2.model.v25.segment.NTE; import ca.uhn.hl7v2.model.v25.segment.ORC; import ca.uhn.hl7v2.model.v25.segment.PID; import ca.uhn.hl7v2.model.v25.segment.PV1; import ca.uhn.hl7v2.model.v25.segment.PV2; import ca.uhn.hl7v2.model.v25.segment.ROL; import ca.uhn.hl7v2.model.v25.segment.RXA; import ca.uhn.hl7v2.model.v25.segment.RXC; import ca.uhn.hl7v2.model.v25.segment.RXE; import ca.uhn.hl7v2.model.v25.segment.RXR; import ca.uhn.hl7v2.util.Terser; public class Converter { public static final String INPUT_PROFILE_2_0 = "CGTA_CDR_INPUT_2_0"; private static DateFormat ourTsHourFormat = new SimpleDateFormat("yyyyMMddHH"); private static DateFormat ourTsLongFormat = new SimpleDateFormat("yyyyMMddHHmmssZ"); private static DateFormat ourDtFormat = new SimpleDateFormat("yyyyMMdd"); private static DateFormat ourTsMonthFormat = new SimpleDateFormat("yyyyMM"); private static DateFormat ourTsYearFormat = new SimpleDateFormat("yyyy"); private static final Logger ourLog = LoggerFactory.getLogger(Converter.class.getName()); private HashSet<FailureCode> myFailureCodes = new HashSet<FailureCode>(); private List<Failure> myFailures = new ArrayList<Failure>(); private ContributorConfigFactory myAuthorization; private Contributor myContributorConfig; private boolean myCheckSecurity; private SendingSystem mySendingSystem; private Boolean myValidatedMsh; private boolean myEnforceUnsupported; public Converter(boolean theCheckSecurity) throws JAXBException { myAuthorization = ContributorConfigFactory.getInstance(); myCheckSecurity = theCheckSecurity; } public Converter() throws JAXBException { this(false); } public void addFailure(String theTerserPath, FailureCode theFailureCode, String theFieldVal) { if (myFailureCodes.contains(theFailureCode)) { ourLog.warn("Not adding message failure because we already have this failure code, in \"" + theTerserPath + "\": " + theFailureCode.getDesc()); } else { myFailureCodes.add(theFailureCode); myFailures.add(new Failure(theTerserPath, theFailureCode, theFailureCode.getDesc(), theFieldVal)); if (isNotBlank(theFieldVal)) { ourLog.warn("Message failure " + theFailureCode + " in \"" + theTerserPath + "\": " + theFailureCode.getDesc() + "\n * Field Value: " + theFieldVal); } else { ourLog.warn("Message failure " + theFailureCode + " in \"" + theTerserPath + "\": " + theFailureCode.getDesc()); } } } /** * If true, generate a failure code if data exists in an unsupported field */ public void setEnforceUnsupported(boolean theEnforceUnsupported) { myEnforceUnsupported = theEnforceUnsupported; } //Hashsets for orgs that contribute to cGTA and/or HRM. Orgs that contribute to both must be in both sets. public static Set<String> cgtaContributor = new HashSet<String>(); public static Set<String> hrmContributor = new HashSet<String>(); static { hrmContributor.add("4056"); //SJHC hrmContributor.add("4209"); //TEGH hrmContributor.add("3969"); //HSC hrmContributor.add("1471"); //WPH hrmContributor.add("4052"); //WOHS hrmContributor.add("4263"); //Baycrest // cgtaContributor.add("2.16.840.1.113883.3.239.23.11"); } public boolean isHrm = false; public boolean isCgta = true; public void getMessageDestination(ORU_R01 theDocument) throws HL7Exception { isHrm = false; isCgta = true; String sendingApplication = theDocument.getMSH().getMsh3_SendingApplication().getHd1_NamespaceID() .getValue(); String sendingFacility = theDocument.getMSH().getMsh4_SendingFacility().getHd1_NamespaceID().encode(); if (isEmpty(sendingFacility)) { sendingFacility = theDocument.getMSH().getMsh4_SendingFacility().getHd2_UniversalID().encode(); } // if (cgtaContributor.contains(sendingApplication)) { // isCgta = true; // return; // } if (hrmContributor.contains(sendingFacility)) { isHrm = true; isCgta = false; return; } } public PatientWithVisits convertPatientWithVisits(ADT_A01 theAdt) throws HL7Exception { if (!validateMsh(theAdt.getMSH())) { return null; } String triggerEvt = theAdt.getMSH().getMsh9_MessageType().getMsg2_TriggerEvent().getValue(); Set<String> triggersWithStructureAdtA01 = new HashSet<String>(); triggersWithStructureAdtA01.add("A01"); triggersWithStructureAdtA01.add("A02"); triggersWithStructureAdtA01.add("A03"); triggersWithStructureAdtA01.add("A04"); triggersWithStructureAdtA01.add("A05"); triggersWithStructureAdtA01.add("A06"); triggersWithStructureAdtA01.add("A07"); triggersWithStructureAdtA01.add("A08"); triggersWithStructureAdtA01.add("A10"); triggersWithStructureAdtA01.add("A11"); triggersWithStructureAdtA01.add("A13"); triggersWithStructureAdtA01.add("A28"); triggersWithStructureAdtA01.add("A31"); triggersWithStructureAdtA01.add("A60"); if (triggersWithStructureAdtA01.contains(triggerEvt)) { try { List<String> segments = Arrays.asList(theAdt.getNames()); if (!segments.contains("MRG")) { theAdt.addNonstandardSegment("MRG"); } if (!segments.contains("IAM")) { theAdt.addNonstandardSegment("IAM"); } // RuntimeProfile pp = new ProfileParser(false).parseClasspath("profile_adt_a01.xml"); // HL7Exception[] validationResults = new DefaultValidator().validate(theAdt, pp.getMessage()); // processProfileValidationResults(validationResults); } catch (Exception e) { throw new HL7Exception(e); } } PatientWithVisits retVal = new PatientWithVisits(); retVal.myMostRecentEventCode = theAdt.getMSH().getMsh9_MessageType().getMsg2_TriggerEvent().getValue(); if (Tables.lookupHl7Code("0003ADT", retVal.myMostRecentEventCode) == null) { addFailure("MSH-9-2", FailureCode.F092, theAdt.getMSH().getMsh9_MessageType().encode()); } Date lastTransactionTime = null; String lastTransactionTimeFormatted = null; if (isNotBlank(theAdt.getEVN().getEvn2_RecordedDateTime().getTs1_Time().getValue())) { lastTransactionTime = theAdt.getEVN().getEvn2_RecordedDateTime().getTs1_Time().getValueAsDate(); lastTransactionTimeFormatted = DateFormatter .formatDate(theAdt.getEVN().getEvn2_RecordedDateTime().getTs1_Time().getValue()); } else { lastTransactionTime = theAdt.getMSH().getMsh7_DateTimeOfMessage().getTs1_Time().getValueAsDate(); lastTransactionTimeFormatted = DateFormatter .formatDate(theAdt.getMSH().getMsh7_DateTimeOfMessage().getTs1_Time().getValue()); } retVal.myAdminHistory = new ArrayList<String>(); retVal.myPatient = convertPid("PID", theAdt.getPID()); retVal.myPatient.myLastTransactionDate = lastTransactionTime; retVal.myPatient.myLastTransactionDateFormatted = lastTransactionTimeFormatted; if (!retVal.myPatient.hasIdWithTypeMr()) { addFailure("PID-3", FailureCode.F060, null); return null; } // ROL retVal.myPatient.myPersonInRoles = new ArrayList<PersonInRole>(); int index = 1; for (ROL next : theAdt.getROLAll()) { if (next.encode().length() < 5) { continue; } PersonInRole rol = convertRol("ROL(" + index + ")", next); if (rol != null) { retVal.myPatient.myPersonInRoles.add(rol); } index++; } index = 1; for (ROL next : theAdt.getROL2All()) { if (next.encode().length() < 5) { continue; } PersonInRole rol = convertRol("ROL2(" + index + ")", next); if (rol != null) { retVal.myPatient.myPersonInRoles.add(rol); } index++; } // NK1 retVal.myPatient.myAssociatedParties = new ArrayList<AssociatedParty>(); index = 1; for (NK1 next : theAdt.getNK1All()) { if (next.encode().length() <= 4) { continue; } AssociatedParty nk1 = convertNk1("NK1(" + index + ")", next); if (nk1 != null) { retVal.myPatient.myAssociatedParties.add(nk1); } index++; } // IAM retVal.myPatient.myAdverseReactions = new ArrayList<AdverseReaction>(); index = 1; if (theAdt.getNonStandardNames().contains("IAM")) { for (Structure next : theAdt.getAll("IAM")) { IAM iam = (IAM) next; if (iam.encode().length() <= 4) { continue; } AdverseReaction adv = convertIam("IAM(" + index + ")", iam); if (adv != null) { retVal.myPatient.myAdverseReactions.add(adv); } index++; } } retVal.myVisits = new ArrayList<Visit>(); boolean processVisit = true; boolean processRecordLock = true; if ("A31".equals(retVal.myMostRecentEventCode)) { processVisit = false; if (theAdt.getNonStandardNames().contains("ZPD")) { GenericSegment zpd = (GenericSegment) theAdt.get("ZPD"); retVal.myPatient.myDeactivatePatientIndicator = Terser.get(zpd, 1, 0, 1, 1); } } if ("A28".equals(retVal.myMostRecentEventCode)) { processVisit = false; } if ("A40".equals(retVal.myMostRecentEventCode)) { processVisit = false; } //PV1 segment is optional for an A45 - will process if it is there if ("A45".equals(retVal.myMostRecentEventCode)) { if (theAdt.getPV1().isEmpty()) { processVisit = false; } } // Unlink person if ("A37".equals(retVal.myMostRecentEventCode)) { processVisit = false; processRecordLock = false; PID pid2 = (PID) theAdt.get("PID2"); retVal.myUnlinkSecondPatient = convertPid("PID2", pid2); if (retVal.myUnlinkSecondPatient == null || retVal.myUnlinkSecondPatient.hasIdWithTypeMr() == false) { addFailure("PID2-3", FailureCode.F059, null); } } // Swap beds if ("A17".equals(retVal.myMostRecentEventCode)) { processRecordLock = false; // get second PID mrn PID pid2 = (PID) theAdt.get("PID2"); retVal.myBedSwapSecondPatientMrn = obtainPidMrn("PID2", pid2); if (retVal.myBedSwapSecondPatientMrn == null) { addFailure("PID2-3", FailureCode.F085, null); } // get second PV1 visitNumber PV1 pv12 = (PV1) theAdt.get("PV12"); retVal.myBedSwapSecondPatientVisitNumber = obtainPv1VisitNumber("PV12", pv12); if (retVal.myBedSwapSecondPatientVisitNumber == null) { addFailure("PV12-19", FailureCode.F086, null); } // get second PV1 location retVal.myBedSwapSecondPatientLocation = obtainPv1Loc("PV12", pv12); if (retVal.myBedSwapSecondPatientLocation == null) { addFailure("PV12-3", FailureCode.F087, null); } } //PV1 segment is optional for an A60 - will process if it is there if ("A60".equals(retVal.myMostRecentEventCode)) { if (theAdt.getPV1().isEmpty()) { processVisit = false; } } if (processVisit) { Visit pv1 = convertPv1("PV1", theAdt.getPV1()); pv1.myLastTransactionDate = lastTransactionTime; pv1.myLastTransactionDateFormatted = lastTransactionTimeFormatted; if (pv1.myVisitNumber == null) { addFailure("PV1-19", FailureCode.F128, null); } convertPv2("PV2", theAdt.getPV2(), pv1); // DG1 pv1.myDiagnoses = new ArrayList<Diagnosis>(); for (DG1 next : theAdt.getDG1All()) { Diagnosis dg1 = convertDg1("DG1", next); if (dg1 != null) { pv1.myDiagnoses.add(dg1); } } retVal.myVisits.add(pv1); } if (processRecordLock) { addRecordLockIndicator(theAdt.getPV1(), retVal.myPatient); } if (theAdt.getNonStandardNames().contains("MRG")) { retVal.myMergeInfo = convertMrg("MRG", (MRG) theAdt.get("MRG")); } if ("A40".equals(retVal.myMostRecentEventCode)) { if (retVal.myMergeInfo == null || retVal.myMergeInfo.hasIdWithTypeMr() == false) { addFailure("MRG-1", FailureCode.F063, null); } if (retVal.myMergeInfo != null && retVal.myMergeInfo.hasMultipleIdWithTypeMr()) { addFailure("MRG-1", FailureCode.F064, null); } } if ("A45".equals(retVal.myMostRecentEventCode)) { if (retVal.myMergeInfo == null || retVal.myMergeInfo.hasIdWithTypeMr() == false) { addFailure("MRG-1", FailureCode.F063, null); } if (retVal.myMergeInfo != null && retVal.myMergeInfo.hasMultipleIdWithTypeMr()) { addFailure("MRG-1", FailureCode.F064, null); } if (retVal.myMergeInfo != null && retVal.myMergeInfo.myMergeVisitId == null) { addFailure("MRG-5", FailureCode.F065, null); } } List<String> inpatientVisitTypes = Arrays.asList("I", "P", "U"); if ("A01".equals(retVal.myMostRecentEventCode) && !inpatientVisitTypes.contains(retVal.myVisits.get(0).myPatientClassCode)) { addFailure("PV1-2", FailureCode.F129, null); } List<String> outpatientVisitTypes = Arrays.asList("E", "O", "R", "U", "C"); if ("A04".equals(retVal.myMostRecentEventCode) && !outpatientVisitTypes.contains(retVal.myVisits.get(0).myPatientClassCode)) { addFailure("PV1-2", FailureCode.F130, null); } if ("A06".equals(retVal.myMostRecentEventCode) || "A07".equals(retVal.myMostRecentEventCode)) { if (retVal.myMergeInfo == null || retVal.myMergeInfo.myMergeVisitId == null) { addFailure("MRG-5", FailureCode.F091, null); } } return retVal; } private void processProfileValidationResults(HL7Exception[] theValidationResults) { for (HL7Exception nextException : theValidationResults) { if (nextException.getMessage().startsWith("Event type") && nextException.getMessage().contains("doesn't match profile type of")) { continue; } if (nextException.getMessage().startsWith("Message structure") && nextException.getMessage().contains("doesn't match profile type of")) { continue; } ourLog.info("Validation exception: " + nextException); nextException.toString(); } } public List<ClinicalDocumentGroup> convertClinicalDocument(ORU_R01 theDocument) throws HL7Exception { getMessageDestination(theDocument); if (!validateMsh(theDocument.getMSH())) { return Collections.emptyList(); } int i = 0; Map<String, ClinicalDocumentGroup> placerGroupsToDocuments = new HashMap<String, ClinicalDocumentGroup>(); for (ORU_R01_PATIENT_RESULT nextPatientResult : theDocument.getPATIENT_RESULTAll()) { i++; String terserPath = "/PATIENT_RESULT(" + i + ")"; ourLog.info("Processing {}", terserPath); convert(terserPath, nextPatientResult, placerGroupsToDocuments); } List<ClinicalDocumentGroup> retVal = new ArrayList<ClinicalDocumentGroup>(); retVal.addAll(placerGroupsToDocuments.values()); return retVal; } public List<MedicationOrderWithAdmins> convertMedicationAdmin(RAS_O17 theRas) throws HL7Exception { if (!validateMsh(theRas.getMSH())) { return Collections.emptyList(); } List<MedicationOrderWithAdmins> retVal = new ArrayList<MedicationOrderWithAdmins>(); int index = 0; for (RAS_O17_ORDER nextOrderObj : theRas.getORDERAll()) { index++; MedicationOrder nextOrder = new MedicationOrder(); MedicationOrderWithAdmins owa = new MedicationOrderWithAdmins(nextOrder); owa.myRecordUpdatedDate = new Date(); owa.myRecordUpdatedDateFormatted = DateFormatter.formatDateWithGmt(owa.myRecordUpdatedDate); if (isBlank(nextOrderObj.getORC().getOrc2_PlacerOrderNumber().getEi1_EntityIdentifier().getValue())) { addFailure("ORDER(" + index + ")/ORC-2", FailureCode.F093, null); continue; } nextOrder.myPatient = convertPid("PATIENT/PID", theRas.getPATIENT().getPID()); nextOrder.myVisit = convertPv1("PATIENT/PATIENT_VISIT/PV1", theRas.getPATIENT().getPATIENT_VISIT().getPV1()); convertOrcForMedOrder(index, nextOrder, nextOrderObj.getORC()); if (nextOrder.myPlacerOrderNumber == null) { ourLog.warn("Did not find a placer order number, so I am going to skip this order"); continue; } //obtain optional ENCODING group and convert/extract the data //NOTE, if RXE is not present then we may assume that the ENCODING GROUP is empty if (nextOrderObj.getENCODING().getRXE().encode().length() >= 5) { convertRxe("ORDER(" + index + ")/ENCODING", nextOrder, nextOrderObj.getENCODING().getRXE()); // Process Pharmacy Routes for Encoding group (optional and repeating) convertMedicationRoutes("ORDER(" + index + ")/ENCODING", nextOrderObj.getENCODING().getRXRAll(), nextOrder.myMedicationRoutes); // Process Components for Encoding group (optional and repeating) convertMedicationComponents("ORDER(" + index + ")/ENCODING", nextOrderObj.getENCODING().getRXCAll(), nextOrder.myMedicationComponents); //Do a check on a mandatory med order field before setting the overwrite flag if (nextOrder.myEncodedOrderGiveCode != null) { owa.overwriteExistingMedOrder = true; } } else { //We don't have any medication order content, so if the med order exists in the database //we won't overwrite it owa.overwriteExistingMedOrder = false; } List<MedicationAdmin> admins = new ArrayList<MedicationAdmin>(); owa.myAdmins = admins; int administrationIndex = 0; for (RAS_O17_ADMINISTRATION nextAdminGroup : nextOrderObj.getADMINISTRATIONAll()) { administrationIndex++; int rxaIndex = 0; for (RXA nextRxa : nextAdminGroup.getRXAAll()) { rxaIndex++; String rxaTerser = "ORDER(" + index + ")/ADMINISTRATION(" + administrationIndex + ")/RXA(" + rxaIndex + ")"; MedicationAdmin nextAdmin = new MedicationAdmin(); //set the placer order number nextAdmin.myPlacerOrderNumber = nextOrder.myPlacerOrderNumber; // RXA-2 (optional field) if (isNotBlank(nextRxa.getRxa2_AdministrationSubIDCounter().getValue())) { nextAdmin.myAdministrationNumber = toNumber(rxaTerser + "-2", nextRxa.getRxa2_AdministrationSubIDCounter().getValue()); } // RXA-3 (start time) if (isBlank(nextRxa.getRxa3_DateTimeStartOfAdministration().getTs1_Time().getValue())) { addFailure(rxaTerser + "-3", FailureCode.F100, null); } else { if (validateTsWithAtLeastMinutePrecisionAndAddFailure(rxaTerser + "-3", nextRxa.getRxa3_DateTimeStartOfAdministration().getTs1_Time().getValue())) { nextAdmin.myStartTime = nextRxa.getRxa3_DateTimeStartOfAdministration().getTs1_Time() .getValueAsDate(); nextAdmin.myStartTimeFormatted = DateFormatter.formatDate( nextRxa.getRxa3_DateTimeStartOfAdministration().getTs1_Time().getValue()); } } // RXA-4 (end time) (optional field) if (isNotBlank(nextRxa.getRxa4_DateTimeEndOfAdministration().getTs1_Time().getValue())) { if (validateTsWithAtLeastMinutePrecisionAndAddFailure(rxaTerser + "-4", nextRxa.getRxa4_DateTimeEndOfAdministration().getTs1_Time().getValue())) { nextAdmin.myEndTime = nextRxa.getRxa4_DateTimeEndOfAdministration().getTs1_Time() .getValueAsDate(); nextAdmin.myEndTimeFormatted = DateFormatter.formatDate( nextRxa.getRxa4_DateTimeEndOfAdministration().getTs1_Time().getValue()); } } //RXA-5 (optional field) if (isNotBlank(nextRxa.getRxa5_AdministeredCode().encode())) { nextAdmin.myAdministeredCode = convertCeWithOptionalIdentifier(rxaTerser + "-5", nextRxa.getRxa5_AdministeredCode()); if (isNotBlank(nextAdmin.myAdministeredCode.myCode) && !mySendingSystem.getDrugAdministrationCodeSystemRxa5() .contains(nextAdmin.myAdministeredCode.myCodeSystem)) { addFailure(rxaTerser + "-5-3", FailureCode.F123, nextRxa.getRxa5_AdministeredCode().encode()); } } //RXA-6 (optional field) if (isNotBlank(nextRxa.getRxa6_AdministeredAmount().getValue())) { nextAdmin.myAdministeredAmount = toNumberDecimal(rxaTerser + "-6", nextRxa.getRxa6_AdministeredAmount().getValue()); } // RXA-7 (Units) (optional field) if (isNotBlank(nextRxa.getRxa7_AdministeredUnits().encode())) { nextAdmin.myAdministeredUnits = convertCe(rxaTerser + "-7", nextRxa.getRxa7_AdministeredUnits()); } // RXA-9 (Admin Notes) nextAdmin.myAdministrationNotes = new ArrayList<Ce>(); for (int i = 0; i < nextRxa.getRxa9_AdministrationNotesReps(); i++) { CE ce = nextRxa.getRxa9_AdministrationNotes(i); if (ce != null && (isNotBlank(ce.getCe1_Identifier().getValue()) || isNotBlank(ce.getCe2_Text().getValue()))) { nextAdmin.myAdministrationNotes .add(convertCeWithOptionalIdentifier(rxaTerser + "-9(" + (i + 1) + ")", ce)); } } //RXA-12 (optional field) nextAdmin.myAdministeredPerTimeUnit = nextRxa.getRxa12_AdministeredPerTimeUnit().getValue(); //NOTE: Process optional Pharmacy Route for Administration group but add the data to the MedicationAdmin object even though it will be //the same info added to each MedicationAdmin object created from the Administration group if (nextAdminGroup.getRXR().encode().length() >= 5) { convertMedicationRoute( "ORDER(" + index + ")/ADMINISTRATION(" + administrationIndex + ")/RXR", nextAdminGroup.getRXR(), nextAdmin); } admins.add(nextAdmin); } } retVal.add(owa); } return retVal; } public List<MedicationOrder> convertMedicationOrder(RDE_O11 theRde) throws HL7Exception { if (!validateMsh(theRde.getMSH())) { return Collections.emptyList(); } List<MedicationOrder> retVal = new ArrayList<MedicationOrder>(); int index = 0; for (RDE_O11_ORDER nextOrderObj : theRde.getORDERAll()) { index++; MedicationOrder nextOrder = new MedicationOrder(); if (isBlank(nextOrderObj.getORC().getOrc2_PlacerOrderNumber().getEi1_EntityIdentifier().getValue())) { addFailure("ORDER(" + index + ")/ORC-2", FailureCode.F093, null); continue; } nextOrder.myPatient = convertPid("PATIENT/PID", theRde.getPATIENT().getPID()); nextOrder.myVisit = convertPv1("PATIENT/PATIENT_VISIT/PV1", theRde.getPATIENT().getPATIENT_VISIT().getPV1()); convertOrcForMedOrder(index, nextOrder, nextOrderObj.getORC()); if (nextOrder.myPlacerOrderNumber == null) { ourLog.warn("Did not find a placer order number, so I am going to skip this order"); continue; } //Process encoded order convertRxe("ORDER(" + index + ")", nextOrder, nextOrderObj.getRXE()); //Process Notes/Comments for Encoded Order group (optional and repeating) convertNotes("ORDER(" + index + ")", nextOrderObj.getNTEAll(), nextOrder.myNotes); //Process Pharmacy Routes for Encoded Order group (optional and repeating) convertMedicationRoutes("ORDER(" + index + ")", nextOrderObj.getRXRAll(), nextOrder.myMedicationRoutes); //Process Components Encoded Order group (optional and repeating) convertMedicationComponents("ORDER(" + index + ")", nextOrderObj.getRXCAll(), nextOrder.myMedicationComponents); retVal.add(nextOrder); } return retVal; } private void convert(String theTerserPath, ORU_R01_PATIENT_RESULT thePatientResult, Map<String, ClinicalDocumentGroup> thePlacerGroupsToDocuments) throws HL7Exception { int orderObservationIndex = 0; for (ORU_R01_ORDER_OBSERVATION nextOrderObservation : thePatientResult.getORDER_OBSERVATIONAll()) { orderObservationIndex++; Ei placerGroupNumber = null; if (isNotBlank( nextOrderObservation.getORC().getPlacerGroupNumber().getEi1_EntityIdentifier().getValue())) { placerGroupNumber = convertEiDocumentNumber( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/ORC-4", nextOrderObservation.getORC().getPlacerGroupNumber()); } if (placerGroupNumber != null && !placerGroupNumber.isValid()) { continue; } Ei placerOrderNumber = convertEiDocumentNumber( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-2", nextOrderObservation.getOBR().getObr2_PlacerOrderNumber()); if (placerOrderNumber == null || !placerOrderNumber.isValid()) { continue; } /* * More than one ORDER_OBSERVATION can be stored in a single group using a placer group number, * but the default behaviour is for the placer order number in OBR-2 to be used as the document ID. * * This could in theory cause issues if the numbers overlap, which they shouldn't. */ if (placerGroupNumber == null) { placerGroupNumber = placerOrderNumber; } if (thePlacerGroupsToDocuments.containsKey(placerGroupNumber.toKey()) == false) { ClinicalDocumentGroup documentGroup = new ClinicalDocumentGroup(); documentGroup.mySections = new ArrayList<ClinicalDocumentSection>(); documentGroup.myPlacerGroupNumber = placerGroupNumber; documentGroup.myRecordUpdatedDate = new Date(); documentGroup.myRecordUpdatedDateFormatted = DateFormatter .formatDateWithGmt(documentGroup.myRecordUpdatedDate); thePlacerGroupsToDocuments.put(placerGroupNumber.toKey(), documentGroup); } ClinicalDocumentGroup document = thePlacerGroupsToDocuments.get(placerGroupNumber.toKey()); document.myPatient = convertPid(theTerserPath + "/PATIENT/PID", thePatientResult.getPATIENT().getPID()); if (thePatientResult.getPATIENT().getVISIT().getPV1().encode().length() >= 5) { document.myVisit = convertPv1(theTerserPath + "/PATIENT/VISIT/PV1", thePatientResult.getPATIENT().getVISIT().getPV1()); if (thePatientResult.getPATIENT().getVISIT().getPV2().encode().length() >= 5) { convertPv2(theTerserPath + "/PATIENT/VISIT/PV2", thePatientResult.getPATIENT().getVISIT().getPV2(), document.myVisit); } } ClinicalDocumentSection section = new ClinicalDocumentSection(); section.myData = new ArrayList<ClinicalDocumentData>(); section.mySectionId = placerOrderNumber; CE usi = nextOrderObservation.getOBR().getObr4_UniversalServiceIdentifier(); section.mySectionCode = convertCe( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-4", usi); if (section.mySectionCode == null || isBlank(section.mySectionCode.myText)) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-4", FailureCode.F011, usi.encode()); } if (isCgta) { if (section.mySectionCode != null && (isBlank(section.mySectionCode.myCodeSystem) || !mySendingSystem .getRequestCodeSystemSystemObr4().contains(section.mySectionCode.myCodeSystem))) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-4", FailureCode.F012, usi.encode()); } } section.mySectionName = usi.getCe2_Text().getValue(); if (isBlank(section.mySectionName)) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-4-2", FailureCode.F003, usi.encode()); section.mySectionName = "MISSING PROCEDURE NAME"; } // OBR-7 if (nextOrderObservation.getOBR().getObr7_ObservationDateTime().encode().isEmpty()) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-7", FailureCode.F004, nextOrderObservation.getOBR().getObr7_ObservationDateTime().encode()); } else { String dt = nextOrderObservation.getOBR().getObr7_ObservationDateTime().getTime().getValue(); if (validateTsWithAtLeastSecondPrecisionAndAddFailure( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-7", dt)) { section.myDate = nextOrderObservation.getOBR().getObr7_ObservationDateTime().getTime() .getValueAsDate(); section.myDateFormatted = DateFormatter.formatDate( nextOrderObservation.getOBR().getObr7_ObservationDateTime().getTime().getValue()); } } // OBR-8 if (isCgta) { if (!nextOrderObservation.getOBR().getObr8_ObservationEndDateTime().encode().isEmpty()) { String dt = nextOrderObservation.getOBR().getObr8_ObservationEndDateTime().getTime().getValue(); if (validateTsWithAtLeastSecondPrecisionAndAddFailure( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-8", dt)) { section.myEndDate = nextOrderObservation.getOBR().getObr8_ObservationEndDateTime().getTime() .getValueAsDate(); section.myEndDateFormatted = DateFormatter.formatDate(nextOrderObservation.getOBR() .getObr8_ObservationEndDateTime().getTime().getValue()); } } } section.myOrderingProviders = new ArrayList<Xcn>(); for (int j = 1; j <= nextOrderObservation.getOBR().getObr16_OrderingProviderReps(); j++) { section.myOrderingProviders.add(convertXcn( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-16(" + j + ")", nextOrderObservation.getOBR().getObr16_OrderingProvider(j - 1))); } if (section.myOrderingProviders.size() > 10) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-16", FailureCode.F071, null); } if (isCgta) { String resultConfidentiality = nextOrderObservation.getOBR().getObr18_PlacerField1().getValue(); if (StringUtils.isBlank(resultConfidentiality)) { section.myConfidentiality = ConfidentialityStatusEnum.NORMAL; } else { section.myConfidentiality = ConfidentialityStatusEnum.fromHl7Code(resultConfidentiality); if (section.myConfidentiality == null) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-18", FailureCode.F005, resultConfidentiality); } } } // OBR-20 if (isHrm) { if (StringUtils.isNotBlank(nextOrderObservation.getOBR().getObr20_FillerField1().getValue())) { if (Tables.lookupHl7Code("9006", nextOrderObservation.getOBR().getObr20_FillerField1().getValue()) == null) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-20", FailureCode.F006, nextOrderObservation.getOBR().getObr20_FillerField1().getValue()); } } } String resultStatus = nextOrderObservation.getOBR().getObr25_ResultStatus().getValue(); section.myStatusCode = resultStatus; section.myStatus = Tables.lookupHl7Code("0085", section.myStatusCode); if (section.myStatus == null) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-25", FailureCode.F007, resultStatus); } section.myCopyToProviders = new ArrayList<Xcn>(); if (isCgta) { for (int j = 1; j <= nextOrderObservation.getOBR().getObr28_ResultCopiesToReps(); j++) { section.myCopyToProviders.add(convertXcn( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-28(" + j + ")", nextOrderObservation.getOBR().getObr28_ResultCopiesTo(j - 1))); } } if (isCgta) { if (section.myCopyToProviders.size() > 10) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-28", FailureCode.F071, null); } } if (isCgta) { if (isNotBlank(nextOrderObservation.getOBR().getObr26_ParentResult().encode())) { section.myParentSectionId = convertPrlDocumentNumber( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-26", nextOrderObservation.getOBR().getObr26_ParentResult()); } } if (isNotBlank(nextOrderObservation.getOBR().getObr32_PrincipalResultInterpreter().encode())) { section.myPrincipalInterpreter = convertNdl( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-32", nextOrderObservation.getOBR().getObr32_PrincipalResultInterpreter()); } //Get Order Notes and Comments convertNotes(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")", nextOrderObservation.getNTEAll(), section.myNotes); document.mySections.add(section); String appendMode = nextOrderObservation.getOBR().getObr19_PlacerField2().getValue(); if (isBlank(appendMode)) { // Snapshot is the default appendMode = "S"; } else { if (Tables.lookupHl7Code("9009", appendMode) == null) { addFailure(theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBR-19", FailureCode.F127, appendMode); appendMode = "S"; } } section.myAppendMode = appendMode; // OBX ClinicalDocumentData prevDocData = null; for (int k = 1; k <= nextOrderObservation.getOBSERVATIONReps(); k++) { if (nextOrderObservation.getOBSERVATION(k - 1).getOBX().encode().length() < 5) { continue; } int setId = toNumber( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBSERVATION(" + k + ")/OBX-1", nextOrderObservation.getOBSERVATION(k - 1).getOBX().getSetIDOBX().getValue()); if (setId != k) { addFailure( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBSERVATION(" + k + ")/OBX-1", FailureCode.F008, nextOrderObservation.getOBSERVATION(k - 1).getOBX().getSetIDOBX().encode()); } ClinicalDocumentData nextDocData = convertObservation( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBSERVATION(" + k + ")", prevDocData, nextOrderObservation.getOBSERVATION(k - 1)); if (nextDocData != null && nextDocData != prevDocData) { section.myData.add(nextDocData); } if (nextDocData != null) { convertNotes( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBSERVATION(" + k + ")", nextOrderObservation.getOBSERVATION(k - 1).getNTEAll(), nextDocData.myNotes); } else if (prevDocData != null) { convertNotes( theTerserPath + "/ORDER_OBSERVATION(" + orderObservationIndex + ")/OBSERVATION(" + k + ")", nextOrderObservation.getOBSERVATION(k - 1).getNTEAll(), prevDocData.myNotes); } else { // This shouldn't happen throw new HL7Exception("No repetition of notes"); } prevDocData = nextDocData; } //Collapse consecutive ClinicalDocumentData objects with a dataType of ED that have the same code into one ClinicalDocumentData object with the data from their value fields concatonated. //The data in each of these value fields is a separate line from a single electronic document. List<ClinicalDocumentData> currentCddList = section.myData; ArrayList<ClinicalDocumentData> revisedCddList = new ArrayList<ClinicalDocumentData>(); ClinicalDocumentData prev = null; for (ClinicalDocumentData clinicalDocumentData : currentCddList) { ClinicalDocumentData next = clinicalDocumentData; if (prev != null && next != null && partitionedEdValueCheck(next, prev)) { ClinicalDocumentData lastRevisedCdd = revisedCddList.get(revisedCddList.size() - 1); lastRevisedCdd.myValue = lastRevisedCdd.myValue + next.myValue; if (lastRevisedCdd.myNotes != null) { lastRevisedCdd.myNotes.addAll(next.myNotes); } else { lastRevisedCdd.myNotes = next.myNotes; } } else { revisedCddList.add(next); } prev = next; } section.myData = revisedCddList; //Ignore processing ZDR } } /** * * @return ... */ private boolean partitionedEdValueCheck(ClinicalDocumentData theNextCd, ClinicalDocumentData thePrevCd) { if (theNextCd.myDataType.equals("ED") && thePrevCd.myDataType.equals("ED") && theNextCd.myCode.equals(thePrevCd.myCode)) { return true; } return false; } // private void convert(String theTerserPath, XTN theXTN) throws HL7Exception { // // String xtn1number = theXTN.getXtn1_TelephoneNumber().getValue(); // String xtn4email = theXTN.getXtn4_EmailAddress().getValue(); // if (StringUtils.isNotBlank(xtn1number) && StringUtils.isNotBlank(xtn4email)) { // addFailure(theTerserPath, FailureCode.F052, theXTN.encode()); // } // // if (StringUtils.isNotBlank(theXTN.getXtn1_TelephoneNumber().getValue()) && theXTN.getXtn1_TelephoneNumber().getValue().contains("@")) { // addFailure(theTerserPath, FailureCode.F053, theXTN.encode()); // } // // } /** * @return the contributorConfig */ public Contributor getContributorConfig() { return myContributorConfig; } /** * @return the sendingSystem */ public SendingSystem getSendingSystem() { return mySendingSystem; } private Ce convertCe(String theTerserPath, CE theCe) throws HL7Exception { if (isBlank(theCe.getCe1_Identifier().getValue())) { return null; } return convertCeAndAllowNoCode(theTerserPath, theCe); } private Ce convertCeAndAllowNoCode(String theTerserPath, CE theCe) throws HL7Exception { Ce retVal = new Ce(); retVal.myCode = theCe.getCe1_Identifier().getValue(); retVal.myText = theCe.getCe2_Text().getValue(); retVal.myCodeSystem = theCe.getCe3_NameOfCodingSystem().getValue(); return retVal; } private Ce convertCeWithOptionalIdentifier(String theTerserPath, CE theCe) throws HL7Exception { Ce retVal = new Ce(); retVal.myCode = theCe.getCe1_Identifier().getValue(); retVal.myText = theCe.getCe2_Text().getValue(); retVal.myCodeSystem = theCe.getCe3_NameOfCodingSystem().getValue(); return retVal; } @SuppressWarnings("unused") private Ce convertCneToCe(String theTerserPath, CNE theCne) throws HL7Exception { if (isBlank(theCne.getCne1_Identifier().getValue())) { return null; } Ce retVal = new Ce(); retVal.myCode = theCne.getCne1_Identifier().getValue(); retVal.myText = theCne.getCne2_Text().getValue(); retVal.myCodeSystem = theCne.getCne3_NameOfCodingSystem().getValue(); return retVal; } private Cx convertCx(String theTerserPath, CX theCx) throws HL7Exception { Cx retVal = new Cx(); retVal.myIdNumber = theCx.getCx1_IDNumber().getValue(); validateStringLength(theTerserPath + "-1", retVal.myIdNumber, 50); retVal.myCheckDigit = theCx.getCx2_CheckDigit().getValue(); validateStringLength(theTerserPath + "-2", retVal.myCheckDigit, 5); retVal.myAssigningAuthorityHspId = theCx.getCx4_AssigningAuthority().getHd1_NamespaceID().getValue(); validateStringLength(theTerserPath + "-4-1", retVal.myAssigningAuthorityHspId, 50); retVal.myAssigningAuthoritySystemId = theCx.getCx4_AssigningAuthority().getHd2_UniversalID().getValue(); validateStringLength(theTerserPath + "-4-2", retVal.myAssigningAuthoritySystemId, 50); retVal.myIdTypeCode = theCx.getCx5_IdentifierTypeCode().getValue(); retVal.myIdTypeDescription = Tables.lookupHl7Code("0203", retVal.myIdTypeCode); if (retVal.myIdTypeDescription == null) { addFailure(theTerserPath + "-5", FailureCode.F043, theCx.encode()); } retVal.myEffectiveDate = theCx.getCx7_EffectiveDate().getValue(); if (isNotBlank(retVal.myEffectiveDate)) { validateDtAndAddFailure(theTerserPath + "-7", theCx.getCx7_EffectiveDate().getValue()); } retVal.myExpirationDate = theCx.getCx8_ExpirationDate().getValue(); if (isNotBlank(retVal.myExpirationDate)) { validateDtAndAddFailure(theTerserPath + "-8", theCx.getCx8_ExpirationDate().getValue()); } retVal.myAssigningJurisdictionId = theCx.getCx9_AssigningJurisdiction().getCwe1_Identifier().getValue(); if (isNotBlank(retVal.myAssigningJurisdictionId)) { retVal.myAssigningJurisdictionText = Tables.lookupHl7Code("0363", retVal.myAssigningJurisdictionId); if (retVal.myAssigningJurisdictionText == null) { addFailure(theTerserPath + "-9-1", FailureCode.F044, theCx.encode()); } if ("OTHER".equals(retVal.myAssigningJurisdictionId)) { retVal.myAssigningJurisdictionText = theCx.getCx9_AssigningJurisdiction().getCwe2_Text().getValue(); if (isBlank(retVal.myAssigningJurisdictionText)) { addFailure(theTerserPath + "-9-2", FailureCode.F045, theCx.encode()); } } if (!"HL70363".equals(theCx.getCx9_AssigningJurisdiction().getCwe3_NameOfCodingSystem().getValue())) { addFailure(theTerserPath, FailureCode.F046, theCx.encode()); } } if (isNotBlank(retVal.myAssigningAuthorityHspId) && isNotBlank(retVal.myAssigningJurisdictionId)) { addFailure(theTerserPath, FailureCode.F048, theCx.encode()); } if (isBlank(retVal.myIdTypeCode)) { //addFailure(theTerserPath + "-5", FailureCode.F049, theCx.encode()); // this is caught by F043 above } else if (retVal.myIdTypeCode.equals("JHN") || retVal.myIdTypeCode.equals("PPN")) { if (isBlank(retVal.myAssigningJurisdictionId)) { addFailure(theTerserPath, FailureCode.F050, theCx.encode()); } } else { if (isBlank(retVal.myAssigningAuthorityHspId)) { addFailure(theTerserPath, FailureCode.F051, theCx.encode()); } } // Validate CX.4 if (isNotBlank(retVal.myAssigningAuthorityHspId) && !isNotBlank(retVal.myAssigningAuthoritySystemId)) { addFailure(theTerserPath + "-4", FailureCode.F051, theCx.encode()); } else if (!isNotBlank(retVal.myAssigningAuthorityHspId) && isNotBlank(retVal.myAssigningAuthoritySystemId)) { addFailure(theTerserPath + "-4", FailureCode.F051, theCx.encode()); } if (isNotBlank(retVal.myAssigningAuthorityHspId)) { if (!myContributorConfig.getHspId9004().equals(retVal.myAssigningAuthorityHspId)) { addFailure(theTerserPath + "-4-1", FailureCode.F116, retVal.myAssigningAuthorityHspId); } } if (isNotBlank(retVal.myAssigningAuthoritySystemId)) { if (myContributorConfig.getSendingSystem9008WithOid(retVal.myAssigningAuthoritySystemId) == null) { addFailure(theTerserPath + "-4-2", FailureCode.F117, retVal.myAssigningAuthoritySystemId); } } return retVal; } private Cx convertCxPatient(String theTerserPath, CX theNextRep) throws HL7Exception { Cx retVal = convertCx(theTerserPath, theNextRep); if ("VN".equals(retVal.myIdTypeCode) || "AN".equals(retVal.myIdTypeCode)) { addFailure(theTerserPath + "-5", FailureCode.F041, theNextRep.encode()); } return retVal; } private Cx convertCxVisit(String theTerserPath, CX theNextRep) throws HL7Exception { Cx retVal = convertCx(theTerserPath, theNextRep); if (!"VN".equals(retVal.myIdTypeCode) && !"AN".equals(retVal.myIdTypeCode)) { addFailure(theTerserPath + "-5", FailureCode.F042, theNextRep.encode()); } return retVal; } private Diagnosis convertDg1(String theTerserPath, DG1 theDG1) throws HL7Exception { if (theDG1.encode().length() < 5) { return null; } Diagnosis retVal = new Diagnosis(); if (isNotBlank(theDG1.getDg13_DiagnosisCodeDG1().encode())) { retVal.myDiagnosis = convertCeWithOptionalIdentifier(theTerserPath + "-3", theDG1.getDg13_DiagnosisCodeDG1()); if (isNotBlank(retVal.myDiagnosis.myCodeSystem) && isBlank(retVal.myDiagnosis.myCode)) { addFailure(theTerserPath + "-3", FailureCode.F082, theDG1.getDg13_DiagnosisCodeDG1().encode()); } if (isBlank(retVal.myDiagnosis.myCodeSystem) && isNotBlank(retVal.myDiagnosis.myCode)) { addFailure(theTerserPath + "-3", FailureCode.F080, theDG1.getDg13_DiagnosisCodeDG1().encode()); } if (isNotBlank(retVal.myDiagnosis.myCodeSystem) && Tables.lookupHl7Code("0053", retVal.myDiagnosis.myCodeSystem) == null) { addFailure(theTerserPath + "-3", FailureCode.F079, theDG1.getDg13_DiagnosisCodeDG1().encode()); } } // else { // addFailure(theTerserPath + "-3", FailureCode.F078, theDG1.getDg13_DiagnosisCodeDG1().encode()); // } return retVal; } private Ei convertEiDocumentNumber(String theTerserPath, EI theEi) throws HL7Exception { Ei retVal = new Ei(); retVal.myId = theEi.getEi1_EntityIdentifier().getValue(); if (isBlank(retVal.myId)) { addFailure(theTerserPath + "-1", FailureCode.F020, theEi.encode()); return null; } retVal.myFacilityId = theEi.getEi2_NamespaceID().getValue(); retVal.myFacilityName = lookup9004AndReturnName(retVal.myFacilityId); if (isBlank(retVal.myFacilityName)) { addFailure(theTerserPath + "-2", FailureCode.F021, theEi.encode()); return null; } retVal.mySystemId = theEi.getEi3_UniversalID().getValue(); if (retVal.mySystemId == null || myContributorConfig.getSendingSystem9008WithOid(retVal.mySystemId) == null) { addFailure(theTerserPath + "-3", FailureCode.F022, theEi.encode()); return null; } return retVal; } private void convertRxe(String theTerserPath, MedicationOrder nextOrder, RXE rxe) throws DataTypeException, HL7Exception { // RXE-1 (Quantity/Timing) /*if (isBlank(rxe.getRxe1_QuantityTiming().getTq1_Quantity().getCq1_Quantity().getValue())) { addFailure(theTerserPath + "/RXE-1-1-1", FailureCode.F124, null); } else { nextOrder.myEncodedOrderQuantityNumber = toNumber(theTerserPath + "/RXE-1-1-1", rxe.getRxe1_QuantityTiming().getTq1_Quantity().getCq1_Quantity().getValue()); }*/ if (isNotBlank(rxe.getRxe1_QuantityTiming().getTq1_Quantity().getCq1_Quantity().getValue())) { nextOrder.myEncodedOrderQuantityNumber = toNumberDecimal(theTerserPath + "/RXE-1-1-1", rxe.getRxe1_QuantityTiming().getTq1_Quantity().getCq1_Quantity().getValue()); } if (isNotBlank(rxe.getRxe1_QuantityTiming().getTq2_Interval().getRi1_RepeatPattern().getValue())) { nextOrder.myEncodedOrderQuantityRepeatPattern = rxe.getRxe1_QuantityTiming().getTq2_Interval() .getRi1_RepeatPattern().getValue(); } if (isNotBlank(rxe.getRxe1_QuantityTiming().getTq3_Duration().getValue())) { nextOrder.myEncodedOrderQuantityDuration = rxe.getRxe1_QuantityTiming().getTq3_Duration().getValue(); } if (isNotBlank(rxe.getRxe1_QuantityTiming().getTq4_StartDateTime().getTs1_Time().getValue())) { if (validateTsWithAtLeastMinutePrecisionAndAddFailure(theTerserPath + "/RXE-1-4", rxe.getRxe1_QuantityTiming().getTq4_StartDateTime().getTs1_Time().getValue())) { nextOrder.myEncodedOrderQuantityStartTime = rxe.getRxe1_QuantityTiming().getTq4_StartDateTime() .getTs1_Time().getValueAsDate(); nextOrder.myEncodedOrderQuantityStartTimeFormatted = DateFormatter .formatDate(rxe.getRxe1_QuantityTiming().getTq4_StartDateTime().getTs1_Time().getValue()); } } if (isNotBlank(rxe.getRxe1_QuantityTiming().getTq5_EndDateTime().getTs1_Time().getValue())) { if (validateTsWithAtLeastMinutePrecisionAndAddFailure(theTerserPath + "/RXE-1-5", rxe.getRxe1_QuantityTiming().getTq5_EndDateTime().getTs1_Time().getValue())) { nextOrder.myEncodedOrderQuantityEndTime = rxe.getRxe1_QuantityTiming().getTq5_EndDateTime() .getTs1_Time().getValueAsDate(); nextOrder.myEncodedOrderQuantityEndTimeFormatted = DateFormatter .formatDate(rxe.getRxe1_QuantityTiming().getTq5_EndDateTime().getTs1_Time().getValue()); } } // RXE-2 (Give Code) nextOrder.myEncodedOrderGiveCode = convertCe(theTerserPath + "/RXE-2", rxe.getRxe2_GiveCode()); if (nextOrder.myEncodedOrderGiveCode != null && isNotBlank(nextOrder.myEncodedOrderGiveCode.myCodeSystem) && (!mySendingSystem.getDrugGiveCodeSystemRxe2() .contains(nextOrder.myEncodedOrderGiveCode.myCodeSystem))) { addFailure(theTerserPath + "/RXE-2", FailureCode.F123, rxe.getRxe2_GiveCode().encode()); } else if (nextOrder.myEncodedOrderGiveCode == null || nextOrder.myEncodedOrderGiveCode.hasBlanks()) { addFailure(theTerserPath + "/RXE-2", FailureCode.F097, rxe.getRxe2_GiveCode().encode()); } // RXE-3,4,5 (Minimum, Maxiumum, and Units) if (isNotBlank(rxe.getRxe3_GiveAmountMinimum().getValue())) { nextOrder.myEncodedOrderGiveMinimum = toNumberDecimal(theTerserPath + "/RXE-3", rxe.getRxe3_GiveAmountMinimum().getValue()); } if (isNotBlank(rxe.getRxe4_GiveAmountMaximum().getValue())) { nextOrder.myEncodedOrderGiveMaximum = toNumberDecimal(theTerserPath + "/RXE-4", rxe.getRxe4_GiveAmountMaximum().getValue()); } if (isNotBlank(rxe.getRxe5_GiveUnits().encode())) { nextOrder.myEncodedOrderGiveUnits = convertCe(theTerserPath + "/RXE-5", rxe.getRxe5_GiveUnits()); if (nextOrder.myEncodedOrderGiveUnits == null || !nextOrder.myEncodedOrderGiveUnits.hasCodeAndText()) { addFailure(theTerserPath + "/RXE-5", FailureCode.F125, rxe.getRxe5_GiveUnits().encode()); } } // RXE-6 (Give Dosage Form) if (isNotBlank(rxe.getRxe6_GiveDosageForm().encode())) { nextOrder.myEncodedOrderGiveDosageForm = convertCe(theTerserPath + "/RXE-6", rxe.getRxe6_GiveDosageForm()); if (nextOrder.myEncodedOrderGiveDosageForm == null || !nextOrder.myEncodedOrderGiveDosageForm.hasCodeAndText()) { addFailure(theTerserPath + "/RXE-6", FailureCode.F126, rxe.getRxe6_GiveDosageForm().encode()); } } // RXE-7 (Provider's Admnistration Instructions) nextOrder.myEncodedOrderProvidersAdministrationInstructions = new ArrayList<Ce>(); for (int i = 0; i < rxe.getRxe7_ProviderSAdministrationInstructionsReps(); i++) { Ce next = convertCeWithOptionalIdentifier(theTerserPath + "/RXE-7", rxe.getRxe7_ProviderSAdministrationInstructions(i)); if (next != null && (isNotBlank(next.myCode) || isNotBlank(next.myText))) { nextOrder.myEncodedOrderProvidersAdministrationInstructions.add(next); } } } /** * * @param theTerserPath * @param theRxrAll * @param theNotes ... * @throws HL7Exception */ private void convertMedicationRoutes(String theTerserPath, List<RXR> theRxrAll, List<Ce> theMedicationRoutes) throws HL7Exception { int index = 0; for (RXR next : theRxrAll) { if (next.encode().length() < 5) { continue; } index++; Ce route = new Ce(); route.myCode = next.getRxr1_Route().getCe1_Identifier().getValue(); route.myText = next.getRxr1_Route().getCe2_Text().getValue(); route.myCodeSystem = next.getRxr1_Route().getCe3_NameOfCodingSystem().getValue(); if (isBlank(route.myText)) { addFailure(theTerserPath + "/RXR(" + index + ")-1-2", FailureCode.F118, next.getRxr1_Route().encode()); } theMedicationRoutes.add(route); } } /** * * @param theTerserPath * @param theRxrAll * @param theNotes ... * @throws HL7Exception */ private void convertMedicationRoute(String theTerserPath, RXR theRxr, MedicationAdmin theMedAdmin) throws HL7Exception { Ce route = new Ce(); route.myCode = theRxr.getRxr1_Route().getCe1_Identifier().getValue(); route.myText = theRxr.getRxr1_Route().getCe2_Text().getValue(); route.myCodeSystem = theRxr.getRxr1_Route().getCe3_NameOfCodingSystem().getValue(); if (isBlank(route.myText)) { addFailure(theTerserPath + "/RXR-1-2", FailureCode.F118, theRxr.getRxr1_Route().encode()); } theMedAdmin.myMedicationRoute = route; } /** * * @param theTerserPath * @param theRxcAll * @param theMedicationComponents ... * @throws HL7Exception */ private void convertMedicationComponents(String theTerserPath, List<RXC> theRxcAll, ArrayList<MedicationComponent> theMedicationComponents) throws HL7Exception { int index = 0; for (RXC next : theRxcAll) { if (next.encode().length() < 5) { continue; } index++; MedicationComponent mc = new MedicationComponent(); mc.myComponentType = next.getRxc1_RXComponentType().getValue(); if (isBlank(mc.myComponentType) || Tables.lookupHl7Code("0166", mc.myComponentType) == null) { addFailure(theTerserPath + "/RXC(" + index + ")-1", FailureCode.F119, mc.myComponentType); } mc.myComponentCode = convertCe(theTerserPath + "/RXC(" + index + ")-2", next.getRxc2_ComponentCode()); if (mc.myComponentCode == null || mc.myComponentCode.hasBlanks()) { addFailure(theTerserPath + "/RXC(" + index + ")-2", FailureCode.F122, next.getRxc2_ComponentCode().encode()); } if (mc.myComponentCode != null && !mySendingSystem.getDrugComponentCodeSystemRxc2() .contains(mc.myComponentCode.myCodeSystem)) { addFailure(theTerserPath + "/RXC(" + index + ")-2-3", FailureCode.F123, next.getRxc2_ComponentCode().encode()); } if (isBlank(next.getRxc3_ComponentAmount().getValue())) { addFailure(theTerserPath + "/RXC(" + index + ")-3", FailureCode.F019, null); } else { mc.myComponentAmount = toNumberDecimal(theTerserPath + "/RXC(" + index + ")-3", next.getRxc3_ComponentAmount().getValue()); } mc.myComponentUnits = convertCe(theTerserPath + "/RXC(" + index + ")-4", next.getRxc4_ComponentUnits()); if (mc.myComponentUnits == null || !mc.myComponentUnits.hasCodeAndText()) { addFailure(theTerserPath + "/RXC(" + index + ")-4", FailureCode.F120, next.getRxc2_ComponentCode().encode()); } theMedicationComponents.add(mc); } } private Mrg convertMrg(String theTerserPath, MRG theMrg) throws HL7Exception { Mrg retVal = new Mrg(); retVal.myMergePatientIds = new ArrayList<Cx>(); if (isNotBlank(theMrg.getMrg1_PriorPatientIdentifierList(0).encode())) { CX nextRep = theMrg.getMrg1_PriorPatientIdentifierList(0); if (isNotBlank(nextRep.getCx1_IDNumber().encode())) { retVal.myMergePatientIds.add(convertCxPatient(theTerserPath + "-1", nextRep)); } } if (isNotBlank(theMrg.getMrg5_PriorVisitNumber().encode())) { CX nextRep = theMrg.getMrg5_PriorVisitNumber(); if (isNotBlank(nextRep.getCx1_IDNumber().encode())) { retVal.myMergeVisitId = (convertCxVisit(theTerserPath + "-5", nextRep)); } } return retVal; } private Xcn convertNdl(String theTerserPath, NDL theNdl) throws HL7Exception { Xcn retVal = new Xcn(); ourLog.info("+++ " + theNdl.encode()); CNN cnn = theNdl.getNdl1_NameOfPerson(); retVal.myId = cnn.getCnn1_IDNumber().getValue(); if (isBlank(retVal.myId)) { addFailure(theTerserPath + "-1-1", FailureCode.F023, theNdl.encode()); } retVal.myLastName = cnn.getCnn2_FamilyName().getValue(); retVal.myFirstName = cnn.getCnn3_GivenName().getValue(); retVal.myMiddleName = cnn.getCnn4_SecondAndFurtherGivenNamesOrInitialsThereof().getValue(); String authType = cnn.getCnn9_AssigningAuthorityNamespaceID().getValue(); retVal.myIdType = lookupIdType9001(authType); if (retVal.myIdType == null) { addFailure(theTerserPath + "-1-9", FailureCode.F024, theNdl.encode()); } if ("1.3.6.1.4.1.12201.1.2.1.5".equals(authType)) { retVal.myIdType = "Site Specific ID"; retVal.myAssigningHspName = lookup9004AndReturnName( cnn.getCnn10_AssigningAuthorityUniversalID().getValue()); retVal.myAssigningHspSystemId = cnn.getCnn11_AssigningAuthorityUniversalIDType().getValue(); if (isBlank(retVal.myAssigningHspName)) { addFailure(theTerserPath + "-1-10", FailureCode.F025, theNdl.encode()); } if (retVal.myAssigningHspSystemId == null || myContributorConfig.getSendingSystem9008WithOid(retVal.myAssigningHspSystemId) == null) { addFailure(theTerserPath + "-1-11", FailureCode.F026, theNdl.encode()); } } else if (retVal.myIdType != null) { // Canonical License Number if (isNotBlank(cnn.getCnn10_AssigningAuthorityUniversalID().getValue())) { addFailure(theTerserPath + "-1-10", FailureCode.F027, theNdl.encode()); } if (isNotBlank(cnn.getCnn11_AssigningAuthorityUniversalIDType().getValue())) { addFailure(theTerserPath + "-1-11", FailureCode.F028, theNdl.encode()); } } return retVal; } private AssociatedParty convertNk1(String theTerserPath, NK1 theNk1) throws HL7Exception { AssociatedParty retVal = new AssociatedParty(); retVal.myNames = new ArrayList<Xpn>(); for (int i = 1; i <= theNk1.getNk12_NKNameReps(); i++) { if (isNotBlank(theNk1.getNk12_NKName(i - 1).encode())) { Xpn next = convertXpn(theTerserPath + "-2(" + i + ")", theNk1.getNk12_NKName(i - 1)); if (next != null) { retVal.myNames.add(next); } } } retVal.myRelationship = convertCeAndAllowNoCode(theTerserPath + "-3", theNk1.getNk13_Relationship()); if (retVal == null || retVal.myRelationship == null || isBlank(retVal.myRelationship.myCode) && isBlank(retVal.myRelationship.myText) || (isNotBlank(retVal.myRelationship.myCode) && (Tables.lookupHl7Code("0063", retVal.myRelationship.myCode) == null))) { addFailure(theTerserPath + "-3", FailureCode.F083, theNk1.getNk13_Relationship().encode()); } else { if (isNotBlank(retVal.myRelationship.myCode)) { retVal.myRelationship.myText = Tables.lookupHl7Code("0063", retVal.myRelationship.myCode); retVal.myRelationshipName = retVal.myRelationship.myText; } else if (isNotBlank(retVal.myRelationship.myText)) { retVal.myRelationshipName = retVal.myRelationship.myText; } } retVal.myAddresses = new ArrayList<Xad>(); for (int i = 0; i < theNk1.getNk14_AddressReps(); i++) { if (isBlank(theNk1.getNk14_Address(i).encode())) { continue; } Xad next = convertXad(theTerserPath + "-4(" + (i + 1) + ")", theNk1.getNk14_Address(i)); if (next != null) { retVal.myAddresses.add(next); } } retVal.myContactInformation = new ArrayList<Xtn>(); for (int i = 0; i < theNk1.getNk15_PhoneNumberReps(); i++) { if (isBlank(theNk1.getNk15_PhoneNumber(i).encode())) { continue; } Xtn next = convertXtn(theTerserPath + "-5(" + (i + 1) + ")", theNk1.getNk15_PhoneNumber(i)); if (next != null) { retVal.myContactInformation.add(next); } } return retVal; } private void convertNotes(String theTerserPath, List<NTE> theNoteSegments, List<Note> theNotes) throws HL7Exception { // int index = 0; for (NTE next : theNoteSegments) { if (next.encode().length() < 5) { continue; } // index++; // if (!Integer.toString(index).equals(next.getNte1_SetIDNTE().getValue())) { // addFailure(theTerserPath + "/NTE(" + index + ")-1", FailureCode.F054, next.getNte1_SetIDNTE().getValue()); // } for (int i = 0; i < next.getNte3_CommentReps(); i++) { FT nextComment = next.getNte3_Comment(i); if (StringUtils.isNotBlank(nextComment.getValue())) { Note note = new Note(); note.myName = "Note"; note.myNoteText = nextComment.getValueAsHtml(); theNotes.add(note); } } } } private ClinicalDocumentData convertObservation(String theTerserPath, ClinicalDocumentData thePrevSection, ORU_R01_OBSERVATION theGroup) throws HL7Exception { ClinicalDocumentData retVal = new ClinicalDocumentData(); retVal.myDataType = theGroup.getOBX().getObx2_ValueType().getValue(); retVal.myCode = convertCe(theTerserPath + "/OBX-3", theGroup.getOBX().getObx3_ObservationIdentifier()); if (isCgta) { if (retVal.myCode == null || isBlank(retVal.myCode.myText) || isBlank(retVal.myCode.myCode)) { addFailure(theTerserPath + "/OBX-3", FailureCode.F009, theGroup.getOBX().getObx3_ObservationIdentifier().encode()); } } if (isCgta) { if (retVal.myCode != null && !mySendingSystem.getResultCodeSystemSystemObx3().contains((retVal.myCode.myCodeSystem))) { addFailure(theTerserPath + "/OBX-3-3", FailureCode.F010, theGroup.getOBX().getObx3_ObservationIdentifier().encode()); } } if (isCgta) { if (isNotBlank(theGroup.getOBX().getObx4_ObservationSubID().getValue())) { retVal.mySubId = toNumber(theTerserPath + "/OBX-4", theGroup.getOBX().getObx4_ObservationSubID().getValue()); } } boolean isTextType = false; if ("FT".equals(retVal.myDataType) || "ST".equals(retVal.myDataType) || "TX".equals(retVal.myDataType)) { isTextType = true; StringBuilder b = new StringBuilder(); for (int i = 0; i < theGroup.getOBX().getObx5_ObservationValueReps(); i++) { Primitive nextRep = (Primitive) theGroup.getOBX().getObx5_ObservationValue(i).getData(); if (b.length() > 0) { b.append("<br>"); } AbstractTextPrimitive text = (AbstractTextPrimitive) nextRep; String v = text.getValueAsHtml(); if (v != null) { v = v.replaceAll("<", "<"); v = v.replaceAll(">", ">"); b.append(v); } } retVal.myValue = b.toString(); } else if ("DT".equals(retVal.myDataType)) { validateOnlyOneRep(theTerserPath, theGroup, retVal); DT dt = (DT) theGroup.getOBX().getObx5_ObservationValue(0).getData(); validateDtAndAddFailure(theTerserPath + "/OBX-5", dt.getValue()); retVal.myValue = DateFormatter.formatDate(dt.getValue()); } else if ("TS".equals(retVal.myDataType)) { validateOnlyOneRep(theTerserPath, theGroup, retVal); TS dt = (TS) theGroup.getOBX().getObx5_ObservationValue(0).getData(); validateTsWithAtLeastSecondPrecisionAndAddFailure(theTerserPath + "/OBX-5", dt.getTs1_Time().getValue()); retVal.myValue = DateFormatter.formatDate(dt.getTs1_Time().getValue()); } else if ("NM".equals(retVal.myDataType)) { validateOnlyOneRep(theTerserPath, theGroup, retVal); NM dt = (NM) theGroup.getOBX().getObx5_ObservationValue(0).getData(); retVal.myValue = DateFormatter.formatDate(dt.getValue()); } else if ("TM".equals(retVal.myDataType)) { validateOnlyOneRep(theTerserPath, theGroup, retVal); TM dt = (TM) theGroup.getOBX().getObx5_ObservationValue(0).getData(); retVal.myValue = DateFormatter.formatTime(dt.getValue()); } else if ("SN".equals(retVal.myDataType)) { validateOnlyOneRep(theTerserPath, theGroup, retVal); SN dt = (SN) theGroup.getOBX().getObx5_ObservationValue(0).getData(); StringBuilder b = new StringBuilder(); if (isNotBlank(dt.getSn1_Comparator().getValue())) { b.append(dt.getSn1_Comparator().getValue()); } if (isNotBlank(dt.getSn2_Num1().getValue())) { b.append(dt.getSn2_Num1().getValue()); } if (isNotBlank(dt.getSn3_SeparatorSuffix().getValue())) { b.append(dt.getSn3_SeparatorSuffix().getValue()); } if (isNotBlank(dt.getSn4_Num2().getValue())) { b.append(dt.getSn4_Num2().getValue()); } retVal.myValue = b.toString(); } else if ("ED".equals(retVal.myDataType)) { validateOnlyOneRep(theTerserPath, theGroup, retVal); ED ed = (ED) theGroup.getOBX().getObx5_ObservationValue(0).getData(); retVal.myEncapsulatedDataType = ed.getEd2_TypeOfData().getValue(); if (retVal.myEncapsulatedDataType == null || Tables.lookupHl7Code("0191", retVal.myEncapsulatedDataType) == null) { addFailure(theTerserPath + "-5-2", FailureCode.F104, retVal.myEncapsulatedDataType); } retVal.myEncapsulatedDataSubType = ed.getEd3_DataSubtype().getValue(); if (retVal.myEncapsulatedDataSubType == null || Tables.lookupHl7Code("0291", retVal.myEncapsulatedDataSubType) == null) { addFailure(theTerserPath + "-5-3", FailureCode.F105, retVal.myEncapsulatedDataSubType); } if (retVal.myEncapsulatedDataSubType != null) { retVal.myEncapsulatedDataMimeType = getMimeType(retVal.myEncapsulatedDataSubType); } retVal.myEncapsulatedDataEncoding = ed.getEd4_Encoding().getValue(); if (retVal.myEncapsulatedDataEncoding == null || !retVal.myEncapsulatedDataEncoding.equalsIgnoreCase("Base64")) { addFailure(theTerserPath + "-5-4", FailureCode.F106, retVal.myEncapsulatedDataEncoding); } retVal.myValue = ed.getEd5_Data().getValue(); if (retVal.myValue == null || retVal.myValue.length() == 0) { addFailure(theTerserPath + "-5-5", FailureCode.F107, null); } } else { addFailure(theTerserPath + "/OBX-2", FailureCode.F013, retVal.myDataType); } if (isCgta) { if (isNotBlank(theGroup.getOBX().getObx6_Units().encode())) { retVal.myUnits = convertCe(theTerserPath + "/OBX-6", theGroup.getOBX().getObx6_Units()); } } if (isCgta) { if (isNotBlank(theGroup.getOBX().getObx7_ReferencesRange().encode())) { retVal.myRefRange = theGroup.getOBX().getObx7_ReferencesRange().getValue(); } } if (isCgta) { if (isNotBlank(theGroup.getOBX().getObx8_AbnormalFlags(0).encode())) { retVal.myAbnormalFlagCode = theGroup.getOBX().getObx8_AbnormalFlags(0).getValue(); retVal.myAbnormalFlagName = Tables.lookupHl7Code("0078", retVal.myAbnormalFlagCode); if (retVal.myAbnormalFlagName == null) { addFailure(theTerserPath + "/OBX-8", FailureCode.F014, theGroup.getOBX().getObx8_AbnormalFlags(0).encode()); } } } retVal.myDataStatusCode = theGroup.getOBX().getObx11_ObservationResultStatus().getValue(); retVal.myDataStatus = Tables.lookupHl7Code("0085", retVal.myDataStatusCode); if (isCgta) { if (retVal.myDataStatus == null) { addFailure(theTerserPath + "/OBX-11", FailureCode.F015, theGroup.getOBX().getObx11_ObservationResultStatus().encode()); } } if (thePrevSection != null && retVal.myCode != null && retVal.myCode.equals(thePrevSection.myCode)) { // if (thePrevSection.mySubId != (retVal.mySubId - 1)) { // addFailure(theTerserPath, FailureCode.F016, theGroup.getOBX().getObx4_ObservationSubID().encode()); // } if (isTextType) { thePrevSection.myValue = thePrevSection.myValue + (isNotEmpty(thePrevSection.myValue) ? "<br>" : "") + retVal.myValue; thePrevSection.mySubId = retVal.mySubId; return thePrevSection; } } String obx14 = theGroup.getOBX().getObx14_DateTimeOfTheObservation().encode(); if (isCgta) { if (isNotBlank(obx14)) { if (validateTsWithAtLeastSecondPrecisionAndAddFailure(theTerserPath + "-14", theGroup.getOBX().getObx14_DateTimeOfTheObservation().getTs1_Time().getValue())) { retVal.myDateTimeOfObservation = theGroup.getOBX().getObx14_DateTimeOfTheObservation() .getTs1_Time().getValueAsDate(); } } } return retVal; } private void convertOrcForMedOrder(int theIndex, MedicationOrder theOrder, ORC theOrc) throws HL7Exception { // ORC-2 (Placer Order Number) theOrder.myPlacerOrderNumber = convertEiDocumentNumber("ORDER(" + theIndex + ")/ORC-2", theOrc.getOrc2_PlacerOrderNumber()); // ORC-4 (Placer Group Number) if (isNotBlank(theOrc.getOrc4_PlacerGroupNumber().encode())) { theOrder.myPlacerGroupNumber = convertEiDocumentNumber("ORDER(" + theIndex + ")/ORC-4", theOrc.getOrc4_PlacerGroupNumber()); } //ORC-1 String orderControl = theOrc.getOrc1_OrderControl().getValue(); String orderControlName = Tables.lookupHl7Code("0119", orderControl); theOrder.myStatusCode = orderControl; theOrder.myStatusName = orderControlName; if (StringUtils.isBlank(theOrder.myStatusName)) { addFailure("ORDER(" + theIndex + ")/ORC-1", FailureCode.F094, orderControl); } } private Patient convertPid(String theTerserPath, PID thePID) throws HL7Exception { Patient retVal = new Patient(); // if (!"1".equals(thePID.getPid1_SetIDPID().getValue())) { // addFailure(theTerserPath, FailureCode.F030, thePID.getPid1_SetIDPID().encode()); // } retVal.myPatientIds = new ArrayList<Cx>(); boolean haveMr = false; for (int i = 1; i <= thePID.getPid3_PatientIdentifierListReps(); i++) { CX nextRep = thePID.getPid3_PatientIdentifierList(i - 1); if (isBlank(nextRep.getCx1_IDNumber().getValue())) { continue; } Cx nextRepConv = convertCxPatient(theTerserPath + "-3(" + i + ")", nextRep); if (nextRepConv == null) { continue; } if ("MR".equals(nextRepConv.myIdTypeCode)) { if (haveMr) { // Make sure we don't have more than one MRN addFailure(theTerserPath + "-3(" + i + ")", FailureCode.F072, nextRep.encode()); continue; } else { haveMr = true; } } retVal.myPatientIds.add(nextRepConv); } if (retVal.myPatientIds.size() > 10) { addFailure(theTerserPath + "-3", FailureCode.F071, null); } retVal.myPatientNames = new ArrayList<Xpn>(); for (int i = 1; i <= thePID.getPid5_PatientNameReps(); i++) { XPN nextRep = thePID.getPid5_PatientName(i - 1); Xpn nextRepConv = convertXpn(theTerserPath + "-5(" + i + ")", nextRep); retVal.myPatientNames.add(nextRepConv); } if (retVal.myPatientNames.size() > 10) { addFailure(theTerserPath + "-5", FailureCode.F071, null); } if (isCgta) { if (thePID.getPid6_MotherSMaidenNameReps() > 1) { addFailure(theTerserPath + "-6", FailureCode.F031, null); } } for (int i = 1; i <= thePID.getPid6_MotherSMaidenNameReps(); i++) { XPN nextRep = thePID.getPid6_MotherSMaidenName(i - 1); Xpn nextRepConv = convertXpn(theTerserPath + "-6(" + i + ")", nextRep); retVal.myMothersMaidenName = (nextRepConv); } TS dob = thePID.getPid7_DateTimeOfBirth(); if (StringUtils.isNotBlank(dob.getTs1_Time().getValue())) { if (validateTsWithAnyPrecisionAndAddFailure(theTerserPath + "-7", dob.getTs1_Time().getValue())) { retVal.myDateOfBirth = dob.getTs1_Time().getValueAsDate(); } // String dobString = dob.getTs1_Time().getValue(); // //System.out.println(dobString); // if (dobString != null) { // dobString = dobString.substring(0, 8); // try { // retVal.myDateOfBirth = ourDtFormat.parse(dobString); // } // catch (ParseException e) { // addFailure(theTerserPath, FailureCode.F084, dobString); // } // } } if (isNotBlank(thePID.getPid8_AdministrativeSex().getValue())) { retVal.myAdministrativeSex = thePID.getPid8_AdministrativeSex().getValue(); if (Tables.lookupHl7Code("0001", retVal.myAdministrativeSex) == null) { addFailure(theTerserPath + "-8", FailureCode.F072, retVal.myAdministrativeSex); } } retVal.myPatientAddresses = new ArrayList<Xad>(); for (int i = 1; i <= thePID.getPid11_PatientAddressReps(); i++) { XAD nextRep = thePID.getPid11_PatientAddress(i - 1); if (nextRep.encode().isEmpty()) { continue; } Xad nextRepConv = convertXad(theTerserPath + "-11(" + i + ")", nextRep); retVal.myPatientAddresses.add(nextRepConv); } if (retVal.myPatientAddresses.size() > 10) { addFailure(theTerserPath + "-10", FailureCode.F071, null); } retVal.myPhoneNumbers = new ArrayList<Xtn>(); for (int i = 1; i <= thePID.getPid13_PhoneNumberHomeReps(); i++) { XTN nextRep = thePID.getPid13_PhoneNumberHome(i - 1); Xtn nextRepConv = convertXtn(theTerserPath + "-13(" + i + ")", nextRep); retVal.myPhoneNumbers.add(nextRepConv); } if (retVal.myPhoneNumbers.size() > 10) { addFailure(theTerserPath + "-13", FailureCode.F071, null); } if (isCgta) { if (isNotBlank(thePID.getPid15_PrimaryLanguage().encode())) { if (!"HL70296".equals(thePID.getPrimaryLanguage().getCe3_NameOfCodingSystem().getValue())) { addFailure(theTerserPath, FailureCode.F032, thePID.getPrimaryLanguage().encode()); } retVal.myPrimaryLanguage = convertCe(theTerserPath + "-15", thePID.getPid15_PrimaryLanguage()); } } // if (isNotBlank(thePID.getPid17_Religion().encode())) { // if // (!"HL70002".equals(thePID.getReligion().getCe3_NameOfCodingSystem().getValue())) // { // addFailure(theTerserPath, "PID-17-3 must be 'HL70002'"); // } // retVal.myReligion = convert(theTerserPath + "-17", // thePID.getPid17_Religion()); // } if (isNotBlank(thePID.getPid29_PatientDeathDateAndTime().encode())) { if (validateTsWithAtLeastSecondPrecisionAndAddFailure(theTerserPath + "-29", thePID.getPid29_PatientDeathDateAndTime().getTs1_Time().getValue())) { retVal.myDeathDateAndTime = thePID.getPid29_PatientDeathDateAndTime().getTs1_Time() .getValueAsDate(); retVal.myDeathDateAndTimeFormatted = DateFormatter .formatDate(thePID.getPid29_PatientDeathDateAndTime().getTs1_Time().getValue()); } } String deathInd = thePID.getPid30_PatientDeathIndicator().getValue(); if (deathInd != null && !"".equals(deathInd) && !"Y".equals(deathInd) && !"N".equals(deathInd)) { addFailure(theTerserPath, FailureCode.F033, thePID.getPid30_PatientDeathIndicator().encode()); } retVal.myDeathIndicator = deathInd; return retVal; } private Pl convertPl(String theTerserPath, PL thePl) throws HL7Exception { Pl retVal = new Pl(); retVal.myPointOfCare = thePl.getPointOfCare().getValue(); validateStringLength(theTerserPath + "-1", retVal.myPointOfCare, 50); retVal.myRoom = thePl.getRoom().getValue(); validateStringLength(theTerserPath + "-2", retVal.myRoom, 50); retVal.myBed = thePl.getBed().getValue(); validateStringLength(theTerserPath + "-3", retVal.myBed, 50); retVal.myHspId = thePl.getPl4_Facility().getHd1_NamespaceID().getValue(); retVal.myHspName = lookup9004AndReturnName(retVal.myHspId); if (retVal.myHspName == null) { addFailure(theTerserPath + "-4-1", FailureCode.F029, thePl.encode()); } if (StringUtils.isNotBlank(thePl.getFacility().getHd2_UniversalID().getValue())) { retVal.myFacilityId = thePl.getFacility().getUniversalID().getValue(); retVal.myFacilityName = myContributorConfig.getFacilityNameWithOid(retVal.myFacilityId); } retVal.myBuilding = thePl.getBuilding().getValue(); validateStringLength(theTerserPath + "-7", retVal.myBuilding, 50); retVal.myFloor = thePl.getFloor().getValue(); validateStringLength(theTerserPath + "-8", retVal.myFloor, 50); retVal.myLocationDescription = thePl.getLocationDescription().getValue(); validateStringLength(theTerserPath + "-9", retVal.myLocationDescription, 50); return retVal; } private String lookup9004AndReturnName(String theValue) { String retVal = myAuthorization.getContributorConfig().getNameOfHspId9004(theValue); // TODO: validate security return retVal; } private Ei convertPrlDocumentNumber(String theTerserPath, PRL theEi) throws HL7Exception { Ei retVal = new Ei(); retVal.myId = theEi.getPrl1_ParentObservationIdentifier().getCe1_Identifier().getValue(); if (isBlank(retVal.myId)) { addFailure(theTerserPath + "-1-1", FailureCode.F020, theEi.encode()); } retVal.myFacilityName = lookup9004AndReturnName( theEi.getPrl1_ParentObservationIdentifier().getCe2_Text().getValue()); if (isBlank(retVal.myFacilityName)) { addFailure(theTerserPath + "-1-2", FailureCode.F021, theEi.encode()); } retVal.mySystemId = theEi.getPrl1_ParentObservationIdentifier().getCe3_NameOfCodingSystem().getValue(); if (retVal.mySystemId == null || myContributorConfig.getSendingSystem9008WithOid(retVal.mySystemId) == null) { addFailure(theTerserPath + "-1-3", FailureCode.F022, theEi.encode()); } return retVal; } private void addRecordLockIndicator(PV1 thePV1, Patient thePatient) throws HL7Exception { String theTerserPath = "PV1"; thePatient.myPatientRequestedRecordLock = thePV1.getPv116_VIPIndicator().getValue(); if (isNotBlank(thePatient.myPatientRequestedRecordLock)) { if (!"Y".equals(thePatient.myPatientRequestedRecordLock) && !"N".equals(thePatient.myPatientRequestedRecordLock)) { addFailure(theTerserPath + "-16", FailureCode.F076, thePatient.myPatientRequestedRecordLock); } } } private Visit convertPv1(String theTerserPath, PV1 thePV1) throws HL7Exception { Visit retVal = new Visit(); if (!"1".equals(thePV1.getSetIDPV1().getValue())) { addFailure(theTerserPath + "-1", FailureCode.F001, thePV1.getSetIDPV1().encode()); } retVal.myPatientClassCode = thePV1.getPv12_PatientClass().getValue(); if (retVal.myPatientClassCode != null) { retVal.myPatientClassName = Tables.lookupHl7Code("0004", thePV1.getPv12_PatientClass().getValue()); if (retVal.myPatientClassName == null) { addFailure(theTerserPath + "-2", FailureCode.F002, retVal.myPatientClassCode); } } // System.out.println(thePV1.getPv13_AssignedPatientLocation().encode()); if (isNotBlank(thePV1.getPv13_AssignedPatientLocation().encode())) { retVal.myAssignedPatientLocation = convertPl(theTerserPath + "-3", thePV1.getPv13_AssignedPatientLocation()); } retVal.myAdmissionType = thePV1.getPv14_AdmissionType().getValue(); validateStringLength(theTerserPath + "-4", retVal.myAdmissionType, 10); if (isNotBlank(thePV1.getPv16_PriorPatientLocation().encode())) { retVal.myPriorPatientLocation = convertPl(theTerserPath + "-6", thePV1.getPv16_PriorPatientLocation()); } retVal.myAttendingDoctors = new ArrayList<Xcn>(); for (int i = 1; i <= thePV1.getPv17_AttendingDoctorReps(); i++) { if ("\"\"".equals(thePV1.getPv17_AttendingDoctor(0).getXcn1_IDNumber().getValue())) { Xcn deleteVal = new Xcn(); deleteVal.myId = "\"\""; retVal.myAttendingDoctors.add(deleteVal); break; } retVal.myAttendingDoctors .add(convertXcn(theTerserPath + "-7(" + i + ")", thePV1.getPv17_AttendingDoctor(i - 1))); } if (retVal.myAttendingDoctors.size() > 10) { addFailure(theTerserPath + "-7", FailureCode.F071, null); } retVal.myReferringDoctors = new ArrayList<Xcn>(); for (int i = 1; i <= thePV1.getPv18_ReferringDoctorReps(); i++) { if ("\"\"".equals(thePV1.getPv18_ReferringDoctor(0).getXcn1_IDNumber().getValue())) { Xcn deleteVal = new Xcn(); deleteVal.myId = "\"\""; retVal.myReferringDoctors.add(deleteVal); break; } retVal.myReferringDoctors .add(convertXcn(theTerserPath + "-8(" + i + ")", thePV1.getPv18_ReferringDoctor(i - 1))); } if (retVal.myReferringDoctors.size() > 10) { addFailure(theTerserPath + "-8", FailureCode.F071, null); } retVal.myConsultingDoctors = new ArrayList<Xcn>(); for (int i = 1; i <= thePV1.getPv19_ConsultingDoctorReps(); i++) { if ("\"\"".equals(thePV1.getPv19_ConsultingDoctor(0).getXcn1_IDNumber().getValue())) { Xcn deleteVal = new Xcn(); deleteVal.myId = "\"\""; retVal.myConsultingDoctors.add(deleteVal); break; } retVal.myConsultingDoctors .add(convertXcn(theTerserPath + "-9(" + i + ")", thePV1.getPv19_ConsultingDoctor(i - 1))); } if (retVal.myConsultingDoctors.size() > 10) { addFailure(theTerserPath + "-9", FailureCode.F071, null); } retVal.myHospitalService = thePV1.getPv110_HospitalService().getValue(); if (isNotBlank(retVal.myHospitalService)) { retVal.myHospitalServiceName = retVal.myHospitalService; } // retVal.myPatientRequestedRecordLock = thePV1.getPv116_VIPIndicator().getValue(); // if (isNotBlank(retVal.myPatientRequestedRecordLock)) { // if (!"Y".equals(retVal.myPatientRequestedRecordLock) && !"N".equals(retVal.myPatientRequestedRecordLock)) { // addFailure(theTerserPath + "-16", FailureCode.F076, retVal.myPatientRequestedRecordLock); // } // } retVal.myAdmittingDoctors = new ArrayList<Xcn>(); for (int i = 1; i <= thePV1.getPv117_AdmittingDoctorReps(); i++) { if ("\"\"".equals(thePV1.getPv117_AdmittingDoctor(0).getXcn1_IDNumber().getValue())) { Xcn deleteVal = new Xcn(); deleteVal.myId = "\"\""; retVal.myAdmittingDoctors.add(deleteVal); break; } retVal.myAdmittingDoctors .add(convertXcn(theTerserPath + "-17(" + i + ")", thePV1.getPv117_AdmittingDoctor(i - 1))); } if (retVal.myAdmittingDoctors.size() > 10) { addFailure(theTerserPath + "-17", FailureCode.F071, null); } if (isNotBlank(thePV1.getPv119_VisitNumber().encode())) { retVal.myVisitNumber = convertCxVisit(theTerserPath + "-19", thePV1.getPv119_VisitNumber()); } if (isNotBlank(thePV1.getAdmitDateTime().getTs1_Time().getValue())) { if (validateTsWithAtLeastSecondPrecisionAndAddFailure(theTerserPath + "-44", thePV1.getAdmitDateTime().getTs1_Time().getValue())) { retVal.myAdmitDate = thePV1.getPv144_AdmitDateTime().getTs1_Time().getValueAsDate(); retVal.myAdmitDateFormatted = DateFormatter .formatDate(thePV1.getPv144_AdmitDateTime().getTs1_Time().getValue()); } } retVal.myDischargeDates = new ArrayList<Date>(); retVal.myDischargeDatesFormatted = new ArrayList<String>(); for (int i = 0; i < thePV1.getPv145_DischargeDateTimeReps(); i++) { if (StringUtils.isBlank(thePV1.getDischargeDateTime(i).getTs1_Time().getValue())) { continue; } if (validateTsWithAtLeastSecondPrecisionAndAddFailure(theTerserPath + "-45", thePV1.getDischargeDateTime(i).getTs1_Time().getValue())) { retVal.myDischargeDates.add(thePV1.getDischargeDateTime(i).getTs1_Time().getValueAsDate()); retVal.myDischargeDatesFormatted .add(DateFormatter.formatDate(thePV1.getDischargeDateTime(i).getTs1_Time().getValue())); } } if (retVal.myDischargeDates.size() > 10) { addFailure(theTerserPath + "-17", FailureCode.F071, null); } return retVal; } private void convertPv2(String theTerserPath, PV2 thePV2, Visit theVisit) throws HL7Exception { if (isNotBlank(thePV2.getPv23_AdmitReason().encode())) { theVisit.myAdmitReasonForEmergencyVisit = convertCe(theTerserPath + "-3", thePV2.getPv23_AdmitReason()); if (theVisit.myAdmitReasonForEmergencyVisit != null) { validateStringLength(theTerserPath + "-3-1", theVisit.myAdmitReasonForEmergencyVisit.myCode, 60); validateStringLength(theTerserPath + "-3-2", theVisit.myAdmitReasonForEmergencyVisit.myText, 250); } } if (isNotBlank(thePV2.getPv240_AdmissionLevelOfCareCode().encode())) { theVisit.myAdmissionLevelOfCareForEmergencyVisit = convertCe(theTerserPath + "-40", thePV2.getPv240_AdmissionLevelOfCareCode()); if (theVisit.myAdmissionLevelOfCareForEmergencyVisit != null) { validateStringLength(theTerserPath + "-40-1", theVisit.myAdmissionLevelOfCareForEmergencyVisit.myCode, 60); validateStringLength(theTerserPath + "-40-2", theVisit.myAdmissionLevelOfCareForEmergencyVisit.myText, 250); if (Tables.lookupHl7Code("0432", theVisit.myAdmissionLevelOfCareForEmergencyVisit.myCode) == null) { addFailure(theTerserPath + "-40-1", FailureCode.F077, theVisit.myAdmissionLevelOfCareForEmergencyVisit.myCode); } } } } private PersonInRole convertRol(String theTerserPath, ROL theRol) throws HL7Exception { if (theRol.encode().length() < 5) { return null; } PersonInRole retVal = new PersonInRole(); retVal.myRole = convertCe(theTerserPath + "-3", theRol.getRol3_RoleROL()); if (retVal.myRole == null || Tables.lookupHl7Code("0443", retVal.myRole.myCode) == null) { addFailure(theTerserPath + "-3-1", FailureCode.F081, theRol.getRol3_RoleROL().encode()); } retVal.myPersonNames = new ArrayList<Xcn>(); for (int i = 0; i < theRol.getRol4_RolePersonReps(); i++) { Xcn next = convertXcn(theTerserPath + "-4(" + (i + 1) + ")", theRol.getRol4_RolePerson(i), false); if (next != null) { retVal.myPersonNames.add(next); } } // if (retVal.myPersonNames.size() == 0) { // addFailure(theTerserPath + "-4", FailureCode.F082, null); // } retVal.myAddresses = new ArrayList<Xad>(); for (int i = 0; i < theRol.getRol11_OfficeHomeAddressBirthplaceReps(); i++) { if (isBlank(theRol.getRol11_OfficeHomeAddressBirthplace(i).encode())) { continue; } Xad next = convertXad(theTerserPath + "-11(" + (i + 1) + ")", theRol.getRol11_OfficeHomeAddressBirthplace(i)); if (next != null) { retVal.myAddresses.add(next); } } retVal.myContactInformation = new ArrayList<Xtn>(); for (int i = 0; i < theRol.getRol12_PhoneReps(); i++) { if (isNotBlank(theRol.getRol12_Phone(i).encode())) { Xtn next = convertXtn(theTerserPath + "-12(" + (i + 1) + ")", theRol.getRol12_Phone(i)); if (next != null) { retVal.myContactInformation.add(next); } } } return retVal; } //2 250 CE O 0127 00204 Allergen Type Code //3 250 CE R 00205 Allergen Code/Mnemonic/Description //4 250 CE O 0128 00206 Allergy Severity Code //5 15 ST O Y 00207 Allergy Reaction Code //6 250 CNE R 0323 01551 Allergy Action Code //11 8 DT O 01556 Onset Date //12 60 ST O Onset Text //13 19 TS O Reported Date/Time //15 250 CE O Relationship to Patient Code private AdverseReaction convertIam(String theTerserPath, IAM theIAM) throws HL7Exception { AdverseReaction retVal = new AdverseReaction(); if (isNotBlank(theIAM.getIam2_AllergenTypeCode().encode())) { retVal.myAllergenTypeCode = convertCe(theTerserPath + "-2", theIAM.getIam2_AllergenTypeCode()); if (retVal.myAllergenTypeCode == null || Tables.lookupHl7Code("0127", retVal.myAllergenTypeCode.myCode) == null) { addFailure(theTerserPath + "-2", FailureCode.F088, theIAM.getIam2_AllergenTypeCode().encode()); } } if (isNotBlank(theIAM.getIam3_AllergenCodeMnemonicDescription().encode())) { retVal.myAllergenCode = convertCeAndAllowNoCode(theTerserPath + "-3", theIAM.getIam3_AllergenCodeMnemonicDescription()); if (isBlank(retVal.myAllergenCode.myText)) { addFailure(theTerserPath + "-3-2", FailureCode.F103, theIAM.getIam3_AllergenCodeMnemonicDescription().encode()); } if (retVal.myAllergenCode.myCodeSystem == null || !mySendingSystem.getAllergenCodeSystemIam3().contains(retVal.myAllergenCode.myCodeSystem)) { ourLog.info("IAM-3-3 code system {} isn't in allowable list: {}", retVal.myAllergenCode.myCodeSystem, mySendingSystem.getAllergenCodeSystemIam3()); addFailure(theTerserPath + "-3", FailureCode.F123, theIAM.getIam3_AllergenCodeMnemonicDescription().encode()); } } if (isNotBlank(theIAM.getIam4_AllergySeverityCode().encode())) { retVal.myAllergySeverityCode = convertCe(theTerserPath + "-4", theIAM.getIam4_AllergySeverityCode()); if (retVal.myAllergySeverityCode == null || Tables.lookupHl7Code("0128", retVal.myAllergySeverityCode.myCode) == null) { addFailure(theTerserPath + "-4", FailureCode.F089, theIAM.getIam4_AllergySeverityCode().encode()); } } retVal.myAllergyReactionCodes = new ArrayList<String>(); for (int i = 1; i <= theIAM.getIam5_AllergyReactionCodeReps(); i++) { if (isNotBlank(theIAM.getIam5_AllergyReactionCode(i - 1).encode())) { String next = theIAM.getIam5_AllergyReactionCode(i - 1).getValue(); if (next != null) { retVal.myAllergyReactionCodes.add(next); } } } if (retVal.myAllergyReactionCodes.size() > 10) { addFailure(theTerserPath + "-5", FailureCode.F071, null); } // if (isNotBlank(theIAM.getIam9_SensitivityToCausativeAgentCode().encode())) { // retVal.mySensitivityToCausativeAgentCode = convertCe(theTerserPath + "-9", theIAM.getIam9_SensitivityToCausativeAgentCode()); // if (retVal.mySensitivityToCausativeAgentCode == null || Tables.lookupHl7Code("0436", retVal.mySensitivityToCausativeAgentCode.myCode) == null) { // addFailure(theTerserPath + "-9", FailureCode.F090, theIAM.getIam9_SensitivityToCausativeAgentCode().encode()); // } // } String onsetDateStr = theIAM.getIam11_OnsetDate().getValue(); if (isNotBlank(onsetDateStr)) { if (validateDtAndAddFailure(theTerserPath + "-11", onsetDateStr)) { try { retVal.myOnsetDate = ourDtFormat.parse(onsetDateStr); retVal.myOnsetDateFormatted = DateFormatter.formatDate(onsetDateStr); } catch (ParseException e) { ourLog.error("Should not happen! " + onsetDateStr); // should not happen } } } if (isNotBlank(theIAM.getIam12_OnsetDateText().getValue())) { retVal.myOnsetText = theIAM.getIam12_OnsetDateText().getValue(); validateStringLength(theTerserPath + "-12", retVal.myOnsetText, 60); } String reportedDtTimeStr = theIAM.getIam13_ReportedDateTime().getTs1_Time().getValue(); if (isNotBlank(reportedDtTimeStr)) { validateTsWithAnyPrecisionAndAddFailure(theTerserPath + "-13", reportedDtTimeStr); retVal.myReportedDateTime = convertVariableTsToDate(theTerserPath + "-13", theIAM.getIam13_ReportedDateTime()); retVal.myReportedDateTimeFormatted = DateFormatter.formatDate(reportedDtTimeStr); } if (isNotBlank(theIAM.getIam15_RelationshipToPatientCode().encode())) { retVal.myRelationshipToPatient = convertCe(theTerserPath + "-15", theIAM.getIam15_RelationshipToPatientCode()); if (retVal.myRelationshipToPatient == null || Tables.lookupHl7Code("0063", retVal.myRelationshipToPatient.myCode) == null) { addFailure(theTerserPath + "-15", FailureCode.F083, theIAM.getIam15_RelationshipToPatientCode().encode()); } } return retVal; } private Xad convertXad(String theTerserPath, XAD theXad) throws HL7Exception { Xad retVal = new Xad(); retVal.myStreetAddress = theXad.getXad1_StreetAddress().getSad1_StreetOrMailingAddress().getValue(); validateStringLength(theTerserPath + "-1-1", retVal.myStreetAddress, 50); retVal.myStreetAddress2 = theXad.getXad2_OtherDesignation().getValue(); validateStringLength(theTerserPath + "-2", retVal.myStreetAddress2, 50); retVal.myCity = theXad.getXad3_City().getValue(); validateStringLength(theTerserPath + "-3", retVal.myCity, 80); String sop = theXad.getXad4_StateOrProvince().getValue(); if (StringUtils.isNotBlank(sop)) { retVal.myProvince = Tables.lookupHl7Code("9003", sop); if (retVal.myProvince == null) { addFailure(theTerserPath + "-4", FailureCode.F035, theXad.encode()); } } retVal.myPostalCode = theXad.getXad5_ZipOrPostalCode().getValue(); validateStringLength(theTerserPath + "-5", retVal.myPostalCode, 12); retVal.myCountry = theXad.getXad6_Country().getValue(); validateStringLength(theTerserPath + "-6", retVal.myCountry, 50); retVal.myAddressType = Tables.lookupHl7Code("0190", theXad.getXad7_AddressType().getValue()); if (retVal.myAddressType == null) { addFailure(theTerserPath + "-7", FailureCode.F037, theXad.encode()); } String effectiveDtTimeStr = theXad.getXad13_EffectiveDate().getTs1_Time().getValue(); if (isNotBlank(effectiveDtTimeStr)) { validateTsWithAnyPrecisionAndAddFailure(theTerserPath + "-13", effectiveDtTimeStr); retVal.myEffectiveDate = convertVariableTsToDate(theTerserPath + "-13", theXad.getXad13_EffectiveDate()); retVal.myEffectiveDateFormatted = DateFormatter.formatDate(effectiveDtTimeStr); } String expirationDtTimeStr = theXad.getXad14_ExpirationDate().getTs1_Time().getValue(); if (isNotBlank(expirationDtTimeStr)) { validateTsWithAnyPrecisionAndAddFailure(theTerserPath + "-14", expirationDtTimeStr); retVal.myExpirationDate = convertVariableTsToDate(theTerserPath + "-14", theXad.getXad14_ExpirationDate()); retVal.myExpirationDateFormatted = DateFormatter.formatDate(expirationDtTimeStr); } return retVal; } private Xcn convertXcn(String theTerserPath, XCN theXcn) throws HL7Exception { return convertXcn(theTerserPath, theXcn, true); } private Xcn convertXcn(String theTerserPath, XCN theXcn, boolean idRequired) throws HL7Exception { Xcn retVal = new Xcn(); retVal.myId = theXcn.getXcn1_IDNumber().getValue(); if (idRequired && isBlank(retVal.myId)) { addFailure(theTerserPath + "-1", FailureCode.F023, theXcn.encode()); } retVal.myLastName = theXcn.getXcn2_FamilyName().getFn1_Surname().getValue(); retVal.myFirstName = theXcn.getXcn3_GivenName().getValue(); retVal.myMiddleName = theXcn.getXcn4_SecondAndFurtherGivenNamesOrInitialsThereof().getValue(); if (idRequired || isNotBlank(retVal.myId)) { String authType = theXcn.getXcn9_AssigningAuthority().getHd1_NamespaceID().getValue(); retVal.myIdType = lookupIdType9001(authType); if (retVal.myIdType == null) { addFailure(theTerserPath + "-9-1", FailureCode.F024, theXcn.encode()); } retVal.myAssigningHspName = lookup9004AndReturnName( theXcn.getXcn9_AssigningAuthority().getHd2_UniversalID().getValue()); HD xcn9_AssigningAuthority = theXcn.getXcn9_AssigningAuthority(); retVal.myAssigningHspSystemId = xcn9_AssigningAuthority.getHd3_UniversalIDType().getValue(); if ("1.3.6.1.4.1.12201.1.2.1.5".equals(authType)) { retVal.myIdType = "Site Specific ID"; if (isBlank(retVal.myAssigningHspName)) { addFailure(theTerserPath + "-9-2", FailureCode.F025, theXcn.encode()); } if (retVal.myAssigningHspSystemId == null || myContributorConfig.getSendingSystem9008WithOid(retVal.myAssigningHspSystemId) == null) { addFailure(theTerserPath + "-9-2", FailureCode.F026, theXcn.encode()); } } else if (retVal.myIdType != null) { // Canonical License Number if (isNotBlank(retVal.myAssigningHspName)) { addFailure(theTerserPath + "-9-2", FailureCode.F027, theXcn.encode()); } if (isNotBlank(retVal.myAssigningHspSystemId)) { addFailure(theTerserPath + "-9-2", FailureCode.F028, theXcn.encode()); } } } return retVal; } private String lookupIdType9001(String theAuthType) { Map<String, Code> toProvider = myAuthorization.getContributorConfig().getProviderId9001ToProvider(); Code retVal = toProvider.get(theAuthType); return retVal != null ? retVal.getDescription() : null; } private Xpn convertXpn(String theTerserPath, XPN theXpn) throws HL7Exception { Xpn retVal = new Xpn(); retVal.myLastName = theXpn.getXpn1_FamilyName().getFn1_Surname().getValue(); validateStringLength(theTerserPath + "-1-1", retVal.myLastName, 50); if (isBlank(retVal.myLastName)) { addFailure(theTerserPath + "-1-1", FailureCode.F073, null); } retVal.myFirstName = theXpn.getXpn2_GivenName().getValue(); validateStringLength(theTerserPath + "-2", retVal.myFirstName, 50); retVal.mySecondName = theXpn.getXpn3_SecondAndFurtherGivenNamesOrInitialsThereof().getValue(); validateStringLength(theTerserPath + "-3", retVal.mySecondName, 50); retVal.mySuffix = theXpn.getXpn4_SuffixEgJRorIII().getValue(); validateStringLength(theTerserPath + "-4", retVal.mySuffix, 20); retVal.myPrefix = theXpn.getXpn5_PrefixEgDR().getValue(); validateStringLength(theTerserPath + "-5", retVal.myPrefix, 20); retVal.myDegree = theXpn.getXpn6_DegreeEgMD().getValue(); validateStringLength(theTerserPath + "-6", retVal.myDegree, 20); retVal.myNameType = Tables.lookupHl7Code("0200", theXpn.getXpn7_NameTypeCode().getValue()); if (retVal.myNameType == null) { addFailure(theTerserPath, FailureCode.F034, theXpn.encode()); } return retVal; } private Xtn convertXtn(String theTerserPath, XTN theXtn) throws HL7Exception { Xtn retVal = new Xtn(); retVal.myPhoneNumber = theXtn.getXtn1_TelephoneNumber().getValue(); validateStringLength(theTerserPath + "-1", retVal.myPhoneNumber, 25); retVal.myPhoneNumberTypeCode = theXtn.getXtn2_TelecommunicationUseCode().getValue(); retVal.myPhoneNumberType = Tables.lookupHl7Code("0201", retVal.myPhoneNumberTypeCode); if (retVal.myPhoneNumberType == null) { addFailure(theTerserPath + "-2", FailureCode.F038, theXtn.encode()); } retVal.myPhoneNumberEquipmentTypeCode = theXtn.getXtn3_TelecommunicationEquipmentType().getValue(); retVal.myPhoneNumberEquipmentType = Tables.lookupHl7Code("0202", retVal.myPhoneNumberEquipmentTypeCode); retVal.myEmailAddress = theXtn.getXtn4_EmailAddress().getValue(); validateStringLength(theTerserPath + "-4", retVal.myEmailAddress, 199); retVal.myNumberParts1CountryCode = theXtn.getXtn5_CountryCode().getValue(); validateStringLength(theTerserPath + "-5", retVal.myNumberParts1CountryCode, 3); if (isNotBlank(retVal.myNumberParts1CountryCode) && !retVal.myNumberParts1CountryCode.matches("^[0-9]+$")) { addFailure(theTerserPath + "-5", FailureCode.F074, retVal.myNumberParts1CountryCode); } retVal.myNumberParts2AreaCode = theXtn.getXtn6_AreaCityCode().getValue(); validateStringLength(theTerserPath + "-6", retVal.myNumberParts2AreaCode, 5); if (isNotBlank(retVal.myNumberParts2AreaCode) && !retVal.myNumberParts2AreaCode.matches("^[0-9]+$")) { addFailure(theTerserPath + "-6", FailureCode.F074, retVal.myNumberParts2AreaCode); } retVal.myNumberParts3LocalNumber = theXtn.getXtn7_LocalNumber().getValue(); validateStringLength(theTerserPath + "-7", retVal.myNumberParts3LocalNumber, 9); if (isNotBlank(retVal.myNumberParts3LocalNumber) && !retVal.myNumberParts3LocalNumber.matches("^[0-9]+$")) { addFailure(theTerserPath + "-7", FailureCode.F074, retVal.myNumberParts3LocalNumber); } retVal.myNumberParts4Ext = theXtn.getXtn8_Extension().getValue(); validateStringLength(theTerserPath + "-8", retVal.myNumberParts4Ext, 5); if (isNotBlank(retVal.myNumberParts4Ext) && !retVal.myNumberParts4Ext.matches("^[0-9]+$")) { addFailure(theTerserPath + "-8", FailureCode.F074, retVal.myNumberParts4Ext); } retVal.myAnyText = theXtn.getXtn9_AnyText().getValue(); validateStringLength(theTerserPath + "-9", retVal.myAnyText, 199); if (!"NET".equals(retVal.myPhoneNumberTypeCode)) { if (isNotBlank(retVal.myEmailAddress)) { addFailure(theTerserPath, FailureCode.F039, theXtn.encode()); } } if ("NET".equals(retVal.myPhoneNumberTypeCode)) { if (isNotBlank(retVal.myPhoneNumber)) { addFailure(theTerserPath, FailureCode.F040, theXtn.encode()); } } return retVal; } public List<Failure> getFailures() { return myFailures; } public boolean hasFailure() { return myFailures.size() > 0; } private Cx obtainPidMrn(String theTerserPath, PID thePID) throws HL7Exception { Cx retVal = null; boolean haveMr = false; for (int i = 1; i <= thePID.getPid3_PatientIdentifierListReps(); i++) { CX nextRep = thePID.getPid3_PatientIdentifierList(i - 1); if (isBlank(nextRep.getCx1_IDNumber().getValue())) { continue; } Cx nextRepConv = convertCxPatient(theTerserPath + "-3(" + i + ")", nextRep); if ("MR".equals(nextRepConv.myIdTypeCode)) { if (haveMr) { // Make sure we don't have more than one MRN addFailure(theTerserPath + "-3(" + i + ")", FailureCode.F072, nextRep.encode()); continue; } else { haveMr = true; retVal = nextRepConv; } } } return retVal; } private Pl obtainPv1Loc(String theTerserPath, PV1 thePV1) throws HL7Exception { Pl retVal = null; if (isNotBlank(thePV1.getPv13_AssignedPatientLocation().encode())) { retVal = convertPl(theTerserPath + "-3", thePV1.getPv13_AssignedPatientLocation()); } return retVal; } private Cx obtainPv1VisitNumber(String theTerserPath, PV1 thePV1) throws HL7Exception { Cx retVal = null; if (isNotBlank(thePV1.getPv119_VisitNumber().encode())) { retVal = convertCxVisit(theTerserPath + "-19", thePV1.getPv119_VisitNumber()); } return retVal; } int toNumber(String theTerserPath, String theValue) { if (theValue == null || theValue.isEmpty()) { return 0; } if (!theValue.matches("^[0-9]+$")) { addFailure(theTerserPath, FailureCode.F019, theValue); return 0; } long value = Long.parseLong(theValue); if (value > Integer.MAX_VALUE) { addFailure(theTerserPath, FailureCode.F132, theValue); return 0; } return (int) value; } double toNumberDecimal(String theTerserPath, String theValue) { if (theValue == null || theValue.isEmpty()) { return 0.0; } if (!theValue.matches("^[0-9.]+$")) { addFailure(theTerserPath, FailureCode.F131, theValue); return 0.0; } return Double.parseDouble(theValue); } private boolean validateDtAndAddFailure(String theTerserPath, String theValue) { if (theValue == null || !theValue.matches("^[0-9]{8}$")) { addFailure(theTerserPath, FailureCode.F084, theValue); return false; } else { return true; } } public boolean validateMsh(MSH theMsh) throws HL7Exception { // Only validate once if (myValidatedMsh != null) { return myValidatedMsh; } if (!"|".equals(theMsh.getFieldSeparator().getValue())) { addFailure("MSH-1", FailureCode.F066, theMsh.getFieldSeparator().getValue()); } if (!"^~\\&".equals(theMsh.getMsh2_EncodingCharacters().getValue())) { addFailure("MSH-2", FailureCode.F066, theMsh.getMsh2_EncodingCharacters().getValue()); } String sendingOrg = theMsh.getMsh3_SendingApplication().getHd1_NamespaceID().getValue(); String sendingFacility = theMsh.getMsh4_SendingFacility().getHd1_NamespaceID().encode(); if (isEmpty(sendingOrg) && isEmpty(sendingFacility)) { addFailure("MSH-3/4-1", FailureCode.F134, theMsh.getMsh3_SendingApplication().getHd1_NamespaceID().encode()); myValidatedMsh = false; return false; } if (isCgta) { myContributorConfig = myAuthorization.getContributorConfig().getHspId9004ToContributor() .get(StringUtils.defaultString(sendingOrg)); if (myContributorConfig == null) { addFailure("MSH-3-1", FailureCode.F112, theMsh.getMsh3_SendingApplication().getHd1_NamespaceID().getValue()); myValidatedMsh = false; return false; } else { String sendingSystemId = theMsh.getMsh3_SendingApplication().getHd2_UniversalID().getValue(); mySendingSystem = myContributorConfig.getSendingSystem9008WithOid(sendingSystemId); if (mySendingSystem == null) { addFailure("MSH-3-2", FailureCode.F113, sendingSystemId); myValidatedMsh = false; return false; } String securityToken = theMsh.getMsh8_Security().getValue(); if (myCheckSecurity) { if (!myContributorConfig.getDevSecurityToken().equals(securityToken)) { addFailure("MSH-8", FailureCode.F114, securityToken); myValidatedMsh = false; return false; } } } } if (isHrm) { myContributorConfig = myAuthorization.getContributorConfig().getHrmId0362ToContributor() .get(StringUtils.defaultString(sendingFacility)); // if (!hrmContributor.contains(sendingFacility)) { if (myContributorConfig == null) { addFailure("MSH-4", FailureCode.F133, sendingFacility); myValidatedMsh = false; return false; } } if (isCgta) { String receivingFacility = theMsh.getMsh5_ReceivingApplication().getHd1_NamespaceID().getValue(); if (!"ConnectingGTA".equals(receivingFacility)) { addFailure("MSH-5", FailureCode.F066, null); } } if (isHrm) { String receivingFacility = theMsh.getMsh6_ReceivingFacility().getHd1_NamespaceID().getValue(); if (!"ConnectingGTA".equals(receivingFacility)) { addFailure("MSH-6", FailureCode.F066, null); } } validateTsWithAtLeastSecondPrecisionAndAddFailure("MSH-7", theMsh.getMsh7_DateTimeOfMessage().getTs1_Time().getValue()); String controlId = theMsh.getMsh10_MessageControlID().getValue(); if (isBlank(controlId)) { addFailure("MSH-10", FailureCode.F069, null); } String processingMode = theMsh.getMsh11_ProcessingID().getPt1_ProcessingID().getValue(); if (!"T".equals(processingMode)) { addFailure("MSH-11-1", FailureCode.F070, processingMode); } String vid = theMsh.getMsh12_VersionID().getVid1_VersionID().getValue(); if (!"2.5".equals(vid)) { addFailure("MSH-12", FailureCode.F066, vid); } if (isCgta) { String accAck = theMsh.getMsh15_AcceptAcknowledgmentType().getValue(); if (!"NE".equals(accAck)) { addFailure("MSH-15", FailureCode.F066, accAck); } } if (isCgta) { String appAck = theMsh.getMsh16_ApplicationAcknowledgmentType().getValue(); if (!"AL".equals(appAck)) { addFailure("MSH-16", FailureCode.F066, appAck); } } if (isCgta) { String country = theMsh.getMsh17_CountryCode().getValue(); if (!"CAN".equals(country)) { addFailure("MSH-17", FailureCode.F066, country); } } if (isCgta) { String charset = theMsh.getMsh18_CharacterSet(0).getValue(); if (!"8859/1".equals(charset)) { addFailure("MSH-18", FailureCode.F066, charset); } } if (isCgta) { String profile = theMsh.getMsh21_MessageProfileIdentifier(0).getEi1_EntityIdentifier().getValue(); if (!INPUT_PROFILE_2_0.equals(profile)) { addFailure("MSH-21(1)-1", FailureCode.F115, profile); } } myValidatedMsh = true; return true; } private void validateOnlyOneRep(String theTerserPath, ORU_R01_OBSERVATION theGroup, ClinicalDocumentData retVal) { if (theGroup.getOBX().getObx5_ObservationValueReps() > 1) { addFailure(theTerserPath + "/OBX-5", FailureCode.F018, null); } } private void validateStringLength(String theTerserPath, String theString, int theMaxLength) { if (theString != null && theString.length() > theMaxLength) { addFailure(theTerserPath, FailureCode.F071, theString); } } private boolean validateTsWithAtLeastSecondPrecisionAndAddFailure(String theTerserPath, String theValue) { if (theValue == null || !theValue.matches("^[0-9]{8}([0-9]{6})(\\.[0-9]{4})?(-[0-9]{4})?$")) { addFailure(theTerserPath, FailureCode.F017, theValue); return false; } else { return true; } } boolean validateTsWithAtLeastMinutePrecisionAndAddFailure(String theTerserPath, String theValue) { if (theValue == null || !theValue.matches("^[0-9]{8}[0-9]{4}([0-9]{2})?(\\.[0-9]{1,4})?([\\-\\+][0-9]{4})?$")) { addFailure(theTerserPath, FailureCode.F101, theValue); return false; } else { return true; } } private boolean validateTsWithAnyPrecisionAndAddFailure(String theTerserPath, String theValue) { if (theValue != null && theValue.matches( "^[0-9]{4}([0-9]{2}([0-9]{2}([0-9]{2}([0-9]{2}([0-9]{2}(\\.[0-9]{1,4})?)?)?)?)?)?([\\-\\+][0-9]{4})?$")) { return true; } else { addFailure(theTerserPath, FailureCode.F102, theValue); return false; } } /** * This method will account for issues when converting low precision ts values into Dates. * It seems that the TSComponentOne getValueAsDate() method does not properly convert TS values * with less than hour precision * @throws HL7Exception */ private Date convertVariableTsToDate(String theTerserPath, TS theTs) throws HL7Exception { if (theTs == null) { return null; } String tsString = theTs.getTs1_Time().getValue(); if (tsString == null || tsString.length() == 0) { return null; } Date retVal = null; try { if (tsString.length() >= 12) { retVal = theTs.getTs1_Time().getValueAsDate(); } else if (tsString.length() == 10) { retVal = ourTsHourFormat.parse(tsString); } else if (tsString.length() == 8) { retVal = ourDtFormat.parse(tsString); } else if (tsString.length() == 6) { retVal = ourTsMonthFormat.parse(tsString); } else if (tsString.length() == 4) { retVal = ourTsYearFormat.parse(tsString); } else { addFailure(theTerserPath, FailureCode.F102, tsString); } } catch (ParseException e) { addFailure(theTerserPath, FailureCode.F102, tsString); } return retVal; } private String getMimeType(String theDataSubType) { if (theDataSubType.equals("HTML")) { return "text/html"; } else if (theDataSubType.equals("RTF")) { return "text/rtf"; } else if (theDataSubType.equals("TIFF")) { return "image/tiff"; } else if (theDataSubType.equals("JPEG")) { return "image/jpeg"; } else if (theDataSubType.equals("GIF")) { return "image/gif"; } else if (theDataSubType.equals("PNG")) { return "image/png"; } else if (theDataSubType.equals("WAV")) { return "audio/wav"; } else if (theDataSubType.equals("MP3")) { return "audio/mp3"; } else if (theDataSubType.equals("PDF")) { return "application/pdf"; } else { return theDataSubType; } } public long toNumberLong(String theTerserPath, String theValue) { if (theValue == null || theValue.isEmpty()) { return 0; } if (!theValue.matches("^[0-9]+$")) { addFailure(theTerserPath, FailureCode.F019, theValue); return 0; } return Long.parseLong(theValue); } }