/**
* 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) CIRG, University of Washington, Seattle WA. All Rights Reserved.
*
*/
package us.mn.state.health.lims.reports.action.implementation;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.validator.GenericValidator;
import org.hibernate.Transaction;
import us.mn.state.health.lims.address.dao.PersonAddressDAO;
import us.mn.state.health.lims.address.daoimpl.AddressPartDAOImpl;
import us.mn.state.health.lims.address.daoimpl.PersonAddressDAOImpl;
import us.mn.state.health.lims.address.valueholder.AddressPart;
import us.mn.state.health.lims.address.valueholder.PersonAddress;
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.formfields.FormFields;
import us.mn.state.health.lims.common.formfields.FormFields.Field;
import us.mn.state.health.lims.common.provider.validation.IAccessionNumberValidator;
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.ObservationHistoryService.ObservationType;
import us.mn.state.health.lims.common.services.StatusService.AnalysisStatus;
import us.mn.state.health.lims.common.util.ConfigurationProperties;
import us.mn.state.health.lims.common.util.ConfigurationProperties.Property;
import us.mn.state.health.lims.common.util.DateUtil;
import us.mn.state.health.lims.common.util.StringUtil;
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.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.observationhistory.dao.ObservationHistoryDAO;
import us.mn.state.health.lims.observationhistory.daoimpl.ObservationHistoryDAOImpl;
import us.mn.state.health.lims.organization.valueholder.Organization;
import us.mn.state.health.lims.patient.dao.PatientDAO;
import us.mn.state.health.lims.patient.daoimpl.PatientDAOImpl;
import us.mn.state.health.lims.patient.valueholder.Patient;
import us.mn.state.health.lims.patientidentity.dao.PatientIdentityDAO;
import us.mn.state.health.lims.patientidentity.daoimpl.PatientIdentityDAOImpl;
import us.mn.state.health.lims.patientidentity.valueholder.PatientIdentity;
import us.mn.state.health.lims.person.dao.PersonDAO;
import us.mn.state.health.lims.person.daoimpl.PersonDAOImpl;
import us.mn.state.health.lims.person.valueholder.Person;
import us.mn.state.health.lims.provider.dao.ProviderDAO;
import us.mn.state.health.lims.provider.daoimpl.ProviderDAOImpl;
import us.mn.state.health.lims.provider.valueholder.Provider;
import us.mn.state.health.lims.referral.dao.ReferralDAO;
import us.mn.state.health.lims.referral.dao.ReferralReasonDAO;
import us.mn.state.health.lims.referral.dao.ReferralResultDAO;
import us.mn.state.health.lims.referral.daoimpl.ReferralDAOImpl;
import us.mn.state.health.lims.referral.daoimpl.ReferralReasonDAOImpl;
import us.mn.state.health.lims.referral.daoimpl.ReferralResultDAOImpl;
import us.mn.state.health.lims.referral.valueholder.ReferralResult;
import us.mn.state.health.lims.reports.action.implementation.reportBeans.ClinicalPatientData;
import us.mn.state.health.lims.result.valueholder.Result;
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.util.AccessionNumberUtil;
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.sampleitem.valueholder.SampleItem;
import us.mn.state.health.lims.test.dao.TestDAO;
import us.mn.state.health.lims.test.daoimpl.TestDAOImpl;
import us.mn.state.health.lims.test.valueholder.Test;
import java.lang.reflect.InvocationTargetException;
import java.sql.Date;
import java.text.DecimalFormat;
import java.util.*;
public abstract class PatientReport extends Report{
private static final DecimalFormat twoDecimalFormat = new DecimalFormat( "#.##" );
private static String ADDRESS_DEPT_ID;
private static String ADDRESS_COMMUNE_ID;
protected String currentContactInfo = "";
protected String currentSiteInfo = "";
protected SampleHumanDAO sampleHumanDAO = new SampleHumanDAOImpl();
protected DictionaryDAO dictionaryDAO = new DictionaryDAOImpl();
protected SampleDAO sampleDAO = new SampleDAOImpl();
protected PatientDAO patientDAO = new PatientDAOImpl();
protected PersonDAO personDAO = new PersonDAOImpl();
protected ProviderDAO providerDAO = new ProviderDAOImpl();
protected TestDAO testDAO = new TestDAOImpl();
protected ReferralReasonDAO referralReasonDAO = new ReferralReasonDAOImpl();
protected ReferralDAO referralDao = new ReferralDAOImpl();
protected ReferralResultDAO referralResultDAO = new ReferralResultDAOImpl();
protected ObservationHistoryDAO observationDAO = new ObservationHistoryDAOImpl();
protected AnalysisDAO analysisDAO = new AnalysisDAOImpl();
protected NoteDAO noteDAO = new NoteDAOImpl();
protected PersonAddressDAO addressDAO = new PersonAddressDAOImpl();
private List<String> handledOrders;
private List<Analysis> updatedAnalysis = new ArrayList<Analysis>( );
private String lowerNumber;
private String upperNumber;
protected String STNumber = null;
protected String subjectNumber = null;
protected String healthRegion = null;
protected String healthDistrict = null;
protected String patientName = null;
protected String patientDOB = null;
protected String currentConclusion = null;
protected String patientDept = null;
protected String patientCommune = null;
protected IPatientService patientService;
protected Provider currentProvider;
protected AnalysisService currentAnalysisService;
protected String reportReferralResultValue;
protected List<ClinicalPatientData> reportItems;
protected String completionDate;
protected SampleService currentSampleService;
protected static final NoteType[] FILTER = {NoteType.EXTERNAL, NoteType.REJECTION_REASON, NoteType.NON_CONFORMITY};
protected Map<String, Boolean> sampleCompleteMap;
protected Map<String, Boolean> sampleCorrectedMap;
static{
List<AddressPart> partList = new AddressPartDAOImpl().getAll();
for( AddressPart part : partList ){
if( "department".equals( part.getPartName() ) ){
ADDRESS_DEPT_ID = part.getId();
}else if( "commune".equals( part.getPartName() ) ){
ADDRESS_COMMUNE_ID = part.getId();
}
}
}
abstract protected String getReportNameForParameterPage();
abstract protected void postSampleBuild();
abstract protected void createReportItems();
abstract protected void setReferredResult( ClinicalPatientData data, Result result );
protected boolean appendUOMToRange(){
return true;
}
protected boolean augmentResultWithFlag(){
return true;
}
protected boolean useReportingDescription(){
return true;
}
public void setRequestParameters( BaseActionForm dynaForm ){
try{
PropertyUtils.setProperty( dynaForm, "reportName", getReportNameForParameterPage() );
PropertyUtils.setProperty( dynaForm, "useAccessionDirect", Boolean.TRUE );
PropertyUtils.setProperty( dynaForm, "useHighAccessionDirect", Boolean.TRUE );
PropertyUtils.setProperty( dynaForm, "usePatientNumberDirect", Boolean.TRUE );
}catch( IllegalAccessException e ){
e.printStackTrace();
}catch( InvocationTargetException e ){
e.printStackTrace();
}catch( NoSuchMethodException e ){
e.printStackTrace();
}
}
public void initializeReport( BaseActionForm dynaForm ){
super.initializeReport();
errorFound = false;
lowerNumber = dynaForm.getString( "accessionDirect" );
upperNumber = dynaForm.getString( "highAccessionDirect" );
String patientNumber = dynaForm.getString( "patientNumberDirect" );
handledOrders = new ArrayList<String>();
createReportParameters();
boolean valid;
List<Sample> reportSampleList = new ArrayList<Sample>();
if( GenericValidator.isBlankOrNull( lowerNumber ) && GenericValidator.isBlankOrNull( upperNumber ) ){
List<Patient> patientList = new ArrayList<Patient>();
valid = findPatientByPatientNumber( patientNumber, patientList );
if( valid ){
reportSampleList = findReportSamplesForReportPatient( patientList );
}
}else{
valid = validateAccessionNumbers();
if( valid ){
reportSampleList = findReportSamples( lowerNumber, upperNumber );
}
}
sampleCompleteMap = new HashMap<String, Boolean>();
sampleCorrectedMap = new HashMap<String, Boolean>();
initializeReportItems();
if( reportSampleList.isEmpty() ){
add1LineErrorMessage( "report.error.message.noPrintableItems" );
}else{
for( Sample sample : reportSampleList ){
currentSampleService = new SampleService( sample );
handledOrders.add( sample.getId() );
sampleCompleteMap.put( sample.getAccessionNumber(), Boolean.TRUE );
findCompletionDate();
findPatientFromSample();
findContactInfo();
findPatientInfo();
createReportItems();
}
postSampleBuild();
}
if( !updatedAnalysis.isEmpty()){
Transaction tx = HibernateUtil.getSession().beginTransaction();
try{
for( Analysis analysis : updatedAnalysis ){
analysisDAO.updateData( analysis, true );
}
tx.commit();
}catch( LIMSRuntimeException lre ){
tx.rollback();
}
}
}
private void findCompletionDate(){
Date date = currentSampleService.getCompletedDate();
completionDate = date == null ? null : DateUtil.convertSqlDateToStringDate( date );
}
private void findPatientInfo(){
if( patientService.getPerson() == null){
return;
}
patientDept = "";
patientCommune = "";
if( ADDRESS_DEPT_ID != null ){
PersonAddress deptAddress = addressDAO.getByPersonIdAndPartId( patientService.getPerson().getId(), ADDRESS_DEPT_ID );
if( deptAddress != null && !GenericValidator.isBlankOrNull( deptAddress.getValue() ) ){
patientDept = dictionaryDAO.getDictionaryById( deptAddress.getValue() ).getDictEntry();
}
}
if( ADDRESS_COMMUNE_ID != null ){
PersonAddress deptAddress = addressDAO.getByPersonIdAndPartId( patientService.getPerson().getId(), ADDRESS_COMMUNE_ID );
if( deptAddress != null ){
patientCommune = deptAddress.getValue();
}
}
}
private void findContactInfo(){
currentContactInfo = "";
currentSiteInfo = "";
currentProvider = null;
Organization org = currentSampleService.getOrganizationRequester();
if( org != null ){
currentSiteInfo = org.getOrganizationName();
}
Person person = currentSampleService.getPersonRequester();
if( person != null){
currentContactInfo = new PersonService( person ).getLastFirstName();
currentProvider = providerDAO.getProviderByPerson( person );
}
}
private boolean findPatientByPatientNumber( String patientNumber, List<Patient> patientList ){
patientService = null;
PatientIdentityDAO patientIdentityDAO = new PatientIdentityDAOImpl();
patientList.addAll( patientDAO.getPatientsByNationalId( patientNumber ) );
if( patientList.isEmpty() ){
List<PatientIdentity> identities = patientIdentityDAO.getPatientIdentitiesByValueAndType( patientNumber, PatientService.PATIENT_ST_IDENTITY);
if( identities.isEmpty() ){
identities = patientIdentityDAO.getPatientIdentitiesByValueAndType( patientNumber, PatientService.PATIENT_SUBJECT_IDENTITY );
}
if( !identities.isEmpty() ){
for( PatientIdentity patientIdentity : identities ){
String reportPatientId = patientIdentity.getPatientId();
Patient patient = new Patient();
patient.setId( reportPatientId );
patientDAO.getData( patient );
patientList.add( patient );
}
}
}
return !patientList.isEmpty();
}
private List<Sample> findReportSamplesForReportPatient( List<Patient> patientList ){
List<Sample> sampleList = new ArrayList<Sample>();
for( Patient searchPatient : patientList ){
sampleList.addAll( sampleHumanDAO.getSamplesForPatient( searchPatient.getId() ) );
}
return sampleList;
}
private boolean validateAccessionNumbers(){
if( GenericValidator.isBlankOrNull( lowerNumber ) && GenericValidator.isBlankOrNull( upperNumber ) ){
add1LineErrorMessage( "report.error.message.noParameters" );
return false;
}
if( GenericValidator.isBlankOrNull( lowerNumber ) ){
lowerNumber = upperNumber;
}else if( GenericValidator.isBlankOrNull( upperNumber ) ){
upperNumber = lowerNumber;
}
if( lowerNumber.length() != upperNumber.length() ||
AccessionNumberUtil.correctFormat( lowerNumber, false ) != IAccessionNumberValidator.ValidationResults.SUCCESS ||
AccessionNumberUtil.correctFormat( lowerNumber, false ) != IAccessionNumberValidator.ValidationResults.SUCCESS ){
add1LineErrorMessage( "report.error.message.accession.not.valid" );
return false;
}
if( lowerNumber.compareToIgnoreCase( upperNumber ) > 0 ){
String temp = upperNumber;
upperNumber = lowerNumber;
lowerNumber = temp;
}
return true;
}
private List<Sample> findReportSamples( String lowerNumber, String upperNumber ){
List<Sample> sampleList = sampleDAO.getSamplesByAccessionRange( lowerNumber, upperNumber );
return sampleList == null ? new ArrayList<Sample>() : sampleList;
}
protected void findPatientFromSample(){
Patient patient = sampleHumanDAO.getPatientForSample( currentSampleService.getSample() );
if( patientService == null || !patient.getId().equals( patientService.getPatientId() ) ){
STNumber = null;
patientDOB = null;
patientService = new PatientService( patient );
}
}
@Override
protected void createReportParameters(){
super.createReportParameters();
reportParameters.put( "siteId", ConfigurationProperties.getInstance().getPropertyValue( Property.SiteCode ) );
reportParameters.put("headerName", getHeaderName());
if( ConfigurationProperties.getInstance().isPropertyValueEqual( Property.configurationName, "Haiti LNSP" ) ){
reportParameters.put( "useSTNumber", Boolean.FALSE );
}else{
reportParameters.put( "useSTNumber", Boolean.TRUE );
}
}
protected abstract String getHeaderName();
protected String getPatientDOB(){
if( patientDOB == null ){
patientDOB = patientService.getBirthdayForDisplay();
}
return patientDOB;
}
protected String getLazyPatientIdentity( String identity, String id ){
if( identity == null ){
identity = " ";
List<PatientIdentity> identities = patientService.getIdentityList();
for( PatientIdentity patientIdentity : identities ){
if( patientIdentity.getIdentityTypeId().equals( id ) ){
identity = patientIdentity.getIdentityData();
break;
}
}
}
return identity;
}
protected void setPatientName( ClinicalPatientData data ){
data.setPatientName( patientService.getLastFirstName() );
data.setFirstName( patientService.getFirstName() );
data.setLastName( patientService.getLastName() );
}
protected void reportResultAndConclusion( ClinicalPatientData data ){
List<Result> resultList = currentAnalysisService.getResults();
Test test = currentAnalysisService.getTest();
String note = new NoteService( currentAnalysisService.getAnalysis() ).getNotesAsString( true, true, "<br/>", FILTER, true );
if( note != null){
data.setNote( note );
}
data.setTestSection( currentAnalysisService.getTestSection().getLocalizedName() );
data.setTestSortOrder( GenericValidator.isBlankOrNull( test.getSortOrder() ) ? Integer.MAX_VALUE : Integer.parseInt( test.getSortOrder() ) );
data.setSectionSortOrder( test.getTestSection().getSortOrderInt() );
if( StatusService.getInstance().matches( currentAnalysisService.getStatusId(), AnalysisStatus.Canceled ) ){
data.setResult( StringUtil.getMessageForKey( "report.test.status.canceled" ) );
}else if( currentAnalysisService.getAnalysis().isReferredOut() ){
setReferredOutResult( data );
return;
/* Not sure which rules this would support -- above statement was conditional on no patient alerts
if( noResults( resultList ) ){
data.setResult( StringUtil.getMessageForKey( "report.test.status.referredOut" ) );
}else{
setAppropriateResults( resultList, data );
setReferredResult( data, resultList.get( 0 ) );
setNormalRange( data, test, resultList.get( 0 ) );
}
*/
}else if( !StatusService.getInstance().matches( currentAnalysisService.getStatusId(), AnalysisStatus.Finalized ) ){
sampleCompleteMap.put( currentSampleService.getAccessionNumber(), Boolean.FALSE );
setEmptyResult( data );
}else{
if( resultList.isEmpty()){
setEmptyResult( data );
}else{
setAppropriateResults( resultList, data );
Result result = resultList.get( 0 );
setCorrectedStatus( result, data );
setNormalRange( data, test, result );
data.setResult( getAugmentedResult( data, result ) );
data.setFinishDate( currentAnalysisService.getCompletedDateForDisplay() );
data.setAlerts( getResultFlag( result, null, data ) );
}
}
data.setParentResult( currentAnalysisService.getAnalysis().getParentResult() );
data.setConclusion( currentConclusion );
}
protected void setReferredOutResult(ClinicalPatientData data){
data.setResult( StringUtil.getMessageForKey( "report.test.status.inProgress" ) );
}
protected void setEmptyResult( ClinicalPatientData data ){
data.setResult( StringUtil.getMessageForKey( "report.test.status.inProgress" ) );
}
private void setCorrectedStatus( Result result, ClinicalPatientData data ){
if( currentAnalysisService.getAnalysis().isCorrectedSincePatientReport() && !GenericValidator.isBlankOrNull( result.getValue() )){
data.setCorrectedResult( true );
sampleCorrectedMap.put( currentSampleService.getAccessionNumber(), true);
currentAnalysisService.getAnalysis().setCorrectedSincePatientReport( false );
updatedAnalysis.add( currentAnalysisService.getAnalysis() );
}
}
private void setNormalRange( ClinicalPatientData data, Test test, Result result ){
String uom = getUnitOfMeasure( test );
data.setTestRefRange( addIfNotEmpty( getRange( result ), appendUOMToRange() ? uom : null ) );
data.setUom( uom );
}
private String getAugmentedResult( ClinicalPatientData data, Result result ){
String resultValue = data.getResult();
if( TestIdentityService.isTestNumericViralLoad( currentAnalysisService.getTest() ) ){
try{
resultValue += " (" + twoDecimalFormat.format( Math.log10( Double.parseDouble( resultValue ) ) ) + ")log ";
}catch( IllegalFormatException e ){
// no-op
}
}
return resultValue + ( augmentResultWithFlag() ? getResultFlag( result, null ) : "" );
}
protected String getResultFlag( Result result, String imbed ){
return getResultFlag( result, imbed, null );
}
protected String getResultFlag( Result result, String imbed, ClinicalPatientData data ){
String flag = "";
try{
if( TypeOfTestResultService.ResultType.NUMERIC.matches( result.getResultType() ) && !GenericValidator.isBlankOrNull( result.getValue() ) ){
if( result.getMinNormal() != null & result.getMaxNormal() != null && ( result.getMinNormal() != 0.0 || result.getMaxNormal() != 0.0 ) ){
if( Double.valueOf( result.getValue() ) < result.getMinNormal() ){
flag = "B";
}else if( Double.valueOf( result.getValue() ) > result.getMaxNormal() ){
flag = "E";
}
}
}else if( TypeOfTestResultService.ResultType.isDictionaryVariant( result.getResultType() )){
boolean isAbnormal;
if( data == null){
isAbnormal = new ResultService( result ).isAbnormalDictionaryResult();
} else {
isAbnormal = data.getAbnormalResult();
}
if( isAbnormal ){
flag = "*";
}
}
if( !GenericValidator.isBlankOrNull( flag ) ){
if( data != null ){
data.setAbnormalResult( Boolean.TRUE );
}
if( !GenericValidator.isBlankOrNull( imbed ) ){
return " <b>" + flag + "," + imbed + "</b>";
}else{
return " <b>" + flag + "</b>";
}
}
}catch( NumberFormatException e ){
// no-op
}
if( !GenericValidator.isBlankOrNull( imbed ) ){
return " (<b>" + imbed + "</b>)";
}
return "";
}
protected String getRange( Result result ){
return new ResultService( result ).getDisplayReferenceRange( true );
}
protected String getUnitOfMeasure( Test test ){
return ( test != null && test.getUnitOfMeasure() != null )? test.getUnitOfMeasure().getName() : "";
}
private void setAppropriateResults( List<Result> resultList, ClinicalPatientData data ){
String reportResult = "";
if( !resultList.isEmpty()){
//If only one result just get it and get out
if( resultList.size() == 1 ){
Result result = resultList.get( 0 );
if( TypeOfTestResultService.ResultType.isDictionaryVariant( result.getResultType() ) ){
Dictionary dictionary = new Dictionary();
dictionary.setId( result.getValue() );
dictionaryDAO.getData( dictionary );
data.setAbnormalResult( new ResultService( result ).isAbnormalDictionaryResult() );
if( result.getAnalyte() != null && "Conclusion".equals( result.getAnalyte().getAnalyteName() ) ){
currentConclusion = dictionary.getId() != null ? dictionary.getLocalizedName() : "";
}else{
reportResult = dictionary.getId() != null ? dictionary.getLocalizedName() : "";
}
}else{
reportResult = new ResultService( result ).getResultValue( true );
//TODO - how is this used. Selection types can also have UOM and reference ranges
data.setHasRangeAndUOM( TypeOfTestResultService.ResultType.NUMERIC.matches( result.getResultType() ) );
}
}else{
//If multiple results it can be a quantified result, multiple results with quantified other results or it can be a conclusion
ResultService resultService = new ResultService( resultList.get( 0 ) );
if( TypeOfTestResultService.ResultType.DICTIONARY.matches( resultService.getTestType()) ){
data.setAbnormalResult( resultService.isAbnormalDictionaryResult() );
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;
}
}
Dictionary dictionary = new Dictionary();
for( Result sibResult : dictionaryResults ){
dictionary.setId( sibResult.getValue() );
dictionaryDAO.getData( dictionary );
if( sibResult.getAnalyte() != null && "Conclusion".equals( sibResult.getAnalyte().getAnalyteName() ) ){
currentConclusion = dictionary.getId() != null ? dictionary.getLocalizedName() : "";
}else{
reportResult = dictionary.getId() != null ? dictionary.getLocalizedName() : "";
if( quantification != null && quantification.getParentResult().getId().equals( sibResult.getId() ) ){
reportResult += ": " + quantification.getValue();
}
}
}
}else if( TypeOfTestResultService.ResultType.isMultiSelectVariant( resultService.getTestType()) ){
Dictionary dictionary = new Dictionary();
StringBuilder multiResult = new StringBuilder();
Collections.sort( resultList, new Comparator<Result>(){
@Override
public int compare( Result o1, Result o2 ){
if( o1.getGrouping() == o2.getGrouping() ){
return Integer.parseInt( o1.getId() ) - Integer.parseInt( o2.getId() );
}else{
return o1.getGrouping() - o2.getGrouping();
}
}
} );
Result quantifiedResult = null;
for( Result subResult : resultList ){
if( TypeOfTestResultService.ResultType.ALPHA.matches( subResult.getResultType() ) ){
quantifiedResult = subResult;
resultList.remove( subResult );
break;
}
}
int currentGrouping = resultList.get( 0 ).getGrouping();
for( Result subResult : resultList ){
if( subResult.getGrouping() != currentGrouping ){
currentGrouping = subResult.getGrouping();
multiResult.append( "-------\n" );
}
dictionary.setId( subResult.getValue() );
dictionaryDAO.getData( dictionary );
if( dictionary.getId() != null ){
multiResult.append( dictionary.getLocalizedName() );
if( quantifiedResult != null &&
quantifiedResult.getParentResult().getId().equals( subResult.getId() ) &&
!GenericValidator.isBlankOrNull( quantifiedResult.getValue() ) ){
multiResult.append( ": " );
multiResult.append( quantifiedResult.getValue() );
}
multiResult.append( "\n" );
}
}
if( multiResult.length() > 1 ){
// remove last "\n"
multiResult.setLength( multiResult.length() - 1 );
}
reportResult = multiResult.toString();
}
}
}
data.setResult( reportResult );
}
protected void setCollectionTime( Set<SampleItem> sampleSet, List<ClinicalPatientData> currentSampleReportItems, boolean addAccessionNumber ){
StringBuilder buffer = new StringBuilder( );
boolean firstItem = true;
for( SampleItem sampleItem : sampleSet){
if( firstItem){
firstItem = false;
}else{
buffer.append( ", " );
}
buffer.append( sampleItem.getTypeOfSample().getLocalizedName() );
if (addAccessionNumber) {
buffer.append( " " );
buffer.append( sampleItem.getSample().getAccessionNumber() + "-" + sampleItem.getSortOrder());
}
if( sampleItem.getCollectionDate() == null){
buffer.append( " -- " );
buffer.append( StringUtil.getMessageForKey( "label.not.available" ) );
}else{
buffer.append( " " );
buffer.append( DateUtil.convertTimestampToStringDateAndConfiguredHourTime( sampleItem.getCollectionDate() ) );
}
}
String collectionTimes = buffer.toString();
for( ClinicalPatientData clinicalPatientData: currentSampleReportItems){
clinicalPatientData.setCollectionDateTime( collectionTimes );
}
}
/**
* @see PatientReport#initializeReportItems()
*/
protected void initializeReportItems(){
reportItems = new ArrayList<ClinicalPatientData>();
}
/**
* If you have a string that you wish to add a suffix like units of measure,
* use this.
*
* @param base something
* @param plus something to add, if the above is not null or blank.
* @return the two args put together, or the original if it was blank to
* begin with.
*/
protected String addIfNotEmpty( String base, String plus ){
return ( !GenericValidator.isBlankOrNull( plus ) ) ? base + " " + plus : base;
}
/**
* Pushes all of the information about a patient, analysis, result and the
* conclusion into a new reporting object
*
* @return A single record
*/
protected ClinicalPatientData buildClinicalPatientData( boolean hasParent ){
ClinicalPatientData data = new ClinicalPatientData();
String testName = null;
String sortOrder = "";
String receivedDate = currentSampleService.getReceivedDateForDisplay();
boolean doAnalysis = currentAnalysisService != null;
if( doAnalysis ){
testName = getTestName(hasParent);
//Not sure if it is a bug in escapeHtml but the wrong markup is generated
testName = StringEscapeUtils.escapeHtml( testName ).replace( "&mu", "µ" );
}
if( FormFields.getInstance().useField( Field.SampleEntryUseReceptionHour ) ){
receivedDate += " " + currentSampleService.getReceivedTimeForDisplay( );
}
data.setContactInfo( currentContactInfo );
data.setSiteInfo( currentSiteInfo );
data.setReceivedDate( receivedDate );
data.setDob( getPatientDOB() );
data.setAge( createReadableAge( data.getDob() ) );
data.setGender( patientService.getGender() );
data.setNationalId( patientService.getNationalId() );
setPatientName( data );
data.setDept( patientDept );
data.setCommune( patientCommune );
data.setStNumber( getLazyPatientIdentity( STNumber, PatientService.PATIENT_ST_IDENTITY ) );
data.setSubjectNumber( getLazyPatientIdentity( subjectNumber, PatientService.PATIENT_SUBJECT_IDENTITY ) );
data.setHealthRegion( getLazyPatientIdentity( healthRegion, PatientService.PATIENT_HEALTH_REGION_IDENTITY ) );
data.setHealthDistrict( getLazyPatientIdentity( healthDistrict, PatientService.PATIENT_HEALTH_DISTRICT_IDENTITY ) );
data.setLabOrderType( ObservationHistoryService.getValueForSample( ObservationType.PROGRAM, currentSampleService.getId() ) );
data.setTestName( testName );
data.setPatientSiteNumber( ObservationHistoryService.getValueForSample( ObservationType.REFERRERS_PATIENT_ID, currentSampleService.getId() ) );
data.setBillingNumber( ObservationHistoryService.getValueForSample( ObservationType.BILLING_REFERENCE_NUMBER, currentSampleService.getId() ) );
if( doAnalysis ){
data.setPanel( currentAnalysisService.getPanel());
if( currentAnalysisService.getPanel() != null ){
data.setPanelName( currentAnalysisService.getPanel().getLocalizedName() );
}
data.setTestDate( currentAnalysisService.getCompletedDateForDisplay());
data.setSampleSortOrder(currentAnalysisService.getAnalysis().getSampleItem().getSortOrder());
data.setOrderFinishDate( completionDate );
data.setOrderDate( DateUtil.convertTimestampToStringDateAndConfiguredHourTime( currentSampleService.getOrderedDate() ) );
data.setSampleId( currentSampleService.getAccessionNumber() + "-" + data.getSampleSortOrder() );
data.setSampleType( currentAnalysisService.getTypeOfSample().getLocalizedName() );
data.setCollectionDateTime( DateUtil.convertTimestampToStringDateAndConfiguredHourTime( currentAnalysisService.getAnalysis().getSampleItem().getCollectionDate() ));
}
data.setAccessionNumber( currentSampleService.getAccessionNumber() + "-" + sortOrder );
if( doAnalysis ){
reportResultAndConclusion( data );
}
return data;
}
private String getTestName(boolean indent){
String testName;
if( useReportingDescription() ){
testName = TestService.getUserLocalizedReportingTestName( currentAnalysisService.getTest() );
}else{
testName = TestService.getUserLocalizedTestName( currentAnalysisService.getTest() );
}
if( GenericValidator.isBlankOrNull( testName ) ){
testName = TestService.getUserLocalizedTestName( currentAnalysisService.getTest() );
}
return (indent ? " " : "") + testName;
}
/**
* Given a list of referralResults for a particular analysis, generated the
* next displayable value made of from one or more of the values from the
* list starting at the given index. It uses multiresult form the list when
* the results are for the same test.
*
* @param referralResultsForReferral The referral
* @param i starting index.
* @return last index actually used. If you start with 2 and this routine
* uses just item #2, then return result is 2, but if there are two
* results for the same test (e.g. a multi-select result) and those
* are in item item 2 and item 3 this routine returns #3.
*/
protected int reportReferralResultValue( List<ReferralResult> referralResultsForReferral, int i ){
ReferralResult referralResult = referralResultsForReferral.get( i );
reportReferralResultValue = "";
String currTestId = referralResult.getTestId();
do{
reportReferralResultValue += findDisplayableReportResult( referralResult.getResult() ) + ", ";
i++;
if( i >= referralResultsForReferral.size() ){
break;
}
referralResult = referralResultsForReferral.get( i );
}while(currTestId.equals( referralResult.getTestId() ));
reportReferralResultValue = reportReferralResultValue.substring( 0, reportReferralResultValue.length() - 2 );
i--;
return i;
}
/**
* Derive the appropriate displayable string results, either dictionary
* result or direct value.
*
* @param result The result
* @return a reportable result string.
*/
private String findDisplayableReportResult( Result result ){
String reportResult = "";
if( result == null ){
return reportResult;
}
String type = result.getResultType();
String value = result.getValue();
if( value == null ){
return reportResult;
}
if( TypeOfTestResultService.ResultType.isDictionaryVariant( type ) ){
if( result.getValue() != null && !"null".equals( result.getValue() )){
Dictionary dictionary = new Dictionary();
dictionary.setId( result.getValue() );
dictionaryDAO.getData( dictionary );
reportResult = dictionary.getId() != null ? dictionary.getLocalizedName() : "";
}
}else{
reportResult = result.getValue();
}
return reportResult;
}
private String createReadableAge( String dob ){
if( GenericValidator.isBlankOrNull( dob ) ){
return "";
}
dob = dob.replaceAll( "xx", "01" );
Date dobDate = DateUtil.convertStringDateToSqlDate( dob );
int months = DateUtil.getAgeInMonths( dobDate, DateUtil.getNowAsSqlDate() );
if( months > 35 ){
return ( months / 12 ) + " " + StringUtil.getMessageForKey("abbreviation.year.single");
}else if( months > 0 ){
return months + " " + StringUtil.getMessageForKey("abbreviation.month.single");
}else{
int days = DateUtil.getAgeInDays( dobDate, DateUtil.getNowAsSqlDate() );
return days + " " + StringUtil.getMessageForKey("abbreviation.day.single");
}
}
@Override
public List<String> getReportedOrders(){
return handledOrders;
}
}