package org.akaza.openclinica.validator.rule.action; import java.text.MessageFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.ResourceBundle; import org.akaza.openclinica.bean.managestudy.StudyBean; import org.akaza.openclinica.bean.managestudy.StudyEventDefinitionBean; import org.akaza.openclinica.dao.hibernate.StudyDao; import org.akaza.openclinica.dao.managestudy.StudyDAO; import org.akaza.openclinica.domain.rule.AuditableBeanWrapper; import org.akaza.openclinica.domain.rule.RuleSetBean; import org.akaza.openclinica.domain.rule.action.EventActionBean; import org.akaza.openclinica.domain.rule.action.PropertyBean; import org.akaza.openclinica.domain.rule.expression.Context; import org.akaza.openclinica.domain.rule.expression.ExpressionBean; import org.akaza.openclinica.domain.rule.expression.ExpressionObjectWrapper; import org.akaza.openclinica.domain.rule.expression.ExpressionProcessor; import org.akaza.openclinica.domain.rule.expression.ExpressionProcessorFactory; import org.akaza.openclinica.exception.OpenClinicaSystemException; import org.akaza.openclinica.service.rule.expression.ExpressionService; import org.springframework.validation.Errors; import org.springframework.validation.Validator; import javax.sql.DataSource; public class EventActionValidator implements Validator { DataSource dataSource; ExpressionService expressionService; AuditableBeanWrapper<RuleSetBean> ruleSetBeanWrapper; ResourceBundle respage; public static final String VALUE_EXPRESSION_DATE_FORMAT = "yyyy-MM-dd"; public static final String BRACKETS_AND_CONTENTS = ".*\\[(END|ALL|[1-9]\\d*)\\]"; private final String REPEATING = ".*\\[(END|ALL|[1-9]\\d*)\\]"; public EventActionValidator(DataSource dataSource) { this.dataSource = dataSource; } /** * This Validator validates just Person instances */ public boolean supports(Class clazz) { return EventActionBean.class.equals(clazz); } public void validate(Object obj, Errors e) { EventActionBean eventActionBean = (EventActionBean) obj; validateOidInAction(eventActionBean.getOc_oid_reference(), e); boolean foundStartDate=false; for (int i = 0; i < eventActionBean.getProperties().size(); i++) { PropertyBean propertyBean = eventActionBean.getProperties().get(i); if (!foundStartDate && propertyBean.getProperty().equals("STARTDATE")) { foundStartDate=true; if (!isEventActionValueExpressionValid(propertyBean, ruleSetBeanWrapper)) getRuleSetBeanWrapper().error(createError("OCRERR_0035")); } //Throw error for getting more than one STARTDATE property else if (propertyBean.getProperty().equals("STARTDATE") && foundStartDate) getRuleSetBeanWrapper().error(createError("OCRERR_0037")); //Throw error for unknown Property value else getRuleSetBeanWrapper().error(createError("OCRERR_0036")); } } public void validateOidInAction(String oid, Errors e) { try { if (oid.contains(".") ||oid.contains("[ALL]")) { getRuleSetBeanWrapper().error(createError("OCRERR_0041", new String[]{oid})); return; } StudyEventDefinitionBean studyEventBean = getExpressionService().getStudyEventDefinitionFromExpressionForEventScheduling(oid,true); if (studyEventBean == null) { getRuleSetBeanWrapper().error(createError("OCRERR_0019", new String[]{oid})); return; } if (oid.matches(REPEATING) && !studyEventBean.isRepeating()) { getRuleSetBeanWrapper().error(createError("OCRERR_0039", new String[]{oid})); //throw new OpenClinicaSystemException("OCRERR_0039", new String[] { oid }); return; } } catch (OpenClinicaSystemException ose) { getRuleSetBeanWrapper().error(createError("OCRERR_0019", new String[]{oid})); } } private boolean isEventActionValueExpressionValid(PropertyBean property, AuditableBeanWrapper<RuleSetBean> ruleSetBeanWrapper) { StudyDAO studyDAO = new StudyDAO<String, ArrayList>(getDataSource()); StudyBean study = (StudyBean) studyDAO.findByPK(ruleSetBeanWrapper.getAuditableBean().getStudyId()); ExpressionBean expressionBean = isExpressionValid(property.getValueExpression(), ruleSetBeanWrapper); ExpressionObjectWrapper eow = new ExpressionObjectWrapper(dataSource,study, expressionBean, ruleSetBeanWrapper.getAuditableBean(), ExpressionObjectWrapper.CONTEXT_VALUE_EXPRESSION); ExpressionProcessor ep = ExpressionProcessorFactory.createExpressionProcessor(eow); ep.setRespage(respage); String errorString = ep.isRuleExpressionValid(); if (errorString != null) { ruleSetBeanWrapper.error(errorString); return false; } //Verify expression generates a valid date string. try { SimpleDateFormat df = new SimpleDateFormat(VALUE_EXPRESSION_DATE_FORMAT); df.setLenient(false); String valueExpression = ep.testEvaluateExpression(); Date valueExpressionDate = df.parse(valueExpression); // simpledateformat.parse will accept any date as long as it's in the format // you defined, it simply rolls dates over, for example, december 32 // becomes jan 1 and december 0 becomes november 30 // This statement will make sure that once the string // has been checked for proper formatting that the date is still the // date that was entered, if it's not, we assume that the date is invalid if (!df.format(valueExpressionDate).equals(valueExpression)) { return false; } } catch (ParseException ex) { return false; } return true; } private ExpressionBean isExpressionValid(ExpressionBean expressionBean, AuditableBeanWrapper<?> beanWrapper) { if (expressionBean.getContextName() == null && expressionBean.getContext() == null) { expressionBean.setContext(Context.OC_RULES_V1); } if (expressionBean.getContextName() != null && expressionBean.getContext() == null) { beanWrapper.warning(createError("OCRERR_0029")); expressionBean.setContext(Context.OC_RULES_V1); } return expressionBean; } private String createError(String key) { String[] arguments = {}; return createError(key,arguments); } private String createError(String key, String[] arguments) { MessageFormat mf = new MessageFormat(""); mf.applyPattern(respage.getString(key)); return key + ": " + mf.format(arguments); } public ExpressionService getExpressionService() { return expressionService; } public void setExpressionService(ExpressionService expressionService) { this.expressionService = expressionService; } public AuditableBeanWrapper<RuleSetBean> getRuleSetBeanWrapper() { return ruleSetBeanWrapper; } public void setRuleSetBeanWrapper(AuditableBeanWrapper<RuleSetBean> ruleSetBeanWrapper) { this.ruleSetBeanWrapper = ruleSetBeanWrapper; } public ResourceBundle getRespage() { return respage; } public void setRespage(ResourceBundle respage) { this.respage = respage; } public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } }