<commit_before>package gov.nih.nci.cabig.caaers.rules.business.service;

import gov.nih.nci.cabig.caaers.CaaersSystemException;
import gov.nih.nci.cabig.caaers.dao.ExpeditedAdverseEventReportDao;
import gov.nih.nci.cabig.caaers.dao.OrganizationDao;
import gov.nih.nci.cabig.caaers.dao.report.ReportDefinitionDao;
import gov.nih.nci.cabig.caaers.domain.AdverseEvent;
import gov.nih.nci.cabig.caaers.domain.ExpeditedAdverseEventReport;
import gov.nih.nci.cabig.caaers.domain.StudyOrganization;
import gov.nih.nci.cabig.caaers.domain.StudyParticipantAssignment;
import gov.nih.nci.cabig.caaers.domain.expeditedfields.ExpeditedReportSection;
import gov.nih.nci.cabig.caaers.domain.report.Report;
import gov.nih.nci.cabig.caaers.domain.report.ReportDefinition;
import gov.nih.nci.cabig.caaers.service.ErrorMessages;
import gov.nih.nci.cabig.caaers.service.EvaluationService;
import gov.nih.nci.cabig.caaers.service.ReportService;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.annotation.Transactional;

@Transactional(readOnly=true)
public class EvaluationServiceImpl implements EvaluationService {
    private AdverseEventEvaluationService adverseEventEvaluationService = new AdverseEventEvaluationServiceImpl();
    private static final Log log = LogFactory.getLog(EvaluationServiceImpl.class);

    private ReportDefinitionDao reportDefinitionDao;
    private ExpeditedAdverseEventReportDao expeditedAdverseEventReportDao;
    private ReportService reportService;
    private OrganizationDao  organizationDao;

    /**
     * @return true if the given adverse event is severe in the context of the provided
     *  study, site, and participant
     */
    public boolean isSevere(StudyParticipantAssignment assignment, AdverseEvent adverseEvent) {
        boolean isSevere = false;

        try {
            String msg = adverseEventEvaluationService.assesAdverseEvent(adverseEvent, assignment.getStudySite().getStudy());
            if ("SERIOUS_ADVERSE_EVENT".equals(msg)) {
                isSevere = true;
            }
        } catch (Exception e) {
            throw new CaaersSystemException("Could not assess the given AE", e);
        }

        return isSevere;
    }

    /**
     * The report definitions that are marked as mandatory at rules engine.
     * @param expeditedData - The {@link ExpeditedAdverseEventReport}
     * @return - The list of {@link ReportDefinition} objects, that are associated to this report.
     */
    public List<ReportDefinition> findRequiredReportDefinitions(ExpeditedAdverseEventReport expeditedData){
    	Map<String,List<String>> map;
    	List<ReportDefinition> defList = new ArrayList<ReportDefinition>();
    	try {
            map = adverseEventEvaluationService.evaluateSAEReportSchedule(expeditedData);
        } catch (Exception e) {
            throw new CaaersSystemException("Could not determine the reports necessary for the given expedited adverse event data", e);
        }
        for(List<String> nameList : map.values()){
        	for(String name : nameList){
        		ReportDefinition reportDefinition = reportDefinitionDao.getByName(name);
        		defList.add(reportDefinition);
        	}
        }
        return defList;
    }

    /**
     * Evaluates the provided data and associates new {@link Report}
     * instances with the given {@link ExpeditedAdverseEventReport}.
     * <p>
     * This method may be called multiple times for the same expedited data.  Implementors must be
     * sure not to add multiple {@link Report}s for the same
     * {@link ReportDefinition}.  Implementors must also <em>not</em> remove
     * {@link gov.nih.nci.cabig.caaers.domain.report.Report}s if they don't evaluate as required
     * (e.g., some reports may have been directly selected by the user).  Instead, implementors
     * should update the {@link Report#setRequired} flag.
     *
     * @param expeditedData
     * @return the report definitions which the evaluation indicated were required.
     */
    @Transactional(readOnly=false)
    public void addRequiredReports(ExpeditedAdverseEventReport expeditedData) {
        Map<String,List<String>> map;
        List<String> reportDefinitionNames = new ArrayList<String>();
        try {
            map = adverseEventEvaluationService.evaluateSAEReportSchedule(expeditedData);
        } catch (Exception e) {
            throw new CaaersSystemException(
                "Could not determine the reports necessary for the given expedited adverse event data", e);
        }

        Set<String> keys = map.keySet();
        for (String key : keys) {
            List<String> reportDefNames = map.get(key);
            /* TO-DO need to clarify this ranking incase of multi actions in rules
            if (reportDefNames.size() != 0) {
                String reportDefName = extractTopPriorityReportDefintionName(reportDefNames);
                reportDefinitionNames.add(reportDefName);
            }
            */
            //uncomment the above part and comment the below code after figuring oout ranking.
            for (String reportDefName : reportDefNames) {
            	reportDefinitionNames.add(reportDefName);
            }
        }

        for (Object reportDefinitionName : reportDefinitionNames) {

            ReportDefinition def = reportDefinitionDao.getByName(reportDefinitionName.toString());
            Report report = existingReportWithDef(expeditedData, def);

            if (report == null) {
                report = reportService.createReport(def, expeditedData);
                expeditedAdverseEventReportDao.save(expeditedData);
            }
            report.setRequired(true);
        }

    }
    /**
     * Will create the Report by calling ReportService, then saves the ExpeditedAdverseEventReport
     */
    @Transactional(readOnly=false)
    public void addOptionalReports(ExpeditedAdverseEventReport expeditedData, List<ReportDefinition> reportDefs) {
    	for(ReportDefinition def : reportDefs){
    		reportService.createReport(def, expeditedData);
    	}
    	expeditedAdverseEventReportDao.save(expeditedData);
    }

    private Report existingReportWithDef(ExpeditedAdverseEventReport expeditedData, ReportDefinition def) {
        for (Report report : expeditedData.getReports()) {
            log.debug("Examining Report with def "+ report.getReportDefinition().getName()
                + " (id: " + report.getReportDefinition().getId() + "; hash: "
                + Integer.toHexString(report.getReportDefinition().hashCode()) + ')');
            if (report.getReportDefinition().equals(def)) {
                log.debug("Matched");
                return report;
            }
        }
        log.debug("No Report with def matching " + def.getName()
            + " (id: " + def.getId() + "; hash: "<commit_msg>saving of report disabled in addRequiredReports()<commit_after>package gov.nih.nci.cabig.caaers.rules.business.service;

import gov.nih.nci.cabig.caaers.CaaersSystemException;
import gov.nih.nci.cabig.caaers.dao.ExpeditedAdverseEventReportDao;
import gov.nih.nci.cabig.caaers.dao.OrganizationDao;
import gov.nih.nci.cabig.caaers.dao.report.ReportDefinitionDao;
import gov.nih.nci.cabig.caaers.domain.AdverseEvent;
import gov.nih.nci.cabig.caaers.domain.ExpeditedAdverseEventReport;
import gov.nih.nci.cabig.caaers.domain.StudyOrganization;
import gov.nih.nci.cabig.caaers.domain.StudyParticipantAssignment;
import gov.nih.nci.cabig.caaers.domain.expeditedfields.ExpeditedReportSection;
import gov.nih.nci.cabig.caaers.domain.report.Report;
import gov.nih.nci.cabig.caaers.domain.report.ReportDefinition;
import gov.nih.nci.cabig.caaers.service.ErrorMessages;
import gov.nih.nci.cabig.caaers.service.EvaluationService;
import gov.nih.nci.cabig.caaers.service.ReportService;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.annotation.Transactional;

@Transactional(readOnly=true)
public class EvaluationServiceImpl implements EvaluationService {
    private AdverseEventEvaluationService adverseEventEvaluationService = new AdverseEventEvaluationServiceImpl();
    private static final Log log = LogFactory.getLog(EvaluationServiceImpl.class);

    private ReportDefinitionDao reportDefinitionDao;
    private ExpeditedAdverseEventReportDao expeditedAdverseEventReportDao;
    private ReportService reportService;
    private OrganizationDao  organizationDao;

    /**
     * @return true if the given adverse event is severe in the context of the provided
     *  study, site, and participant
     */
    public boolean isSevere(StudyParticipantAssignment assignment, AdverseEvent adverseEvent) {
        boolean isSevere = false;

        try {
            String msg = adverseEventEvaluationService.assesAdverseEvent(adverseEvent, assignment.getStudySite().getStudy());
            if ("SERIOUS_ADVERSE_EVENT".equals(msg)) {
                isSevere = true;
            }
        } catch (Exception e) {
            throw new CaaersSystemException("Could not assess the given AE", e);
        }

        return isSevere;
    }

    /**
     * The report definitions that are marked as mandatory at rules engine.
     * @param expeditedData - The {@link ExpeditedAdverseEventReport}
     * @return - The list of {@link ReportDefinition} objects, that are associated to this report.
     */
    public List<ReportDefinition> findRequiredReportDefinitions(ExpeditedAdverseEventReport expeditedData){
    	Map<String,List<String>> map;
    	List<ReportDefinition> defList = new ArrayList<ReportDefinition>();
    	try {
            map = adverseEventEvaluationService.evaluateSAEReportSchedule(expeditedData);
        } catch (Exception e) {
            throw new CaaersSystemException("Could not determine the reports necessary for the given expedited adverse event data", e);
        }
        for(List<String> nameList : map.values()){
        	for(String name : nameList){
        		ReportDefinition reportDefinition = reportDefinitionDao.getByName(name);
        		defList.add(reportDefinition);
        	}
        }
        return defList;
    }

    /**
     * Evaluates the provided data and associates new {@link Report}
     * instances with the given {@link ExpeditedAdverseEventReport}.
     * <p>
     * This method may be called multiple times for the same expedited data.  Implementors must be
     * sure not to add multiple {@link Report}s for the same
     * {@link ReportDefinition}.  Implementors must also <em>not</em> remove
     * {@link gov.nih.nci.cabig.caaers.domain.report.Report}s if they don't evaluate as required
     * (e.g., some reports may have been directly selected by the user).  Instead, implementors
     * should update the {@link Report#setRequired} flag.
     *
     * @param expeditedData
     * @return the report definitions which the evaluation indicated were required.
     */
    @Transactional(readOnly=false)
    public void addRequiredReports(ExpeditedAdverseEventReport expeditedData) {
        Map<String,List<String>> map;
        List<String> reportDefinitionNames = new ArrayList<String>();
        try {
            map = adverseEventEvaluationService.evaluateSAEReportSchedule(expeditedData);
        } catch (Exception e) {
            throw new CaaersSystemException(
                "Could not determine the reports necessary for the given expedited adverse event data", e);
        }

        Set<String> keys = map.keySet();
        for (String key : keys) {
            List<String> reportDefNames = map.get(key);
            /* TO-DO need to clarify this ranking incase of multi actions in rules
            if (reportDefNames.size() != 0) {
                String reportDefName = extractTopPriorityReportDefintionName(reportDefNames);
                reportDefinitionNames.add(reportDefName);
            }
            */
            //uncomment the above part and comment the below code after figuring oout ranking.
            for (String reportDefName : reportDefNames) {
            	reportDefinitionNames.add(reportDefName);
            }
        }

        for (Object reportDefinitionName : reportDefinitionNames) {

            ReportDefinition def = reportDefinitionDao.getByName(reportDefinitionName.toString());
            Report report = existingReportWithDef(expeditedData, def);

            if (report == null) {
                report = reportService.createReport(def, expeditedData);
                //expeditedAdverseEventReportDao.save(expeditedData);
            }
            report.setRequired(true);
        }

    }
    /**
     * Will create the Report by calling ReportService, then saves the ExpeditedAdverseEventReport
     */
    @Transactional(readOnly=false)
    public void addOptionalReports(ExpeditedAdverseEventReport expeditedData, List<ReportDefinition> reportDefs) {
    	for(ReportDefinition def : reportDefs){
    		reportService.createReport(def, expeditedData);
    	}
    	expeditedAdverseEventReportDao.save(expeditedData);
    }

    private Report existingReportWithDef(ExpeditedAdverseEventReport expeditedData, ReportDefinition def) {
        for (Report report : expeditedData.getReports()) {
            log.debug("Examining Report with def "+ report.getReportDefinition().getName()
                + " (id: " + report.getReportDefinition().getId() + "; hash: "
                + Integer.toHexString(report.getReportDefinition().hashCode()) + ')');
            if (report.getReportDefinition().equals(def)) {
                log.debug("Matched");
                return report;
            }
        }
        log.debug("No Report with def matching " + def.getName()
            + " (id: " + def.getId() + "; hash: "
{'fraction_non_alphanumeric': 0.08869712830669119, 'fraction_numerical': 0.00014146272457207527, 'mean_word_length': 3.151203758073987, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5331001', 'n_tokens_mistral': 3962, 'n_tokens_neox': 3851, 'n_words': 899}