package net.sf.jsqlparser.util.deparser;
import java.util.Iterator;
import java.util.List;
import net.sf.jsqlparser.expression.AllComparisonExpression;
import net.sf.jsqlparser.expression.AnyComparisonExpression;
import net.sf.jsqlparser.expression.BinaryExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.DateValue;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.InverseExpression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NamedParameter;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.Connect;
import net.sf.jsqlparser.statement.select.SelectVisitor;
import net.sf.jsqlparser.statement.select.SubSelect;
/**
* A class to de-parse (that is, tranform from JSqlParser hierarchy into a string)
* an {@link net.sf.jsqlparser.expression.Expression}
*/
public class ExpressionDeParser implements ExpressionVisitor, ItemsListVisitor {
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
protected StringBuilder buffer;
protected SelectVisitor selectVisitor;
protected boolean useBracketsInExprList = true;
public ExpressionDeParser() {
}
/**
* @param aSelectVisitor a SelectVisitor to de-parse SubSelects. It has to share the same<br>
* StringBuilder as this object in order to work, as:
* <pre>
* <code>
* StringBuilder myBuf = new StringBuilder();
* MySelectDeparser selectDeparser = new MySelectDeparser();
* selectDeparser.setBuffer(myBuf);
* ExpressionDeParser expressionDeParser = new ExpressionDeParser(selectDeparser, myBuf);
* </code>
* </pre>
* @param aBuffer the buffer that will be filled with the expression
*/
public ExpressionDeParser(SelectVisitor aSelectVisitor, StringBuilder aBuffer) {
selectVisitor = aSelectVisitor;
buffer = aBuffer;
}
public StringBuilder getBuffer() {
return buffer;
}
public void setBuffer(StringBuilder aBuffer) {
buffer = aBuffer;
}
public void visit(Addition addition) {
visitBinaryExpression(addition, (addition.getComment() != null ? " " + addition.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " + ");
}
public void visit(AndExpression andExpression) {
visitBinaryExpression(andExpression, (andExpression.getComment() != null ? " " + andExpression.getComment() : "")
+ ExpressionDeParser.LINE_SEPARATOR + " and ");
}
public void visit(Between between) {
between.getLeftExpression().accept(this);
if (between.isNot()) {
buffer.append(between.getCommentNot() != null ? " " + between.getCommentNot() + ExpressionDeParser.LINE_SEPARATOR : "").append(" not");
}
buffer.append(between.getCommentBetween() != null ? " " + between.getCommentBetween() + ExpressionDeParser.LINE_SEPARATOR : "").append(" between ");
between.getBetweenExpressionStart().accept(this);
buffer.append(between.getCommentAnd() != null ? " " + between.getCommentAnd() + ExpressionDeParser.LINE_SEPARATOR : "").append(" and ");
between.getBetweenExpressionEnd().accept(this);
}
public void visit(Division division) {
visitBinaryExpression(division, (division.getComment() != null ? " " + division.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " / ");
}
public void visit(DoubleValue doubleValue) {
buffer.append(doubleValue.getComment() != null ? doubleValue.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(doubleValue.getValue());
}
public void visit(EqualsTo equalsTo) {
visitBinaryExpression(equalsTo, (equalsTo.getComment() != null ? " " + equalsTo.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " = ");
}
public void visit(GreaterThan greaterThan) {
visitBinaryExpression(greaterThan, (greaterThan.getComment() != null ? " " + greaterThan.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " > ");
}
public void visit(GreaterThanEquals greaterThanEquals) {
visitBinaryExpression(greaterThanEquals, (greaterThanEquals.getComment() != null ? " " + greaterThanEquals.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " >= ");
}
public void visit(InExpression inExpression) {
inExpression.getLeftExpression().accept(this);
if (inExpression.isNot()) {
buffer.append(inExpression.getCommentNot() != null ? " " + inExpression.getCommentNot() + ExpressionDeParser.LINE_SEPARATOR : "").append(" not");
}
buffer.append(inExpression.getCommentIn() != null ? " " + inExpression.getCommentIn() + ExpressionDeParser.LINE_SEPARATOR : "").append(" in ");
inExpression.getItemsList().accept(this);
}
public void visit(InverseExpression inverseExpression) {
buffer.append(inverseExpression.getComment() != null ? inverseExpression.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("-");
inverseExpression.getExpression().accept(this);
}
public void visit(IsNullExpression isNullExpression) {
isNullExpression.getLeftExpression().accept(this);
if (isNullExpression.isNot()) {
buffer.append(isNullExpression.getCommentIs() != null ? " " + isNullExpression.getCommentIs() + ExpressionDeParser.LINE_SEPARATOR : "").append(" is").append(isNullExpression.getCommentNot() != null ? " " + isNullExpression.getCommentNot() + ExpressionDeParser.LINE_SEPARATOR : "").append(" not").append(isNullExpression.getCommentNull() != null ? " " + isNullExpression.getCommentNull() + ExpressionDeParser.LINE_SEPARATOR : "").append(" null");
} else {
buffer.append(isNullExpression.getCommentIs() != null ? " " + isNullExpression.getCommentIs() + ExpressionDeParser.LINE_SEPARATOR : "").append(" is").append(isNullExpression.getCommentNull() != null ? " " + isNullExpression.getCommentNull() + ExpressionDeParser.LINE_SEPARATOR : "").append(" null");
}
}
public void visit(JdbcParameter jdbcParameter) {
buffer.append(jdbcParameter.getComment() != null ? jdbcParameter.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("?");
}
public void visit(NamedParameter namedParameter) {
buffer.append(namedParameter.toString());
}
public void visit(LikeExpression likeExpression) {
visitBinaryExpression(likeExpression, (likeExpression.getCommentLike() != null ? " " + likeExpression.getCommentLike() + ExpressionDeParser.LINE_SEPARATOR : "") + " Like ");
}
public void visit(ExistsExpression existsExpression) {
if (existsExpression.isNot()) {
buffer.append(existsExpression.getCommentNot() != null ? " " + existsExpression.getCommentNot() + ExpressionDeParser.LINE_SEPARATOR : "").append(" not").append(existsExpression.getCommentExists() != null ? " " + existsExpression.getCommentExists() + ExpressionDeParser.LINE_SEPARATOR : "").append(" exists ");
} else {
buffer.append(existsExpression.getCommentExists() != null ? " " + existsExpression.getCommentExists() + ExpressionDeParser.LINE_SEPARATOR : "").append(" exists ");
}
existsExpression.getRightExpression().accept(this);
}
public void visit(LongValue longValue) {
buffer.append(longValue.getComment() != null ? longValue.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(longValue.getStringValue());
}
public void visit(MinorThan minorThan) {
visitBinaryExpression(minorThan, (minorThan.getComment() != null ? " " + minorThan.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " < ");
}
public void visit(MinorThanEquals minorThanEquals) {
visitBinaryExpression(minorThanEquals, (minorThanEquals.getComment() != null ? " " + minorThanEquals.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " <= ");
}
public void visit(Multiplication multiplication) {
visitBinaryExpression(multiplication, (multiplication.getComment() != null ? " " + multiplication.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " * ");
}
public void visit(NotEqualsTo notEqualsTo) {
visitBinaryExpression(notEqualsTo, (notEqualsTo.getComment() != null ? " " + notEqualsTo.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " <> ");
}
public void visit(NullValue nullValue) {
buffer.append(nullValue.getComment() != null ? nullValue.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("null");
}
public void visit(OrExpression orExpression) {
visitBinaryExpression(orExpression, (orExpression.getComment() != null ? " " + orExpression.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " or ");
}
public void visit(Parenthesis parenthesis) {
if (parenthesis.isNot()) {
buffer.append(parenthesis.getCommentNot() != null ? " " + parenthesis.getCommentNot() + ExpressionDeParser.LINE_SEPARATOR : "").append(" not ");
}
buffer.append(parenthesis.getCommentBeginBracket() != null ? parenthesis.getCommentBeginBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("(");
parenthesis.getExpression().accept(this);
buffer.append(parenthesis.getCommentEndBracket() != null ? parenthesis.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")");
}
public void visit(StringValue stringValue) {
buffer.append(stringValue.getComment() != null ? stringValue.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("'").append(stringValue.getValue()).append("'");
}
public void visit(Subtraction subtraction) {
visitBinaryExpression(subtraction, (subtraction.getComment() != null ? subtraction.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "") + "-");
}
private void visitBinaryExpression(BinaryExpression binaryExpression, String operator) {
if (binaryExpression.isNot()) {
buffer.append(binaryExpression.getCommentNot() != null ? " " + binaryExpression.getCommentNot() + ExpressionDeParser.LINE_SEPARATOR : "").append(" not ");
}
binaryExpression.getLeftExpression().accept(this);
buffer.append(operator);
binaryExpression.getRightExpression().accept(this);
}
public void visit(SubSelect subSelect) {
buffer.append(subSelect.getCommentBeginBracket() != null ? subSelect.getCommentBeginBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("(");
subSelect.getSelectBody().accept(selectVisitor);
buffer.append(subSelect.getCommentEndBracket() != null ? subSelect.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")");
}
public void visit(Column tableColumn) {
buffer.append(tableColumn.getComment() != null ? tableColumn.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "");
if (tableColumn.getTable().getName() != null) {
String tableName = tableColumn.getTable().getWholeTableName();
buffer.append(tableName).append(".");
}
buffer.append(tableColumn.getColumnName());
}
public void visit(Function function) {
if (function.isEscaped()) {
buffer.append(function.getCommentBeginEscaped() != null ? function.getCommentBeginEscaped() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("{fn ");
}
buffer.append(function.getCommentName() != null ? function.getCommentName() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(function.getName());
if (function.isAllColumns()) {
buffer.append(function.getCommentBeginEscaped() != null ? function.getCommentBeginBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("(").append(function.getCommentBeginEscaped() != null ? function.getCommentAllColumns() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("*").append(function.getCommentBeginEscaped() != null ? function.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")");
} else if (function.getParameters() == null) {
buffer.append(function.getCommentBeginEscaped() != null ? function.getCommentBeginBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("(").append(function.getCommentEndEscaped() != null ? function.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")");
} else {
boolean oldUseBracketsInExprList = useBracketsInExprList;
if (function.isDistinct()) {
useBracketsInExprList = false;
buffer.append(function.getCommentBeginEscaped() != null ? function.getCommentBeginBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("(").append(function.getCommentDistinct() != null ? function.getCommentDistinct() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Distinct ");
}
visit(function.getParameters());
useBracketsInExprList = oldUseBracketsInExprList;
if (function.isDistinct()) {
buffer.append(function.getCommentBeginEscaped() != null ? function.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")");
}
}
if (function.isEscaped()) {
buffer.append(function.getCommentEndEscaped() != null ? function.getCommentEndEscaped() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("}");
}
}
public void visit(ExpressionList expressionList) {
if (useBracketsInExprList) {
buffer.append("(");
}
for (int i = 0; i < expressionList.getExpressions().size(); i++) {
Expression expression = (Expression) expressionList.getExpressions().get(i);
expression.accept(this);
buffer.append((i < expressionList.getExpressions().size() - 1) ? (!"".equals(expressionList.getCommentsComma().get(i)) ? " "
+ expressionList.getCommentsComma().get(i) + ExpressionDeParser.LINE_SEPARATOR : "") + ", " : "");
}
if (useBracketsInExprList) {
buffer.append(expressionList.getCommentEndBracket() != null ? expressionList.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")");
}
}
public SelectVisitor getSelectVisitor() {
return selectVisitor;
}
public void setSelectVisitor(SelectVisitor visitor) {
selectVisitor = visitor;
}
public void visit(DateValue dateValue) {
buffer.append(dateValue.getComment() != null ? dateValue.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("{d '").append(dateValue.getValue().toString()).append("'}");
}
public void visit(TimestampValue timestampValue) {
buffer.append(timestampValue.getComment() != null ? timestampValue.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("{ts '").append(timestampValue.getValue().toString()).append("'}");
}
public void visit(TimeValue timeValue) {
buffer.append(timeValue.getComment() != null ? timeValue.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("{t '").append(timeValue.getValue().toString()).append("'}");
}
public void visit(CaseExpression caseExpression) {
buffer.append(caseExpression.getCommentCase() != null ? caseExpression.getCommentElse() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Case ");
Expression switchExp = caseExpression.getSwitchExpression();
if (switchExp != null) {
switchExp.accept(this);
}
List clauses = caseExpression.getWhenClauses();
for (Iterator iter = clauses.iterator(); iter.hasNext();) {
Expression exp = (Expression) iter.next();
exp.accept(this);
}
Expression elseExp = caseExpression.getElseExpression();
if (elseExp != null) {
elseExp.accept(this);
}
buffer.append(caseExpression.getCommentEnd() != null ? " " + caseExpression.getCommentEnd() + ExpressionDeParser.LINE_SEPARATOR : "").append(" End");
}
public void visit(WhenClause whenClause) {
buffer.append(whenClause.getCommentWhen() != null ? " " + whenClause.getCommentWhen() + ExpressionDeParser.LINE_SEPARATOR : "").append(" When ");
whenClause.getWhenExpression().accept(this);
buffer.append(whenClause.getCommentThen() != null ? " " + whenClause.getCommentThen() + ExpressionDeParser.LINE_SEPARATOR : "").append(" Then ");
whenClause.getThenExpression().accept(this);
}
public void visit(AllComparisonExpression allComparisonExpression) {
buffer.append(allComparisonExpression.getComment() != null ? " " + allComparisonExpression.getComment() + ExpressionDeParser.LINE_SEPARATOR : "").append(" all ");
allComparisonExpression.GetSubSelect().accept((ExpressionVisitor) this);
}
public void visit(AnyComparisonExpression anyComparisonExpression) {
buffer.append(anyComparisonExpression.getComment() != null ? " " + anyComparisonExpression.getComment() + ExpressionDeParser.LINE_SEPARATOR : "").append(" any ");
anyComparisonExpression.GetSubSelect().accept((ExpressionVisitor) this);
}
public void visit(Concat concat) {
visitBinaryExpression(concat, (concat.getComment() != null ? " " + concat.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " || ");
}
public void visit(Matches matches) {
visitBinaryExpression(matches, (matches.getComment() != null ? " " + matches.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " @@ ");
}
public void visit(BitwiseAnd bitwiseAnd) {
visitBinaryExpression(bitwiseAnd, (bitwiseAnd.getComment() != null ? " " + bitwiseAnd.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " & ");
}
public void visit(BitwiseOr bitwiseOr) {
visitBinaryExpression(bitwiseOr, (bitwiseOr.getComment() != null ? " " + bitwiseOr.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " | ");
}
public void visit(BitwiseXor bitwiseXor) {
visitBinaryExpression(bitwiseXor, (bitwiseXor.getComment() != null ? " " + bitwiseXor.getComment() + ExpressionDeParser.LINE_SEPARATOR : "") + " ^ ");
}
public void visit(Connect aConnect) {
buffer.append(" ").append(aConnect.toString());
}
}