package org.akaza.openclinica.validator.rule.action;
import org.akaza.openclinica.bean.admin.CRFBean;
import org.akaza.openclinica.bean.core.NullValue;
import org.akaza.openclinica.bean.core.ResponseType;
import org.akaza.openclinica.bean.managestudy.EventDefinitionCRFBean;
import org.akaza.openclinica.bean.managestudy.StudyEventDefinitionBean;
import org.akaza.openclinica.bean.submit.ItemBean;
import org.akaza.openclinica.bean.submit.ItemFormMetadataBean;
import org.akaza.openclinica.bean.submit.ResponseOptionBean;
import org.akaza.openclinica.dao.admin.CRFDAO;
import org.akaza.openclinica.dao.managestudy.EventDefinitionCRFDAO;
import org.akaza.openclinica.dao.managestudy.StudyEventDefinitionDAO;
import org.akaza.openclinica.dao.submit.ItemDAO;
import org.akaza.openclinica.dao.submit.ItemFormMetadataDAO;
import org.akaza.openclinica.domain.rule.RuleSetBean;
import org.akaza.openclinica.domain.rule.action.InsertActionBean;
import org.akaza.openclinica.domain.rule.action.PropertyBean;
import org.akaza.openclinica.domain.rule.expression.Context;
import org.akaza.openclinica.exception.OpenClinicaSystemException;
import org.akaza.openclinica.logic.expressionTree.ExpressionTreeHelper;
import org.akaza.openclinica.service.rule.expression.ExpressionService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.sql.DataSource;
public class InsertActionValidator implements Validator {
ItemDAO itemDAO;
ItemFormMetadataDAO itemFormMetadataDAO;
EventDefinitionCRFDAO eventDefinitionCRFDAO;
StudyEventDefinitionDAO studyEventDefinitionDAO;
CRFDAO crfDAO;
DataSource dataSource;
EventDefinitionCRFBean eventDefinitionCRFBean;
ExpressionService expressionService;
RuleSetBean ruleSetBean;
public InsertActionValidator(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* This Validator validates just Person instances
*/
public boolean supports(Class clazz) {
return InsertActionBean.class.equals(clazz);
}
public void validateOidInPropertyBean(PropertyBean propertyBean, Errors e, String p) {
if (getExpressionService().isExpressionPartial(getRuleSetBean().getTarget().getValue())) {
if (getExpressionService().getExpressionSize(propertyBean.getOid()).intValue() > 3) {
e.rejectValue(p + "oid", "oid.invalid", "OID: " + propertyBean.getOid() + " is Invalid.");
}
try {
getExpressionService().isExpressionValid(propertyBean.getOid());
} catch (OpenClinicaSystemException ose) {
e.rejectValue(p + "oid", "oid.invalid", "OID: " + propertyBean.getOid() + " is Invalid.");
}
// Use OID in destinationProperty to get CRF
CRFBean destinationPropertyOidCrf = getExpressionService().getCRFFromExpression(propertyBean.getOid());
if (destinationPropertyOidCrf == null) {
ItemBean item = getExpressionService().getItemBeanFromExpression(propertyBean.getOid());
destinationPropertyOidCrf = getCrfDAO().findByItemOid(item.getOid());
}
// Use Target get CRF
CRFBean targetCrf = getExpressionService().getCRFFromExpression(getRuleSetBean().getTarget().getValue());
if (targetCrf == null) {
ItemBean item = getExpressionService().getItemBeanFromExpression(getRuleSetBean().getTarget().getValue());
targetCrf = getCrfDAO().findByItemOid(item.getOid());
}
// Get All event definitions the selected CRF belongs to
List<StudyEventDefinitionBean> destinationPropertyStudyEventDefinitions = getStudyEventDefinitionDAO().findAllByCrf(destinationPropertyOidCrf);
List<StudyEventDefinitionBean> targetStudyEventDefinitions = getStudyEventDefinitionDAO().findAllByCrf(targetCrf);
Collection intersection = CollectionUtils.intersection(destinationPropertyStudyEventDefinitions, targetStudyEventDefinitions);
if (intersection.size() == 0) {
e.rejectValue(p + "oid", "oid.invalid", "OID: " + propertyBean.getOid() + " is Invalid.");
}
} else {
String expression = getExpressionService().constructFullExpressionIfPartialProvided(propertyBean.getOid(), getRuleSetBean().getTarget().getValue());
ItemBean item = getExpressionService().getItemBeanFromExpression(expression);
if (!getExpressionService().isInsertActionExpressionValid(propertyBean.getOid(), getRuleSetBean(), 3) || item == null) {
e.rejectValue(p + "oid", "oid.invalid", "OID: " + propertyBean.getOid() + " is Invalid.");
}
}
}
public void validateValueExpressionInPropertyBean(PropertyBean propertyBean, Errors e, String p) {
if (getExpressionService().isExpressionPartial(getRuleSetBean().getTarget().getValue())) {
if (getExpressionService().getExpressionSize(propertyBean.getValueExpression().getValue()).intValue() > 2) {
e.rejectValue(p + "valueExpression", "valueExpression.invalid", "Value provided for ValueExpression is Invalid");
}
try {
getExpressionService().isExpressionValid(propertyBean.getValueExpression().getValue());
} catch (OpenClinicaSystemException ose) {
e.rejectValue(p + "valueExpression", "valueExpression.invalid", "Value provided for ValueExpression is Invalid");
}
// Use ValueExression in destinationProperty to get CRF
ItemBean item = getExpressionService().getItemBeanFromExpression(propertyBean.getValueExpression().getValue());
if (item == null) return;
CRFBean destinationPropertyValueExpressionCrf = getCrfDAO().findByItemOid(item.getOid());
// Use Target to get CRF
CRFBean targetCrf = getExpressionService().getCRFFromExpression(getRuleSetBean().getTarget().getValue());
if (targetCrf == null) {
ItemBean targetItem = getExpressionService().getItemBeanFromExpression(getRuleSetBean().getTarget().getValue());
targetCrf = getCrfDAO().findByItemOid(targetItem.getOid());
}
if (destinationPropertyValueExpressionCrf.getId() != targetCrf.getId()) {
e.rejectValue(p + "valueExpression", "valueExpression.invalid", "Value provided for ValueExpression is Invalid");
}
} else {
String valueExpression =
getExpressionService().constructFullExpressionIfPartialProvided(propertyBean.getValueExpression().getValue(),
getRuleSetBean().getTarget().getValue());
ItemBean item = getExpressionService().getItemBeanFromExpression(valueExpression);
if (!getExpressionService().isExpressionValid(propertyBean.getValueExpression().getValue(), getRuleSetBean(), 2) || item == null) {
e.rejectValue(p + "valueExpression", "valueExpression.invalid", "Value provided for ValueExpression is Invalid");
}
}
}
public void validate(Object obj, Errors e) {
InsertActionBean insertActionBean = (InsertActionBean) obj;
for (int i = 0; i < insertActionBean.getProperties().size(); i++) {
String p = "properties[" + i + "].";
PropertyBean propertyBean = insertActionBean.getProperties().get(i);
ValidationUtils.rejectIfEmpty(e, p + "oid", "oid.empty");
validateOidInPropertyBean(propertyBean, e, p);
if (propertyBean.getValueExpression() != null && propertyBean.getValueExpression().getValue() != null
&& propertyBean.getValueExpression().getValue().length() != 0) {
String expressionContextName = propertyBean.getValueExpression().getContextName();
Context context = expressionContextName != null ? Context.getByName(expressionContextName) : Context.OC_RULES_V1;
propertyBean.getValueExpression().setContext(context);
validateValueExpressionInPropertyBean(propertyBean, e, p);
} else {
if (propertyBean.getValue() == null || propertyBean.getValue().length() == 0) {
ValidationUtils.rejectIfEmpty(e, p + "value", "value.empty");
} else {
checkValidity(getExpressionService().getItemBeanFromExpression(propertyBean.getOid()), propertyBean.getValue(), p, e);
}
}
}
}
@SuppressWarnings("unchecked")
private void checkValidity(ItemBean itemBean, String value, String index, Errors e) {
Boolean result = false;
List<ItemFormMetadataBean> itemFormMetadataBeans = getItemFormMetadataDAO().findAllByItemId(itemBean.getId());
for (ItemFormMetadataBean itemFormMetadataBean : itemFormMetadataBeans) {
if (itemFormMetadataBean.getResponseSet().getResponseType().equals(ResponseType.RADIO)
|| itemFormMetadataBean.getResponseSet().getResponseType().equals(ResponseType.SELECT)) {
if (matchValueWithOptions(value, itemFormMetadataBean.getResponseSet().getOptions()) != null) {
result = true;
break;
}
}
// TODO: check Null Value logic based on not event definition crf being selected
if (itemFormMetadataBean.getResponseSet().getResponseType().equals(ResponseType.CHECKBOX)
|| itemFormMetadataBean.getResponseSet().getResponseType().equals(ResponseType.SELECTMULTI)) {
if (getEventDefinitionCRFBean() == null) {
result = true;
break;
}
if (matchValueWithManyOptions(value, itemFormMetadataBean.getResponseSet().getOptions()) != null) {
result = true;
break;
}
}
// TODO: check Null Value logic based on not event definition crf being selected
if (itemFormMetadataBean.getResponseSet().getResponseType().equals(ResponseType.TEXT)
|| itemFormMetadataBean.getResponseSet().getResponseType().equals(ResponseType.TEXTAREA)) {
if (getEventDefinitionCRFBean() == null) {
int errorCount = e.getErrorCount();
checkValidityBasedOnDataType(itemBean, value, index, e);
if (e.getErrorCount() == errorCount) {
result = true;
break;
}
} else if (checkValidityBasedonNullValues(value, index, e)) {
result = true;
break;
} else {
int errorCount = e.getErrorCount();
checkValidityBasedOnDataType(itemBean, value, index, e);
if (e.getErrorCount() == errorCount) {
result = true;
break;
}
}
}
if (itemFormMetadataBean.getResponseSet().getResponseType().equals(ResponseType.CALCULATION)
|| itemFormMetadataBean.getResponseSet().getResponseType().equals(ResponseType.GROUP_CALCULATION)) {
result = false;
break;
}
}
if (!result) {
e.rejectValue(index + "value", "value.invalid");
}
}
private String matchValueWithOptions(String value, List<ResponseOptionBean> options) {
String returnedValue = null;
if (!options.isEmpty()) {
for (ResponseOptionBean responseOptionBean : options) {
if (responseOptionBean.getValue().equals(value)) {
return responseOptionBean.getValue();
}
}
}
return returnedValue;
}
@SuppressWarnings("unchecked")
private String matchValueWithManyOptions(String value, List<ResponseOptionBean> options) {
String returnedValue = null;
String entireOptions = "";
String[] simValues = value.split(",");
String simValue = value.replace(",", "");
simValue = simValue.replace(" ", "");
boolean checkComplete = true;
if (!options.isEmpty()) {
for (ResponseOptionBean responseOptionBean : options) {
entireOptions += responseOptionBean.getValue();
}
// remove spaces, since they are causing problems:
entireOptions = entireOptions.replace(" ", "");
ArrayList nullValues = getEventDefinitionCRFBean().getNullValuesList();
for (Object nullValue : nullValues) {
NullValue nullValueTerm = (NullValue) nullValue;
entireOptions += nullValueTerm.getName();
}
for (String sim : simValues) {
sim = sim.replace(" ", "");
checkComplete = entireOptions.contains(sim);// Pattern.matches(entireOptions,sim);
if (!checkComplete) {
return returnedValue;
}
}
}
return value;
}
private Boolean checkValidityBasedonNullValues(String value, String index, Errors e) {
return getEventDefinitionCRFBean().getNullValuesList().contains(NullValue.getByName(value)) ? true : false;
}
private void checkValidityBasedOnDataType(ItemBean itemBean, String value, String index, Errors e) {
switch (itemBean.getItemDataTypeId()) {
case 6: { //ItemDataType.INTEGER
try {
Integer.valueOf(value);
} catch (NumberFormatException nfe) {
e.rejectValue(index + "value", "value.invalid.integer");
}
break;
}
case 7: { //ItemDataType.REAL
try {
Float.valueOf(value);
} catch (NumberFormatException nfe) {
e.rejectValue(index + "value", "value.invalid.float");
}
break;
}
case 9: { //ItemDataType.DATE
if (!ExpressionTreeHelper.isDateyyyyMMddDashes(value)) {
e.rejectValue(index + "value", "value.invalid.date");
}
break;
}
case 10: { //ItemDataType.PDATE
e.rejectValue(index + "value", "value.invalid.pdate");
break;
}
case 11: { //ItemDataType.FILE
e.rejectValue(index + "value", "value.notSupported.file");
break;
}
default:
break;
}
}
public ItemDAO getItemDAO() {
return this.itemDAO != null ? itemDAO : new ItemDAO(dataSource);
}
public StudyEventDefinitionDAO getStudyEventDefinitionDAO() {
return this.studyEventDefinitionDAO != null ? studyEventDefinitionDAO : new StudyEventDefinitionDAO(dataSource);
}
public CRFDAO getCrfDAO() {
return this.crfDAO != null ? crfDAO : new CRFDAO(dataSource);
}
public EventDefinitionCRFDAO getEventDefinitionCRFDAO() {
return this.eventDefinitionCRFDAO != null ? eventDefinitionCRFDAO : new EventDefinitionCRFDAO(dataSource);
}
public ItemFormMetadataDAO getItemFormMetadataDAO() {
return this.itemFormMetadataDAO != null ? itemFormMetadataDAO : new ItemFormMetadataDAO(dataSource);
}
public EventDefinitionCRFBean getEventDefinitionCRFBean() {
return eventDefinitionCRFBean;
}
public void setEventDefinitionCRFBean(EventDefinitionCRFBean eventDefinitionCRFBean) {
this.eventDefinitionCRFBean = eventDefinitionCRFBean;
}
public ExpressionService getExpressionService() {
return expressionService;
}
public void setExpressionService(ExpressionService expressionService) {
this.expressionService = expressionService;
}
public RuleSetBean getRuleSetBean() {
return ruleSetBean;
}
public void setRuleSetBean(RuleSetBean ruleSetBean) {
this.ruleSetBean = ruleSetBean;
}
}