/** * 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.lang.StringEscapeUtils; import org.apache.commons.validator.GenericValidator; import org.json.simple.JSONObject; import us.mn.state.health.lims.common.util.DateUtil; 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.referencetables.daoimpl.ReferenceTablesDAOImpl; import us.mn.state.health.lims.result.dao.ResultDAO; import us.mn.state.health.lims.result.dao.ResultSignatureDAO; import us.mn.state.health.lims.result.daoimpl.ResultDAOImpl; import us.mn.state.health.lims.result.daoimpl.ResultSignatureDAOImpl; import us.mn.state.health.lims.result.valueholder.Result; import us.mn.state.health.lims.result.valueholder.ResultSignature; import us.mn.state.health.lims.resultlimits.daoimpl.ResultLimitDAOImpl; import us.mn.state.health.lims.resultlimits.valueholder.ResultLimit; import us.mn.state.health.lims.test.valueholder.Test; import us.mn.state.health.lims.typeofsample.daoimpl.TypeOfSampleDAOImpl; import us.mn.state.health.lims.typeofsample.daoimpl.TypeOfSampleTestDAOImpl; import us.mn.state.health.lims.typeofsample.valueholder.TypeOfSampleTest; import java.sql.Date; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class ResultService { private static DictionaryDAO dictionaryDAO = new DictionaryDAOImpl(); private static ResultDAO resultDAO = new ResultDAOImpl(); private static ResultSignatureDAO signatureDAO = new ResultSignatureDAOImpl(); private Result result; private Test test; private List<ResultLimit> resultLimit; public static final String TABLE_REFERENCE_ID; static{ TABLE_REFERENCE_ID = new ReferenceTablesDAOImpl().getReferenceTableByName("RESULT").getId(); } public ResultService(Result result) { this.result = result; test = result.getAnalysis() != null ? result.getAnalysis().getTest() : null; } public String getLabSectionName() { return result.getAnalysis().getTestSection().getName(); } public String getTestName() { return TestService.getUserLocalizedTestName(test); } public String getReportingTestName() { return TestService.getUserLocalizedReportingTestName(test); } public String getTestDescription() { return TestService.getLocalizedTestNameWithType( test ); } public String getSampleType() { if( test == null){ return ""; } TypeOfSampleTest sampleTestType = new TypeOfSampleTestDAOImpl().getTypeOfSampleTestForTest(test.getId()); if (sampleTestType != null) { return new TypeOfSampleDAOImpl().getNameForTypeOfSampleId(sampleTestType.getTypeOfSampleId()); } return ""; } public String getLOINCCode() { return test != null ? test.getLoinc() : ""; } public String getTestTime() { return result.getAnalysis().getCompletedDateForDisplay(); } public String getTestType() { return result.getResultType(); } /** * This gets the simple value of the result, it treats multiresults as single dictionary values and * does not try to get the complete set * @return The String value */ public String getSimpleResultValue(){ if (GenericValidator.isBlankOrNull(result.getValue())) { return ""; } if (TypeOfTestResultService.ResultType.isDictionaryVariant( getTestType() )) { return getDictEntry( ); } else if (TypeOfTestResultService.ResultType.NUMERIC.matches(getTestType())) { int significantPlaces = result.getSignificantDigits(); if (significantPlaces == 0) { return result.getValue().split("\\.")[0]; } StringBuilder value = new StringBuilder(); value.append(result.getValue()); int startFill = 0; if (!result.getValue().contains(".")) { value.append("."); } else { startFill = result.getValue().length() - result.getValue().lastIndexOf(".") - 1; } for (int i = startFill ; i < significantPlaces; i++) { value.append("0"); } return value.toString(); }else if (TypeOfTestResultService.ResultType.ALPHA.matches(result.getResultType()) && !GenericValidator.isBlankOrNull(result.getValue())) { return result.getValue().split("\\(")[0].trim(); }else { return result.getValue(); } } /** * This returns a textual representation of the result value. Multiselect results are returned as a comma * delimited string. If there is a qualified value it is not included * @param printable If true the results will be suitable for printing, otherwise they will be suitable for a * web form * @return A textual representation of the value */ public String getResultValue(boolean printable ){ return getResultValue( ",", printable, false ); } public String getResultValue( String separator, boolean printable, boolean includeUOM){ if (GenericValidator.isBlankOrNull(result.getValue())) { return ""; } if (TypeOfTestResultService.ResultType.DICTIONARY.matches(getTestType())) { if (!printable) { return result.getValue(); } String reportResult = ""; List<Result> resultList = resultDAO.getResultsByAnalysis( result.getAnalysis()); if( !resultList.isEmpty()){ if( resultList.size() == 1 ){ reportResult = getDictEntry(); }else{ //If dictionary result it can also have a quantified result List<Result> dictionaryResults = new ArrayList<Result>(); Result quantification = null; for( Result sibResult : resultList ){ if( TypeOfTestResultService.ResultType.DICTIONARY.matches( sibResult.getResultType() ) ){ dictionaryResults.add( sibResult ); }else if( TypeOfTestResultService.ResultType.ALPHA.matches( sibResult.getResultType() ) && sibResult.getParentResult() != null ){ quantification = sibResult; } } for( Result sibResult : dictionaryResults ){ Dictionary dictionary = dictionaryDAO.getDictionaryById(sibResult.getValue()); reportResult = (dictionary != null && dictionary.getId() != null) ? dictionary.getLocalizedName() : ""; if( quantification != null && quantification.getParentResult().getId().equals( sibResult.getId() ) ){ reportResult += separator + quantification.getValue(); } } } } if( includeUOM && !GenericValidator.isBlankOrNull( reportResult )){ String uom = getUOM(); if( !GenericValidator.isBlankOrNull( uom )){ reportResult += " " + uom; } } return StringEscapeUtils.escapeHtml(reportResult); } else if (TypeOfTestResultService.ResultType.isMultiSelectVariant(getTestType())) { StringBuilder buffer = new StringBuilder(); boolean firstPass = true; List<Result> results = new ResultDAOImpl().getResultsByAnalysis(result.getAnalysis()); for (Result multiResult : results) { if (!GenericValidator.isBlankOrNull(multiResult.getValue()) && TypeOfTestResultService.ResultType.isMultiSelectVariant(multiResult.getResultType())) { if (firstPass) { firstPass = false; } else { buffer.append(separator); } buffer.append(dictionaryDAO.getDataForId(multiResult.getValue()).getDictEntry()); } } return buffer.toString(); } else if (TypeOfTestResultService.ResultType.NUMERIC.matches(getTestType())) { int significantPlaces = result.getSignificantDigits(); if( significantPlaces == -1){ return result.getValue() + appendUOM( includeUOM ); } if (significantPlaces == 0) { return result.getValue().split("\\.")[0] + appendUOM( includeUOM ); } StringBuilder value = new StringBuilder(); value.append(result.getValue()); int startFill = 0; if (!result.getValue().contains(".")) { value.append("."); } else { startFill = result.getValue().length() - result.getValue().lastIndexOf(".") - 1; } for (int i = startFill ; i < significantPlaces; i++) { value.append("0"); } return value.toString() + appendUOM( includeUOM ); }else if (TypeOfTestResultService.ResultType.ALPHA.matches(result.getResultType()) && !GenericValidator.isBlankOrNull(result.getValue())) { return result.getValue().split("\\(")[0].trim(); }else { return result.getValue(); } } private String getDictEntry( ){ Dictionary dictionary = dictionaryDAO.getDataForId( result.getValue() ); return dictionary != null ? dictionary.getDictEntry() : ""; } private String appendUOM( boolean includeUOM ){ if( includeUOM && result.getAnalysis().getTest().getUnitOfMeasure() != null ){ return " " + result.getAnalysis().getTest().getUnitOfMeasure().getName(); }else{ return ""; } } public String getMultiSelectSelectedIdValues(){ if (GenericValidator.isBlankOrNull(result.getValue())) { return ""; } if (TypeOfTestResultService.ResultType.MULTISELECT.getCharacterValue().equals(getTestType())) { StringBuilder buffer = new StringBuilder(); boolean firstPass = true; List<Result> results = new ResultDAOImpl().getResultsByAnalysis(result.getAnalysis()); for (Result multiResult : results) { if (!GenericValidator.isBlankOrNull(multiResult.getValue()) && TypeOfTestResultService.ResultType.isMultiSelectVariant(multiResult.getResultType())) { if (firstPass) { firstPass = false; } else { buffer.append(","); } buffer.append(multiResult.getValue()); } } return buffer.toString(); } return ""; } public String getUOM() { return test != null && test.getUnitOfMeasure() != null ? test.getUnitOfMeasure().getUnitOfMeasureName() : ""; } public double getlowNormalRange() { return result.getMinNormal(); } public double getHighNormalRange() { return result.getMaxNormal(); } /** * * @return true if any of the result limits for this test have a gender * specification */ public boolean ageInRangeCriteria() { List<ResultLimit> resultLimits = getResultLimits(); for (ResultLimit limit : resultLimits) { if (limit.getMaxAge() != limit.getMinAge()) { return true; } } return false; } public boolean genderInRangeCritera() { List<ResultLimit> resultLimits = getResultLimits(); for (ResultLimit limit : resultLimits) { if (!GenericValidator.isBlankOrNull(limit.getGender())) { return true; } } return false; } public String getDisplayReferenceRange(boolean includeSelectList){ String range = ""; if( TypeOfTestResultService.ResultType.NUMERIC.matches( result.getResultType() ) ){ if( result.getMinNormal() != null && result.getMaxNormal() != null && !result.getMinNormal().equals( result.getMaxNormal() ) ){ range = ResultLimitService.getDisplayNormalRange( result.getMinNormal(), result.getMaxNormal(), String.valueOf( result.getSignificantDigits() ), "-" ); } }else if( includeSelectList && TypeOfTestResultService.ResultType.isDictionaryVariant( result.getResultType() )){ List<ResultLimit> limits = getResultLimits(); if( !limits.isEmpty() && !GenericValidator.isBlankOrNull( limits.get( 0 ).getDictionaryNormalId() )){ range = dictionaryDAO.getDataForId( limits.get( 0 ).getDictionaryNormalId() ).getLocalizedName(); } } return range; } private List<ResultLimit> getResultLimits() { if (resultLimit == null) { resultLimit = test != null ? new ResultLimitDAOImpl().getAllResultLimitsForTest(test.getId()) : new ArrayList<ResultLimit>(); } return resultLimit; } public boolean isAbnormalDictionaryResult(){ if( result.getValue() != null && TypeOfTestResultService.ResultType.isDictionaryVariant( result.getResultType() )){ List<ResultLimit> limits = getResultLimits(); if( !limits.isEmpty()){ return !result.getValue().equals( limits.get(0).getDictionaryNormalId() ); } } return false; } public String getLastUpdatedTime() { return DateUtil.convertTimestampToStringDate(result.getLastupdated()); } public String getSignature(){ List<ResultSignature> signatures = signatureDAO.getResultSignaturesByResult( result ); return signatures.isEmpty() ? "" : signatures.get( 0 ).getNonUserName(); } public static List<Result> getResultsInTimePeriodWithTest( Date startDate, Date endDate, String testId){ return resultDAO.getResultsForTestInDateRange( testId, startDate, DateUtil.addDaysToSQLDate( endDate, 1) ); } public static List<Result> getResultsInTimePeriodInPanel( Date lowDate, Date highDate, String panelId ){ return resultDAO.getResultsForPanelInDateRange( panelId, lowDate, DateUtil.addDaysToSQLDate( highDate, 1 ) ); } public static List<Result> getResultsInTimePeriodInTestSection( Date lowDate, Date highDate, String testSectionId ){ return resultDAO.getResultsForTestSectionInDateRange( testSectionId, lowDate, DateUtil.addDaysToSQLDate(highDate, 1 ) ); } public static String getJSONStringForMultiSelect( List<Result> resultList){ Collections.sort( resultList, new Comparator<Result>(){ @Override public int compare( Result o1, Result o2 ){ return o1.getGrouping() - o2.getGrouping(); } } ); JSONObject jsonRep =new JSONObject(); int currentGrouping = -1; StringBuilder currentString = new StringBuilder( ); for(Result result : resultList){ if( TypeOfTestResultService.ResultType.isMultiSelectVariant( result.getResultType() ) && result.getValue() != null){ if( currentGrouping != result.getGrouping()){ if( currentString.length() > 1 ){ currentString.setLength( currentString.length() - 1 ); jsonRep.put( String.valueOf( currentGrouping ), currentString.toString() ); } currentGrouping = result.getGrouping(); currentString = new StringBuilder( ); } currentString.append( result.getValue() ); currentString.append( "," ); } } if( currentString.length() > 1 ){ currentString.setLength( currentString.length() - 1 ); jsonRep.put( String.valueOf( currentGrouping ), currentString.toString() ); } return jsonRep.toJSONString(); } }