/**
* 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) ITECH, University of Washington, Seattle WA. All Rights Reserved.
*
*/
package us.mn.state.health.lims.common.services;
import org.apache.commons.validator.GenericValidator;
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.dictionary.dao.DictionaryDAO;
import us.mn.state.health.lims.dictionary.daoimpl.DictionaryDAOImpl;
import us.mn.state.health.lims.dictionary.valueholder.Dictionary;
import us.mn.state.health.lims.observationhistory.dao.ObservationHistoryDAO;
import us.mn.state.health.lims.observationhistory.daoimpl.ObservationHistoryDAOImpl;
import us.mn.state.health.lims.observationhistory.valueholder.ObservationHistory;
import us.mn.state.health.lims.observationhistory.valueholder.ObservationHistory.ValueType;
import us.mn.state.health.lims.observationhistorytype.dao.ObservationHistoryTypeDAO;
import us.mn.state.health.lims.observationhistorytype.daoImpl.ObservationHistoryTypeDAOImpl;
import us.mn.state.health.lims.observationhistorytype.valueholder.ObservationHistoryType;
import us.mn.state.health.lims.patient.valueholder.Patient;
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.samplehuman.valueholder.SampleHuman;
import us.mn.state.health.lims.statusofsample.dao.StatusOfSampleDAO;
import us.mn.state.health.lims.statusofsample.daoimpl.StatusOfSampleDAOImpl;
import us.mn.state.health.lims.statusofsample.valueholder.StatusOfSample;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class StatusService{
public enum OrderStatus{
Entered,
Started,
Finished,
NonConforming_depricated
}
public enum AnalysisStatus{
NotStarted,
Canceled,
TechnicalAcceptance,
TechnicalRejected,
BiologistRejected,
NonConforming_depricated,
Finalized
}
public enum RecordStatus{
NotRegistered,
InitialRegistration,
ValidationRegistration
}
public enum SampleStatus{
Entered,
Canceled
}
public enum StatusType{
Analysis,
Sample,
Order,
SampleEntry,
PatientEntry
}
public enum ExternalOrderStatus{
Entered,
Cancelled,
Realized
}
private static Map<String, OrderStatus> idToOrderStatusMap = null;
private static Map<String, SampleStatus> idToSampleStatusMap = null;
private static Map<String, AnalysisStatus> idToAnalysisStatusMap = null;
private static Map<String, RecordStatus> idToRecordStatusMap = null;
private static Map<String, ExternalOrderStatus> idToExternalOrderStatusMap = null;
private static Map<OrderStatus, StatusOfSample> orderStatusToObjectMap = null;
private static Map<SampleStatus, StatusOfSample> sampleStatusToObjectMap = null;
private static Map<AnalysisStatus, StatusOfSample> analysisStatusToObjectMap = null;
private static Map<RecordStatus, Dictionary> recordStatusToObjectMap = null;
private static Map<ExternalOrderStatus, StatusOfSample> externalOrderStatusToObjectMap = null;
private static String orderRecordStatusID;
private static String patientRecordStatusID;
private static ObservationHistoryDAO observationHistoryDAO = new ObservationHistoryDAOImpl();
private static boolean mapsSet = false;
private StatusService(){
}
private static class SingletonHolder{
public static final StatusService INSTANCE = new StatusService();
}
public static StatusService getInstance(){
return SingletonHolder.INSTANCE;
}
public boolean matches(String id, SampleStatus sampleStatus){
insureMapsAreBuilt();
return getStatusID( sampleStatus ).equals( id );
}
public boolean matches(String id, AnalysisStatus analysisStatus){
insureMapsAreBuilt();
return getStatusID( analysisStatus ).equals( id );
}
public boolean matches(String id, OrderStatus orderStatus){
insureMapsAreBuilt();
return getStatusID( orderStatus ).equals( id );
}
public boolean matches(String id, ExternalOrderStatus externalOrderStatus){
insureMapsAreBuilt();
return getStatusID( externalOrderStatus ).equals( id );
}
public String getStatusID(OrderStatus statusType){
insureMapsAreBuilt();
StatusOfSample status = orderStatusToObjectMap.get(statusType);
return status == null ? "-1" : status.getId();
}
public String getStatusID(SampleStatus statusType){
insureMapsAreBuilt();
StatusOfSample status = sampleStatusToObjectMap.get(statusType);
return status == null ? "-1" : status.getId();
}
public String getStatusID(AnalysisStatus statusType){
insureMapsAreBuilt();
StatusOfSample status = analysisStatusToObjectMap.get(statusType);
return status == null ? "-1" : status.getId();
}
public String getStatusID(ExternalOrderStatus statusType){
insureMapsAreBuilt();
StatusOfSample status = externalOrderStatusToObjectMap.get(statusType);
return status == null ? "-1" : status.getId();
}
public String getStatusName(RecordStatus statusType){
insureMapsAreBuilt();
Dictionary dictionary = recordStatusToObjectMap.get(statusType);
return dictionary == null ? "unknown" : dictionary.getLocalizedName();
}
public String getStatusName(OrderStatus statusType){
insureMapsAreBuilt();
StatusOfSample status = orderStatusToObjectMap.get(statusType);
return status == null ? "unknown" : status.getLocalizedName();
}
public String getStatusName(SampleStatus statusType){
insureMapsAreBuilt();
StatusOfSample status = sampleStatusToObjectMap.get(statusType);
return status == null ? "unknown" : status.getLocalizedName();
}
public String getStatusName(AnalysisStatus statusType){
insureMapsAreBuilt();
StatusOfSample status = analysisStatusToObjectMap.get(statusType);
return status == null ? "unknown" : status.getLocalizedName();
}
public String getStatusName(ExternalOrderStatus statusType){
insureMapsAreBuilt();
StatusOfSample status = externalOrderStatusToObjectMap.get(statusType);
return status == null ? "unknown" : status.getLocalizedName();
}
public String getDictionaryID(RecordStatus statusType){
insureMapsAreBuilt();
Dictionary dictionary = recordStatusToObjectMap.get(statusType);
return dictionary == null ? "-1" : dictionary.getId();
}
public OrderStatus getOrderStatusForID(String id){
insureMapsAreBuilt();
return idToOrderStatusMap.get(id);
}
public SampleStatus getSampleStatusForID(String id){
insureMapsAreBuilt();
return idToSampleStatusMap.get(id);
}
public AnalysisStatus getAnalysisStatusForID(String id){
insureMapsAreBuilt();
return idToAnalysisStatusMap.get(id);
}
public ExternalOrderStatus getExternalOrderStatusForID(String id){
insureMapsAreBuilt();
return idToExternalOrderStatusMap.get(id);
}
public RecordStatus getRecordStatusForID(String id){
insureMapsAreBuilt();
return idToRecordStatusMap.get(id);
}
public StatusSet getStatusSetForSampleId(String sampleId){
Sample sample = new Sample();
sample.setId(sampleId);
SampleDAO sampleDAO = new SampleDAOImpl();
sampleDAO.getData(sample);
return buildStatusSet(sample);
}
public StatusSet getStatusSetForAccessionNumber(String accessionNumber){
if(GenericValidator.isBlankOrNull(accessionNumber)){
return new StatusSet();
}
SampleDAO sampleDAO = new SampleDAOImpl();
Sample sample = sampleDAO.getSampleByAccessionNumber(accessionNumber);
return buildStatusSet(sample);
}
/*
* Preconditions: It is called within a transaction Both the patient and
* sample ids are valid
*
* For now it will fail silently Either sampleStatus or patient status may
* be null
*/
public void persistRecordStatusForSample(Sample sample, RecordStatus recordStatus, Patient patient, RecordStatus patientStatus, String sysUserId){
insureMapsAreBuilt();
if(sample == null || patient == null){
return;
}
List<ObservationHistory> observationList = observationHistoryDAO.getAll(patient, sample);
ObservationHistory sampleRecord = null;
ObservationHistory patientRecord = null;
for(ObservationHistory currentHistory : observationList){
if(currentHistory.getObservationHistoryTypeId().equals(orderRecordStatusID)){
sampleRecord = currentHistory;
}else if(currentHistory.getObservationHistoryTypeId().equals(patientRecordStatusID)){
patientRecord = currentHistory;
}
}
if(recordStatus != null){
insertOrUpdateStatus(sample, patient, recordStatus, sysUserId, sampleRecord, orderRecordStatusID);
}
if(patientStatus != null){
insertOrUpdateStatus(sample, patient, patientStatus, sysUserId, patientRecord, patientRecordStatusID);
}
}
private void insertOrUpdateStatus(Sample sample, Patient patient, RecordStatus status, String sysUserId, ObservationHistory record, String historyTypeId) {
if( record == null){
record = new ObservationHistory();
record.setObservationHistoryTypeId(historyTypeId);
record.setPatientId(patient.getId());
record.setSampleId(sample.getId());
record.setSysUserId(sysUserId);
record.setValue(getDictionaryID(status));
record.setValueType(ValueType.DICTIONARY);
observationHistoryDAO.insertData(record);
}else{
record.setSysUserId(sysUserId);
record.setValue(getDictionaryID(status));
observationHistoryDAO.updateData(record);
}
}
public void deleteRecordStatus(Sample sample, Patient patient, String sysUserId){
insureMapsAreBuilt();
if(sample == null || patient == null){
return;
}
List<ObservationHistory> observations = observationHistoryDAO.getAll(patient, sample);
List<ObservationHistory> records = new ArrayList<ObservationHistory>();
for(ObservationHistory observation : observations){
if(observation.getObservationHistoryTypeId().equals(orderRecordStatusID) ||
observation.getObservationHistoryTypeId().equals(patientRecordStatusID)){
observation.setSysUserId(sysUserId);
records.add(observation);
}
}
observationHistoryDAO.delete(records);
}
public String getStatusNameFromId(String id){
insureMapsAreBuilt();
if(idToAnalysisStatusMap.get(id) != null){
return getStatusName(idToAnalysisStatusMap.get(id));
}else if(idToOrderStatusMap.get(id) != null){
return getStatusName(idToOrderStatusMap.get(id));
}else if(idToSampleStatusMap.get(id) != null){
return getStatusName(idToSampleStatusMap.get(id));
}else if(idToRecordStatusMap.get(id) != null){
return getStatusName(idToRecordStatusMap.get(id));
}else if(idToExternalOrderStatusMap.get(id) != null){
return getStatusName(idToExternalOrderStatusMap.get(id));
}
return null;
}
private void insureMapsAreBuilt(){
synchronized(StatusService.class){
if(!mapsSet){
buildMap();
mapsSet = true;
}
}
}
private void buildMap(){
orderStatusToObjectMap = new HashMap<OrderStatus, StatusOfSample>();
sampleStatusToObjectMap = new HashMap<SampleStatus, StatusOfSample>();
analysisStatusToObjectMap = new HashMap<AnalysisStatus, StatusOfSample>();
recordStatusToObjectMap = new HashMap<RecordStatus, Dictionary>();
externalOrderStatusToObjectMap = new HashMap<ExternalOrderStatus, StatusOfSample>();
idToOrderStatusMap = new HashMap<String, OrderStatus>();
idToSampleStatusMap = new HashMap<String, SampleStatus>();
idToAnalysisStatusMap = new HashMap<String, AnalysisStatus>();
idToRecordStatusMap = new HashMap<String, RecordStatus>();
idToExternalOrderStatusMap = new HashMap<String, ExternalOrderStatus>();
buildStatusToIdMaps();
// now put everything in the reverse map
buildIdToStatusMapsFromStatusToIdMaps();
getObservationHistoryTypeIDs();
}
@SuppressWarnings("unchecked")
private void buildStatusToIdMaps(){
StatusOfSampleDAO statusOfSampleDAO = new StatusOfSampleDAOImpl();
List<StatusOfSample> statusList = statusOfSampleDAO.getAllStatusOfSamples();
// sorry about this but it is only done once and until Java 7 we have to
// use if..else
for(StatusOfSample status : statusList){
if(status.getStatusType().equals("ORDER")){
addToOrderMap(status);
}else if(status.getStatusType().equals("ANALYSIS")){
addToAnalysisMap(status);
}else if(status.getStatusType().equals("SAMPLE")){
addToSampleMap(status);
}else if(status.getStatusType().equals("EXTERNAL_ORDER")){
addToExternalOrderMap(status);
}
}
DictionaryDAO dictionaryDAO = new DictionaryDAOImpl();
List<Dictionary> dictionaryList = dictionaryDAO.getDictionaryEntrysByCategoryNameLocalizedSort("REC_STATUS");
for(Dictionary dictionary : dictionaryList){
addToRecordMap(dictionary);
}
}
private void addToOrderMap(StatusOfSample status){
String name = status.getStatusOfSampleName();
if(name.equals("Test Entered")){
orderStatusToObjectMap.put(OrderStatus.Entered, status);
}else if(name.equals("Testing Started")){
orderStatusToObjectMap.put(OrderStatus.Started, status);
}else if(name.equals("Testing finished")){
orderStatusToObjectMap.put(OrderStatus.Finished, status);
}else if(name.equals("NonConforming")){
orderStatusToObjectMap.put(OrderStatus.NonConforming_depricated, status);
}
}
private void addToAnalysisMap(StatusOfSample status){
String name = status.getStatusOfSampleName();
if(name.equals("Not Tested")){
analysisStatusToObjectMap.put(AnalysisStatus.NotStarted, status);
}else if(name.equals("Test Canceled")){
analysisStatusToObjectMap.put(AnalysisStatus.Canceled, status);
}else if(name.equals("Technical Acceptance")){
analysisStatusToObjectMap.put(AnalysisStatus.TechnicalAcceptance, status);
}else if(name.equals("Technical Rejected")){
analysisStatusToObjectMap.put(AnalysisStatus.TechnicalRejected, status);
}else if(name.equals("Biologist Rejection")){
analysisStatusToObjectMap.put(AnalysisStatus.BiologistRejected, status);
}else if(name.equals("Finalized")){
analysisStatusToObjectMap.put(AnalysisStatus.Finalized, status);
}else if(name.equals("NonConforming")){
analysisStatusToObjectMap.put(AnalysisStatus.NonConforming_depricated, status);
}
}
private void addToExternalOrderMap(StatusOfSample status){
String name = status.getStatusOfSampleName();
if(name.equals("Entered")){
externalOrderStatusToObjectMap.put(ExternalOrderStatus.Entered, status);
}else if(name.equals("Cancelled")){
externalOrderStatusToObjectMap.put(ExternalOrderStatus.Cancelled, status);
}else if(name.equals("Realized")){
externalOrderStatusToObjectMap.put(ExternalOrderStatus.Realized, status);
}
}
private void addToSampleMap(StatusOfSample status){
String name = status.getStatusOfSampleName();
if(name.equals("SampleEntered")){
sampleStatusToObjectMap.put(SampleStatus.Entered, status);
}else if(name.equals("SampleCanceled")){
sampleStatusToObjectMap.put(SampleStatus.Canceled, status);
}
}
private void addToRecordMap(Dictionary dictionary) {
String name = dictionary.getLocalAbbreviation();
if( name.equals("Not Start")){
recordStatusToObjectMap.put(RecordStatus.NotRegistered, dictionary);
}else if( name.equals("Init Ent")){
recordStatusToObjectMap.put(RecordStatus.InitialRegistration, dictionary);
}else if( name.equals("Valid Ent")){
recordStatusToObjectMap.put(RecordStatus.ValidationRegistration, dictionary);
}
}
private void buildIdToStatusMapsFromStatusToIdMaps() {
for( Entry<OrderStatus, StatusOfSample> status : orderStatusToObjectMap.entrySet()){
idToOrderStatusMap.put(status.getValue().getId(), status.getKey());
}
for( Entry<SampleStatus, StatusOfSample> status : sampleStatusToObjectMap.entrySet()){
idToSampleStatusMap.put(status.getValue().getId(), status.getKey());
}
for( Entry<AnalysisStatus, StatusOfSample> status : analysisStatusToObjectMap.entrySet()){
idToAnalysisStatusMap.put(status.getValue().getId(), status.getKey());
}
for( Entry<RecordStatus, Dictionary> status : recordStatusToObjectMap.entrySet()){
idToRecordStatusMap.put(status.getValue().getId(), status.getKey());
}
for( Entry<ExternalOrderStatus, StatusOfSample> status : externalOrderStatusToObjectMap.entrySet()){
idToExternalOrderStatusMap.put(status.getValue().getId(), status.getKey());
}
}
private void getObservationHistoryTypeIDs() {
ObservationHistoryTypeDAO observationTypeDAO = new ObservationHistoryTypeDAOImpl();
List<ObservationHistoryType> obsrvationTypeList = observationTypeDAO.getAll();
for( ObservationHistoryType observationType : obsrvationTypeList){
if( "SampleRecordStatus".equals(observationType.getTypeName())){
orderRecordStatusID = observationType.getId();
}else if( "PatientRecordStatus".equals(observationType.getTypeName())){
patientRecordStatusID = observationType.getId();
}
}
}
private StatusSet buildStatusSet(Sample sample){
StatusSet statusSet = new StatusSet();
if(sample == null || sample.getId() == null){
statusSet.setPatientRecordStatus(null);
statusSet.setSampleRecordStatus(null);
}else{
statusSet.setSampleStatus(getOrderStatusForID(sample.getStatusId()));
setAnalysisStatus(statusSet, sample);
setRecordStatus(statusSet, sample);
}
return statusSet;
}
private void setAnalysisStatus(StatusSet statusSet, Sample sample) {
AnalysisDAO analysisDAO = new AnalysisDAOImpl();
List<Analysis> analysisList = analysisDAO.getAnalysesBySampleId(sample.getId());
Map<Analysis, AnalysisStatus> analysisStatusMap = new HashMap<Analysis, AnalysisStatus>();
for( Analysis analysis : analysisList ){
analysisStatusMap.put(analysis, getAnalysisStatusForID(analysis.getStatusId()));
}
statusSet.setAnalysisStatus(analysisStatusMap);
}
private void setRecordStatus(StatusSet statusSet, Sample sample) {
if( "H".equals(sample.getDomain())){
SampleHuman sampleHuman = new SampleHuman();
sampleHuman.setSampleId(sample.getId());
SampleHumanDAO sampleHumanDAO = new SampleHumanDAOImpl();
sampleHumanDAO.getDataBySample(sampleHuman);
String patientId = sampleHuman.getPatientId();
statusSet.setSampleId(sample.getId());
statusSet.setPatientId(patientId);
if( patientId != null ){
Patient patient = new Patient();
patient.setId(patientId);
List<ObservationHistory> observations = observationHistoryDAO.getAll(patient, sample);
for( ObservationHistory observation : observations){
if( observation.getObservationHistoryTypeId().equals( orderRecordStatusID)){
statusSet.setSampleRecordStatus(getRecordStatusForID(observation.getValue()));
}else if( observation.getObservationHistoryTypeId().equals( patientRecordStatusID)){
statusSet.setPatientRecordStatus(getRecordStatusForID(observation.getValue()));
}
}
}
}
}
}