content: 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.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.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 {
  
      protected StringBuffer buffer;
      protected SelectVisitor selectVisitor;
      protected boolean useBracketsInExprList = true;
  
      public ExpressionDeParser() {
      }
  
      /**
       * @param selectVisitor a SelectVisitor to de-parse SubSelects. It has to share the same<br>
       * StringBuffer as this object in order to work, as:
       * <pre>
       * <code>
       * StringBuffer myBuf = new StringBuffer();
       * MySelectDeparser selectDeparser = new  MySelectDeparser();
       * selectDeparser.setBuffer(myBuf);
       * ExpressionDeParser expressionDeParser = new ExpressionDeParser(selectDeparser, myBuf);
       * </code>
       * </pre>
       * @param buffer the buffer that will be filled with the expression
       */
      public ExpressionDeParser(SelectVisitor selectVisitor, StringBuffer buffer) {
          this.selectVisitor = selectVisitor;
          this.buffer = buffer;
      }
  
      public StringBuffer getBuffer() {
          return buffer;
      }
  
      public void setBuffer(StringBuffer buffer) {
          this.buffer = buffer;
      }
  
      public void visit(Addition addition) {
          visitBinaryExpression(addition, " + ");
      }
  
      public void visit(AndExpression andExpression) {
          visitBinaryExpression(andExpression, " AND ");
      }
  
      public void visit(Between between) {
          between.getLeftExpression().accept(this);
          if (between.isNot())
              buffer.append(" NOT");
  
          buffer.append(" BETWEEN ");
          between.getBetweenExpressionStart().accept(this);
          buffer.append(" AND ");
          between.getBetweenExpressionEnd().accept(this);
  
      }
  
      public void visit(Division division) {
          visitBinaryExpression(division, " / ");
  
      }
  
      public void visit(DoubleValue doubleValue) {
          buffer.append(doubleValue.getValue());
  
      }
  
      public void visit(EqualsTo equalsTo) {
          visitBinaryExpression(equalsTo, " = ");
      }
  
      public void visit(GreaterThan greaterThan) {
          visitBinaryExpression(greaterThan, " > ");
      }
  
      public void visit(GreaterThanEquals greaterThanEquals) {
          visitBinaryExpression(greaterThanEquals, " >= ");
  
      }
  
      public void visit(InExpression inExpression) {
  
          inExpression.getLeftExpression().accept(this);
          if (inExpression.isNot())
              buffer.append(" NOT");
          buffer.append(" IN ");
  
          inExpression.getItemsList().accept(this);
      }
  
      public void visit(InverseExpression inverseExpression) {
          buffer.append("-");
          inverseExpression.getExpression().accept(this);
      }
  
      public void visit(IsNullExpression isNullExpression) {
          isNullExpression.getLeftExpression().accept(this);
          if (isNullExpression.isNot()) {
              buffer.append(" IS NOT NULL");
          } else {
              buffer.append(" IS NULL");
          }
      }
  
      public void visit(JdbcParameter jdbcParameter) {
          buffer.append("?");
  
      }
  
      public void visit(LikeExpression likeExpression) {
          visitBinaryExpression(likeExpression, " LIKE ");
  
      }
  
      public void visit(ExistsExpression existsExpression) {
          if (existsExpression.isNot()) {
              buffer.append(" NOT EXISTS ");
          } else {
              buffer.append(" EXISTS ");
          }
          existsExpression.getRightExpression().accept(this);
      }
  
      public void visit(LongValue longValue) {
          buffer.append(longValue.getStringValue());
  
      }
  
      public void visit(MinorThan minorThan) {
          visitBinaryExpression(minorThan, " < ");
  
      }
  
      public void visit(MinorThanEquals minorThanEquals) {
          visitBinaryExpression(minorThanEquals, " <= ");
  
      }
  
      public void visit(Multiplication multiplication) {
          visitBinaryExpression(multiplication, " * ");
  
      }
  
      public void visit(NotEqualsTo notEqualsTo) {
          visitBinaryExpression(notEqualsTo, " <> ");
  
      }
  
      public void visit(NullValue nullValue) {
          buffer.append("NULL");
  
      }
  
      public void visit(OrExpression orExpression) {
          visitBinaryExpression(orExpression, " OR ");
  
      }
  
      public void visit(Parenthesis parenthesis) {
      	if (parenthesis.isNot())
              buffer.append(" NOT ");
      		
          buffer.append("(");
          parenthesis.getExpression().accept(this);
          buffer.append(")");
  
      }
  
      public void visit(StringValue stringValue) {
          buffer.append("'" + stringValue.getValue() + "'");
  
      }
  
      public void visit(Subtraction subtraction) {
          visitBinaryExpression(subtraction, "-");
  
      }
  
      private void visitBinaryExpression(BinaryExpression binaryExpression, String operator) {
          if (binaryExpression.isNot())
              buffer.append(" NOT ");
          binaryExpression.getLeftExpression().accept(this);
          buffer.append(operator);
          binaryExpression.getRightExpression().accept(this);
  
      }
  
      public void visit(SubSelect subSelect) {
          buffer.append("(");
          subSelect.getSelectBody().accept(selectVisitor);
          buffer.append(")");
      }
  
      public void visit(Column tableColumn) {
          String tableName = tableColumn.getTable().getWholeTableName();
          if (tableName != null) {
              buffer.append(tableName + ".");
          }
  
          buffer.append(tableColumn.getColumnName());
      }
  
      public void visit(Function function) {
          if (function.isEscaped()) {
              buffer.append("{fn ");
          }
  
          buffer.append(function.getName());
          if (function.isAllColumns()) {
              buffer.append("(*)");
          } else if (function.getParameters() == null) {
              buffer.append("()");
          } else {
          	boolean oldUseBracketsInExprList = useBracketsInExprList;
              if (function.isDistinct()) {
              	useBracketsInExprList = false;
          		buffer.append("(DISTINCT ");
              }
              visit(function.getParameters());
              useBracketsInExprList = oldUseBracketsInExprList;
              if (function.isDistinct()) {
          		buffer.append(")");
              }
          }
  
          if (function.isEscaped()) {
              buffer.append("}");
          }
  
      }
  
      public void visit(ExpressionList expressionList) {
      	if (useBracketsInExprList)
      		buffer.append("(");
          for (Iterator iter = expressionList.getExpressions().iterator(); iter.hasNext();) {
              Expression expression = (Expression) iter.next();
              expression.accept(this);
              if (iter.hasNext())
                  buffer.append(", ");
          }
      	if (useBracketsInExprList)
      		buffer.append(")");
      }
  
  
      public SelectVisitor getSelectVisitor() {
          return selectVisitor;
      }
  
      public void setSelectVisitor(SelectVisitor visitor) {
          selectVisitor = visitor;
      }
  
      public void visit(DateValue dateValue) {
          buffer.append("{d '" + dateValue.getValue().toString() + "'}");
      }
      public void visit(TimestampValue timestampValue) {
          buffer.append("{ts '" + timestampValue.getValue().toString() + "'}");
      }
      public void visit(TimeValue timeValue) {
          buffer.append("{t '" + timeValue.getValue().toString() + "'}");
      }
  
  	public void visit(CaseExpression caseExpression) {
  		buffer.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(" END");
  	}
  
  	public void visit(WhenClause whenClause) {
  		buffer.append(" WHEN ");
  		whenClause.getWhenExpression().accept(this);
  		buffer.append(" THEN ");
  		whenClause.getThenExpression().accept(this);
  	}
  
  	public void visit(AllComparisonExpression allComparisonExpression) {
  		buffer.append(" ALL ");
  		allComparisonExpression.GetSubSelect().accept((ExpressionVisitor)this);
  	}
  
  	public void visit(AnyComparisonExpression anyComparisonExpression) {
  		buffer.append(" ANY ");
  		anyComparisonExpression.GetSubSelect().accept((ExpressionVisitor)this);
  	}
  
  	public void visit(Concat concat) {
          visitBinaryExpression(concat, " || ");
  	}
  
  	public void visit(Matches matches) {
          visitBinaryExpression(matches, " @@ ");
  	}
  
  	public void visit(BitwiseAnd bitwiseAnd) {
          visitBinaryExpression(bitwiseAnd, " & ");
  	}
  
  	public void visit(BitwiseOr bitwiseOr) {
          visitBinaryExpression(bitwiseOr, " | ");
  	}
  
  	public void visit(BitwiseXor bitwiseXor) {
          visitBinaryExpression(bitwiseXor, " ^ ");
  	}
  
  }