/**
* 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.hadoop.hive.ql.io.sarg;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* The inner representation of the SearchArgument. Most users should not
* need this interface, it is only for file formats that need to translate
* the SearchArgument into an internal form.
*/
public class ExpressionTree {
public enum Operator {OR, AND, NOT, LEAF, CONSTANT}
private final Operator operator;
private final List<ExpressionTree> children;
private int leaf;
private final SearchArgument.TruthValue constant;
ExpressionTree() {
operator = null;
children = null;
leaf = 0;
constant = null;
}
ExpressionTree(Operator op, ExpressionTree... kids) {
operator = op;
children = new ArrayList<ExpressionTree>();
leaf = -1;
this.constant = null;
Collections.addAll(children, kids);
}
ExpressionTree(int leaf) {
operator = Operator.LEAF;
children = null;
this.leaf = leaf;
this.constant = null;
}
ExpressionTree(SearchArgument.TruthValue constant) {
operator = Operator.CONSTANT;
children = null;
this.leaf = -1;
this.constant = constant;
}
ExpressionTree(ExpressionTree other) {
this.operator = other.operator;
if (other.children == null) {
this.children = null;
} else {
this.children = new ArrayList<ExpressionTree>();
for(ExpressionTree child: other.children) {
children.add(new ExpressionTree(child));
}
}
this.leaf = other.leaf;
this.constant = other.constant;
}
public SearchArgument.TruthValue evaluate(SearchArgument.TruthValue[] leaves
) {
SearchArgument.TruthValue result = null;
switch (operator) {
case OR:
for(ExpressionTree child: children) {
result = child.evaluate(leaves).or(result);
}
return result;
case AND:
for(ExpressionTree child: children) {
result = child.evaluate(leaves).and(result);
}
return result;
case NOT:
return children.get(0).evaluate(leaves).not();
case LEAF:
return leaves[leaf];
case CONSTANT:
return constant;
default:
throw new IllegalStateException("Unknown operator: " + operator);
}
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
switch (operator) {
case OR:
buffer.append("(or");
for(ExpressionTree child: children) {
buffer.append(' ');
buffer.append(child.toString());
}
buffer.append(')');
break;
case AND:
buffer.append("(and");
for(ExpressionTree child: children) {
buffer.append(' ');
buffer.append(child.toString());
}
buffer.append(')');
break;
case NOT:
buffer.append("(not ");
buffer.append(children.get(0));
buffer.append(')');
break;
case LEAF:
buffer.append("leaf-");
buffer.append(leaf);
break;
case CONSTANT:
buffer.append(constant);
break;
}
return buffer.toString();
}
public Operator getOperator() {
return operator;
}
public List<ExpressionTree> getChildren() {
return children;
}
public SearchArgument.TruthValue getConstant() {
return constant;
}
public int getLeaf() {
return leaf;
}
public void setLeaf(int leaf) {
this.leaf = leaf;
}
}