/* * #%L * BroadleafCommerce Open Admin Platform * %% * Copyright (C) 2009 - 2013 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.web.rulebuilder; import java.util.ArrayList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.broadleafcommerce.common.presentation.client.SupportedFieldType; import org.broadleafcommerce.openadmin.dto.Entity; import org.broadleafcommerce.openadmin.dto.Property; import org.broadleafcommerce.openadmin.web.rulebuilder.dto.DataDTO; import org.broadleafcommerce.openadmin.web.rulebuilder.dto.DataWrapper; import org.broadleafcommerce.openadmin.web.rulebuilder.dto.ExpressionDTO; import org.broadleafcommerce.openadmin.web.rulebuilder.dto.FieldDTO; import org.broadleafcommerce.openadmin.web.rulebuilder.grouping.Group; import org.broadleafcommerce.openadmin.web.rulebuilder.grouping.GroupingTranslator; import org.broadleafcommerce.openadmin.web.rulebuilder.service.RuleBuilderFieldService; import org.broadleafcommerce.openadmin.web.rulebuilder.statement.Expression; import org.broadleafcommerce.openadmin.web.rulebuilder.statement.PhraseTranslator; /** * Utility class to convert an MVEL string into a DataWrapper object * which can then be serialized on your view. * * @author Elbert Bautista (elbertbautista) */ public class MVELToDataWrapperTranslator { private static final Log LOG = LogFactory.getLog(MVELToDataWrapperTranslator.class); protected GroupingTranslator groupingTranslator = new GroupingTranslator(); protected PhraseTranslator phraseTranslator = new PhraseTranslator(); public DataWrapper createRuleData(Entity[] entities, String mvelProperty, String quantityProperty, String idProperty, RuleBuilderFieldService fieldService) { if (entities == null || entities.length == 0 || mvelProperty == null) { return null; } DataWrapper dataWrapper = new DataWrapper(); String mvel = null; try { for (Entity e : entities) { Integer qty = null; Long id = null; for (Property p : e.getProperties()) { if (mvelProperty.equals(p.getName())){ mvel = p.getValue(); } if (quantityProperty !=null && quantityProperty.equals(p.getName())){ qty = Integer.parseInt(p.getValue()); } if (idProperty != null && idProperty.equals(p.getName())) { id = Long.parseLong(p.getValue()); } } if (mvel != null) { Group group = groupingTranslator.createGroups(mvel); DataDTO dataDTO = createRuleDataDTO(null, group, fieldService); if (dataDTO != null) { dataDTO.setId(id); dataDTO.setQuantity(qty); dataWrapper.getData().add(dataDTO); } } } } catch (MVELTranslationException e) { LOG.error("Unable to translate rule MVEL", e); dataWrapper.getData().clear(); dataWrapper.setError(e.getLocalizedMessage()); dataWrapper.setRawMvel(mvel); } return dataWrapper; } protected DataDTO createRuleDataDTO(DataDTO parentDTO, Group group, RuleBuilderFieldService fieldService) throws MVELTranslationException { DataDTO data = new DataDTO(); if (group.getOperatorType() == null) { group.setOperatorType(BLCOperator.AND); } BLCOperator operator = group.getOperatorType(); data.setGroupOperator(operator.name()); List<ExpressionDTO> myCriteriaList = new ArrayList<ExpressionDTO>(); if (BLCOperator.NOT.equals(group.getOperatorType()) && group.getIsTopGroup()) { group = group.getSubGroups().get(0); group.setOperatorType(operator); } int j = 0; for (String phrase : group.getPhrases()) { appendExpression(phrase, fieldService, j, parentDTO, myCriteriaList); j++; } if (myCriteriaList.size() > 0) { data.getGroups().addAll(myCriteriaList); } for (Group subgroup : group.getSubGroups()) { DataDTO subCriteria = createRuleDataDTO(data, subgroup, fieldService); if (subCriteria != null && !subCriteria.getGroups().isEmpty()) { data.getGroups().add(subCriteria); } } if (data.getGroups() != null && !data.getGroups().isEmpty()) { return data; } else { return null; } } public void appendExpression(String phrase, RuleBuilderFieldService fieldService, int count, DataDTO parentDTO, List<ExpressionDTO> myCriteriaList) throws MVELTranslationException { Expression expression = phraseTranslator.createExpression(phrase); FieldDTO field = fieldService.getField(expression.getField()); if (field == null) { throw new MVELTranslationException(MVELTranslationException.SPECIFIED_FIELD_NOT_FOUND, "MVEL phrase is not compatible with the RuleBuilderFieldService " + "associated with the current rules builder. Unable to find the field " + "specified: ("+expression.getField()+")"); } SupportedFieldType type = fieldService.getSupportedFieldType(expression.getField()); ExpressionDTO expressionDTO = createExpressionDTO(expression); postProcessCriteria(parentDTO, myCriteriaList, count, expressionDTO, type); } public ExpressionDTO createExpressionDTO(Expression expression) { ExpressionDTO expressionDTO = new ExpressionDTO(); expressionDTO.setName(expression.getField()); expressionDTO.setOperator(expression.getOperator().name()); expressionDTO.setValue(expression.getValue()); return expressionDTO; } public boolean isProjection(Object value) { String stringValue = value.toString().trim(); return stringValue.startsWith("[") && stringValue.endsWith("]") && stringValue.indexOf(",") > 0; } protected void postProcessCriteria(DataDTO parentDTO, List<ExpressionDTO> myCriteriaList, int count, ExpressionDTO temp, SupportedFieldType type) { if ( count > 0 && temp.getName().equals(myCriteriaList.get(count - 1).getName()) && myCriteriaList.get(count - 1).getOperator().equals(BLCOperator.GREATER_THAN.name()) && temp.getOperator().equals(BLCOperator.LESS_THAN.name()) ) { myCriteriaList.get(count-1).setOperator(BLCOperator.BETWEEN.name()); String start; String end; if (type.toString().equals(SupportedFieldType.DATE.toString())) { start = myCriteriaList.get(count-1).getValue(); end = temp.getValue(); } else { start = myCriteriaList.get(count-1).getValue(); end = temp.getValue(); } myCriteriaList.get(count-1).setStart(start); myCriteriaList.get(count-1).setEnd(end); myCriteriaList.get(count-1).setValue(null); if (parentDTO != null) { parentDTO.getGroups().add(myCriteriaList.remove(count-1)); } } else if ( count > 0 && temp.getName().equals(myCriteriaList.get(count-1).getName()) && myCriteriaList.get(count-1).getOperator().equals(BLCOperator.GREATER_OR_EQUAL.name()) && temp.getOperator().equals(BLCOperator.LESS_OR_EQUAL.name()) ) { myCriteriaList.get(count - 1).setOperator(BLCOperator.BETWEEN_INCLUSIVE.name()); String start; String end; if (type.toString().equals(SupportedFieldType.DATE.toString())) { start = myCriteriaList.get(count-1).getValue(); end = temp.getValue(); } else { start = myCriteriaList.get(count-1).getValue(); end = temp.getValue(); } myCriteriaList.get(count-1).setStart(start); myCriteriaList.get(count-1).setEnd(end); myCriteriaList.get(count-1).setValue(null); if (parentDTO != null) { parentDTO.getGroups().add(myCriteriaList.remove(count-1)); } } else if (isProjection(temp.getValue())) { if (parentDTO != null) { parentDTO.getGroups().add(temp); } else { myCriteriaList.add(temp); } } else { myCriteriaList.add(temp); } } }