Package org.grules.ast

Source Code of org.grules.ast.RuleExpressionVerifier

package org.grules.ast;

import groovy.lang.Script;

import java.lang.reflect.Method;
import java.util.List;
import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.BinaryExpression;
import org.codehaus.groovy.ast.expr.BitwiseNegationExpression;
import org.codehaus.groovy.ast.expr.ClosureExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.GStringExpression;
import org.codehaus.groovy.ast.expr.ListExpression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.NotExpression;
import org.codehaus.groovy.ast.expr.TernaryExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types;
import org.grules.GroovyConstants;
import org.grules.script.RulesScriptAPI;
import org.grules.utils.AstUtils;

import com.google.common.collect.ImmutableSet;

/**
* A helper class that checks validity of a rule expression.
*/
class RuleExpressionVerifier {

  static boolean isValidRuleBinaryOperation(Token token) {
    ImmutableSet<Integer> binaryOpertions = ImmutableSet.of(
        Types.LOGICAL_AND,
        Types.LOGICAL_OR,
        Types.RIGHT_SHIFT,
        Types.LEFT_SQUARE_BRACKET);
    return binaryOpertions.contains(token.getType());
  }

  static boolean isAtomExpression(Expression expression) {
    if (expression instanceof BinaryExpression) {
      BinaryExpression binaryExpression = (BinaryExpression) expression;
      return AstUtils.isArrayItemExpression(binaryExpression) && isAtomExpression(binaryExpression.getLeftExpression());
    } else {
      return !(expression instanceof NotExpression) && !(expression instanceof BitwiseNegationExpression);
    }
  }

  static boolean isFirstExpressionMethodCall(Expression expression) {
    if (isAtomExpression(expression)) {
      if (expression instanceof MethodCallExpression) {
        MethodCallExpression methodCallExpression = (MethodCallExpression)expression;
        return ((ArgumentListExpression)methodCallExpression.getArguments()).getExpressions().size() == 1;
      } else {
        return false;
      }
    } else if (expression instanceof BinaryExpression) {
      return isFirstExpressionMethodCall(((BinaryExpression)expression).getLeftExpression());
    } else {
      return false;
    }
  }

  private static boolean isValidRuleApplicationMethodNameExpression(Expression expression) {
    if (expression instanceof ConstantExpression) {
      for (Class<?> inheritedType : ImmutableSet.of(Script.class, RulesScriptAPI.class)) {
        for (Method method : inheritedType.getMethods()) {
          if (method.getName().equals((((ConstantExpression)expression).getValue()))) {
            return false;
          }
        }
      }
      return true;
    } else {
      return isValidParameterNameExpression(expression);
    }
  }

  private static boolean isValidParameterNameExpression(Expression expression) {
    return expression instanceof GStringExpression || expression instanceof VariableExpression;
  }

  private static boolean isValidListRuleExpression(List<Expression> expressions) {
    for (Expression expression : expressions) {
      if (!isValidParameterNameExpression(expression) &&
          !(expression instanceof BinaryExpression &&
          isValidParameterBinaryExpression((BinaryExpression)expression))) {
        return false;
      }
    }
    return true;
  }

  static boolean isValidRuleMethodCallExpression(MethodCallExpression methodCallExpression) {
    Expression objectExpression = methodCallExpression.getObjectExpression();
    Expression method = methodCallExpression.getMethod();
    ArgumentListExpression arguments = (ArgumentListExpression) methodCallExpression.getArguments();
    boolean validObjectExpression = false;
    boolean validMethod = false;
    boolean validArguments;
    if (objectExpression == VariableExpression.THIS_EXPRESSION) {
      validObjectExpression = true;
      validMethod = isValidRuleApplicationMethodNameExpression(method);
    } else if (objectExpression instanceof ListExpression) {
      ListExpression listExpression = (ListExpression) objectExpression;
      validObjectExpression = isValidListRuleExpression(listExpression.getExpressions());
      if (method instanceof ConstantExpression) {
        validMethod = ((ConstantExpression)method).getValue().equals(GroovyConstants.CALL_METHOD_NAME);
      } else {
        validMethod = false;
      }
    } else if (objectExpression instanceof BinaryExpression) {
      validMethod = true;
      validObjectExpression = isValidParameterBinaryExpression((BinaryExpression) objectExpression);
    }
    validArguments = arguments.getExpressions().size() == 1 && isValidRuleExpression(arguments.getExpressions().get(0));
    return validObjectExpression && validMethod && validArguments;
  }

  private static boolean isValidParameterBinaryExpression(BinaryExpression parameterExpression) {
    boolean ruleParameterIsValid = isValidParameterNameExpression(parameterExpression.getLeftExpression());
    return parameterExpression.getOperation().getType() == Types.LEFT_SQUARE_BRACKET && ruleParameterIsValid;
  }

  static boolean isValidRuleExpression(Expression expression) {
    if (expression instanceof BinaryExpression) {
      if (AstUtils.isArrayItemExpression(expression)) {
        return isValidRuleExpression(((BinaryExpression)expression).getLeftExpression());
      else {
        BinaryExpression binaryExpression = (BinaryExpression) expression;
        boolean isValidLeftExpression = isValidRuleExpression(binaryExpression.getLeftExpression());
        boolean isValidRightExpression = isValidRuleExpression(binaryExpression.getRightExpression());
        boolean isValidBinaryOperation = RuleExpressionVerifier.isValidRuleBinaryOperation(binaryExpression.getOperation());
        return isValidBinaryOperation && isValidLeftExpression && isValidRightExpression;
      }
    } else if (expression instanceof NotExpression) {
      return isValidRuleExpression(((NotExpression)expression).getExpression());
    } else if (expression instanceof BitwiseNegationExpression) {
      return isValidRuleExpression(((BitwiseNegationExpression)expression).getExpression());
    } else if (expression instanceof TernaryExpression) {
      TernaryExpression ternaryExpression = (TernaryExpression) expression;
      Boolean isValidRuleTrueExpression = isValidRuleExpression(ternaryExpression.getTrueExpression());
      Boolean isValidRuleFalseExpression = isValidRuleExpression(ternaryExpression.getFalseExpression());
      return isValidRuleTrueExpression && isValidRuleFalseExpression;
    } else {
      ImmutableSet<Class<? extends Expression>> ruleExpressionClasses = ImmutableSet.of(
          VariableExpression.class,
          ClosureExpression.class,
          MethodCallExpression.class,
          GStringExpression.class);
      for (Class<?> ruleExpressionClass : ruleExpressionClasses) {
        if (ruleExpressionClass.isInstance(expression)) {
          return true;
        }
      }
      return false;
    }
  }
}
TOP

Related Classes of org.grules.ast.RuleExpressionVerifier

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.