/** * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations under * the License. * * The Original Code is OpenELIS code. * * Copyright (C) The Minnesota Department of Health. All Rights Reserved. * * Contributor(s): CIRG, University of Washington, Seattle WA. */ package us.mn.state.health.lims.resultvalidation.action; import org.apache.commons.validator.GenericValidator; import org.apache.struts.Globals; import org.apache.struts.action.*; import org.hibernate.Transaction; import us.mn.state.health.lims.analysis.dao.AnalysisDAO; import us.mn.state.health.lims.analysis.daoimpl.AnalysisDAOImpl; import us.mn.state.health.lims.analysis.valueholder.Analysis; import us.mn.state.health.lims.common.action.BaseActionForm; import us.mn.state.health.lims.common.exception.LIMSRuntimeException; import us.mn.state.health.lims.common.services.*; import us.mn.state.health.lims.common.services.NoteService.NoteType; import us.mn.state.health.lims.common.services.StatusService.AnalysisStatus; import us.mn.state.health.lims.common.services.StatusService.OrderStatus; import us.mn.state.health.lims.common.services.beanAdapters.ResultSaveBeanAdapter; import us.mn.state.health.lims.common.services.registration.ValidationUpdateRegister; import us.mn.state.health.lims.common.services.registration.interfaces.IResultUpdate; import us.mn.state.health.lims.common.services.serviceBeans.ResultSaveBean; //import us.mn.state.health.lims.common.util.ConfigurationProperties; import us.mn.state.health.lims.common.util.StringUtil; //import us.mn.state.health.lims.common.util.ConfigurationProperties.Property; import us.mn.state.health.lims.common.util.validator.ActionError; import us.mn.state.health.lims.hibernate.HibernateUtil; import us.mn.state.health.lims.note.dao.NoteDAO; import us.mn.state.health.lims.note.daoimpl.NoteDAOImpl; import us.mn.state.health.lims.note.valueholder.Note; import us.mn.state.health.lims.patient.valueholder.Patient; import us.mn.state.health.lims.referencetables.daoimpl.ReferenceTablesDAOImpl; import us.mn.state.health.lims.reports.dao.DocumentTrackDAO; import us.mn.state.health.lims.reports.daoimpl.DocumentTrackDAOImpl; import us.mn.state.health.lims.reports.daoimpl.DocumentTypeDAOImpl; import us.mn.state.health.lims.reports.valueholder.DocumentTrack; import us.mn.state.health.lims.result.action.util.ResultSet; import us.mn.state.health.lims.result.dao.ResultDAO; import us.mn.state.health.lims.result.daoimpl.ResultDAOImpl; import us.mn.state.health.lims.result.valueholder.Result; import us.mn.state.health.lims.resultvalidation.action.util.ResultValidationPaging; import us.mn.state.health.lims.resultvalidation.bean.AnalysisItem; import us.mn.state.health.lims.sample.dao.SampleDAO; import us.mn.state.health.lims.sample.daoimpl.SampleDAOImpl; import us.mn.state.health.lims.sample.valueholder.Sample; import us.mn.state.health.lims.samplehuman.dao.SampleHumanDAO; import us.mn.state.health.lims.samplehuman.daoimpl.SampleHumanDAOImpl; import us.mn.state.health.lims.systemuser.dao.SystemUserDAO; import us.mn.state.health.lims.systemuser.daoimpl.SystemUserDAOImpl; import us.mn.state.health.lims.systemuser.valueholder.SystemUser; import us.mn.state.health.lims.testresult.dao.TestResultDAO; import us.mn.state.health.lims.testresult.daoimpl.TestResultDAOImpl; import us.mn.state.health.lims.testresult.valueholder.TestResult; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; import static org.apache.commons.validator.GenericValidator.isBlankOrNull; public class ResultValidationSaveAction extends BaseResultValidationAction implements IResultSaveService { // DAOs private static final AnalysisDAO analysisDAO = new AnalysisDAOImpl(); private static final SampleDAO sampleDAO = new SampleDAOImpl(); private static final TestResultDAO testResultDAO = new TestResultDAOImpl(); private static final ResultDAO resultDAO = new ResultDAOImpl(); private static final NoteDAO noteDAO = new NoteDAOImpl(); private static final SampleHumanDAO sampleHumanDAO = new SampleHumanDAOImpl(); private static final DocumentTrackDAO documentTrackDAO = new DocumentTrackDAOImpl(); // Update Lists private List<Analysis> analysisUpdateList; private ArrayList<Sample> sampleUpdateList; private ArrayList<Note> noteUpdateList; private ArrayList<Result> resultUpdateList; private List<Result> deletableList; private SystemUser systemUser; private ArrayList<Integer> sampleFinishedStatus = new ArrayList<Integer>(); private List<ResultSet> modifiedResultSet; private List<ResultSet> newResultSet; private static final String RESULT_SUBJECT = "Result Note"; private static final String RESULT_TABLE_ID; private static final String RESULT_REPORT_ID; static{ RESULT_TABLE_ID = new ReferenceTablesDAOImpl().getReferenceTableByName("RESULT").getId(); RESULT_REPORT_ID = new DocumentTypeDAOImpl().getDocumentTypeByName("resultExport").getId(); } @Override protected ActionForward performAction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception{ String forward = FWD_SUCCESS; List<IResultUpdate> updaters = ValidationUpdateRegister.getRegisteredUpdaters(); boolean areListeners = updaters != null && !updaters.isEmpty(); request.getSession().setAttribute(SAVE_DISABLED, "true"); BaseActionForm dynaForm = (BaseActionForm)form; ResultValidationPaging paging = new ResultValidationPaging(); paging.updatePagedResults(request, dynaForm); List<AnalysisItem> resultItemList = paging.getResults(request); String testSectionName = (String)dynaForm.get("testSection"); String testName = (String)dynaForm.get("testName"); setRequestType(testSectionName); //---------------------- String url = request.getRequestURL().toString(); ActionMessages errors = validateModifiedItems(resultItemList); if(errors.size() > 0){ saveErrors(request, errors); request.setAttribute(Globals.ERROR_KEY, errors); return mapping.findForward(FWD_VALIDATION_ERROR); } createSystemUser(); setSampleFinishedStatuses(); noteUpdateList = new ArrayList<Note>(); resultUpdateList = new ArrayList<Result>(); analysisUpdateList = new ArrayList<Analysis>(); modifiedResultSet = new ArrayList<ResultSet>(); newResultSet = new ArrayList<ResultSet>(); deletableList = new ArrayList<Result>(); if(testSectionName.equals("serology")){ createUpdateElisaList(resultItemList); }else{ createUpdateList(resultItemList, areListeners); } Transaction tx = HibernateUtil.getSession().beginTransaction(); try{ ResultSaveService.removeDeletedResultsInTransaction( deletableList,currentUserId); // update analysis for(Analysis analysis : analysisUpdateList){ analysisDAO.updateData(analysis); } for(Result result : resultUpdateList){ if( result.getId() != null){ resultDAO.updateData(result); }else{ resultDAO.insertData(result); } } checkIfSamplesFinished(resultItemList); // update finished samples for(Sample sample : sampleUpdateList){ sampleDAO.updateData(sample); } // create or update notes for(Note note : noteUpdateList){ if(note != null){ if(note.getId() == null){ noteDAO.insertData(note); }else{ noteDAO.updateData(note); } } } for(IResultUpdate updater : updaters){ updater.transactionalUpdate(this); } tx.commit(); }catch(LIMSRuntimeException lre){ tx.rollback(); } for(IResultUpdate updater : updaters){ updater.postTransactionalCommitUpdate(this); } // route save back to RetroC specific ResultValidationRetroCAction // if (ConfigurationProperties.getInstance().isPropertyValueEqual(Property.configurationName, "CI RetroCI")) if (url.contains("RetroC")) forward = "successRetroC"; if( isBlankOrNull( testSectionName )){ return mapping.findForward(forward); }else{ Map<String, String> params = new HashMap<String, String>(); params.put("type", testSectionName); params.put("test", testName); params.put("forward", forward); return getForwardWithParameters(mapping.findForward(forward), params); } } private ActionMessages validateModifiedItems(List<AnalysisItem> resultItemList){ ActionErrors errors = new ActionErrors(); for (AnalysisItem item : resultItemList) { List<ActionError> errorList = new ArrayList<ActionError>(); validateQuantifiableItems(item, errorList); if (errorList.size() > 0) { StringBuilder augmentedAccession = new StringBuilder(item.getAccessionNumber()); augmentedAccession.append(" : "); augmentedAccession.append(item.getTestName()); ActionError accessionError = new ActionError("errors.followingAccession", augmentedAccession); errors.add(ActionErrors.GLOBAL_MESSAGE, accessionError); for (ActionError error : errorList) { errors.add(ActionErrors.GLOBAL_MESSAGE, error); } } } return errors; } public void validateQuantifiableItems(AnalysisItem analysisItem, List<ActionError> errors){ if( analysisItem.isHasQualifiedResult() && isBlankOrNull( analysisItem.getQualifiedResultValue() ) && analysisItemWillBeUpdated(analysisItem)){ errors.add(new ActionError("errors.missing.result.details", new StringBuilder("Result"))); } // verify that qualifiedResultValue has been entered if required if (!isBlankOrNull( analysisItem.getQualifiedDictionaryId() )) { String[] qualifiedDictionaryIds = analysisItem.getQualifiedDictionaryId().replace("[", "").replace("]", "").split(","); Set<String> qualifiedDictIdsSet = new HashSet<String>(Arrays.asList(qualifiedDictionaryIds)); if (qualifiedDictIdsSet.contains(analysisItem.getResult()) && isBlankOrNull( analysisItem.getQualifiedResultValue() )) { errors.add(new ActionError("errors.missing.result.details", new StringBuilder("Result"))); } } } private void createUpdateList(List<AnalysisItem> analysisItems, boolean areListeners){ List<String> analysisIdList = new ArrayList<String>(); for(AnalysisItem analysisItem : analysisItems){ if(!analysisItem.isReadOnly() && analysisItemWillBeUpdated(analysisItem)){ AnalysisService analysisService = new AnalysisService( analysisItem.getAnalysisId() ); Analysis analysis = analysisService.getAnalysis(); NoteService noteService = new NoteService( analysis ); analysis.setSysUserId(currentUserId); if(!analysisIdList.contains(analysis.getId())){ if(analysisItem.getIsAccepted()){ analysis.setStatusId(StatusService.getInstance().getStatusID(AnalysisStatus.Finalized)); analysis.setReleasedDate(new java.sql.Date(Calendar.getInstance().getTimeInMillis())); analysisIdList.add(analysis.getId()); analysisUpdateList.add(analysis); } if(analysisItem.getIsRejected()){ analysis.setStatusId(StatusService.getInstance().getStatusID(AnalysisStatus.BiologistRejected)); analysisIdList.add(analysis.getId()); analysisUpdateList.add(analysis); } } createNeededNotes( analysisItem, noteService ); if (areResults(analysisItem)) { List<Result> results = createResultFromAnalysisItem(analysisItem, analysisService, noteService); for (Result result : results) { resultUpdateList.add(result); if (areListeners) { addResultSets(analysis, result); } } } } } } private void createNeededNotes( AnalysisItem analysisItem, NoteService noteService ){ if( analysisItem.getIsRejected()){ Note note = noteService.createSavableNote( NoteType.INTERNAL, StringUtil.getMessageForKey( "validation.note.retest" ), RESULT_SUBJECT, currentUserId ); noteUpdateList.add( note ); } if( !GenericValidator.isBlankOrNull( analysisItem.getNote() )){ NoteType noteType = analysisItem.getIsAccepted() ? NoteType.EXTERNAL : NoteType.INTERNAL; Note note = noteService.createSavableNote( noteType, analysisItem.getNote(), RESULT_SUBJECT, currentUserId ); noteUpdateList.add( note ); } } private void addResultSets(Analysis analysis, Result result){ Sample sample = analysis.getSampleItem().getSample(); Patient patient = sampleHumanDAO.getPatientForSample(sample); List<DocumentTrack> documents = documentTrackDAO.getByTypeRecordAndTable(RESULT_REPORT_ID, RESULT_TABLE_ID, result.getId()); if( documents.isEmpty()){ newResultSet.add(new ResultSet(result, null,null, patient, sample, null, false)); }else{ modifiedResultSet.add(new ResultSet(result, null,null, patient, sample, null, false)); } } private boolean analysisItemWillBeUpdated(AnalysisItem analysisItem){ return analysisItem.getIsAccepted() || analysisItem.getIsRejected(); } private void createUpdateElisaList(List<AnalysisItem> resultItems){ for(AnalysisItem resultItem : resultItems){ if(resultItem.getIsAccepted()){ List<Analysis> acceptedAnalysisList = createAnalysisFromElisaAnalysisItem(resultItem); for(Analysis analysis : acceptedAnalysisList){ analysis.setStatusId(StatusService.getInstance().getStatusID(AnalysisStatus.Finalized)); analysisUpdateList.add(analysis); } } if(resultItem.getIsRejected()){ List<Analysis> rejectedAnalysisList = createAnalysisFromElisaAnalysisItem(resultItem); for(Analysis analysis : rejectedAnalysisList){ analysis.setStatusId(StatusService.getInstance().getStatusID(AnalysisStatus.BiologistRejected)); analysisUpdateList.add(analysis); } } } } private List<Analysis> createAnalysisFromElisaAnalysisItem(AnalysisItem analysisItem){ List<Analysis> analysisList = new ArrayList<Analysis>(); Analysis analysis = new Analysis(); if(!isBlankOrNull( analysisItem.getMurexResult() )){ analysis = getAnalysisFromId(analysisItem.getMurexAnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getBiolineResult() )){ analysis = getAnalysisFromId(analysisItem.getBiolineAnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getIntegralResult() )){ analysis = getAnalysisFromId(analysisItem.getIntegralAnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getVironostikaResult() )){ analysis = getAnalysisFromId(analysisItem.getVironostikaAnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getGenieIIResult() )){ analysis = getAnalysisFromId(analysisItem.getGenieIIAnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getGenieII10Result() )){ analysis = getAnalysisFromId(analysisItem.getGenieII10AnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getGenieII100Result() )){ analysis = getAnalysisFromId(analysisItem.getGenieII100AnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getWesternBlot1Result() )){ analysis = getAnalysisFromId(analysisItem.getWesternBlot1AnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getWesternBlot2Result() )){ analysis = getAnalysisFromId(analysisItem.getWesternBlot2AnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getP24AgResult() )){ analysis = getAnalysisFromId(analysisItem.getP24AgAnalysisId()); analysisList.add(analysis); } if(!isBlankOrNull( analysisItem.getInnoliaResult() )){ analysis = getAnalysisFromId(analysisItem.getInnoliaAnalysisId()); analysisList.add(analysis); } analysisList.add(analysis); return analysisList; } private void checkIfSamplesFinished(List<AnalysisItem> resultItemList){ sampleUpdateList = new ArrayList<Sample>(); String currentSampleId = ""; boolean sampleFinished = true; for(AnalysisItem analysisItem : resultItemList){ String analysisSampleId = sampleDAO.getSampleByAccessionNumber(analysisItem.getAccessionNumber()).getId(); if(!analysisSampleId.equals(currentSampleId)){ currentSampleId = analysisSampleId; List<Analysis> analysisList = analysisDAO.getAnalysesBySampleId(currentSampleId); for(Analysis analysis : analysisList){ if(!sampleFinishedStatus.contains(Integer.parseInt(analysis.getStatusId()))){ sampleFinished = false; break; } } if(sampleFinished){ Sample sample = new Sample(); sample.setId(currentSampleId); sampleDAO.getData(sample); sample.setStatusId(StatusService.getInstance().getStatusID(OrderStatus.Finished)); sampleUpdateList.add(sample); } sampleFinished = true; } } } private Analysis getAnalysisFromId(String id){ Analysis analysis = new Analysis(); analysis.setId(id); analysisDAO.getData(analysis); analysis.setSysUserId(currentUserId); return analysis; } private List<Result> createResultFromAnalysisItem(AnalysisItem analysisItem, AnalysisService analysisService, NoteService noteService){ ResultSaveBean bean = ResultSaveBeanAdapter.fromAnalysisItem(analysisItem); ResultSaveService resultSaveService = new ResultSaveService(analysisService.getAnalysis(), currentUserId ); List<Result> results = resultSaveService.createResultsFromTestResultItem(bean,deletableList); if( analysisService.patientReportHasBeenDone() && resultSaveService.isUpdatedResult()){ analysisService.getAnalysis().setCorrectedSincePatientReport( true ); noteUpdateList.add( noteService.createSavableNote( NoteType.EXTERNAL, StringUtil.getMessageForKey( "note.corrected.result" ), RESULT_SUBJECT, currentUserId )); } return results; } protected TestResult getTestResult(AnalysisItem analysisItem){ TestResult testResult = null; if(TypeOfTestResultService.ResultType.DICTIONARY.matches( analysisItem.getResultType() )){ testResult = testResultDAO.getTestResultsByTestAndDictonaryResult(analysisItem.getTestId(), analysisItem.getResult()); }else{ List<TestResult> testResultList = testResultDAO.getActiveTestResultsByTest( analysisItem.getTestId() ); // we are assuming there is only one testResult for a numeric type // result if(!testResultList.isEmpty()){ testResult = testResultList.get(0); } } return testResult; } private boolean areResults(AnalysisItem item){ return !( isBlankOrNull( item.getResult() ) || (TypeOfTestResultService.ResultType.DICTIONARY.matches( item.getResultType() ) && "0".equals(item.getResult()))) || (TypeOfTestResultService.ResultType.isMultiSelectVariant( item.getResultType() ) && !isBlankOrNull( item.getMultiSelectResultValues() )); } private void createSystemUser(){ systemUser = new SystemUser(); systemUser.setId(currentUserId); SystemUserDAO systemUserDAO = new SystemUserDAOImpl(); systemUserDAO.getData(systemUser); } private void setSampleFinishedStatuses(){ sampleFinishedStatus = new ArrayList<Integer>(); sampleFinishedStatus.add(Integer.parseInt(StatusService.getInstance().getStatusID(AnalysisStatus.Finalized))); sampleFinishedStatus.add(Integer.parseInt(StatusService.getInstance().getStatusID(AnalysisStatus.Canceled))); sampleFinishedStatus.add(Integer.parseInt(StatusService.getInstance().getStatusID(AnalysisStatus.NonConforming_depricated))); } @Override public String getCurrentUserId(){ return currentUserId; } @Override public List<ResultSet> getNewResults(){ return newResultSet; } @Override public List<ResultSet> getModifiedResults(){ return modifiedResultSet; } }