Package org.objectweb.speedo.generation.jorm.rdb

Source Code of org.objectweb.speedo.generation.jorm.rdb.FilterManager$FilterParser

/**
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package org.objectweb.speedo.generation.jorm.rdb;

import org.objectweb.speedo.query.jdo.parser.SpeedoQLVisitor;
import org.objectweb.speedo.query.jdo.parser.SimpleNode;
import org.objectweb.speedo.query.jdo.parser.ASTSpeedoPrimary;
import org.objectweb.speedo.query.jdo.parser.ASTSpeedoQL;
import org.objectweb.speedo.query.jdo.parser.ASTPrimary;
import org.objectweb.speedo.query.jdo.parser.ASTRelationalExpression;
import org.objectweb.speedo.query.jdo.parser.ASTAdditiveExpression;
import org.objectweb.speedo.query.jdo.parser.ASTUnaryExpression;
import org.objectweb.speedo.query.jdo.parser.ASTCastExpression;
import org.objectweb.speedo.query.jdo.parser.ASTArgumentList;
import org.objectweb.speedo.query.jdo.parser.ASTLiteral;
import org.objectweb.speedo.query.jdo.parser.ASTType;
import org.objectweb.speedo.query.jdo.parser.ASTQualifiedName;
import org.objectweb.speedo.query.jdo.parser.SpeedoQLConstants;
import org.objectweb.speedo.query.jdo.parser.SpeedoQL;
import org.objectweb.speedo.query.jdo.parser.ParseException;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.medor.expression.api.Expression;
import org.objectweb.medor.expression.api.Operator;
import org.objectweb.medor.expression.api.Operand;
import org.objectweb.medor.expression.lib.ConditionalOr;
import org.objectweb.medor.expression.lib.ConditionalAnd;
import org.objectweb.medor.expression.lib.Or;
import org.objectweb.medor.expression.lib.And;
import org.objectweb.medor.expression.lib.Equal;
import org.objectweb.medor.expression.lib.NotEqual;
import org.objectweb.medor.expression.lib.Lower;
import org.objectweb.medor.expression.lib.Greater;
import org.objectweb.medor.expression.lib.GreaterEqual;
import org.objectweb.medor.expression.lib.LowerEqual;
import org.objectweb.medor.expression.lib.Plus;
import org.objectweb.medor.expression.lib.Minus;
import org.objectweb.medor.expression.lib.Mult;
import org.objectweb.medor.expression.lib.DivideBy;
import org.objectweb.medor.expression.lib.UMinus;
import org.objectweb.medor.expression.lib.Bitwize;
import org.objectweb.medor.expression.lib.Not;
import org.objectweb.medor.expression.lib.BasicOperand;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.objectweb.jorm.mapper.rdb.metainfo.RdbFilter;
import org.objectweb.jorm.type.api.PTypeSpace;

import java.util.Stack;
import java.io.CharArrayReader;

/**
* It manages the filter dedicated to the filtered inheritance mapping.
*
* @author S.Chassande-Barrioz
*/
public class FilterManager {

  private Logger logger;
  private boolean debug = false;
  private FilterParser parser = new FilterParser();

  public FilterManager(Logger logger) {
    this.logger = logger;
  }

  public FilterParser getParser() {
    return parser;
  }

  public void assignFilter(String filter,
                           RdbFilter rdbFilter,
                           SpeedoClass sc,
                           String projectName,
                           String mapperName) throws SpeedoException {
    debug = logger != null && logger.isLoggable(BasicLevel.DEBUG);
    Expression medorExpression = parser.parse(filter);
    if (!isJormPredicate(medorExpression)) {
      throw new SpeedoException(
          "The specified filter is not supported, \n\tclass"
          + sc.getFQName() + "\n\tfilter=" + filter);
    }
    rdbFilter.setExpression(medorExpression);
  }

  public class FilterParser implements SpeedoQLVisitor {
    private Expression expression;
    private String tab = "";

    public synchronized Expression parse(String filter) throws SpeedoException {
      try {
        visit(new SpeedoQL(new CharArrayReader(filter.toCharArray())).SpeedoQL());
        return expression;
      } catch (ParseException e) {
        throw new SpeedoException(
            "Impossible to parse the filter and to create AST", e);
      } catch (SpeedoException e) {
        throw e;
      } catch (Exception e) {
        throw new SpeedoException("Impossible to parse the filter", e);
      }
    }

    // IMPLEMENTATION OF THE SpeedoQLVisitor INTERFACE //
    //-------------------------------------------------//

    public Object visit(ASTPrimary node, Object data) {
      visit((SimpleNode) node, data);
      return null;
    }

    public Object visit(ASTSpeedoPrimary node, Object data) {
      visit((SimpleNode) node, data);
      Stack stack = (Stack) data;
      expression = (Expression) stack.pop();
      return null;
    }

    public Object visit(ASTRelationalExpression node, Object data) {
      logger.log(BasicLevel.DEBUG, tab + "Visit RelationalExpression: " + node);
      tab += '\t';
      visit((SimpleNode) node, data);
      tab = tab.substring(1);
      Stack stack = (Stack) data;
      if (stack.size() > 0) {
        if (debug) {
          logger.log(BasicLevel.DEBUG, "manage relational expression: "
              + "(children: " + node.jjtGetNumChildren()
              + ", stack: " + stack.size()
              + ", peek:" + stack.peek() + ")");
        }
        for (int i = 0; (i < (node.jjtGetNumChildren() - 1) && stack.size() > 0); i++) {
          int op = ((Integer) node.ops.get(node.jjtGetNumChildren() - 2 - i)).intValue();
          if (usedInRelationalExpresssion(op)) {
            Object child2 = stack.pop();
            Object child1 = stack.pop();
            if (debug) {
              logger.log(BasicLevel.DEBUG, "pop child1: " + child1);
              logger.log(BasicLevel.DEBUG, "pop child2: " + child2);
            }
            Expression ret = null;
            switch (op) {
            case SpeedoQLConstants.OR:
              ret = new ConditionalOr((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.AND:
              ret = new ConditionalAnd((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.BITWISEOR:
              ret = new Or((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.BITWISEXOR:
              ret = null;
              break;
            case SpeedoQLConstants.BITWISEAND:
              ret = new And((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.EQ:
              ret = new Equal((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.NEQ:
              ret = new NotEqual((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.LT:
              ret = new Lower((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.GT:
              ret = new Greater((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.GTE:
              ret = new GreaterEqual((Expression) child1, (Expression) child2);
              break;
            case SpeedoQLConstants.LTE:
              ret = new LowerEqual((Expression) child1, (Expression) child2);
              break;
            }
            if (debug) {
              logger.log(BasicLevel.DEBUG, "push(" + ret + ")");
            }
            stack.push(ret);
          }
        }
      }
      if (debug) {
        logger.log(BasicLevel.DEBUG, "children:" + node.jjtGetNumChildren()
            + " / stack: " + stack.size());
        logger.log(BasicLevel.DEBUG, tab + "End of Visit RelationalExpression: " + node);
      }
      return null;
    }

    public Object visit(ASTAdditiveExpression node, Object data) {
      logger.log(BasicLevel.DEBUG, tab + "Visit AdditiveExpression: " + node);
      tab += '\t';
      visit((SimpleNode) node, data);
      tab = tab.substring(1);
      Stack stack = (Stack) data;
      if (stack.size() > 0) {
        Expression ret = (Expression) stack.pop();
        for (int i = 0; i < node.jjtGetNumChildren() - 1; i++) {
          logger.log(BasicLevel.DEBUG, "Visit AdditiveExpression... children...[" + i + "]");

          switch (((Integer) node.ops.get(node.jjtGetNumChildren() - 2 - i)).intValue()) {

          case SpeedoQLConstants.PLUS:
            ret = new Plus((Expression) stack.pop(), ret);
            break;
          case SpeedoQLConstants.MINUS:
            ret = new Minus((Expression) stack.pop(), ret);
            break;
          case SpeedoQLConstants.MULT:
            ret = new Mult((Expression) stack.pop(), ret);
            break;
          case SpeedoQLConstants.DIV:
            ret = new DivideBy((Expression) stack.pop(), ret);
            break;
          default:

          }
        }
        ((Stack) data).push(ret);
      }
      logger.log(BasicLevel.DEBUG, tab + "End of Visit AdditiveExpression: " + node);
      return null;
    }

    public Object visit(ASTUnaryExpression node, Object data) {
      logger.log(BasicLevel.DEBUG, tab + "Visit UnaryExpression" + node);
      tab += '\t';
      visit((SimpleNode) node, data);
      tab = tab.substring(1);
      Stack stack = (Stack) data;
      if (stack.size() > 0) {
        Object o = stack.pop();
        if (node.ops.size() > 0) {
          switch (((Integer) node.ops.get(0)).intValue()) {
          case SpeedoQLConstants.MINUS:
            o = new UMinus((Expression) o);
            break;
          case SpeedoQLConstants.BITWISECOMPL:
            o = new Bitwize((Expression) o);
            break;
          case SpeedoQLConstants.NOT:
            logger.log(BasicLevel.DEBUG, "NOT(" + o + "): " + node);
            o = new Not((Expression) o);
            break;
          }
        }
        ((Stack) data).push(o);
      }
      logger.log(BasicLevel.DEBUG, tab + "End of Visit UnaryExpression: " + node);
      return null;
    }

    public Object visit(ASTCastExpression node, Object data) {
      return null;
    }

    public Object visit(ASTArgumentList node, Object data) {
      return null;
    }

    public Object visit(ASTLiteral node, Object data) {
      if (node.value instanceof Integer) {
        ((Stack) data).push(new BasicOperand(((Integer) node.value).intValue()));
      } else if (node.value instanceof Float) {
        ((Stack) data).push(new BasicOperand(((Float) node.value).floatValue()));
      } else if (node.value instanceof Character) {
        ((Stack) data).push(new BasicOperand(((Character) node.value).charValue()));
      } else if (node.value instanceof String) {
        String s = (String) (node.value);
        s = s.substring(1, s.length() - 1);
        ((Stack) data).push(new BasicOperand(s));
      } else if (node.value instanceof Boolean) {
        ((Stack) data).push(new BasicOperand(((Boolean) node.value).booleanValue()));
      }
      return null;
    }

    public Object visit(ASTType node, Object data) {
      logger.log(BasicLevel.DEBUG, "Visit Type: " + node);
      return null;
    }

    public Object visit(ASTQualifiedName node, Object data) {
      ((Stack) data).push(new BasicOperand((String) node.value));
      return null;
    }


    /**
     * Visit method to call from constructor.
     * Child node visitors get a <code>java.util.Stack</code> as data parameter.
     * @throws java.lang.Exception any nested exception thrown from other visit method
     */
    public Object visit(SimpleNode node) throws Exception {
      return visit(node, new Stack());
    }

    /**
     * Generic visit method that traverses all child nodes
     */
    public Object visit(SimpleNode node, Object data) {
      return node.childrenAccept(this, data);
    }

    public Object visit(ASTSpeedoQL node, Object data) {
      return null;
    }

    private boolean usedInRelationalExpresssion(int op) {
      switch (op) {
      case SpeedoQLConstants.OR:
      case SpeedoQLConstants.AND:
      case SpeedoQLConstants.BITWISEOR:
      case SpeedoQLConstants.BITWISEXOR:
      case SpeedoQLConstants.BITWISEAND:
      case SpeedoQLConstants.EQ:
      case SpeedoQLConstants.NEQ:
      case SpeedoQLConstants.LT:
      case SpeedoQLConstants.GT:
      case SpeedoQLConstants.GTE:
      case SpeedoQLConstants.LTE:
        logger.log(BasicLevel.DEBUG, "node useful");
        return true;
      default:
        logger.log(BasicLevel.DEBUG, "node useless");
        return false;
      }
    }

  }
  // OTHER METHODS //
  //---------------//

  /**
   * Calculates if an expression can be used as Jorm predicate as inheritance
   * filter.
   * @param e is the medor Expression to analyze.
   * @return true if the expression is compatible.
   */
  private boolean isJormPredicate(Expression e) {
    return isSimpleOperator(e)
        || (e instanceof ConditionalAnd
        && isJormPredicate(((Operator) e).getExpression(0))
        && isJormPredicate(((Operator) e).getExpression(1)));
  }

  private boolean isSimpleOperator(Expression e) {
    boolean res = e instanceof Equal
        || e instanceof Greater
        || e instanceof GreaterEqual
        || e instanceof Lower
        || e instanceof LowerEqual;
    if (res == false) {
      return false;
    }
    Operator op = (Operator) e;

    if (!(op.getExpression(0) instanceof Operand
        && op.getExpression(1) instanceof Operand)) {
      return false;
    }
    Operand o0 = (Operand) op.getExpression(0);
    Operand o1 = (Operand) op.getExpression(1);
    if (o0.getType().getTypeCode() == PTypeSpace.STRING.getTypeCode()) {
      return true;
    } else if (o1.getType().getTypeCode() == PTypeSpace.STRING.getTypeCode()) {
      //reverse the order: column name at left
      op.setExpression(0, o1);
      op.setExpression(1, o0);
      return true;
    } else {
      return false;
    }
  }
}
TOP

Related Classes of org.objectweb.speedo.generation.jorm.rdb.FilterManager$FilterParser

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.