package us.mn.state.health.lims.result.action.util;
import org.apache.commons.validator.GenericValidator;
import org.apache.struts.action.ActionErrors;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import us.mn.state.health.lims.common.action.IActionConstants;
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.DateValidationProvider;
import us.mn.state.health.lims.common.services.AnalysisService;
import us.mn.state.health.lims.common.services.TypeOfTestResultService;
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.validator.ActionError;
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.test.beanItems.TestResultItem;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ResultsValidation {
private static final String SPECIAL_CASE = "XXXX";
private boolean supportReferrals = FormFields.getInstance().useField( Field.ResultsReferral );
private boolean useTechnicianName = ConfigurationProperties.getInstance().isPropertyValueEqual( Property.resultTechnicianName, "true");
private boolean noteRequiredForChangedResults = false;
private boolean useRejected = ConfigurationProperties.getInstance().isPropertyValueEqual(Property.allowResultRejection, "true");
private static ResultDAO resultDAO = new ResultDAOImpl();
public List<ActionError> validateItem(TestResultItem item ) {
List<ActionError> errors = new ArrayList<ActionError>();
validateTestDate(item, errors);
if (!item.isRejected())
validateResult(item, errors);
if( noteRequiredForChangedResults && !item.isRejected()) {
validateRequiredNote( item, errors);
}
if (supportReferrals) {
validateReferral(item, errors);
}
if (useTechnicianName) {
validateTesterSignature(item, errors);
}
if (useRejected) {
validateRejection(item, errors);
}
return errors;
}
public ActionErrors validateModifiedItems(List<TestResultItem> modifiedItems) {
noteRequiredForChangedResults = "true".equals(ConfigurationProperties.getInstance().getPropertyValue(Property.notesRequiredForModifyResults));
ActionErrors errors = new ActionErrors();
for (TestResultItem item : modifiedItems) {
List<ActionError> itemErrors = validateItem(item );
if (itemErrors.size() > 0) {
StringBuilder augmentedAccession = new StringBuilder(item.getSequenceAccessionNumber());
augmentedAccession.append(" : ");
augmentedAccession.append(item.getTestName());
ActionError accessionError = new ActionError("errors.followingAccession", augmentedAccession);
errors.add(ActionErrors.GLOBAL_MESSAGE, accessionError);
for (ActionError error : itemErrors) {
errors.add(ActionErrors.GLOBAL_MESSAGE, error);
}
}
}
return errors;
}
private void validateTestDate(TestResultItem item, List<ActionError> errors) {
DateValidationProvider dateValidator = new DateValidationProvider();
Date date = dateValidator.getDate(item.getTestDate());
if (date == null) {
errors.add(new ActionError("errors.date", new StringBuilder(item.getTestDate())));
} else if (!IActionConstants.VALID.equals(dateValidator.validateDate(date, DateValidationProvider.PAST))) {
errors.add(new ActionError("error.date.inFuture"));
}
}
private void validateResult(TestResultItem testResultItem, List<ActionError> errors) {
String resultValue = testResultItem.getShadowResultValue();
if (GenericValidator.isBlankOrNull(resultValue) && testResultItem.isRejected())
return;
if (!(ResultUtil.areNotes(testResultItem) ||
(supportReferrals && ResultUtil.isReferred(testResultItem)) ||
ResultUtil.areResults(testResultItem) ||
ResultUtil.isForcedToAcceptance(testResultItem))) {
errors.add(new ActionError("errors.result.required"));
}
if (!GenericValidator.isBlankOrNull(resultValue) && "N".equals(testResultItem.getResultType())) {
if( resultValue.equals(SPECIAL_CASE)){
return;
}
try {
Double.parseDouble(resultValue);
} catch (NumberFormatException e) {
errors.add(new ActionError("errors.number.format", new StringBuilder("Result")));
}
}
if( testResultItem.isHasQualifiedResult() && GenericValidator.isBlankOrNull(testResultItem.getQualifiedResultValue())){
errors.add(new ActionError("errors.missing.result.details", new StringBuilder("Result")));
}
}
private void validateReferral(TestResultItem item, List<ActionError> errors) {
if (item.isShadowReferredOut() && "0".equals(item.getReferralReasonId())) {
errors.add(new ActionError("error.referral.noReason"));
}
}
private void validateRequiredNote(TestResultItem item, List<ActionError> errors) {
if( GenericValidator.isBlankOrNull(item.getNote())&&
!GenericValidator.isBlankOrNull(item.getResultId())){
if( resultHasChanged(item)){
errors.add(new ActionError("error.requiredNote.missing"));
}
}
}
private boolean resultHasChanged( TestResultItem item ){
if( TypeOfTestResultService.ResultType.isMultiSelectVariant( item.getResultType() )){
List<Result> resultList = new AnalysisService( item.getAnalysisId() ).getResults();
ArrayList<String> dictionaryIds = new ArrayList<String>( resultList.size() );
for(Result result : resultList){
dictionaryIds.add( result.getValue() );
}
if( !GenericValidator.isBlankOrNull( item.getMultiSelectResultValues() ) && !"{}".equals( item.getMultiSelectResultValues() ) ){
JSONParser parser = new JSONParser();
try{
int matchCount = 0;
JSONObject jsonResult = ( JSONObject ) parser.parse( item.getMultiSelectResultValues() );
for( Object key : jsonResult.keySet() ){
String[] ids = ( ( String ) jsonResult.get( key ) ).trim().split( "," );
for( String id : ids ){
if( dictionaryIds.contains( id )){
matchCount++;
}else{
return false;
}
}
}
return matchCount != dictionaryIds.size();
}catch( ParseException e ){
e.printStackTrace();
return false;
}
}
} else{
Result dbResult = resultDAO.getResultById( item.getResultId() );
return !item.getShadowResultValue().equals( dbResult.getValue() ) && !GenericValidator.isBlankOrNull( dbResult.getValue() );
}
return false;
}
private void validateTesterSignature(TestResultItem item, List<ActionError> errors) {
// Conclusions may not need a signature. If the user changed the value
// and then changed it back it will be
// marked as dirty but the signature may still be blank.
if ("0".equals(item.getResultId())) {
return;
}
Result result = resultDAO.getResultById(item.getResultId());
if (result != null && result.getAnalyte() != null && "Conclusion".equals(result.getAnalyte().getAnalyteName())) {
if (result.getValue().equals(item.getShadowResultValue())) {
return;
}
}
if (GenericValidator.isBlankOrNull(item.getTechnician())) {
errors.add(new ActionError("errors.signature.required"));
}
}
private void validateRejection(TestResultItem item, List<ActionError> errors) {
if (item.isRejected() && "0".equals(item.getRejectReasonId())) {
errors.add(new ActionError("error.reject.noReason"));
}
}
}