/* * PatientView * * Copyright (c) Worth Solutions Limited 2004-2013 * * This file is part of PatientView. * * PatientView is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * PatientView is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License along with PatientView in a file * titled COPYING. If not, see <http://www.gnu.org/licenses/>. * * @package PatientView * @link http://www.patientview.org * @author PatientView <info@patientview.org> * @copyright Copyright (c) 2004-2013, Worth Solutions Limited * @license http://www.gnu.org/licenses/gpl-3.0.html The GNU General Public License V3.0 */ package org.patientview.test.importer; import org.junit.Before; import org.junit.Test; import org.patientview.ibd.model.Allergy; import org.patientview.ibd.model.MyIbd; import org.patientview.ibd.model.Procedure; import org.patientview.model.Patient; import org.patientview.model.Specialty; import org.patientview.model.Unit; import org.patientview.model.enums.SourceType; import org.patientview.patientview.XmlImportUtils; import org.patientview.patientview.logging.AddLog; import org.patientview.patientview.model.Centre; import org.patientview.patientview.model.Diagnostic; import org.patientview.patientview.model.Letter; import org.patientview.patientview.model.Medicine; import org.patientview.patientview.model.TestResult; import org.patientview.patientview.model.User; import org.patientview.quartz.exception.ProcessException; import org.patientview.service.CentreManager; import org.patientview.service.DiagnosticManager; import org.patientview.service.ImportManager; import org.patientview.service.LetterManager; import org.patientview.service.LogEntryManager; import org.patientview.service.MedicineManager; import org.patientview.service.PatientManager; import org.patientview.service.TestResultManager; import org.patientview.service.TimeManager; import org.patientview.service.UnitManager; import org.patientview.service.ibd.IbdManager; import org.patientview.service.impl.SpringApplicationContextBean; import org.patientview.test.helpers.SecurityHelpers; import org.patientview.test.helpers.ServiceHelpers; import org.patientview.test.service.BaseServiceTest; import org.patientview.utils.LegacySpringUtils; import org.springframework.core.io.Resource; import javax.inject.Inject; import java.io.IOException; import java.util.Calendar; import java.util.Date; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** * The importer is kicked off from Quartz. * * There are 3 threads - XmlParserThread, UktParserThread & UktExportThread. * * There are 2 versions of the patient view xml schema in the examples directory. * * - pv_schema_1.0.xml - used by rpv * - pv_schema_2.0.xml - used by ibd */ public class ImporterTest extends BaseServiceTest { @Inject private SpringApplicationContextBean springApplicationContextBean; @Inject private CentreManager centreManager; @Inject private LetterManager letterManager; @Inject private DiagnosticManager diagnosticManager; @Inject private ImportManager importManager; @Inject private MedicineManager medicineManager; @Inject private PatientManager patientManager; @Inject private TestResultManager testResultManager; @Inject private IbdManager ibdManager; @Inject private UnitManager unitManager; @Inject private ServiceHelpers serviceHelpers; @Inject private LogEntryManager logEntryManager; @Inject private XmlImportUtils xmlImportUtils; @Inject private SecurityHelpers securityHelpers; @Before public void setupSystem() { Unit mockUnit = new Unit(); mockUnit.setUnitcode("RM301"); mockUnit.setName("RM301: RUNNING MAN TEST UNIT"); mockUnit.setShortname("RM301"); mockUnit.setRenaladminemail("renaladmin@mailinator.com"); Specialty mockSpecialty = new Specialty(); mockSpecialty.setName("Renal Patient View"); mockSpecialty.setContext("renal"); mockSpecialty.setDescription("Renal Patient View"); mockSpecialty = serviceHelpers.createSpecialty("Specialty1", "ten1", "A test specialty"); mockUnit.setSpecialty(mockSpecialty); User mockUser = serviceHelpers.createUserWithMapping("testname1", "test1@admin.com", "p", "test1", "UNITA", "nhstest1", mockSpecialty); serviceHelpers.createSpecialtyUserRole(mockSpecialty, mockUser, "patient"); securityHelpers.loginAsUser("testname1"); unitManager.save(mockUnit); } @Test /** * Calls XmlParserUtils.updateXmlData with files and a dao ref * * - ResultParser * - parseResults * - removePatientFromSystem * - updatePatientData * - updatePatientDetails * - updateCentreDetails * - deleteDateRanges * - insertResults * - deleteLetters * - insertLetters * - deleteOtherDiagnoses * - insertOtherDiagnoses * - deleteMedicines * - insertMedicines */ public void testXmlParserUsingRenalFile() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:A_00794_1234567890.gpg.xml"); importManager.process(xmlFileResource.getFile()); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FOLLOWUP); List<Centre> centres = centreManager.getAll(); assertEquals("Incorrect number of centres", 1, centres.size()); assertEquals("Incorrect centre", "A", centres.get(0).getCentreCode()); List<Patient> patients = patientManager.get("A"); assertEquals("Incorrect number of patients", 1, patients.size()); assertEquals("Incorrect patient", "1234567890", patients.get(0).getNhsno()); List<TestResult> results = testResultManager.get("1234567890", "A"); assertEquals("Incorrect number of results", 316, results.size()); List<Medicine> medicines = medicineManager.getAll(); assertEquals("Incorrect number of medicines", 8, medicines.size()); List<Letter> letters = letterManager.getAll(); assertEquals("Incorrect number of letters", 2, letters.size()); } /** * RPV - 138 Update the same patient twice and see if the gender gets changed as the * second XML uses a different gender. * * * @throws Exception */ @Test public void testXmlParserUpdatesPatientRecord() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:A_00794_1234567890.gpg.xml"); importManager.process(xmlFileResource.getFile()); List<Patient> patients = patientManager.getByNhsNo("1234567890"); assertTrue("The first patient record is female", patients.get(0).getSex().equals("Female")); xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:A_00794_1234567890_duplicate.gpg.xml"); importManager.process(xmlFileResource.getFile()); patients = patientManager.getByNhsNo("1234567890"); assertTrue("There is still only one patient record for this NHS Number", patients.size() == 1); assertTrue("The updated patient record is male", patients.get(0).getSex().equals("Male")); } /** * Test for a Process Exception with a invalid * * @throws Exception */ @Test(expected = ProcessException.class) public void testXmlParserChecksInvalidUnitCode() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:A_00794_1234567890-InvalidUnitCode.gpg.xml"); importManager.process(xmlFileResource.getFile()); } /** * Test to see if an exception is thrown when an update is being carried out on a radar patient * * * @throws IOException * @throws ProcessException */ @Test(expected = ProcessException.class) public void testFileImportUpdatingRadarPatient() throws IOException, ProcessException { // Create the Radar patient to map the patient in the XML file Patient patient = new Patient(); patient.setNhsno("1234567890"); patient.setSurname("Test"); patient.setForename("Radar"); patient.setUnitcode("A"); patient.setDob(new Date()); patient.setNhsNoType("1"); patient.setSourceType(SourceType.RADAR.getName()); patientManager.save(patient); Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:A_00794_1234567890.gpg.xml"); importManager.process(xmlFileResource.getFile()); } /** * Create a patient in PV and Radar, 2 rows in patient table. * * Then create an update XML for the PV patient. Code should update cleanly and not through an exception * * @throws IOException * @throws ProcessException */ @Test public void testImportPatientUpdateOKWhenPatientIsInPVAndRadar() throws IOException, ProcessException { final String nhsNumber = "1234567890"; System.out.println("1"); // Create the Radar patient to match the patient in the XML file Patient patient = new Patient(); patient.setNhsno(nhsNumber); patient.setSurname("Test"); patient.setForename("Radar"); patient.setUnitcode("A"); patient.setDob(new Date()); patient.setNhsNoType("1"); patient.setSourceType(SourceType.RADAR.getName()); patientManager.save(patient); // import results from same unit, should import cleanly sourceType = 'PatientView' Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:A_00794_1234567890.gpg.xml"); importManager.process(xmlFileResource.getFile()); System.out.println("2"); List<Patient> patients = patientManager.getByNhsNo(nhsNumber); System.out.println("3"); assertEquals("Should now be 2 patient records", 2, patients.size()); assertEquals(SourceType.PATIENT_VIEW.getName(), patients.get(0).getSourceType()); assertEquals(SourceType.RADAR.getName(), patients.get(1).getSourceType()); System.out.println("4"); // now update the patient, this should cleanly update with no errors, or duplicates importManager.process(xmlFileResource.getFile()); System.out.println("5"); patients = patientManager.getByNhsNo(nhsNumber); assertEquals("Should still be 2 patient records", 2, patients.size()); System.out.println("6"); // RPV 141 - Assert that the patient link id is not updated to 0 assertEquals("The patient link id should not be 0", patient.getPatientLinkId(), null); } @Test public void testTestResultIsNotDuplicatedIfDoubleRun() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:DUMMY_000002_9999999995.gpg.xml"); importManager.process(xmlFileResource.getFile()); List<TestResult> results = testResultManager.get("9999999995", "DUMMY"); assertEquals("Incorrect number of results after first import", 1, results.size()); // double run importManager.process(xmlFileResource.getFile()); results = testResultManager.get("9999999995", "DUMMY"); assertEquals("Incorrect number of results after double run import", 1, results.size()); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FOLLOWUP); } /** * Test if importer handles empty test file. This probably means that the encryption did not work. * * An email should be sent to RPV admin email address and an entry should be created in log table * * @throws IOException */ @Test public void testXmlParserUsingEmptyIBDFile() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:rm301_empty_9876543210.xml"); try { importManager.process(xmlFileResource.getFile()); } catch (Exception e) { assertEquals("Exception is not expected", true, e instanceof ProcessException); } checkNoDataHasBeenImportedFromIBDImportFile(); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FAIL); } /** * Check if no data was imported */ private void checkNoDataHasBeenImportedFromIBDImportFile() { List<Centre> centres = centreManager.getAll(); assertEquals("Centres were imported although data file was supposed to be empty", 0, centres.size()); List<Unit> units = unitManager.getAll(false); /** * {@link #setupSystem()} creates one unit so its ok if we have one unit now */ assertEquals("Units were imported although data file was supposed to be empty", 1, units.size()); } /** * Check if log entry was created * * @param nhsNo nhsNo of patient * @param action log type */ private void checkLogEntry(String nhsNo, String action) { assertNotNull("Log entry was not created", logEntryManager.getLatestLogEntry(nhsNo, action)); } /** * Test if importer handles test results with future date * * The whole file should be rejected, an email should be sent to RPV admin email, and a "patient data fail" * entry should be added to the log table * * @throws IOException */ @Test public void testXmlParserCheckFutureTestResultDateInIBDFile() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:rm301_resultWithFutureDate_9876543210.xml"); try { importManager.process(xmlFileResource.getFile()); } catch (Exception e) { assertEquals("Exception is not expected", true, e instanceof ProcessException); } checkNoDataHasBeenImportedFromIBDImportFile(); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FAIL); } /** * Test if importer handles test results outside date ranges specified * * Whole file needs to be rejected, and an email needs to be sent to RPV admin email * * @throws IOException */ @Test public void testXmlParserCheckTestResultOutsideDataRangeInIBDFile() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:rm301_resultWithOutsideDaterange_9876543210.xml"); try { importManager.process(xmlFileResource.getFile()); } catch (Exception e) { assertEquals("Exception is not expected", true, e instanceof ProcessException); } checkNoDataHasBeenImportedFromIBDImportFile(); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FAIL); } /** * Test if importer handles test results with valid dates including edge cases. * * @throws IOException */ @Test public void testXmlParserCheckTestResultWithValidDates() throws Exception { /** * Fix the current date to always be the same. * * Note: this only overrides the behaviour of the timeManager reference used by LegacySpringUtils * If you need to change application wide, add a new implementation to the text-context.xml */ LegacySpringUtils.setTimeManager(new TimeManager() { @Override public Date getCurrentDate() { Calendar calendar = Calendar.getInstance(); calendar.set(2013, Calendar.MARCH, 29, 11, 23, 0); return calendar.getTime(); } }); Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:rm301_resultWithValidDates_9876543210.xml"); importManager.process(xmlFileResource.getFile()); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FOLLOWUP); } /** * Test if importer handles test results with empty values * * Whole file needs to be rejected, n email should be sent to RPV admin and the error should be logged. * * @throws IOException */ @Test public void testXmlParserCheckTestResultWithEmptyValueInIBDFile() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:rm301_resultWithEmptyValue_9876543210.xml"); try { importManager.process(xmlFileResource.getFile()); } catch (Exception e) { assertEquals("Exception is not expected", true, e instanceof ProcessException); } checkNoDataHasBeenImportedFromIBDImportFile(); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FAIL); } /** * Test if the importer imports data * * @throws IOException */ @Test public void testXmlParserUsingIBDFile() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:rm301_1244_9876543210.xml"); importManager.process(xmlFileResource.getFile()); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FOLLOWUP); checkIbdImportedData(); List<TestResult> results = testResultManager.get("9876543210", "RM301"); assertEquals("Incorrect number of results", 3, results.size()); } /** * If you run the import twice for the same file we still have the same data set */ @Test public void testXmlParserUsingIBDFileMultipleRuns() throws Exception { Resource xmlFileResource = springApplicationContextBean.getApplicationContext() .getResource("classpath:rm301_1244_9876543210.xml"); // run twice importManager.process(xmlFileResource.getFile()); importManager.process(xmlFileResource.getFile()); checkLogEntry(xmlImportUtils.getNhsNumber(xmlFileResource.getFile().getName()), AddLog.PATIENT_DATA_FOLLOWUP); checkIbdImportedData(); // Note the results get deleted each run on date range } /** * check the data importer should have imported. */ private void checkIbdImportedData() { // test the stuff that should be the same regardless of how many imports of the file are done List<Centre> centres = centreManager.getAll(); assertEquals("Incorrect number of centres", 1, centres.size()); assertEquals("Incorrect centre", "RM301", centres.get(0).getCentreCode()); List<Patient> patients = patientManager.get("RM301"); assertEquals("Incorrect number of patients", 1, patients.size()); assertEquals("Incorrect patient", "9876543210", patients.get(0).getNhsno()); List<Letter> letters = letterManager.getAll(); assertEquals("Incorrect number of letters", 2, letters.size()); MyIbd myIbd = ibdManager.getMyIbd("9876543210"); assertNotNull("No MyIbd information was parsed", myIbd); Diagnostic diagnostic = diagnosticManager.get("9876543210"); assertNotNull("No diagnostic information was parsed", diagnostic); Procedure procedure = ibdManager.getProcedure("9876543210"); assertNotNull("No procedure information was parsed", procedure); Allergy allergy = ibdManager.getAllergy("9876543210"); assertNotNull("No allergy information was parsed", allergy); } }