Package org.apache.chemistry.opencmis.inmemory.query

Source Code of org.apache.chemistry.opencmis.inmemory.query.AbstractQueryConditionProcessor

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.
*/
package org.apache.chemistry.opencmis.inmemory.query;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;

import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenSource;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.runtime.tree.Tree;
import org.apache.chemistry.opencmis.server.support.query.CalendarHelper;
import org.apache.chemistry.opencmis.server.support.query.CmisQlStrictLexer;
import org.apache.chemistry.opencmis.server.support.query.CmisQlStrictParser;
import org.apache.chemistry.opencmis.server.support.query.CmisQlStrictParser_CmisBaseGrammar.query_return;
import org.apache.chemistry.opencmis.server.support.query.CmisQueryWalker;
import org.apache.chemistry.opencmis.server.support.query.StringUtil;
import org.apache.chemistry.opencmis.server.support.query.TextSearchLexer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class AbstractQueryConditionProcessor implements QueryConditionProcessor {

    private static final Log LOG = LogFactory.getLog(ProcessQueryTest.class);
   
    public abstract void onStartProcessing(Tree whereNode);
    public abstract void onStopProcessing();

    // Compare operators
    public abstract void onEquals(Tree eqNode, Tree leftNode, Tree rightNode);
    public abstract void onNotEquals(Tree neNode, Tree leftNode, Tree rightNode);
    public abstract void onGreaterThan(Tree gtNode, Tree leftNode, Tree rightNode);
    public abstract void onGreaterOrEquals(Tree geNode, Tree leftNode, Tree rightNode);
    public abstract void onLessThan(Tree ltNode, Tree leftNode, Tree rightNode);
    public abstract void onLessOrEquals(Tree leqNode, Tree leftNode, Tree rightNode);

    // Boolean operators
    public void onPreNot(Tree opNode, Tree leftNode) {
    }
    public abstract void onNot(Tree opNode, Tree leftNode);
    public void onPostNot(Tree opNode, Tree leftNode) {
    }
    public void onPreAnd(Tree opNode, Tree leftNode, Tree rightNode) {
    }
    public abstract void onAnd(Tree opNode, Tree leftNode, Tree rightNode);
    public void onPostAnd(Tree opNode, Tree leftNode, Tree rightNode) {
    }
    public void onPreOr(Tree opNode, Tree leftNode, Tree rightNode) {
    }
    public abstract void onOr(Tree opNode, Tree leftNode, Tree rightNode);
    public void onPostOr(Tree opNode, Tree leftNode, Tree rightNode) {
    }

    // Multi-value:
    public abstract void onIn(Tree node, Tree colNode, Tree listNode);
    public abstract void onNotIn(Tree node, Tree colNode, Tree listNode);
    public abstract void onInAny(Tree node, Tree colNode, Tree listNode);
    public abstract void onNotInAny(Tree node, Tree colNode, Tree listNode);
    public abstract void onEqAny(Tree node, Tree literalNode, Tree colNode);

    // Null comparisons:
    public abstract void onIsNull(Tree nullNode, Tree colNode);
    public abstract void onIsNotNull(Tree notNullNode, Tree colNode);

    // String matching:
    public abstract void onIsLike(Tree node, Tree colNode, Tree stringNode);
    public abstract void onIsNotLike(Tree node, Tree colNode, Tree stringNode);

    // Functions:
    public abstract void onInFolder(Tree node, Tree colNode, Tree paramNode);
    public abstract void onInTree(Tree node, Tree colNode, Tree paramNode);
    public abstract void onScore(Tree node);
   
    public void onPreTextAnd(Tree node, List<Tree> conjunctionNodes) {
    }
    public abstract void onTextAnd(Tree node, List<Tree> conjunctionNodes);
    public void onPostTextAnd(Tree node, List<Tree> conjunctionNodes) {
    }
    public void onPreTextOr(Tree node, List<Tree> termNodes) {
    }
    public abstract void onTextOr(Tree node, List<Tree> termNodes);
    public void onPostTextOr(Tree node, List<Tree> termNodes) {
    }
    public abstract void onTextMinus(Tree node, Tree notNode);
    public abstract void onTextWord(String word);
    public abstract void onTextPhrase(String phrase);

    // convenience method because everybody needs this piece of code
    public static CmisQueryWalker getWalker(String statement) throws UnsupportedEncodingException, IOException, RecognitionException {
        CharStream input = new ANTLRInputStream(new ByteArrayInputStream(statement.getBytes("UTF-8")));
        TokenSource lexer = new CmisQlStrictLexer(input);
        TokenStream tokens = new CommonTokenStream(lexer);
        CmisQlStrictParser parser = new CmisQlStrictParser(tokens);
        CommonTree parserTree; // the ANTLR tree after parsing phase

        query_return parsedStatement = parser.query();
//        if (parser.errorMessage != null) {
//            throw new RuntimeException("Cannot parse query: " + statement + " (" + parser.errorMessage + ")");
//        }
        parserTree = (CommonTree) parsedStatement.getTree();

        CommonTreeNodeStream nodes = new CommonTreeNodeStream(parserTree);
        nodes.setTokenStream(tokens);
        CmisQueryWalker walker = new CmisQueryWalker(nodes);
        return walker;
    }


    // Base interface called from query parser
    public Boolean walkPredicate(Tree whereNode) {
        if (null != whereNode) {
            onStartProcessing(whereNode);
            evalWhereNode(whereNode);
            onStopProcessing();
        }
        return null; // unused
    }

    // ///////////////////////////////////////////////////////
    // Processing the WHERE clause

    // default implementation for ^ains
    public void onContains(Tree node, Tree typeNode, Tree searchExprNode) {
        LOG.debug("evaluating text search node: " + searchExprNode);
        evalTextSearchNode(searchExprNode);       
    }

    protected void evalWhereNode(Tree node) {
        // Ensure that we receive only valid tokens and nodes in the where
        // clause:
        LOG.debug("evaluating node: " + node.toString());
        switch (node.getType()) {
        case CmisQlStrictLexer.WHERE:
            break; // ignore
        case CmisQlStrictLexer.EQ:
            evalWhereNode(node.getChild(0));
            onEquals(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.NEQ:
            evalWhereNode(node.getChild(0));
            onNotEquals(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.GT:
            evalWhereNode(node.getChild(0));
            onGreaterThan(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.GTEQ:
            evalWhereNode(node.getChild(0));
            onGreaterOrEquals(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.LT:
            evalWhereNode(node.getChild(0));
            onLessThan(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.LTEQ:
            evalWhereNode(node.getChild(0));
            onLessOrEquals(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;

        case CmisQlStrictLexer.NOT:
            onPreNot(node, node.getChild(0));
            onNot(node, node.getChild(0));
            evalWhereNode(node.getChild(0));
            onPostNot(node, node.getChild(0));
            break;
        case CmisQlStrictLexer.AND:
            onPreAnd(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(0));
            onAnd(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            onPostAnd(node, node.getChild(0), node.getChild(1));
            break;
        case CmisQlStrictLexer.OR:
            onPreOr(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(0));
            onOr(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            onPostOr(node, node.getChild(0), node.getChild(1));
            break;

        // Multi-value:
        case CmisQlStrictLexer.IN:
            evalWhereNode(node.getChild(0));
            onIn(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.NOT_IN:
            evalWhereNode(node.getChild(0));
            onNotIn(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.IN_ANY:
            evalWhereNode(node.getChild(0));
            onInAny(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.NOT_IN_ANY:
            evalWhereNode(node.getChild(0));
            onNotInAny(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.EQ_ANY:
            evalWhereNode(node.getChild(0));
            onEqAny(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;

        // Null comparisons:
        case CmisQlStrictLexer.IS_NULL:
            onIsNull(node, node.getChild(0));
            evalWhereNode(node.getChild(0));
            break;
        case CmisQlStrictLexer.IS_NOT_NULL:
            onIsNotNull(node, node.getChild(0));
            evalWhereNode(node.getChild(0));
            break;

        // String matching
        case CmisQlStrictLexer.LIKE:
            evalWhereNode(node.getChild(0));
            onIsLike(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;
        case CmisQlStrictLexer.NOT_LIKE:
            evalWhereNode(node.getChild(0));
            onIsNotLike(node, node.getChild(0), node.getChild(1));
            evalWhereNode(node.getChild(1));
            break;

        // Functions
        case CmisQlStrictLexer.CONTAINS:
            onContains(node, null, node.getChild(0));
            break;
        case CmisQlStrictLexer.IN_FOLDER:
            if (node.getChildCount() == 1) {
                onInFolder(node, null, node.getChild(0));
                evalWhereNode(node.getChild(0));
            } else {
                evalWhereNode(node.getChild(0));
                onInFolder(node, node.getChild(0), node.getChild(1));
                evalWhereNode(node.getChild(1));
            }
            break;
        case CmisQlStrictLexer.IN_TREE:
            if (node.getChildCount() == 1) {
                onInTree(node, null, node.getChild(0));
                evalWhereNode(node.getChild(0));
            } else {
                evalWhereNode(node.getChild(0));
                onInTree(node, node.getChild(0), node.getChild(1));
                evalWhereNode(node.getChild(1));
            }
            break;
        case CmisQlStrictLexer.SCORE:
            onScore(node);
            break;

        default:
            // do nothing;
        }
    }

    protected void evalTextSearchNode(Tree node) {
        // Ensure that we receive only valid tokens and nodes in the where
        // clause:
        LOG.debug("evaluating node: " + node.toString());
        switch (node.getType()) {
        case TextSearchLexer.TEXT_AND:
            List<Tree> children = getChildrenAsList(node);
            onPreTextAnd(node, children);
            for (Tree child : children)
                evalTextSearchNode(child);
            onTextAnd(node, children);
            onPostTextAnd(node, children);
            break;
        case TextSearchLexer.TEXT_OR:
            children = getChildrenAsList(node);
            onPreTextOr(node, children);
            for (Tree child : children)
                evalTextSearchNode(child);
            onTextOr(node, children);
            onPostTextOr(node, children);
            break;
        case TextSearchLexer.TEXT_MINUS:
            onTextMinus(node, node.getChild(0));
            break;
        case TextSearchLexer.TEXT_SEARCH_PHRASE_STRING_LIT:
            onTextPhrase(onTextLiteral(node));
            break;
        case TextSearchLexer.TEXT_SEARCH_WORD_LIT:
            onTextWord(onTextLiteral(node));
            break;
        }
    }
       
    // helper functions that are needed by most query tree walkers

    protected Object onLiteral(Tree node) {
        int type = node.getType();
        String text = node.getText();
        switch (type) {
        case CmisQlStrictLexer.BOOL_LIT:
            return Boolean.parseBoolean(node.getText());
        case CmisQlStrictLexer.NUM_LIT:
            if (text.contains(".") || text.contains("e") || text.contains("E")) {
                return Double.parseDouble(text);
            } else {
                return Long.parseLong(text);
            }
        case CmisQlStrictLexer.STRING_LIT:
            return text.substring(1, text.length()-1);
        case CmisQlStrictLexer.TIME_LIT:
            GregorianCalendar gc = CalendarHelper.fromString(text.substring(text.indexOf('\'')+1, text.lastIndexOf('\'')));
            return gc;
        default:
            throw new RuntimeException("Unknown literal. " + node);
        }
    }
   
    protected String onTextLiteral(Tree node) {
        int type = node.getType();
        String text = node.getText();
        switch (type) {
        case TextSearchLexer.TEXT_SEARCH_PHRASE_STRING_LIT:
            return StringUtil.unescape(text.substring(1, text.length()-1), null);
        case TextSearchLexer.TEXT_SEARCH_WORD_LIT:
            return StringUtil.unescape(text, null);
        default:
            throw new RuntimeException("Unknown text literal. " + node);
        }

    }

    protected List<Object> onLiteralList(Tree node) {
        List<Object> res = new ArrayList<Object>(node.getChildCount());
        for (int i=0; i<node.getChildCount(); i++) {
            Tree literal =  node.getChild(i);
            res.add(onLiteral(literal));
        }
        return res;
    }
   
    protected List<Tree> getChildrenAsList(Tree node) {
        List<Tree> res = new ArrayList<Tree>(node.getChildCount());
        for (int i=0; i<node.getChildCount(); i++) {
            Tree childNnode =  node.getChild(i);
            res.add(childNnode);
        }
        return res;
    }
}
TOP

Related Classes of org.apache.chemistry.opencmis.inmemory.query.AbstractQueryConditionProcessor

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.