Package org.drools.rule.builder

Source Code of org.drools.rule.builder.ConstraintBuilder

package org.drools.rule.builder;

import org.drools.base.ValueType;
import org.drools.base.evaluators.EvaluatorDefinition;
import org.drools.compiler.DescrBuildError;
import org.drools.lang.descr.BaseDescr;
import org.drools.lang.descr.LiteralRestrictionDescr;
import org.drools.rule.Declaration;
import org.drools.rule.LiteralConstraint;
import org.drools.rule.LiteralRestriction;
import org.drools.rule.MVELDialectRuntimeData;
import org.drools.rule.ReturnValueRestriction;
import org.drools.rule.UnificationRestriction;
import org.drools.rule.VariableConstraint;
import org.drools.rule.constraint.BooleanConversionHandler;
import org.drools.rule.constraint.EvaluatorConstraint;
import org.drools.rule.constraint.MvelConstraint;
import org.drools.spi.Constraint;
import org.drools.spi.Evaluator;
import org.drools.spi.FieldValue;
import org.drools.spi.InternalReadAccessor;
import org.drools.spi.Restriction;
import org.mvel2.DataConversion;
import org.mvel2.ParserConfiguration;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

public class ConstraintBuilder {

    private static final boolean USE_MVEL_EXPRESSION = false;
    private static Set<String> mvelOperators;

    static {
        if (USE_MVEL_EXPRESSION) {
            DataConversion.addConversionHandler(Boolean.class, BooleanConversionHandler.INSTANCE);
            DataConversion.addConversionHandler(boolean.class, BooleanConversionHandler.INSTANCE);

            mvelOperators = new HashSet<String>() {{
                add("==");
                add("!=");
                add(">");
                add(">=");
                add("<");
                add("<=");
                add("str");
                add("contains");
                add("matches");
                add("excludes");
                add("memberOf");
            }};
        }
    }

    private static boolean isMvelOperator(String operator) {
        return mvelOperators.contains(operator);
    }

    public static Constraint buildVariableConstraint(RuleBuildContext context,
                                                     String expression,
                                                     Declaration[] declrations,
                                                     String leftValue,
                                                     String operator,
                                                     String rightValue,
                                                     InternalReadAccessor extractor,
                                                     Restriction restriction) {
        if (USE_MVEL_EXPRESSION) {
            if (!isMvelOperator(operator)) {
                return new EvaluatorConstraint(restriction.getRequiredDeclarations(), restriction.getEvaluator(), extractor);
            }

            expression = resolveUnificationAmbiguity(expression, declrations, leftValue, rightValue, restriction);
            return new MvelConstraint(context.getPkg().getName(), expression, operator, declrations, getIndexingDeclaration(restriction), extractor);
        } else {
            return new VariableConstraint(extractor, restriction);
        }
    }

    public static Constraint buildLiteralConstraint(RuleBuildContext context,
                                                    ValueType vtype,
                                                    FieldValue field,
                                                    String expression,
                                                    String leftValue,
                                                    String operator,
                                                    String rightValue,
                                                    InternalReadAccessor extractor,
                                                    LiteralRestrictionDescr restrictionDescr) {
        if (USE_MVEL_EXPRESSION) {
            if (!isMvelOperator(operator)) {
                Evaluator evaluator = buildLiteralEvaluator(context, extractor, restrictionDescr, field, vtype);
                return new EvaluatorConstraint(field, evaluator, extractor);
            }

            String mvelExpr = normalizeMVELLiteralExpression(vtype, field, expression, leftValue, operator, rightValue, restrictionDescr);
            return new MvelConstraint(context.getPkg().getName(), mvelExpr, operator);
        } else {
            LiteralRestriction restriction = buildLiteralRestriction(context, extractor, restrictionDescr, field, vtype);
            return restriction != null ? new LiteralConstraint(extractor, restriction) : null;
        }
    }

    private static String resolveUnificationAmbiguity(String expr, Declaration[] declrations, String leftValue, String rightValue, Restriction restriction) {
        // resolve ambiguity between variable and bound value with the same name in unifications
        if (restriction instanceof UnificationRestriction && leftValue.equals(rightValue)) {
            rightValue = rightValue + "__";
            for (Declaration declaration : declrations) {
                if (declaration.getIdentifier().equals(leftValue)) {
                    declaration.setBindingName(rightValue);
                }
            }
            expr = leftValue + " == " + rightValue;
        }
        return expr;
    }

    private static Declaration getIndexingDeclaration(Restriction restriction) {
        if (restriction instanceof ReturnValueRestriction) return null;
        Declaration[] declarations = restriction.getRequiredDeclarations();
        return declarations != null && declarations.length > 0 ? declarations[0] : null;
    }

    private static String normalizeMVELLiteralExpression(ValueType vtype,
                                                         FieldValue field,
                                                         String expr,
                                                         String leftValue,
                                                         String operator,
                                                         String rightValue,
                                                         LiteralRestrictionDescr restrictionDescr) {
        if (vtype == ValueType.DATE_TYPE) {
            Date date = (Date)field.getValue();
            return leftValue + " " + operator + (date != null ? " new java.util.Date(" + date.getTime() + ")" : " null");
        }
        if (operator.equals("str")) {
            String method = restrictionDescr.getParameterText();
            if (method.equals("length")) {
                return leftValue + ".length()" + (restrictionDescr.isNegated() ? " != " : " == ") + rightValue;
            }
            return (restrictionDescr.isNegated() ? "!" : "") + leftValue + "." + method + "(" + rightValue + ")";
        }

        // resolve ambiguity between mvel's "empty" keyword and constraints like: List(empty == ...)
        if (expr.startsWith("empty") && (operator.equals("==") || operator.equals("!="))) {
            expr = "isEmpty()" + expr.substring(5);
        }
        return expr;
    }

    public static LiteralRestriction buildLiteralRestriction( RuleBuildContext context,
                                                              InternalReadAccessor extractor,
                                                              LiteralRestrictionDescr literalRestrictionDescr,
                                                              FieldValue field,
                                                              ValueType vtype) {
        Evaluator evaluator = buildLiteralEvaluator(context, extractor, literalRestrictionDescr, field, vtype);
        return evaluator == null ? null : new LiteralRestriction(field, evaluator, extractor);
    }

    public static Evaluator buildLiteralEvaluator( RuleBuildContext context,
                                                   InternalReadAccessor extractor,
                                                   LiteralRestrictionDescr literalRestrictionDescr,
                                                   FieldValue field,
                                                   ValueType vtype) {
        EvaluatorDefinition.Target right = getRightTarget( extractor );
        EvaluatorDefinition.Target left = EvaluatorDefinition.Target.FACT;
        return getEvaluator( context,
                             literalRestrictionDescr,
                             vtype,
                             literalRestrictionDescr.getEvaluator(),
                             literalRestrictionDescr.isNegated(),
                             literalRestrictionDescr.getParameterText(),
                             left,
                             right );
    }

    public static EvaluatorDefinition.Target getRightTarget( final InternalReadAccessor extractor ) {
        return (extractor.isSelfReference() && !(Date.class.isAssignableFrom( extractor.getExtractToClass() ) || Number.class.isAssignableFrom( extractor.getExtractToClass() ))) ? EvaluatorDefinition.Target.HANDLE : EvaluatorDefinition.Target.FACT;
    }

    public static Evaluator getEvaluator( final RuleBuildContext context,
                                    final BaseDescr descr,
                                    final ValueType valueType,
                                    final String evaluatorString,
                                    final boolean isNegated,
                                    final String parameters,
                                    final EvaluatorDefinition.Target left,
                                    final EvaluatorDefinition.Target right ) {

        final EvaluatorDefinition def = context.getConfiguration().getEvaluatorRegistry().getEvaluatorDefinition( evaluatorString );
        if ( def == null ) {
            context.getErrors().add( new DescrBuildError( context.getParentDescr(),
                                                          descr,
                                                          null,
                                                          "Unable to determine the Evaluator for ID '" + evaluatorString + "'" ) );
            return null;
        }

        final Evaluator evaluator = def.getEvaluator( valueType,
                                                      evaluatorString,
                                                      isNegated,
                                                      parameters,
                                                      left,
                                                      right );

        if ( evaluator == null ) {
            context.getErrors().add( new DescrBuildError( context.getParentDescr(),
                                                          descr,
                                                          null,
                                                          "Evaluator '" + (isNegated ? "not " : "") + evaluatorString + "' does not support type '" + valueType ) );
        }

        return evaluator;
    }
}
TOP

Related Classes of org.drools.rule.builder.ConstraintBuilder

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.