Java tutorial
/******************************************************************************* * Copyright SemanticBits, Northwestern University and Akaza Research * * Distributed under the OSI-approved BSD 3-Clause License. * See http://ncip.github.com/caaers/LICENSE.txt for details. ******************************************************************************/ package gov.nih.nci.cabig.caaers.rules.business.service; import com.semanticbits.rules.api.RulesEngineService; import com.semanticbits.rules.brxml.*; import com.semanticbits.rules.brxml.Condition; import com.semanticbits.rules.brxml.RuleSet; import com.semanticbits.rules.exception.RuleException; import com.semanticbits.rules.utils.BRXMLHelper; import com.semanticbits.rules.utils.RuleUtil; import com.semanticbits.rules.utils.XMLUtil; import gov.nih.nci.cabig.caaers.CaaersSystemException; import gov.nih.nci.cabig.caaers.dao.*; import gov.nih.nci.cabig.caaers.dao.query.RuleSetQuery; import gov.nih.nci.cabig.caaers.dao.report.ReportDefinitionDao; import gov.nih.nci.cabig.caaers.domain.*; import gov.nih.nci.cabig.caaers.domain.expeditedfields.ExpeditedReportSection; import gov.nih.nci.cabig.caaers.domain.report.Mandatory; import gov.nih.nci.cabig.caaers.domain.report.ReportDefinition; import gov.nih.nci.cabig.caaers.domain.report.TimeScaleUnit; import gov.nih.nci.cabig.caaers.rules.common.CaaersRuleUtil; import gov.nih.nci.cabig.caaers.rules.common.CategoryConfiguration; import gov.nih.nci.cabig.caaers.rules.common.RuleLevel; import gov.nih.nci.cabig.caaers.rules.common.RuleType; import gov.nih.nci.cabig.caaers.validation.ValidationErrors; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.transaction.annotation.Transactional; import java.io.File; import java.io.IOException; import java.net.URLEncoder; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.UUID; /** * * This is the interface/facade to rules engine. * @author Biju Joseph * @author Ion C. Olaru * */ public class CaaersRulesEngineService { private static final Log log = LogFactory.getLog(CaaersRulesEngineService.class); public static final String SPONSOR_LEVEL = RuleLevel.Sponsor.getName(); public static final String INSTITUTIONAL_LEVEL = RuleLevel.Institution.getName(); public static final String SPONSOR_DEFINED_STUDY_LEVEL = RuleLevel.SponsorDefinedStudy.getName(); public static final String INSTITUTION_DEFINED_STUDY_LEVEL = RuleLevel.InstitutionDefinedStudy.getName(); private RulesEngineService ruleEngineService; private RuleSetDao ruleSetDao; private ReportDefinitionDao reportDefinitionDao; private OrganizationDao organizationDao; private StudyDao studyDao; private ConfigPropertyDao configPropertyDao; private CtcTermDao ctcTermDao; //BJ: refactored , extracted from CreateRulesCommand. private String[] columnsToTrash = { "studySDO", "organizationSDO", "adverseEventEvaluationResult", "factResolver", "ruleEvaluationResult" }; /** * Will return the rule-set from the rules engine, and returns it after necessary clean-up * @param bindURI * @return */ public RuleSet getRuleSet(String bindURI) { RuleSet ruleSet = ruleEngineService.getRuleSet(bindURI); cleanRuleSet(ruleSet); makeRuleSetReadable(ruleSet); return ruleSet; } /** * Will load the rule-set identified by the ID and exports it. * @param bindURI - The binding URI */ @Transactional(readOnly = true) public String exportRules(String bindURI) { try { String xml = ruleEngineService.exportRuleSetXML(bindURI); return xml; } catch (RuleException ruleEx) { log.error("Error while retrieving the rules for bindURI : " + bindURI, ruleEx); throw new CaaersSystemException("Error pulling the rules xml [" + ruleEx.getMessage() + "]", ruleEx); } } /** * This method will import the rules XML. * CAAERS-2325 - requires the use of NCI-code and Sponsor-ID of study to identify the study and organization. * * @param fileName - The file to import. * @return - A list of ReportDefinition names */ @Transactional public List<String> importRules(String fileName) throws CaaersSystemException { File f = new File(fileName); if (!f.isFile() || !f.exists()) { throw new CaaersSystemException("The file :" + fileName + "do not exist"); } String xml = null; try { xml = FileUtils.readFileToString(f); } catch (IOException ioe) { throw new CaaersSystemException("Unable to import rule file : " + ioe.getMessage(), ioe); } RuleSet ruleSet = (RuleSet) XMLUtil.unmarshal(xml); List<Rule> rules = ruleSet.getRule(); if (rules.size() == 0) { throw new CaaersSystemException("The provided rule file has nothing to import"); } log.info("Importing ruleSet :" + ruleSet.getName()); //--------- Modify the package names ---------------------- reconcileRuleSet(ruleSet); RuleType ruleType = parseRuleType(ruleSet.getName()); RuleLevel ruleLevel = parseRuleLevel(ruleSet.getName()); String strOrgId = parseOrganizationId(ruleSet.getName()); String strStudyId = parseStudyId(ruleSet.getName()); if (log.isInfoEnabled()) { log.info("RuleSet : name (package name) : " + ruleSet.getName()); log.info("Rule Set Type : " + String.valueOf(ruleType)); log.info("Rule Set Level : " + String.valueOf(ruleLevel)); log.info("Rule Set orgId : " + String.valueOf(strOrgId)); log.info("Rule Set studyId : " + String.valueOf(strStudyId)); } Organization organization = null; if (StringUtils.isNotBlank(strOrgId)) { organization = organizationDao.getById(Integer.parseInt(strOrgId)); } Study study = null; if (StringUtils.isNotBlank(strStudyId)) { study = studyDao.getById(Integer.parseInt(strStudyId)); } //Find the report definitions required to be created. HashSet<String> reportDefinitionNames = new HashSet<String>(); List<String> reportDefinitionsCreated = new ArrayList<String>(); boolean isAssociatedToDCP = organization == null ? false : organization.getNciInstituteCode().equals("DCP"); boolean isSAERule = ruleSet.getDescription().equals(RuleType.REPORT_SCHEDULING_RULES.getName()); if (isSAERule && !isAssociatedToDCP) { for (Rule rule : rules) { for (String action : rule.getAction()) { reportDefinitionNames.add(action); } } //find the "Expedited" - ConfigProperty ConfigProperty expeditedConfigProperty = configPropertyDao .getByTypeAndCode(ConfigPropertyType.REPORT_GROUP, "RT_AdEERS"); // check report definitions for this org for (String rd : reportDefinitionNames) { if (StringUtils.equals("IGNORE", rd)) continue; ReportDefinition reportDefinition = reportDefinitionDao.getByName(rd, organization.getId()); if (reportDefinition != null) continue; //create a new report definition. ReportDefinition newRd = new ReportDefinition(); newRd.setEnabled(false); newRd.setName(rd); newRd.setLabel(rd); newRd.setOrganization(organization); newRd.setAmendable(true); newRd.setTimeScaleUnitType(TimeScaleUnit.DAY); newRd.setDuration(2); newRd.setReportFormatType(ReportFormatType.ADEERSPDF); newRd.setGroup(expeditedConfigProperty); newRd.setPhysicianSignOff(false); reportDefinitionDao.save(newRd); reportDefinitionsCreated.add(rd); } } gov.nih.nci.cabig.caaers.domain.RuleSet domainRuleSet = createOrFindRuleSet(ruleType, ruleLevel, organization, study, true); saveOrUpdateRuleSet(domainRuleSet, ruleSet); deployRuleSet(domainRuleSet.getRuleBindURI()); reportDefinitionsCreated.add(0, domainRuleSet.getRuleBindURI()); return reportDefinitionsCreated; } @Transactional public void saveOrUpdateRuleSet(gov.nih.nci.cabig.caaers.domain.RuleSet domainRuleSet, RuleSet ruleSet) { saveOrUpdateRuleSet(domainRuleSet); //add imports if necessary if (CollectionUtils.isEmpty(ruleSet.getImport())) { ruleSet.getImport().add("gov.nih.nci.cabig.caaers.domain.*"); } //correct package names RuleType ruleType = domainRuleSet.getRuleType(); RuleLevel ruleLevel = domainRuleSet.getRuleLevel(); Integer orgId = domainRuleSet.getOrganization() == null ? null : domainRuleSet.getOrganization().getId(); Integer studyId = domainRuleSet.getStudy() == null ? null : domainRuleSet.getStudy().getId(); String packageName = constructPackageName(domainRuleSet.getRuleType(), domainRuleSet.getRuleLevel(), orgId, studyId); ruleSet.setName(packageName); //correct subject String nciCode = domainRuleSet.getOrganization() == null ? "" : domainRuleSet.getOrganization().getNciInstituteCode(); String studyPrimaryId = domainRuleSet.getStudy() == null ? "" : domainRuleSet.getStudy().getPrimaryIdentifierValue(); String newSubject = constructSubject(ruleType, ruleLevel, nciCode, studyPrimaryId); ruleSet.setSubject(newSubject); //correct description ruleSet.setDescription(ruleType.getName()); List<Rule> rules = ruleSet.getRule(); // delete columns which are marked as delete . for (Rule rule : rules) { List<Column> colsToDelete = new ArrayList<Column>(); for (Column col : rule.getCondition().getColumn()) { if (col.isMarkedDelete()) colsToDelete.add(col); } if (!colsToDelete.isEmpty()) rule.getCondition().getColumn().removeAll(colsToDelete); } for (Rule rule : rules) { //add rule-id if it is empty if (rule.getId() == null) rule.setId("r-" + UUID.randomUUID().toString()); String categoryId = "0"; String expression = CaaersRuleUtil.fetchFieldExpression(rule, "term"); if (StringUtils.contains(expression, "ctepCode")) { //new pattern String termCtepCode = CaaersRuleUtil.fetchFieldValue(rule, "term"); if (termCtepCode != null) { String ctcVersion = "0"; if (domainRuleSet.getStudy() != null) { ctcVersion = domainRuleSet.getStudy().getCtcVersion() != null ? domainRuleSet.getStudy().getCtcVersion().getName() : "0"; } if (ctcVersion != null) { List<CtcTerm> terms = ctcTermDao.getByCtepCodeandVersion(termCtepCode, ctcVersion); if (terms != null && !terms.isEmpty()) { categoryId = terms.get(0).getCategory().getId() + ""; } } } } else { //old pattern String termName = CaaersRuleUtil.fetchFieldReadableValue(rule, "term"); String categoryName = CaaersRuleUtil.fetchFieldReadableValue(rule, "category"); if (StringUtils.isNotEmpty(termName)) { Integer ctcVersionId = null; if (domainRuleSet.getStudy() != null) { ctcVersionId = domainRuleSet.getStudy().getCtcVersion() != null ? domainRuleSet.getStudy().getCtcVersion().getId() : null; } List<CtcTerm> terms = ctcTermDao.getBySubname(new String[] { termName }, ctcVersionId, null); CtcTerm term = findTerm(terms, categoryName); if (term != null) { categoryId = term.getCategory().getId() + ""; CaaersRuleUtil.updateTermField(rule, term.getCtepCode()); } } } CaaersRuleUtil.updateCategoryField(rule, categoryId); replaceCommaSeperatedStringToList(rule.getCondition()); if (!hasFactResolverColumn(rule.getCondition())) rule.getCondition().getColumn().add(createCriteriaForFactResolver()); if (rule.getMetaData() == null) rule.setMetaData(new MetaData()); rule.getMetaData().setPackageName(packageName); rule.getMetaData().setDescription("Setting Description since its mandatory by JBoss Repository config"); if (ruleLevel != null) { String organizationName = (domainRuleSet.getOrganization() != null) ? StringEscapeUtils.escapeXml(domainRuleSet.getOrganization().getName()) : null; String sponsorName = null; String institutionName = null; if (ruleLevel.isInstitutionBased()) institutionName = organizationName; if (ruleLevel.isSponsorBased()) sponsorName = organizationName; String studyShortTitle = (domainRuleSet.getStudy() != null) ? domainRuleSet.getStudy().getShortTitle() : null; populateCategoryBasedColumns(rule, ruleLevel.getName(), sponsorName, institutionName, studyShortTitle); } } //save the rules in staging area. ruleEngineService.saveOrUpdateRuleSet(domainRuleSet.getRuleBindURI(), ruleSet); } private gov.nih.nci.cabig.caaers.domain.RuleSet saveOrUpdateRuleSet( gov.nih.nci.cabig.caaers.domain.RuleSet domainRuleSet) { if (log.isDebugEnabled()) log.debug("Before saving RuleSet : " + String.valueOf(domainRuleSet)); ValidationErrors errors = domainRuleSet.validate(); if (errors.hasErrors()) throw new CaaersSystemException("Unable to save domain RuleSet : " + String.valueOf(errors)); ruleSetDao.save(domainRuleSet); if (log.isDebugEnabled()) log.debug("After saving RuleSet : " + String.valueOf(domainRuleSet)); return domainRuleSet; } @Transactional(readOnly = true) public gov.nih.nci.cabig.caaers.domain.RuleSet createOrFindRuleSet(RuleType ruleType, RuleLevel ruleLevel, Organization organization, Study study, boolean enabled) { RuleSetQuery ruleSetQuery = new RuleSetQuery(); ruleSetQuery.filterByRuleType(ruleType); if (ruleLevel != null) ruleSetQuery.filterByRuleLevel(ruleLevel); if (organization != null) ruleSetQuery.filterByOrganizationId(organization.getId()); if (study != null) ruleSetQuery.filterByStudyId(study.getId()); List<gov.nih.nci.cabig.caaers.domain.RuleSet> existingRuleSets = (List<gov.nih.nci.cabig.caaers.domain.RuleSet>) ruleSetDao .search(ruleSetQuery); gov.nih.nci.cabig.caaers.domain.RuleSet domainRuleSet; if (!existingRuleSets.isEmpty()) { domainRuleSet = existingRuleSets.get(0); if (log.isDebugEnabled()) log.debug("Found Ruleset in the database [ruleType : " + String.valueOf(ruleType) + ", ruleLevel : " + String.valueOf(ruleLevel) + "Organization " + String.valueOf(organization) + ", study " + String.valueOf(study) + "]:" + String.valueOf(domainRuleSet)); } else { domainRuleSet = new gov.nih.nci.cabig.caaers.domain.RuleSet(); domainRuleSet.setRuleBindURI(CaaersRuleUtil.getRandomBindURI()); domainRuleSet.setRuleLevel(ruleLevel); domainRuleSet.setRuleType(ruleType); domainRuleSet.setStatus(gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_ENABLED); domainRuleSet.setOrganization(organization); domainRuleSet.setStudy(study); if (log.isDebugEnabled()) log.debug("Created new Ruleset [ruleType : " + String.valueOf(ruleType) + ", ruleLevel : " + String.valueOf(ruleLevel) + "Organization " + String.valueOf(organization) + ", study " + String.valueOf(study) + "]:" + String.valueOf(domainRuleSet)); } domainRuleSet.setStatus(enabled ? gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_ENABLED : gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_DISABLED); return domainRuleSet; } /** * This method will take care of reconciling the ruleset,by making sure that * 1. The ruleSet, has the correct package name * 2. The path-to-deploy is correct. * * Note: Backward compatiable with the old ruleset naming convention used. * @param ruleSet */ public void reconcileRuleSet(RuleSet ruleSet) { if (StringUtils.isBlank(ruleSet.getSubject())) return; String level = null; Organization org = null; Study study = null; String strOrgId = null; String strStudyId = null; String[] subjectParts = StringUtils.split(ruleSet.getSubject(), "||"); if (subjectParts.length >= 4) { //new pattern level = subjectParts[1]; String nciCode = null; String studyPrimaryId = null; if (level.equals(SPONSOR_DEFINED_STUDY_LEVEL) || level.equals(SPONSOR_LEVEL)) { nciCode = subjectParts[2].trim(); } if (level.equals(INSTITUTION_DEFINED_STUDY_LEVEL) || level.equals(INSTITUTIONAL_LEVEL)) { nciCode = subjectParts[3].trim(); } studyPrimaryId = subjectParts.length > 4 ? StringUtils.trimToNull(subjectParts[4]) : null; if (StringUtils.isNotBlank(nciCode)) org = organizationDao.getByNCIcode(nciCode); if (StringUtils.isNotBlank(studyPrimaryId)) { OrganizationAssignedIdentifier id = new OrganizationAssignedIdentifier(); id.setValue(studyPrimaryId); id.setType(OrganizationAssignedIdentifier.SPONSOR_IDENTIFIER_TYPE); study = studyDao.getByIdentifier(id); } } else { //old pattern String orgName = null; String studyShortTitle = null; if (StringUtils.equals(subjectParts[0], CategoryConfiguration.SPONSOR_DEFINED_STUDY_BASE.getDescription())) { level = SPONSOR_DEFINED_STUDY_LEVEL; orgName = subjectParts[1].trim(); studyShortTitle = subjectParts[2].trim(); } else if (StringUtils.equals(subjectParts[0], CategoryConfiguration.INSTITUTION_DEFINED_STUDY_BASE.getDescription())) { level = INSTITUTION_DEFINED_STUDY_LEVEL; orgName = subjectParts[1].trim(); studyShortTitle = subjectParts[2].trim(); } else if (StringUtils.equals(subjectParts[0], CategoryConfiguration.SPONSOR_BASE.getDescription())) { level = SPONSOR_LEVEL; orgName = subjectParts[1].trim(); } else if (StringUtils.equals(subjectParts[0], CategoryConfiguration.INSTITUTION_BASE.getDescription())) { level = INSTITUTIONAL_LEVEL; orgName = subjectParts[1].trim(); } if (StringUtils.isNotBlank(orgName)) org = organizationDao.getByName(orgName); if (StringUtils.isNotBlank(studyShortTitle)) study = studyDao.getByShortTitle(studyShortTitle); } //do validations - on organization if (StringUtils.equals(level, SPONSOR_LEVEL) || StringUtils.equals(level, INSTITUTIONAL_LEVEL) || StringUtils.equals(level, INSTITUTION_DEFINED_STUDY_LEVEL) || StringUtils.equals(level, SPONSOR_DEFINED_STUDY_LEVEL)) { if (org == null) throw new CaaersSystemException("RUL_011", "Unable to figureout the sponsor/institution"); } //do validation - study if (StringUtils.equals(level, INSTITUTION_DEFINED_STUDY_LEVEL) || StringUtils.equals(level, SPONSOR_DEFINED_STUDY_LEVEL)) { if (study == null) throw new CaaersSystemException("RUL_021", "Could not figure out the study"); } if (org != null) strOrgId = String.valueOf(org.getId()); if (study != null) strStudyId = String.valueOf(study.getId()); //update the package name on the ruleset RuleLevel ruleLevel = (StringUtils.isBlank(level) ? null : RuleLevel.getByName(level)); RuleType ruleType = RuleType.getByName(ruleSet.getDescription()); Integer orgId = (org != null) ? org.getId() : null; Integer studyId = study != null ? study.getId() : null; String newPackageName = constructPackageName(ruleType, ruleLevel, orgId, studyId); ruleSet.setName(newPackageName); //update the subject \ String nciCode = org == null ? "" : org.getNciInstituteCode(); String studyPrimaryId = study == null ? "" : study.getPrimaryIdentifierValue(); String newSubject = constructSubject(ruleType, ruleLevel, nciCode, studyPrimaryId); ruleSet.setSubject(newSubject); //update the path. String path = generatePath(level, ruleSet.getDescription(), org, org, study); for (Rule rule : ruleSet.getRule()) { List<Category> categories = rule.getMetaData().getCategory(); if (categories == null) { categories = new ArrayList<Category>(); rule.getMetaData().setCategory(categories); } if (categories.isEmpty()) { Category category = new Category(); category.setMetaData(new MetaData()); categories.add(category); } if (categories.get(0).getMetaData() == null) { categories.get(0).setMetaData(new MetaData()); } rule.getMetaData().getCategory().get(0).setPath(path); rule.getMetaData().getCategory().get(0).getMetaData() .setName(RuleUtil.getStringWithoutSpaces(ruleSet.getDescription())); } if (log.isDebugEnabled()) { log.debug("New Package Name :" + newPackageName); log.debug("New Subject :" + newSubject); log.debug("New Path :" + path); } } public String constructSubject(RuleType ruleType, RuleLevel ruleLevel, String nciCode, String studyPrimaryId) { StringBuilder sb = new StringBuilder(ruleType.getName()).append("||") .append(ruleLevel == null ? " " : ruleLevel.getName()).append("||") .append(StringUtils.isEmpty(nciCode) ? " " : nciCode).append("||") .append(StringUtils.isEmpty(nciCode) ? " " : nciCode).append("||") .append(StringUtils.isEmpty(studyPrimaryId) ? " " : studyPrimaryId); return sb.toString(); } /** * This method is used to unDeploy a ruleSet * * @param bindURI - The bind URI * @exception RemoteException */ @Transactional public void unDeployRuleSet(String bindURI) throws RemoteException { gov.nih.nci.cabig.caaers.domain.RuleSet domainRuleSet = ruleSetDao.getByBindURI(bindURI); if (domainRuleSet == null) throw new CaaersSystemException("Unable to find RuleSet having rulesBindURI:" + bindURI); ruleEngineService.undeployRuleSet(bindURI); domainRuleSet.setStatus(gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_DISABLED); ruleSetDao.save(domainRuleSet); } /** * Will remove the rule-set * @param bindURI */ @Transactional public void deleteRuleSet(String bindURI) { ruleEngineService.deleteRuleSet(bindURI); ruleSetDao.deleteRuleSet(bindURI); } /** * This method is used to deploy a ruleSet * * @param bindURI - The bind URI * @exception RemoteException */ @Transactional public void deployRuleSet(String bindURI) { gov.nih.nci.cabig.caaers.domain.RuleSet domainRuleSet = ruleSetDao.getByBindURI(bindURI); if (domainRuleSet == null) throw new CaaersSystemException("Unable to find RuleSet having rulesBindURI:" + bindURI); ruleEngineService.deployRuleSet(bindURI); domainRuleSet.setStatus(gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_ENABLED); ruleSetDao.save(domainRuleSet); } @Transactional(readOnly = true) public List<gov.nih.nci.cabig.caaers.domain.RuleSet> searchRuleSets(RuleSetQuery query) { return (List<gov.nih.nci.cabig.caaers.domain.RuleSet>) ruleSetDao.search(query); } /** * Will generate the path to which the rule should be deployed. * @param level - The level of the rule. * @param ruleSetName - The name of the rule. * @param sponsor - The sponsor organization * @param institution - The institution organization. * @param study - The study. * @return */ public String generatePath(String level, String ruleSetName, Organization sponsor, Organization institution, Study study) { StringBuilder path = new StringBuilder("/").append(CategoryConfiguration.CAAERS_BASE.getName()); if (StringUtils.equals(level, SPONSOR_LEVEL)) { path.append("/").append(CategoryConfiguration.SPONSOR_BASE.getName()).append("/") .append(modifyOrganizationName(sponsor.getId().toString())); } if (StringUtils.equals(level, INSTITUTIONAL_LEVEL)) { path.append("/").append(CategoryConfiguration.INSTITUTION_BASE.getName()).append("/") .append(modifyOrganizationName(institution.getId().toString())); } if (StringUtils.equals(level, SPONSOR_DEFINED_STUDY_LEVEL)) { path.append("/").append(CategoryConfiguration.SPONSOR_DEFINED_STUDY_BASE.getName()).append("/") .append(modifyOrganizationName(sponsor.getId().toString())).append("/") .append(modifyStudyName(study.getId().toString())); } if (StringUtils.equals(level, INSTITUTION_DEFINED_STUDY_LEVEL)) { path.append("/").append(CategoryConfiguration.INSTITUTION_DEFINED_STUDY_BASE.getName()).append("/") .append(modifyOrganizationName(institution.getId().toString())).append("/") .append(modifyStudyName(study.getId().toString())); } if (StringUtils.isNotEmpty(ruleSetName)) { path.append("/").append(RuleUtil.getStringWithoutSpaces(ruleSetName)); } return path.toString(); } private Column createCriteriaForFactResolver() { Column column = BRXMLHelper.newColumn(); column.setObjectType("com.semanticbits.rules.objectgraph.FactResolver"); column.setIdentifier("factResolver"); return column; } private boolean hasFactResolverColumn(Condition condition) { for (Column c : condition.getColumn()) { if (StringUtils.equals(c.getIdentifier(), "factResolver")) return true; } return false; } private void replaceCommaSeperatedStringToList(Condition condition) { for (Column col : condition.getColumn()) { if (CollectionUtils.isEmpty(col.getFieldConstraint())) continue; FieldConstraint fc = col.getFieldConstraint().get(0); if (CollectionUtils.isEmpty(fc.getLiteralRestriction())) continue; LiteralRestriction lr = fc.getLiteralRestriction().get(0); if (CollectionUtils.isEmpty(lr.getValue())) continue; String value = lr.getValue().get(0); if (StringUtils.contains(value, ",")) { List<String> values = CaaersRuleUtil.charSeparatedStringToStringList(value, ","); col.getFieldConstraint().get(0).getLiteralRestriction().get(0).setValue(values); } } } /** * Populates the category based columns in the rule. * @param rule * @param level * @param sponsorName * @param institutionName * @param studyShortTitle */ public void populateCategoryBasedColumns(Rule rule, String level, String sponsorName, String institutionName, String studyShortTitle) { if (SPONSOR_DEFINED_STUDY_LEVEL.equals(level)) { rule.getCondition().getColumn().add(createCriteriaForSponsor(sponsorName)); rule.getCondition().getColumn() .add(createCriteriaForStudy(studyShortTitle, SPONSOR_DEFINED_STUDY_LEVEL)); } else if (SPONSOR_LEVEL.equals(level)) { rule.getCondition().getColumn().add(createCriteriaForSponsor(sponsorName)); } else if (INSTITUTIONAL_LEVEL.equals(level)) { rule.getCondition().getColumn().add(createCriteriaForInstitute(institutionName)); } else if (INSTITUTION_DEFINED_STUDY_LEVEL.equals(level)) { rule.getCondition().getColumn().add(createCriteriaForInstitute(institutionName)); rule.getCondition().getColumn() .add(createCriteriaForStudy(studyShortTitle, INSTITUTION_DEFINED_STUDY_LEVEL)); } } /* * THis method is used to create criteria for sponsor based on the sponsor name */ private Column createCriteriaForSponsor(String criteriaValue) { Column column = BRXMLHelper.newColumn(); column.setObjectType(gov.nih.nci.cabig.caaers.domain.Study.class.getName()); column.setIdentifier("studySDO"); criteriaValue = StringEscapeUtils.escapeXml(criteriaValue); String expression = "factResolver.assertFact(studySDO," + "\"gov.nih.nci.cabig.caaers.domain.Organization" + "\"," + "\"escapedXmlName" + "\"," + "\"" + criteriaValue + "\",\"==\"" + ")"; column.setExpression(expression); List<FieldConstraint> fieldConstraints = new ArrayList<FieldConstraint>(); FieldConstraint fieldConstraint = new FieldConstraint(); fieldConstraint.setFieldName(getFieldNameBasedOnLevel(SPONSOR_LEVEL)); fieldConstraints.add(fieldConstraint); ArrayList<LiteralRestriction> literalRestrictions = new ArrayList<LiteralRestriction>(); LiteralRestriction literalRestriction = new LiteralRestriction(); literalRestriction.setEvaluator("=="); literalRestriction.getValue().add(criteriaValue); literalRestrictions.add(literalRestriction); fieldConstraint.setLiteralRestriction(literalRestrictions); column.setFieldConstraint(fieldConstraints); return column; } /* * This method creates criteria column with study short title as the criteria */ private Column createCriteriaForStudy(String criteriaValue, String level) { Column column = BRXMLHelper.newColumn(); column.setObjectType(gov.nih.nci.cabig.caaers.domain.Study.class.getName()); column.setIdentifier("studySDO"); criteriaValue = StringEscapeUtils.escapeXml(criteriaValue); String expression = "factResolver.assertFact(studySDO,null," + "\"escapeXmlShortTitle" + "\"," + "\"" + criteriaValue + "\",\"==\"" + ")"; column.setExpression(expression); List<FieldConstraint> fieldConstraints = new ArrayList<FieldConstraint>(); FieldConstraint fieldConstraint = new FieldConstraint(); fieldConstraint.setFieldName(getFieldNameBasedOnLevel(level)); fieldConstraints.add(fieldConstraint); ArrayList<LiteralRestriction> literalRestrictions = new ArrayList<LiteralRestriction>(); LiteralRestriction literalRestriction = new LiteralRestriction(); literalRestriction.setEvaluator("=="); literalRestriction.getValue().add(criteriaValue); literalRestrictions.add(literalRestriction); fieldConstraint.setLiteralRestriction(literalRestrictions); column.setFieldConstraint(fieldConstraints); return column; } /* * This method creates criteria column with institute name as the criteria */ private Column createCriteriaForInstitute(String criteriaValue) { Column column = BRXMLHelper.newColumn(); column.setObjectType(gov.nih.nci.cabig.caaers.domain.Organization.class.getName()); column.setIdentifier("organizationSDO"); String expression = "factResolver.assertFact(organizationSDO,null," + "\"escapedXmlName" + "\"," + "\"" + criteriaValue + "\",\"==\"" + ")"; column.setExpression(expression); List<FieldConstraint> fieldConstraints = new ArrayList<FieldConstraint>(); FieldConstraint fieldConstraint = new FieldConstraint(); fieldConstraint.setFieldName(getFieldNameBasedOnLevel(INSTITUTIONAL_LEVEL)); fieldConstraints.add(fieldConstraint); ArrayList<LiteralRestriction> literalRestrictions = new ArrayList<LiteralRestriction>(); LiteralRestriction literalRestriction = new LiteralRestriction(); literalRestriction.setEvaluator("=="); literalRestriction.getValue().add(criteriaValue); literalRestrictions.add(literalRestriction); fieldConstraint.setLiteralRestriction(literalRestrictions); column.setFieldConstraint(fieldConstraints); return column; } public String constructPackageName(RuleType ruleType, RuleLevel ruleLevel, Integer orgId, Integer studyId) { StringBuilder sb = new StringBuilder(ruleType.getPackageName()); if (ruleLevel != null) sb.append(".").append(ruleLevel.getPackageName()); if (orgId != null) sb.append(".ORG_").append(orgId); if (studyId != null) sb.append(".STU_").append(studyId); sb.append(".").append(CaaersRuleUtil.getStringWithoutSpaces(ruleType.getName())); if (log.isDebugEnabled()) log.debug("New Package : " + sb.toString()); return sb.toString(); } /** * This method will prefix "ORG_" to the organization name. * @param orgName * @return */ private String modifyOrganizationName(String orgName) { return "ORG_" + orgName; } /** * This method will prefix "STU_" to the study name. * @param studyName * @return */ private String modifyStudyName(String studyName) { return "STU_" + studyName; } /** * Will return the RuleType from package name. * @param packageName * @return */ public RuleType parseRuleType(String packageName) { if (StringUtils.contains(packageName, "sae_reporting_rules")) return RuleType.REPORT_SCHEDULING_RULES; if (StringUtils.contains(packageName, "field_rules")) return RuleType.FIELD_LEVEL_RULES; if (StringUtils.contains(packageName, "mandatory_sections_rules")) return RuleType.MANDATORY_SECTIONS_RULES; if (StringUtils.contains(packageName, "safety_signalling_rules")) return RuleType.SAFETY_SIGNALLING_RULES; return null; } /** * Will parse and return the level, given a package name. * @param packageName * @return */ public RuleLevel parseRuleLevel(String packageName) { String prefix = StringUtils.substringBefore(packageName, ".ORG_"); if (StringUtils.equals(prefix, "gov.nih.nci.cabig.caaers.rules.sponsor.study")) return RuleLevel.SponsorDefinedStudy; if (StringUtils.equals(prefix, "gov.nih.nci.cabig.caaers.rules.sponsor")) return RuleLevel.Sponsor; if (StringUtils.equals(prefix, "gov.nih.nci.cabig.caaers.rules.institution.study")) return RuleLevel.InstitutionDefinedStudy; if (StringUtils.equals(prefix, "gov.nih.nci.cabig.caaers.rules.institution")) return RuleLevel.Institution; return null; } /** * Will return the organization Id (Sponsor/Institution) id * @param packageName * @return */ public String parseOrganizationId(String packageName) { String s = StringUtils.substringAfter(packageName, ".ORG_"); String orgId = StringUtils.substringBefore(s, "."); return orgId; } /** * Will return the study Id * @param packageName * @return */ public String parseStudyId(String packageName) { String s = StringUtils.substringAfter(packageName, ".STU_"); String studyId = StringUtils.substringBefore(s, "."); return studyId; } /** * Will clean the ruleset retrieved from authoring service, by removing elements like * a. StudySDO * b. OrganizationSDO * c. FactResolver * d. EvaluationResult. * @param ruleSet */ public void cleanRuleSet(RuleSet ruleSet) { if (ruleSet == null || ruleSet.getRule() == null || ruleSet.getRule().size() <= 0) return; for (Rule rule : ruleSet.getRule()) { List<Column> toRemove = new ArrayList<Column>(); for (Column c : rule.getCondition().getColumn()) { if (ArrayUtils.contains(columnsToTrash, c.getIdentifier())) toRemove.add(c); } rule.getCondition().getColumn().removeAll(toRemove); } } /** * Populates the ReadableRule and Readable actions in the given ruleset. * @param ruleSet - A cleaned ruleset */ //BJ : refactored, extracted from ReviewTab.referenceData():Map public void makeRuleSetReadable(RuleSet ruleSet) { if (ruleSet == null || ruleSet.getRule() == null || ruleSet.getRule().size() <= 0) return; int i = 1; for (Rule rule : ruleSet.getRule()) { if (rule.isMarkedDelete()) continue; //add the readable rules (LHS) ReadableRule readableRule = new ReadableRule(); List<String> readableRuleLine = new ArrayList<String>(); List<String> readableActions = new ArrayList<String>(); readableRuleLine.add("If"); if (rule.getCondition() != null && rule.getCondition().getColumn() != null) { int cCount = 0; for (Column column : rule.getCondition().getColumn()) { if (StringUtils.equals(column.getExpression(), "getPrimaryFundingSponsorOrganization().getName()") || StringUtils.equals(column.getObjectType(), "gov.nih.nci.cabig.caaers.rules.common.AdverseEventEvaluationResult") || StringUtils.equals(column.getObjectType(), "com.semanticbits.rules.impl.RuleEvaluationResult") || BooleanUtils.isTrue(column.isMarkedDelete())) continue; if (cCount > 0) readableRuleLine.add("And"); readableRuleLine.add(" " + RuleUtil.readableColumn(column)); cCount++; } } //add the readable actions (RHS) if (ruleSet.getDescription().equals(RuleType.MANDATORY_SECTIONS_RULES.getName())) { for (String action : rule.getAction()) readableActions.add(ExpeditedReportSection.valueOf(action).getDisplayName()); } else if (ruleSet.getDescription().equals(RuleType.FIELD_LEVEL_RULES.getName())) { for (String action : rule.getAction()) readableActions.add(Mandatory.valueOf(action).getDisplayName()); } else { readableActions.addAll(rule.getAction()); } rule.getMetaData().setName("Rule-" + i); readableRule.setLine(readableRuleLine); rule.setReadableRule(readableRule); rule.setReadableAction(readableActions); i++; } } /* * This method returns the attribute to be used for creating the criteria */ private String getFieldNameBasedOnLevel(String level) { String fieldName = "shortTitle"; if (SPONSOR_LEVEL.equals(level)) { fieldName = "primarySponsorCode"; } else if (INSTITUTIONAL_LEVEL.equals(level)) { fieldName = "name"; } else if (SPONSOR_DEFINED_STUDY_LEVEL.equals(level)) { fieldName = "shortTitle"; } else if (INSTITUTION_DEFINED_STUDY_LEVEL.equals(level)) { fieldName = "shortTitle"; } return fieldName; } /* * * @author Ion C. Olaru * Get the fields involved in this particular ruleSet * @param rs - the RuleSet to be evaluated * @param objectIdentifier - object type to consider, ex: adverseEvent * @return - List of String containin the field involved in this ruleSet * */ private List<String> getRuleableFields(RuleSet rs, String objectIdentifier) { List<String> fields = new ArrayList<String>(); if (rs == null) return fields; log.debug(String.format("Get the ruleable fields from RuleSet: %s", rs.getName())); // if(log.isInfoEnabled()) log.info(String.format("Get the ruleable fields from RuleSet: %s", rs.getName())); for (Rule r : rs.getRule()) { Condition condition = r.getCondition(); for (Column c : condition.getColumn()) { if (c.getIdentifier().equals(objectIdentifier)) { for (FieldConstraint fc : c.getFieldConstraint()) { fields.add(fc.getFieldName()); } } } } return fields; } /* * Lists attributes of AdverseEvent used in SAE rules. * * @param r - the aeReport to be evaluated * @return - List of String containin the field involved in the ruleSets * */ @Transactional(readOnly = true) public List<String> getFieldsUsedInSAERules(ExpeditedAdverseEventReport r) throws Exception { List<String> fields = new ArrayList<String>(); Study s = r.getStudy(); for (RuleSet rs : getRuleSetsByExpeditedReport(r)) { fields.addAll(getRuleableFields(rs, "adverseEvent")); } return fields; } /* * * @author Ion C. Olaru * Get the List of rulSets applicable for an AEReport * The result should contain Sponsor level + Institution level RuleSets * Sponsor level RuleSet contains either Sponsor Study specific rules if available, otherwise it takes Sponsor rules * Institution level RuleSet contains either Institution Study specific rules if available, otherwise it takes Institution rules * @param r - the aeReport to be evaluated * @return - List of RuleSets * */ private List<RuleSet> getRuleSetsByExpeditedReport(ExpeditedAdverseEventReport aeReport) throws Exception { List<RuleSet> rs = new ArrayList<RuleSet>(); RuleSet r1 = null; //checking for sponsor + study RuleSetQuery sponsorStudyQuery = new RuleSetQuery(); sponsorStudyQuery .filterByOrganizationId(aeReport.getStudy().getPrimaryFundingSponsorOrganization().getId()); sponsorStudyQuery.filterByStudyId(aeReport.getStudy().getId()); sponsorStudyQuery.filterByRuleType(RuleType.REPORT_SCHEDULING_RULES); sponsorStudyQuery.filterByRuleLevel(RuleLevel.SponsorDefinedStudy); sponsorStudyQuery.filterByStatus(gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_ENABLED); List<gov.nih.nci.cabig.caaers.domain.RuleSet> sponsorStudyruleSets = searchRuleSets(sponsorStudyQuery); if (!sponsorStudyruleSets.isEmpty()) { r1 = getRuleSet(sponsorStudyruleSets.get(0).getRuleBindURI()); } //checking sponsor if (r1 == null) { RuleSetQuery sponsorQuery = new RuleSetQuery(); sponsorQuery.filterByOrganizationId(aeReport.getStudy().getPrimaryFundingSponsorOrganization().getId()); sponsorQuery.filterByRuleType(RuleType.REPORT_SCHEDULING_RULES); sponsorQuery.filterByRuleLevel(RuleLevel.Sponsor); sponsorQuery.filterByStatus(gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_ENABLED); List<gov.nih.nci.cabig.caaers.domain.RuleSet> sponsorRuleSets = searchRuleSets(sponsorQuery); if (!sponsorRuleSets.isEmpty()) { r1 = getRuleSet(sponsorRuleSets.get(0).getRuleBindURI()); } } if (r1 != null) rs.add(r1); r1 = null; //find institution based or institution based study rule sets. RuleSetQuery institutionStudyQuery = new RuleSetQuery(); institutionStudyQuery.filterByOrganizationId(aeReport.getStudySite().getOrganization().getId()); institutionStudyQuery.filterByStudyId(aeReport.getStudy().getId()); institutionStudyQuery.filterByRuleType(RuleType.REPORT_SCHEDULING_RULES); institutionStudyQuery.filterByRuleLevel(RuleLevel.InstitutionDefinedStudy); institutionStudyQuery.filterByStatus(gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_ENABLED); List<gov.nih.nci.cabig.caaers.domain.RuleSet> institutionStudyruleSets = searchRuleSets( institutionStudyQuery); if (!institutionStudyruleSets.isEmpty()) { r1 = getRuleSet(institutionStudyruleSets.get(0).getRuleBindURI()); } //checking sponsor if (r1 == null) { RuleSetQuery institutionQuery = new RuleSetQuery(); institutionQuery.filterByOrganizationId(aeReport.getStudySite().getOrganization().getId()); institutionQuery.filterByRuleType(RuleType.REPORT_SCHEDULING_RULES); institutionQuery.filterByRuleLevel(RuleLevel.Institution); institutionQuery.filterByStatus(gov.nih.nci.cabig.caaers.domain.RuleSet.STATUS_ENABLED); List<gov.nih.nci.cabig.caaers.domain.RuleSet> institutionRuleSets = searchRuleSets(institutionQuery); if (!institutionRuleSets.isEmpty()) { r1 = getRuleSet(institutionRuleSets.get(0).getRuleBindURI()); } } if (r1 != null) rs.add(r1); return rs; } public void setReportDefinitionDao(ReportDefinitionDao reportDefinitionDao) { this.reportDefinitionDao = reportDefinitionDao; } public void setOrganizationDao(OrganizationDao organizationDao) { this.organizationDao = organizationDao; } /** * Retrieves the ruleset configured for Input fields * @return */ @Transactional(readOnly = true) public RuleSet getFieldRuleSet() { RuleSetQuery ruleSetQuery = new RuleSetQuery(); ruleSetQuery.filterByRuleType(RuleType.FIELD_LEVEL_RULES); List<gov.nih.nci.cabig.caaers.domain.RuleSet> ruleSets = searchRuleSets(ruleSetQuery); if (!ruleSets.isEmpty()) { return getRuleSet(ruleSets.get(0).getRuleBindURI()); } return null; } /** * Will return all the rule-set objects availbalbe in caAERS */ @Transactional(readOnly = true) public List<gov.nih.nci.cabig.caaers.domain.RuleSet> getAllRuleSets() { return (List<gov.nih.nci.cabig.caaers.domain.RuleSet>) ruleSetDao.search(new RuleSetQuery()); } private CtcTerm findTerm(List<CtcTerm> terms, String categoryName) { if (terms == null || terms.isEmpty()) return null; if (StringUtils.isEmpty(categoryName)) return terms.get(0); if (terms.size() == 1) return terms.get(0); String c = StringUtils.replaceOnce(categoryName, "...", ""); for (CtcTerm term : terms) { if (StringUtils.containsIgnoreCase(term.getCategory().getName(), c)) return term; } return null; } // public RulesEngineService getRuleEngineService() { return ruleEngineService; } public void setRuleEngineService(RulesEngineService ruleEngineService) { this.ruleEngineService = ruleEngineService; } public ReportDefinitionDao getReportDefinitionDao() { return reportDefinitionDao; } public OrganizationDao getOrganizationDao() { return organizationDao; } public ConfigPropertyDao getConfigPropertyDao() { return configPropertyDao; } public void setConfigPropertyDao(ConfigPropertyDao configPropertyDao) { this.configPropertyDao = configPropertyDao; } public StudyDao getStudyDao() { return studyDao; } public void setStudyDao(StudyDao studyDao) { this.studyDao = studyDao; } public RuleSetDao getRuleSetDao() { return ruleSetDao; } public void setRuleSetDao(RuleSetDao ruleSetDao) { this.ruleSetDao = ruleSetDao; } public void setCtcTermDao(CtcTermDao ctcTermDao) { this.ctcTermDao = ctcTermDao; } }