/* * #%L * BroadleafCommerce Open Admin Platform * %% * Copyright (C) 2009 - 2014 Broadleaf Commerce * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ package org.broadleafcommerce.openadmin.server.service.persistence.validation; import org.apache.commons.lang.StringUtils; import org.broadleafcommerce.common.presentation.RuleIdentifier; import org.broadleafcommerce.common.presentation.client.SupportedFieldType; import org.broadleafcommerce.common.rule.QuantityBasedRule; import org.broadleafcommerce.common.sandbox.SandBoxHelper; import org.broadleafcommerce.openadmin.server.service.persistence.module.FieldNotAvailableException; import org.broadleafcommerce.openadmin.server.service.persistence.module.provider.RuleFieldExtractionUtility; import org.broadleafcommerce.openadmin.server.service.persistence.module.provider.RuleFieldPersistenceProvider; import org.broadleafcommerce.openadmin.server.service.persistence.module.provider.request.PopulateValueRequest; import org.broadleafcommerce.openadmin.web.rulebuilder.DataDTOToMVELTranslator; import org.broadleafcommerce.openadmin.web.rulebuilder.MVELTranslationException; import org.broadleafcommerce.openadmin.web.rulebuilder.dto.DataDTO; import org.broadleafcommerce.openadmin.web.rulebuilder.dto.DataWrapper; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; import java.io.Serializable; import java.util.Collection; import javax.annotation.Resource; import javax.persistence.EntityManager; /** * Validates that a rule can be parsed out successfully. Most of this comes from {@link RuleFieldPersistenceProvider}. * * @author Phillip Verheyden (phillipuniverse) */ @Component("blRuleFieldValidator") public class RuleFieldValidator implements PopulateValueRequestValidator { @Resource(name = "blRuleFieldExtractionUtility") protected RuleFieldExtractionUtility ruleFieldExtractionUtility; @Resource(name = "blSandBoxHelper") protected SandBoxHelper sandBoxHelper; @Override public PropertyValidationResult validate(PopulateValueRequest populateValueRequest, Serializable instance) { if (canHandleValidation(populateValueRequest)) { DataDTOToMVELTranslator translator = new DataDTOToMVELTranslator(); EntityManager em = populateValueRequest.getPersistenceManager().getDynamicEntityDao().getStandardEntityManager(); if (SupportedFieldType.RULE_SIMPLE.equals(populateValueRequest.getMetadata().getFieldType())) { //AntiSamy HTML encodes the rule JSON - pass the unHTMLEncoded version DataWrapper dw = ruleFieldExtractionUtility.convertJsonToDataWrapper(populateValueRequest.getProperty().getUnHtmlEncodedValue()); if (dw != null && StringUtils.isNotEmpty(dw.getError())) { return new PropertyValidationResult(false, "Could not serialize JSON from rule builder: " + dw.getError()); } if (dw == null || StringUtils.isEmpty(dw.getError())) { try { String mvel = ruleFieldExtractionUtility.convertSimpleMatchRuleJsonToMvel(translator, RuleIdentifier.ENTITY_KEY_MAP.get(populateValueRequest.getMetadata().getRuleIdentifier()), populateValueRequest.getMetadata().getRuleIdentifier(), dw); } catch (MVELTranslationException e) { return new PropertyValidationResult(false, getMvelParsingErrorMesage(dw, e)); } } } if (SupportedFieldType.RULE_WITH_QUANTITY.equals(populateValueRequest.getMetadata().getFieldType())) { Collection<QuantityBasedRule> existingRules; try { existingRules = (Collection<QuantityBasedRule>) populateValueRequest.getFieldManager().getFieldValue (instance, populateValueRequest.getProperty().getName()); } catch (FieldNotAvailableException e) { return new PropertyValidationResult(false, "Could not access rule field on Java object to set values"); } catch (IllegalAccessException e) { return new PropertyValidationResult(false, "Could not access rule field on Java object to set values"); } String entityKey = RuleIdentifier.ENTITY_KEY_MAP.get(populateValueRequest.getMetadata().getRuleIdentifier()); String jsonPropertyValue = populateValueRequest.getProperty().getUnHtmlEncodedValue(); String fieldService = populateValueRequest.getMetadata().getRuleIdentifier(); if (!StringUtils.isEmpty(jsonPropertyValue)) { DataWrapper dw = ruleFieldExtractionUtility.convertJsonToDataWrapper(jsonPropertyValue); if (dw != null && StringUtils.isNotEmpty(dw.getError())) { return new PropertyValidationResult(false, "Could not serialize JSON from rule builder: " + dw.getError()); } if (dw != null && StringUtils.isEmpty(dw.getError())) { for (DataDTO dto : dw.getData()) { if (dto.getId() != null) { boolean foundIdToUpdate = false; for (QuantityBasedRule quantityBasedRule : existingRules) { Long sandBoxVersionId = sandBoxHelper.getSandBoxVersionId(quantityBasedRule.getClass(), dto.getId()); if (sandBoxVersionId == null) { sandBoxVersionId = dto.getId(); } if (sandBoxVersionId.equals(quantityBasedRule.getId())) { foundIdToUpdate = true; try { String mvel = ruleFieldExtractionUtility.convertDTOToMvelString(translator, entityKey, dto, fieldService); } catch (MVELTranslationException e) { return new PropertyValidationResult(false, getMvelParsingErrorMesage(dw, e)); } } } if (!foundIdToUpdate) { return new PropertyValidationResult(false, "Tried to update QuantityBasedReule with ID " + dto.getId() + " but that rule does not exist"); } } else { // This is a new rule, just validate that it parses successfully try { ruleFieldExtractionUtility.convertDTOToMvelString(translator, entityKey, dto, fieldService); } catch (MVELTranslationException e) { return new PropertyValidationResult(false, getMvelParsingErrorMesage(dw, e)); } } } } } } } return new PropertyValidationResult(true); } protected String getMvelParsingErrorMesage(DataWrapper dw, MVELTranslationException e) { StringBuilder errorMessage = new StringBuilder(); errorMessage.append("Problem translating rule builder, error code "); errorMessage.append(e.getCode()); errorMessage.append(": "); errorMessage.append(e.getMessage()); return errorMessage.toString(); } protected boolean canHandleValidation(PopulateValueRequest populateValueRequest) { return populateValueRequest.getMetadata().getFieldType() == SupportedFieldType.RULE_WITH_QUANTITY || populateValueRequest.getMetadata().getFieldType() == SupportedFieldType.RULE_SIMPLE; } @Override public int getOrder() { return Ordered.LOWEST_PRECEDENCE - 1000; } }