/*
* This file is part of Zql.
*
* Zql is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Zql is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Zql. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gibello.zql;
import java.io.* ;
import java.util.* ;
/**
* ZExpression: an SQL Expression
* An SQL expression is an operator and one or more operands
* Example: a AND b AND c operator = AND, operands = (a, b, c)
*/
public class ZExpression implements ZExp {
String op_ = null;
Vector operands_ = null;
/**
* Create an SQL Expression given the operator
* @param op The operator
*/
public ZExpression(String op) {
op_ = new String(op);
}
/**
* Create an SQL Expression given the operator and 1st operand
* @param op The operator
* @param o1 The 1st operand
*/
public ZExpression(String op, ZExp o1) {
op_ = new String(op);
addOperand(o1);
}
/**
* Create an SQL Expression given the operator, 1st and 2nd operands
* @param op The operator
* @param o1 The 1st operand
* @param o2 The 2nd operand
*/
public ZExpression(String op, ZExp o1, ZExp o2) {
op_ = new String(op);
addOperand(o1);
addOperand(o2);
}
/**
* Get this expression's operator.
* @return the operator.
*/
public String getOperator() { return op_; }
/**
* Set the operands list
* @param v A vector that contains all operands (ZExp objects).
*/
public void setOperands(Vector v) {
operands_ = v;
}
/**
* Get this expression's operands.
* @return the operands (as a Vector of ZExp objects).
*/
public Vector getOperands() {
return operands_;
}
/**
* Add an operand to the current expression.
* @param o The operand to add.
*/
public void addOperand(ZExp o) {
if(operands_ == null) operands_ = new Vector();
operands_.addElement(o);
}
/**
* Get an operand according to its index (position).
* @param pos The operand index, starting at 0.
* @return The operand at the specified index, null if out of bounds.
*/
public ZExp getOperand(int pos) {
if(operands_ == null || pos >= operands_.size()) return null;
return (ZExp)operands_.elementAt(pos);
}
/**
* Get the number of operands
* @return The number of operands
*/
public int nbOperands() {
if(operands_ == null) return 0;
return operands_.size();
}
/**
* String form of the current expression (reverse polish notation).
* Example: a 》 1 AND b = 2 -》 (AND (》 a 1) (= b 2))
* @return The current expression in reverse polish notation (a String)
*/
public String toReversePolish() {
StringBuffer buf = new StringBuffer("(");
buf.append(op_);
for(int i = 0; i < nbOperands(); i++) {
ZExp opr = getOperand(i);
if(opr instanceof ZExpression)
buf.append(" " + ((ZExpression)opr).toReversePolish()); // Warning recursive call
else if(opr instanceof ZQuery)
buf.append(" (" + opr.toString() + ")");
else
buf.append(" " + opr.toString());
}
buf.append(")");
return buf.toString();
}
public String toString() {
if(op_.equals("?")) return op_; // For prepared columns ("?")
if(ZUtils.isCustomFunction(op_) >= 0)
return formatFunction();
StringBuffer buf = new StringBuffer();
if(needPar(op_)) buf.append("(");
ZExp operand;
switch(nbOperands()) {
case 1:
operand = getOperand(0);
if(operand instanceof ZConstant) {
// Operator may be an aggregate function (MAX, SUM...)
if(ZUtils.isAggregate(op_))
buf.append(op_ + "(" + operand.toString() + ")");
else if(op_.equals("IS NULL") || op_.equals("IS NOT NULL"))
buf.append(operand.toString() + " " + op_);
// "," = list of values, here just one single value
else if(op_.equals(",")) buf.append(operand.toString());
else buf.append(op_ + " " + operand.toString());
} else if(operand instanceof ZQuery) {
buf.append(op_ + " (" + operand.toString() + ")");
} else {
if(op_.equals("IS NULL") || op_.equals("IS NOT NULL"))
buf.append(operand.toString() + " " + op_);
// "," = list of values, here just one single value
else if(op_.equals(",")) buf.append(operand.toString());
else buf.append(op_ + " " + operand.toString());
}
break;
case 3:
if(op_.toUpperCase().endsWith("BETWEEN")) {
buf.append(getOperand(0).toString() + " " + op_ + " "
+ getOperand(1).toString()
+ " AND " + getOperand(2).toString());
break;
}
default:
boolean in_op = op_.equals("IN") || op_.equals("NOT IN");
int nb = nbOperands();
for(int i = 0; i < nb; i++) {
if(in_op && i==1) buf.append(" " + op_ + " (");
operand = getOperand(i);
if(operand instanceof ZQuery && !in_op) {
buf.append("(" + operand.toString() + ")");
} else {
buf.append(operand.toString());
}
if(i < nb-1) {
if(op_.equals(",") || (in_op && i>0)) buf.append(", ");
else if(!in_op) buf.append(" " + op_ + " ");
}
}
if(in_op) buf.append(")");
break;
}
if(needPar(op_)) buf.append(")");
return buf.toString();
}
private boolean needPar(String op) {
String tmp = op.toUpperCase();
return ! (tmp.equals("ANY") || tmp.equals("ALL")
|| tmp.equals("UNION") || ZUtils.isAggregate(tmp));
}
private String formatFunction() {
StringBuffer b = new StringBuffer(op_ + "(");
int nb = nbOperands();
for(int i = 0; i < nb; i++) {
b.append(getOperand(i).toString() + (i < nb-1 ? "," : ""));
}
b.append(")");
return b.toString();
}
};