/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed 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.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.parser.visitor.or;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.alibaba.druid.wall.spi.WallVisitorUtils;
import com.dangdang.ddframe.rdb.sharding.parser.visitor.SQLVisitor;
import com.dangdang.ddframe.rdb.sharding.parser.visitor.basic.mysql.AbstractMySQLVisitor;
import com.dangdang.ddframe.rdb.sharding.parser.visitor.or.node.AbstractOrASTNode;
import com.dangdang.ddframe.rdb.sharding.parser.visitor.or.node.CompositeOrASTNode;
import com.dangdang.ddframe.rdb.sharding.parser.visitor.or.node.SimpleOrASTNode;
import com.google.common.base.Optional;
/**
* 逻辑OR条件访问器.
*
* @author gaohongtao
*/
public class OrVisitor extends AbstractMySQLVisitor {
private AbstractOrASTNode orASTNode;
public OrVisitor(final SQLASTOutputVisitor dependencyVisitor) {
setParameters(dependencyVisitor.getParameters());
SQLVisitor visitor = (SQLVisitor) dependencyVisitor;
if (null != visitor.getParseContext().getCurrentTable()) {
getParseContext().setCurrentTable(visitor.getParseContext().getCurrentTable().getName(), Optional.<String>absent());
}
getParseContext().getParsedResult().getRouteContext().getTables().addAll(visitor.getParseContext().getParsedResult().getRouteContext().getTables());
getParseContext().setShardingRule(visitor.getParseContext().getShardingRule());
}
/**
* 进行OR表达式的访问.
*
* @param sqlObject SQL对象
* @return OR访问节点
*/
public Optional<AbstractOrASTNode> visitHandle(final SQLObject sqlObject) {
reset();
sqlObject.accept(this);
postVisitHandle();
return Optional.fromNullable(orASTNode);
}
private void reset() {
orASTNode = null;
getParseContext().getCurrentConditionContext().clear();
getParseContext().setHasOrCondition(false);
}
private void postVisitHandle() {
if (null == orASTNode) {
return;
}
if (!getParseContext().getCurrentConditionContext().isEmpty()) {
CompositeOrASTNode existingOutConditionOrASTNode = new CompositeOrASTNode();
existingOutConditionOrASTNode.addSubNode(orASTNode);
existingOutConditionOrASTNode.addOutConditions(getParseContext().getCurrentConditionContext());
orASTNode = existingOutConditionOrASTNode;
}
orASTNode.createOrASTAsRootNode();
}
/**
* 逻辑OR访问器, 每次只解析一层OR条件.
*
* @param x 二元表达式
* @return false 停止访问AST
*/
@Override
public boolean visit(final SQLBinaryOpExpr x) {
if (!SQLBinaryOperator.BooleanOr.equals(x.getOperator())) {
return super.visit(x);
}
if (Boolean.TRUE.equals(WallVisitorUtils.getValue(x))) {
return false;
}
if (orASTNode == null) {
orASTNode = new SimpleOrASTNode(x, new OrVisitor(this));
} else {
CompositeOrASTNode existingOutConditionOrASTNode = new CompositeOrASTNode();
existingOutConditionOrASTNode.addSubNode(orASTNode);
existingOutConditionOrASTNode.addSubNode(new SimpleOrASTNode(x, new OrVisitor(this)));
orASTNode = existingOutConditionOrASTNode;
}
return false;
}
}