blob: 23fa3d56952b729fb0213a782e50ef66c7e64817 [file] [log] [blame]
/*
* 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) {
}
}