Package org.broadleafcommerce.openadmin.web.rulebuilder.statement

Source Code of org.broadleafcommerce.openadmin.web.rulebuilder.statement.PhraseTranslator

/*
* #%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.statement;

import java.text.ParseException;

import org.broadleafcommerce.openadmin.server.service.persistence.module.FieldManager;
import org.broadleafcommerce.openadmin.web.rulebuilder.BLCOperator;
import org.broadleafcommerce.openadmin.web.rulebuilder.MVELTranslationException;
import org.broadleafcommerce.openadmin.web.rulebuilder.RuleBuilderFormatUtil;

/**
* @author jfischer
* @author Elbert Bautista (elbertbautista)
*/
public class PhraseTranslator {

    private static final String[] SPECIALCASES = {
            ".startsWith",
            ".endsWith",
            ".contains"
    };

    private static final String[] STANDARDOPERATORS = {
            ".size()>",
            ".size()>=",
            ".size()<",
            ".size()<=",
            ".size()==",
            "==",
            "!=",
            "<=",
            "<",
            ">=",
            ">"
    };

    public Expression createExpression(String phrase) throws MVELTranslationException {
        String[] components = extractComponents(phrase);
        String field = components[0];
        String operator = components[1];
        String value = components[2];

        boolean isNegation = false;
        if (field.startsWith("!")) {
            isNegation = true;
        }

        boolean isIgnoreCase = false;

        //remove null check syntax
        field = field.replaceAll("\\.\\?", ".");

        //keep for backwards compatibility with legacy generated MVEL
        String legacyCaseInsensitivityKey = "MVEL.eval(\"toUpperCase()\",";

        String newCaseInsensitivityKey = "MvelHelper.toUpperCase(";
        String caseInsensitivityKey;
        if (field.contains(legacyCaseInsensitivityKey) || value.contains(legacyCaseInsensitivityKey)) {
            caseInsensitivityKey = legacyCaseInsensitivityKey;
        } else {
            caseInsensitivityKey = newCaseInsensitivityKey;
        }
        if (field.startsWith(caseInsensitivityKey)) {
            isIgnoreCase = true;
            field = field.substring(caseInsensitivityKey.length(), field.length()-1);
        }
        //check for NOT operator
        if (field.startsWith("!" + caseInsensitivityKey)) {
            isIgnoreCase = true;
            field = field.substring(("!" + caseInsensitivityKey).length(), field.length()-1);
        }
        while(value.contains(caseInsensitivityKey)) {
            value = value.substring(0, value.indexOf(caseInsensitivityKey)) +
                    value.substring(value.indexOf(caseInsensitivityKey) + caseInsensitivityKey.length(), value.length());
            value = value.substring(0, value.indexOf(")")) + value.substring(value.indexOf(")")+1, value.length());
        }
        if (value.startsWith("[") && value.endsWith("]")) {
            value = value.substring(1, value.length() - 1);
            String[] temps = value.split(",");
            for (int j = 0;j<temps.length;j++) {
                if (temps[j].startsWith("\"") && temps[j].endsWith("\"")) {
                    temps[j] = temps[j].substring(1, temps[j].length()-1);
                }
            }
            StringBuffer sb = new StringBuffer();
            sb.append("[");
            for (int j = 0;j<temps.length;j++) {
                sb.append(temps[j]);
                if (j < temps.length - 1) {
                    sb.append(",");
                }
            }
            sb.append("]");
            value = sb.toString();
        }
        //keep for backwards compatibility with legacy generated MVEL
        String legacyDateFormatKey = "java.text.DateFormat.getDateTimeInstance(3,3).parse(";

        String newDateFormatKey = "MvelHelper.convertField(\"DATE\",\"";
        String dateFormatKey;
        if (value.contains(legacyDateFormatKey)) {
            dateFormatKey = legacyDateFormatKey;
        } else {
            dateFormatKey = newDateFormatKey;
        }
        if (value.startsWith(dateFormatKey)) {
            value = value.substring(dateFormatKey.length(), value.length()-1);
            //convert the date into admin display format
            try {
                if (value.startsWith("\"")) {
                    value = value.substring(1, value.length());
                }
                if (value.endsWith("\"")) {
                    value = value.substring(0, value.length()-1);
                }
                value = RuleBuilderFormatUtil.formatDate(RuleBuilderFormatUtil.parseDate(value));
            } catch (ParseException e) {
                throw new MVELTranslationException(MVELTranslationException.INCOMPATIBLE_DATE_VALUE, "Unable to convert " +
                        "the persisted date value(" + value + ") to the admin display format.");
            }
        }
        int entityKeyIndex = field.indexOf(".");
        if (entityKeyIndex < 0) {
            throw new MVELTranslationException(MVELTranslationException.NO_FIELD_FOUND_IN_RULE, "Could not identify a " +
                    "valid property field value in the expression: ("+phrase+")");
        }
        if (value.startsWith(caseInsensitivityKey)) {
            value = value.substring(caseInsensitivityKey.length(), value.length()-1);
        }
        String entityKey = field.substring(0, entityKeyIndex);
        boolean isFieldComparison = false;
        if (value.startsWith("\"") && value.endsWith("\"")) {
            value = value.substring(1, value.length()-1);
        } else if (value.startsWith(entityKey + ".")){
            isFieldComparison = true;
            value = value.substring(entityKey.length() + 1, value.length());
        }
        field = field.substring(entityKeyIndex + 1, field.length());
        // If this is a Money field, then DataDTOToMVELTranslator.formatValue() will append .getAmount() onto the end
        // of the field name. We need to remove that as it should not be considered part of the field name, but we still
        // want to support other method invocations in MVEL expressions (like for getProductAttributes())
        String moneyAmountMethod = ".getAmount()";
        int amountMethodPos = field.lastIndexOf(moneyAmountMethod);
        if (amountMethodPos >= 0) {
            field = field.substring(0, amountMethodPos);
        }

        // Same as above, but for Enumeration types
        String typeMethod = ".getType()";
        int typeMethodPos = field.lastIndexOf(typeMethod);
        if (typeMethodPos >= 0) {
           field = field.substring(0, typeMethodPos);
        }
       
        Expression expression = new Expression();
        expression.setField(field);
        BLCOperator operatorId = getOperator(field, operator, value, isNegation, isFieldComparison, isIgnoreCase);
        expression.setOperator(operatorId);
        expression.setValue(value);

        return expression;
    }

    protected String[] extractComponents(String phrase) throws MVELTranslationException {
        String[] components = new String[]{};
        for (String operator : STANDARDOPERATORS) {
            String[] temp;
            if (phrase.contains(operator)) {
                temp = new String[2];
                temp[0] = phrase.substring(0, phrase.indexOf(operator));
                temp[1] = phrase.substring(phrase.indexOf(operator) + operator.length(), phrase.length());
            } else {
                temp = new String[1];
                temp[0] = phrase;
            }
            if (temp.length == 2) {
                components = new String[3];
                components[0] = temp[0];
                components[1] = operator;
                components[2] = temp[1];
                break;
            }
            components = temp;
        }
        if (components.length != 3) {
            //may be a special expression
            try {
                for (String key : SPECIALCASES) {
                    if (components[0].indexOf(key) >= 0) {
                        String[] temp = extractSpecialComponents(components, key);
                        components = temp;
                        break;
                    }
                }
            } catch (Exception e) {
                //do nothing
            }
            if (components.length != 3) {
                //may be a projection
                try {
                    String[] temp = extractProjection(components);
                    components = temp;
                } catch (Exception e1) {
                    //do nothing
                }

                if (components.length != 3) {
                    throw new MVELTranslationException(MVELTranslationException.UNRECOGNIZABLE_RULE, "Could not parse the MVEL expression to a " +
                            "compatible form for the rules builder (" + phrase + ")");
                }
            }
        }

        if (components[0].matches(".*\\[\".*?\"\\].*")) {
            //this is using map access syntax - must be a map field
            components[0] = components[0].substring(0, components[0].lastIndexOf("[")) + FieldManager.MAPFIELDSEPARATOR +
                    components[0].substring(components[0].lastIndexOf("[") + 2, components[0].lastIndexOf("]") - 1) +
                    components[0].substring(components[0].lastIndexOf("]") + 1, components[0].length());
            //strip any convertField usage
            if (components[0].startsWith("MvelHelper.convertField(")) {
                components[0] = components[0].substring(components[0].indexOf("(") + 1, components[0].length()-1);
            }
        }
        return components;
    }

    protected String[] extractProjection(String[] components) {
        String[] temp = new String[3];
        int startsWithIndex = components[0].indexOf("contains");
        temp[0] = components[0].substring(startsWithIndex+"contains".length()+1, components[0].length()).trim();
        if (temp[0].endsWith(".intValue()")) {
            temp[0] = temp[0].substring(0, temp[0].indexOf(".intValue()"));
        }
        temp[1] = "==";
        temp[2] = components[0].substring(components[0].indexOf("["), components[0].indexOf("]") + 1);
        return temp;
    }

    protected String[] extractSpecialComponents(String[] components, String key) {
        String[] temp = new String[3];
        int startsWithIndex = components[0].indexOf(key);
        temp[0] = components[0].substring(0, startsWithIndex);
        temp[1] = key.substring(1, key.length());
        temp[2] = components[0].substring(startsWithIndex + key.length() + 1, components[0].lastIndexOf(")"));
        return temp;
    }

    protected BLCOperator getOperator(String field, String operator, String value, boolean isNegation,
                                     boolean isFieldComparison, boolean isIgnoreCase) throws MVELTranslationException {
        if (operator.equals("==") && value.equals("null")) {
            return BLCOperator.IS_NULL;
        } else if (operator.equals("==") && isFieldComparison) {
            return BLCOperator.EQUALS_FIELD;
        } else if (
                isIgnoreCase &&
                        operator.equals("==")
                ) {
            return BLCOperator.IEQUALS;
        } else if (operator.equals("==")) {
            return BLCOperator.EQUALS;
        } else if (operator.equals("!=") && value.equals("null")) {
            return BLCOperator.NOT_NULL;
        } else if (operator.equals("!=") && isFieldComparison) {
            return BLCOperator.NOT_EQUAL_FIELD;
        } else if (
                isIgnoreCase &&
                        operator.equals("!=")
                ) {
            return BLCOperator.INOT_EQUAL;
        } else if (operator.equals("!=")) {
            return BLCOperator.NOT_EQUAL;
        } else if (operator.equals(">") && isFieldComparison) {
            return BLCOperator.GREATER_THAN_FIELD;
        } else if (operator.equals(">")) {
            return BLCOperator.GREATER_THAN;
        } else if (operator.equals("<") && isFieldComparison) {
            return BLCOperator.LESS_THAN_FIELD;
        } else if (operator.equals("<")) {
            return BLCOperator.LESS_THAN;
        } else if (operator.equals(">=") && isFieldComparison) {
            return BLCOperator.GREATER_OR_EQUAL_FIELD;
        } else if (operator.equals(">=")) {
            return BLCOperator.GREATER_OR_EQUAL;
        } else if (operator.equals("<=") && isFieldComparison) {
            return BLCOperator.LESS_OR_EQUAL_FIELD;
        } else if (operator.equals("<=")) {
            return BLCOperator.LESS_OR_EQUAL;
        } else if (
                isIgnoreCase &&
                        operator.equals("contains") &&
                        isNegation
                ) {
            return BLCOperator.INOT_CONTAINS;
//        } else if (operator.equals("contains") && isNegation) {
//            return BLCOperator.NOT_CONTAINS;
        } else if (
                isIgnoreCase &&
                        operator.equals("contains")
                ) {
            return BLCOperator.ICONTAINS;
        } else if (operator.equals("contains") && isFieldComparison) {
            return BLCOperator.CONTAINS_FIELD;
//        } else if (operator.equals("contains")) {
//            return BLCOperator.CONTAINS;
        } else if (
                isIgnoreCase &&
                        operator.equals("startsWith") &&
                        isNegation
                ) {
            return BLCOperator.INOT_STARTS_WITH;
//        } else if (operator.equals("startsWith") && isNegation) {
//            return BLCOperator.NOT_STARTS_WITH;
        } else if (
                isIgnoreCase &&
                        operator.equals("startsWith")
                ) {
            return BLCOperator.ISTARTS_WITH;
        } else if (operator.equals("startsWith") && isFieldComparison) {
            return BLCOperator.STARTS_WITH_FIELD;
//        } else if (operator.equals("startsWith")) {
//            return BLCOperator.STARTS_WITH;
        } else if (
                isIgnoreCase &&
                        operator.equals("endsWith") &&
                        isNegation
                ) {
            return BLCOperator.INOT_ENDS_WITH;
//        } else if (operator.equals("endsWith") && isNegation) {
//            return BLCOperator.NOT_ENDS_WITH;
        } else if (
                isIgnoreCase &&
                        operator.equals("endsWith")
                ) {
            return BLCOperator.IENDS_WITH;
        } else if (operator.equals("endsWith") && isFieldComparison) {
            return BLCOperator.ENDS_WITH_FIELD;
//        } else if (operator.equals("endsWith")) {
//            return BLCOperator.ENDS_WITH;
        } else if (operator.equals(".size()>")) {
            return BLCOperator.COUNT_GREATER_THAN;
        } else if (operator.equals(".size()>=")) {
            return BLCOperator.COUNT_GREATER_OR_EQUAL;
        } else if (operator.equals(".size()<")) {
            return BLCOperator.COUNT_LESS_THAN;
        } else if (operator.equals(".size()<=")) {
            return BLCOperator.COUNT_LESS_OR_EQUAL;
        } else if (operator.equals(".size()==")) {
            return BLCOperator.COUNT_EQUALS;
        }
        throw new MVELTranslationException(MVELTranslationException.OPERATOR_NOT_FOUND, "Unable to identify an operator compatible with the " +
                "rules builder: ("+(isNegation?"!":""+field+operator+value)+")");
    }

}
TOP

Related Classes of org.broadleafcommerce.openadmin.web.rulebuilder.statement.PhraseTranslator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.