| /* |
| * 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.eagle.query.parser; |
| |
| import org.apache.eagle.query.antlr.generated.EagleFilterListener; |
| import org.apache.eagle.query.antlr.generated.EagleFilterParser; |
| import org.antlr.v4.runtime.ParserRuleContext; |
| import org.antlr.v4.runtime.tree.ErrorNode; |
| import org.antlr.v4.runtime.tree.TerminalNode; |
| import org.apache.commons.lang.StringEscapeUtils; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.util.List; |
| import java.util.Stack; |
| import java.util.regex.Matcher; |
| |
| public class EagleQueryFilterListenerImpl implements EagleFilterListener { |
| private static final Logger LOG = LoggerFactory.getLogger(EagleQueryFilterListenerImpl.class); |
| private Stack<ORExpression> stack = new Stack<ORExpression>(); |
| |
| public ORExpression result() { |
| return stack.pop(); |
| } |
| |
| public void enterEquation(EagleFilterParser.EquationContext ctx) { |
| } |
| |
| public void exitEquation(EagleFilterParser.EquationContext ctx) { |
| TerminalNode id = ctx.ID(); |
| TerminalNode op = ctx.OP(); |
| List<TerminalNode> values = ctx.VALUE(); |
| TerminalNode value = values.get(0); |
| |
| if (values.size() == 2) { |
| // value op value |
| id = values.get(0); |
| value = values.get(1); |
| } |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("ID:" + id.getText() + ", OP:" + op.getText() + ", VALUE:" + value); |
| } |
| |
| AtomicExpression kv = new AtomicExpression(); |
| kv.setKey(id.getText()); |
| kv.setOp(ComparisonOperator.locateOperator(op.getText())); |
| |
| try { |
| kv.setValueType(TokenType.locate(value.getText())); |
| } catch (Exception ex) { |
| LOG.error("Failed to locate value type for: " + value.getText() + " due to exception: " + ex.getMessage(), ex); |
| } |
| |
| try { |
| kv.setKeyType(TokenType.locate(id.getText())); |
| } catch (Exception ex) { |
| LOG.error("Failed to locate id type for: " + id.getText() + " due to exception: " + ex.getMessage(), ex); |
| } |
| |
| // if (id != null) { |
| kv.setKey(postProcessNode(id.getText(),kv.getKeyType())); |
| // } |
| |
| // if (value != null) { |
| kv.setValue(postProcessNode(value.getText(),kv.getValueType())); |
| // As to List value, it will escape in List parser but not here |
| if (kv.getValueType() != TokenType.LIST) { |
| kv.setValue(StringEscapeUtils.unescapeJava(kv.getValue())); |
| } |
| // } |
| |
| // push to stack |
| ORExpression orExpr = new ORExpression(); |
| ANDExpression andExpr = new ANDExpression(); |
| andExpr.getAtomicExprList().add(kv); |
| orExpr.getANDExprList().add(andExpr); |
| stack.push(orExpr); |
| } |
| |
| private String postProcessNode(String text,TokenType type) { |
| int len = text.length(); |
| int start = 0; |
| int end = len; |
| if (text.startsWith("\"")) { |
| start = 1; |
| } |
| if (text.endsWith("\"")) { |
| end = len - 1; |
| } |
| text = text.substring(start, end); |
| if (type == TokenType.EXP) { |
| Matcher matcher = TokenConstant.EXP_PATTERN.matcher(text); |
| if (matcher.find()) { |
| text = matcher.group(1); |
| } |
| text = text.replace(TokenConstant.ID_PREFIX,TokenConstant.WHITE_SPACE); |
| } |
| return text; |
| } |
| |
| public void enterCombine(EagleFilterParser.CombineContext ctx) { |
| |
| } |
| |
| public void exitCombine(EagleFilterParser.CombineContext ctx) { |
| int numChild = ctx.getChildCount(); |
| if (numChild == 1) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Only one child, skip ..."); |
| } |
| return; // does nothing for a combine which has only one equation |
| } |
| |
| if ((ctx.LPAREN() != null) && (ctx.RPAREN() != null)) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("LPAREN + RPAREN rule matched, skip ..."); |
| } |
| return; // does nothing for a combine which is within parenthesis |
| } |
| ORExpression orExprRight = stack.pop(); |
| ORExpression orExprLeft = stack.pop(); |
| TerminalNode node = ctx.AND(); |
| if (node != null) { |
| ORExpression newORExpr = new ORExpression(); |
| for (ANDExpression left : orExprLeft.getANDExprList()) { |
| for (ANDExpression right : orExprRight.getANDExprList()) { |
| ANDExpression tmp = new ANDExpression(); |
| tmp.getAtomicExprList().addAll(left.getAtomicExprList()); |
| tmp.getAtomicExprList().addAll(right.getAtomicExprList()); |
| newORExpr.getANDExprList().add(tmp); |
| } |
| } |
| stack.push(newORExpr); |
| return; |
| } |
| |
| node = ctx.OR(); |
| if (node != null) { |
| ORExpression newORExpr = new ORExpression(); |
| for (ANDExpression andExpr : orExprLeft.getANDExprList()) { |
| newORExpr.getANDExprList().add(andExpr); |
| } |
| for (ANDExpression andExpr : orExprRight.getANDExprList()) { |
| newORExpr.getANDExprList().add(andExpr); |
| } |
| stack.push(newORExpr); |
| return; |
| } |
| LOG.warn("Should never come here!"); |
| } |
| |
| public void enterFilter(EagleFilterParser.FilterContext ctx) { |
| |
| } |
| |
| public void exitFilter(EagleFilterParser.FilterContext ctx) { |
| // print all relations (KeyValueFilter AND KeyValueFilter) OR (KeyValueFilter AND KeyValueFilter) OR (KeyValueFilter AND KeyValueFilter)" |
| ORExpression orExpr = stack.peek(); |
| if (LOG.isDebugEnabled()) { |
| LOG.debug(orExpr.toString()); |
| } |
| } |
| |
| public void visitTerminal(TerminalNode node) { |
| } |
| |
| public void visitErrorNode(ErrorNode node) { |
| } |
| |
| public void enterEveryRule(ParserRuleContext ctx) { |
| } |
| |
| public void exitEveryRule(ParserRuleContext ctx) { |
| } |
| } |