package org.akaza.openclinica.logic.rulerunner; import org.akaza.openclinica.bean.login.UserAccountBean; import org.akaza.openclinica.bean.managestudy.DiscrepancyNoteBean; import org.akaza.openclinica.bean.managestudy.StudyBean; import org.akaza.openclinica.bean.managestudy.StudyEventBean; import org.akaza.openclinica.bean.managestudy.StudySubjectBean; import org.akaza.openclinica.bean.submit.CRFVersionBean; import org.akaza.openclinica.bean.submit.EventCRFBean; import org.akaza.openclinica.bean.submit.ItemBean; import org.akaza.openclinica.bean.submit.ItemDataBean; import org.akaza.openclinica.bean.submit.ItemGroupBean; import org.akaza.openclinica.domain.rule.RuleBean; import org.akaza.openclinica.domain.rule.RuleBulkExecuteContainer; import org.akaza.openclinica.domain.rule.RuleBulkExecuteContainerTwo; import org.akaza.openclinica.domain.rule.RuleSetBean; import org.akaza.openclinica.domain.rule.RuleSetRuleBean; import org.akaza.openclinica.domain.rule.action.ActionProcessor; import org.akaza.openclinica.domain.rule.action.ActionProcessorFacade; import org.akaza.openclinica.domain.rule.action.RuleActionBean; import org.akaza.openclinica.domain.rule.action.RuleActionRunLogBean; import org.akaza.openclinica.domain.rule.action.RuleActionRunBean.Phase; import org.akaza.openclinica.domain.rule.expression.ExpressionBean; import org.akaza.openclinica.domain.rule.expression.ExpressionObjectWrapper; import org.akaza.openclinica.exception.OpenClinicaSystemException; import org.akaza.openclinica.logic.expressionTree.OpenClinicaExpressionParser; import org.springframework.mail.javamail.JavaMailSenderImpl; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.sql.DataSource; public class CrfBulkRuleRunner extends RuleRunner { public CrfBulkRuleRunner(DataSource ds, String requestURLMinusServletPath, String contextPath, JavaMailSenderImpl mailSender) { super(ds, requestURLMinusServletPath, contextPath, mailSender); } /** * Organize objects in a certain way so that we can show to Users on UI. * step1 : Get StudyEvent , eventCrf , crfVersion from studyEventId. * * @param crfViewSpecificOrderedObjects * @param ruleSet * @param rule * @return */ private HashMap<RuleBulkExecuteContainer, HashMap<RuleBulkExecuteContainerTwo, Set<String>>> populateForCrfBasedRulesView( HashMap<RuleBulkExecuteContainer, HashMap<RuleBulkExecuteContainerTwo, Set<String>>> crfViewSpecificOrderedObjects, RuleSetBean ruleSet, RuleBean rule, String result, StudyBean currentStudy, List<RuleActionBean> actions) { // step1 StudyEventBean studyEvent = (StudyEventBean) getStudyEventDao().findByPK( Integer.valueOf(getExpressionService().getStudyEventDefenitionOrdninalCurated(ruleSet.getTarget().getValue()))); EventCRFBean eventCrf = (EventCRFBean) getEventCrfDao().findAllByStudyEventAndCrfOrCrfVersionOid(studyEvent, getExpressionService().getCrfOid(ruleSet.getTarget().getValue())).get(0); CRFVersionBean crfVersion = (CRFVersionBean) getCrfVersionDao().findByPK(eventCrf.getCRFVersionId()); RuleBulkExecuteContainer key = new RuleBulkExecuteContainer(crfVersion.getName(), rule, result, actions); String key2String = getExpressionService().getCustomExpressionUsedToCreateView(ruleSet.getTarget().getValue(), studyEvent.getSampleOrdinal()); String studyEventDefinitionName = getExpressionService().getStudyEventDefinitionFromExpression(ruleSet.getTarget().getValue(), currentStudy).getName(); studyEventDefinitionName += " [" + studyEvent.getSampleOrdinal() + "]"; // String itemGroupName = getExpressionService().getItemGroupNameAndOrdinal(ruleSet.getTarget().getValue()); // String itemName = getExpressionService().getItemGroupExpression(ruleSet.getTarget().getValue()).getName(); String itemGroupName = getExpressionService().getItemGroupNameAndOrdinal(ruleSet.getTarget().getValue()); ItemGroupBean itemGroupBean = getExpressionService().getItemGroupExpression(ruleSet.getTarget().getValue()); ItemBean itemBean = getExpressionService().getItemExpression(ruleSet.getTarget().getValue(), itemGroupBean); String itemName = itemBean.getName(); RuleBulkExecuteContainerTwo key2 = new RuleBulkExecuteContainerTwo(key2String, studyEvent, studyEventDefinitionName, itemGroupName, itemName); StudySubjectBean studySubject = (StudySubjectBean) getStudySubjectDao().findByPK(studyEvent.getStudySubjectId()); if (crfViewSpecificOrderedObjects.containsKey(key)) { HashMap<RuleBulkExecuteContainerTwo, Set<String>> k = crfViewSpecificOrderedObjects.get(key); if (k.containsKey(key2)) { k.get(key2).add(String.valueOf(studySubject.getLabel())); } else { HashSet<String> values = new HashSet<String>(); values.add(String.valueOf(studySubject.getLabel())); k.put(key2, values); } } else { HashMap<RuleBulkExecuteContainerTwo, Set<String>> k = new HashMap<RuleBulkExecuteContainerTwo, Set<String>>(); HashSet<String> values = new HashSet<String>(); values.add(String.valueOf(studySubject.getLabel())); k.put(key2, values); crfViewSpecificOrderedObjects.put(key, k); } return crfViewSpecificOrderedObjects; } @Deprecated public HashMap<RuleBulkExecuteContainer, HashMap<RuleBulkExecuteContainerTwo, Set<String>>> runRulesBulkOLD(List<RuleSetBean> ruleSets, ExecutionMode executionMode, StudyBean currentStudy, HashMap<String, String> variableAndValue, UserAccountBean ub) { if (variableAndValue == null || variableAndValue.isEmpty()) { logger.warn("You must be executing Rules in Batch"); variableAndValue = new HashMap<String, String>(); } HashMap<RuleBulkExecuteContainer, HashMap<RuleBulkExecuteContainerTwo, Set<String>>> crfViewSpecificOrderedObjects = new HashMap<RuleBulkExecuteContainer, HashMap<RuleBulkExecuteContainerTwo, Set<String>>>(); for (RuleSetBean ruleSet : ruleSets) { for (ExpressionBean expressionBean : ruleSet.getExpressions()) { ruleSet.setTarget(expressionBean); for (RuleSetRuleBean ruleSetRule : ruleSet.getRuleSetRules()) { String result = null; RuleBean rule = ruleSetRule.getRuleBean(); ExpressionObjectWrapper eow = new ExpressionObjectWrapper(ds, currentStudy, rule.getExpression(), ruleSet, variableAndValue); try { OpenClinicaExpressionParser oep = new OpenClinicaExpressionParser(eow); result = (String) oep.parseAndEvaluateExpression(rule.getExpression().getValue()); // Actions List<RuleActionBean> actionListBasedOnRuleExecutionResult = ruleSetRule.getActions(result, Phase.BATCH); ItemDataBean itemData = getExpressionService().getItemDataBeanFromDb(ruleSet.getTarget().getValue()); if (itemData != null) { Iterator<RuleActionBean> itr = actionListBasedOnRuleExecutionResult.iterator(); while (itr.hasNext()) { RuleActionBean ruleActionBean = itr.next(); RuleActionRunLogBean ruleActionRunLog = new RuleActionRunLogBean(ruleActionBean.getActionType(), itemData, itemData.getValue(), ruleSetRule.getRuleBean().getOid()); if (getRuleActionRunLogDao().findCountByRuleActionRunLogBean(ruleActionRunLog) > 0) { itr.remove(); } } } List<RuleActionBean> actionBeansToShow = new ArrayList<RuleActionBean>(); if (actionListBasedOnRuleExecutionResult.size() > 0) { //if (!dryRun) { for (RuleActionBean ruleAction : actionListBasedOnRuleExecutionResult) { ruleAction.setCuratedMessage(curateMessage(ruleAction, ruleSetRule)); // getDiscrepancyNoteService().saveFieldNotes(ruleAction.getSummary(), itemDataBeanId, "ItemData", currentStudy, ub); ActionProcessor ap = ActionProcessorFacade.getActionProcessor(ruleAction.getActionType(), ds, getMailSender(), dynamicsMetadataService, ruleSet, getRuleActionRunLogDao(), ruleSetRule); RuleActionBean rab = ap.execute(RuleRunnerMode.RULSET_BULK, executionMode, ruleAction, itemData, DiscrepancyNoteBean.ITEM_DATA, currentStudy, ub, prepareEmailContents(ruleSet, ruleSetRule, currentStudy, ruleAction)); if (rab != null) { actionBeansToShow.add(ruleAction); } } if (actionBeansToShow.size() > 0) { crfViewSpecificOrderedObjects = populateForCrfBasedRulesView(crfViewSpecificOrderedObjects, ruleSet, rule, result, currentStudy, actionBeansToShow); } } } catch (OpenClinicaSystemException osa) { String errorMessage = "RuleSet with target : " + ruleSet.getTarget().getValue() + " , Ran Rule : " + rule.getName() + " , It resulted in an error due to : " + osa.getMessage(); // log error logger.warn(errorMessage); } } } } logCrfViewSpecificOrderedObjects(crfViewSpecificOrderedObjects); return crfViewSpecificOrderedObjects; } public HashMap<RuleBulkExecuteContainer, HashMap<RuleBulkExecuteContainerTwo, Set<String>>> runRulesBulk(List<RuleSetBean> ruleSets, ExecutionMode executionMode, StudyBean currentStudy, HashMap<String, String> variableAndValue, UserAccountBean ub) { if (variableAndValue == null || variableAndValue.isEmpty()) { logger.warn("You must be executing Rules in Batch"); variableAndValue = new HashMap<String, String>(); } HashMap<RuleBulkExecuteContainer, HashMap<RuleBulkExecuteContainerTwo, Set<String>>> crfViewSpecificOrderedObjects = new HashMap<RuleBulkExecuteContainer, HashMap<RuleBulkExecuteContainerTwo, Set<String>>>(); HashMap<String, ArrayList<RuleActionContainer>> toBeExecuted = new HashMap<String, ArrayList<RuleActionContainer>>(); for (RuleSetBean ruleSet : ruleSets) { String key = getExpressionService().getItemOid(ruleSet.getOriginalTarget().getValue()); List<RuleActionContainer> allActionContainerListBasedOnRuleExecutionResult = null; if (toBeExecuted.containsKey(key)) { allActionContainerListBasedOnRuleExecutionResult = toBeExecuted.get(key); } else { toBeExecuted.put(key, new ArrayList<RuleActionContainer>()); allActionContainerListBasedOnRuleExecutionResult = toBeExecuted.get(key); } ItemDataBean itemData = null; for (ExpressionBean expressionBean : ruleSet.getExpressions()) { ruleSet.setTarget(expressionBean); for (RuleSetRuleBean ruleSetRule : ruleSet.getRuleSetRules()) { String result = null; RuleBean rule = ruleSetRule.getRuleBean(); ExpressionObjectWrapper eow = new ExpressionObjectWrapper(ds, currentStudy, rule.getExpression(), ruleSet, variableAndValue); try { OpenClinicaExpressionParser oep = new OpenClinicaExpressionParser(eow); result = (String) oep.parseAndEvaluateExpression(rule.getExpression().getValue()); itemData = getExpressionService().getItemDataBeanFromDb(ruleSet.getTarget().getValue()); // Actions List<RuleActionBean> actionListBasedOnRuleExecutionResult = ruleSetRule.getActions(result, Phase.BATCH); if (itemData != null) { Iterator<RuleActionBean> itr = actionListBasedOnRuleExecutionResult.iterator(); while (itr.hasNext()) { RuleActionBean ruleActionBean = itr.next(); RuleActionRunLogBean ruleActionRunLog = new RuleActionRunLogBean(ruleActionBean.getActionType(), itemData, itemData.getValue(), ruleSetRule.getRuleBean().getOid()); if (getRuleActionRunLogDao().findCountByRuleActionRunLogBean(ruleActionRunLog) > 0) { itr.remove(); } } } for (RuleActionBean ruleActionBean : actionListBasedOnRuleExecutionResult) { RuleActionContainer ruleActionContainer = new RuleActionContainer(ruleActionBean, expressionBean, itemData, ruleSet); allActionContainerListBasedOnRuleExecutionResult.add(ruleActionContainer); } logger.info("RuleSet with target : {} , Ran Rule : {} The Result was : {} , Based on that {} action will be executed in {} mode. ", new Object[] { ruleSet.getTarget().getValue(), rule.getName(), result, actionListBasedOnRuleExecutionResult.size(), executionMode.name() }); } catch (OpenClinicaSystemException osa) { // TODO: report something useful } } } } for (Map.Entry<String, ArrayList<RuleActionContainer>> entry : toBeExecuted.entrySet()) { // Sort the list of actions Collections.sort(entry.getValue(), new RuleActionContainerComparator()); HashMap<Key, List<RuleActionBean>> hms = new HashMap<Key, List<RuleActionBean>>(); for (RuleActionContainer ruleActionContainer : entry.getValue()) { //ruleSet.setTarget(ruleAction.getRuleSetExpression()); ruleActionContainer.getRuleAction().setCuratedMessage( curateMessage(ruleActionContainer.getRuleAction(), ruleActionContainer.getRuleAction().getRuleSetRule())); ActionProcessor ap = ActionProcessorFacade.getActionProcessor(ruleActionContainer.getRuleAction().getActionType(), ds, getMailSender(), dynamicsMetadataService, ruleActionContainer.getRuleSetBean(), getRuleActionRunLogDao(), ruleActionContainer.getRuleAction().getRuleSetRule()); RuleActionBean rab = null; ap.execute(RuleRunnerMode.RULSET_BULK, executionMode, ruleActionContainer.getRuleAction(), ruleActionContainer.getItemDataBean(), DiscrepancyNoteBean.ITEM_DATA, currentStudy, ub, prepareEmailContents(ruleActionContainer.getRuleSetBean(), ruleActionContainer .getRuleAction().getRuleSetRule(), currentStudy, ruleActionContainer.getRuleAction())); if (rab != null) { Key k = new Key(ruleActionContainer.getRuleSetBean(), ruleActionContainer.getRuleAction().getExpressionEvaluatesTo().toString(), ruleActionContainer.getRuleAction().getRuleSetRule().getRuleBean()); if (hms.containsKey(k)) { hms.get(k).add(ruleActionContainer.getRuleAction()); } else { List<RuleActionBean> theActionBeansToShow = new ArrayList<RuleActionBean>(); theActionBeansToShow.add(ruleActionContainer.getRuleAction()); hms.put(k, theActionBeansToShow); } } } for (Map.Entry<Key, List<RuleActionBean>> theEntry : hms.entrySet()) { Key key = theEntry.getKey(); List<RuleActionBean> value = theEntry.getValue(); crfViewSpecificOrderedObjects = populateForCrfBasedRulesView(crfViewSpecificOrderedObjects, key.getRuleSet(), key.getRule(), key.getResult(), currentStudy, value); } } //logCrfViewSpecificOrderedObjects(crfViewSpecificOrderedObjects); return crfViewSpecificOrderedObjects; } } class Key { RuleSetBean ruleSet; String result; RuleBean rule; public Key(RuleSetBean ruleSet, String result, RuleBean rule) { super(); this.ruleSet = ruleSet; this.result = result; this.rule = rule; } public RuleSetBean getRuleSet() { return ruleSet; } public void setRuleSet(RuleSetBean ruleSet) { this.ruleSet = ruleSet; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } public RuleBean getRule() { return rule; } public void setRule(RuleBean rule) { this.rule = rule; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((this.result == null) ? 0 : this.result.hashCode()); result = prime * result + ((rule == null) ? 0 : rule.hashCode()); result = prime * result + ((ruleSet == null) ? 0 : ruleSet.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Key other = (Key) obj; if (result == null) { if (other.result != null) return false; } else if (!result.equals(other.result)) return false; if (rule == null) { if (other.rule != null) return false; } else if (!rule.equals(other.rule)) return false; if (ruleSet == null) { if (other.ruleSet != null) return false; } else if (!ruleSet.equals(other.ruleSet)) return false; return true; } }