From 6493f7e26d989d5bfccb793f2fd1b038afda4ed7 Mon Sep 17 00:00:00 2001 From: jakobbraun Date: Tue, 10 Nov 2020 08:30:44 +0100 Subject: [PATCH] Refactor/95 value expression visitor (#101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #95 Refactored `ValueExpressionVisitor` * removed TreeNode structure; combined BooleanExpressionRenderer and ValueExpressionRenderer Co-authored-by: Sebastian Bär --- doc/changes/changes_4.3.1.md | 1 + doc/diagrams/interfaces.puml | 13 + .../com/exasol/sql/UnnamedPlaceholder.java | 5 +- .../java/com/exasol/sql/ValueTableRow.java | 11 +- .../sql/dml/merge/MergeUpdateClause.java | 20 +- .../dml/merge/rendering/MergeRenderer.java | 9 +- .../dql/select/rendering/SelectRenderer.java | 9 +- .../expression/AbstractBooleanExpression.java | 39 +-- .../expression/AbstractValueExpression.java | 15 - .../java/com/exasol/sql/expression/And.java | 29 +- .../BinaryArithmeticExpression.java | 10 +- .../expression/BooleanExpressionVisitor.java | 7 +- .../exasol/sql/expression/BooleanTerm.java | 1 + .../sql/expression/ColumnReference.java | 14 +- .../exasol/sql/expression/DefaultValue.java | 2 +- .../exasol/sql/expression/ExpressionTerm.java | 25 +- .../java/com/exasol/sql/expression/Not.java | 28 +- .../java/com/exasol/sql/expression/Or.java | 27 +- .../sql/expression/ValueExpression.java | 4 +- .../expression/ValueExpressionVisitor.java | 32 +-- .../comparison/AbstractComparison.java | 15 +- .../expression/function/AbstractFunction.java | 30 +- .../sql/expression/function/Function.java | 9 +- .../expression/function/FunctionVisitor.java | 16 ++ .../function/exasol/CastExasolFunction.java | 11 +- .../function/exasol/ExasolFunction.java | 8 +- .../expression/function/exasol/ExasolUdf.java | 26 +- .../expression/literal/AbstractLiteral.java | 14 + .../{ => literal}/BigDecimalLiteral.java | 14 +- .../{ => literal}/BooleanLiteral.java | 24 +- .../{ => literal}/DoubleLiteral.java | 6 +- .../{ => literal}/FloatLiteral.java | 6 +- .../{ => literal}/IntegerLiteral.java | 6 +- .../sql/expression/literal/Literal.java | 15 + .../expression/literal/LiteralVisitor.java | 23 ++ .../expression/{ => literal}/LongLiteral.java | 6 +- .../expression/{ => literal}/NullLiteral.java | 6 +- .../{ => literal}/StringLiteral.java | 6 +- .../rendering/AbstractExpressionRenderer.java | 32 +-- .../rendering/BooleanExpressionRenderer.java | 78 ------ .../rendering/ComparisonRenderer.java | 65 ----- .../rendering/ValueExpressionRenderer.java | 261 ++++++++++++------ .../rendering/AbstractFragmentRenderer.java | 24 +- .../exasol/util/AbstractBottomUpTreeNode.java | 72 ----- .../java/com/exasol/util/AbstractTree.java | 47 ---- .../com/exasol/util/AbstractTreeNode.java | 46 --- src/main/java/com/exasol/util/TreeNode.java | 85 ------ .../BooleanExpressionRenderResultMatcher.java | 64 ----- .../ValueExpressionRenderResultMatcher.java | 64 +++++ .../dml/merge/MergeMethodDefinitionTest.java | 2 +- .../TestComparisonOperator.java | 4 +- .../exasol/CastExasolFunctionTest.java | 6 +- .../{ => literal}/DoubleLiteralTest.java | 2 +- .../{ => literal}/FloatLiteralTest.java | 2 +- .../{ => literal}/LongLiteralTest.java | 2 +- .../{ => literal}/TestBigDecimalLiteral.java | 2 +- .../{ => literal}/TestBooleanLiteral.java | 2 +- .../{ => literal}/TestIntegerLiteral.java | 2 +- .../{ => literal}/TestStringLiteral.java | 2 +- .../TestBooleanExpressionRenderer.java | 6 +- .../exasol/util/DummyBottomUpTreeNode.java | 11 - .../java/com/exasol/util/DummyTreeNode.java | 7 - .../util/TestAbstractBottomUpTreeNode.java | 139 ---------- .../com/exasol/util/TestAbstractTreeNode.java | 109 -------- 64 files changed, 560 insertions(+), 1118 deletions(-) create mode 100644 doc/diagrams/interfaces.puml delete mode 100644 src/main/java/com/exasol/sql/expression/AbstractValueExpression.java create mode 100644 src/main/java/com/exasol/sql/expression/function/FunctionVisitor.java create mode 100644 src/main/java/com/exasol/sql/expression/literal/AbstractLiteral.java rename src/main/java/com/exasol/sql/expression/{ => literal}/BigDecimalLiteral.java (65%) rename src/main/java/com/exasol/sql/expression/{ => literal}/BooleanLiteral.java (86%) rename src/main/java/com/exasol/sql/expression/{ => literal}/DoubleLiteral.java (82%) rename src/main/java/com/exasol/sql/expression/{ => literal}/FloatLiteral.java (82%) rename src/main/java/com/exasol/sql/expression/{ => literal}/IntegerLiteral.java (82%) create mode 100644 src/main/java/com/exasol/sql/expression/literal/Literal.java create mode 100644 src/main/java/com/exasol/sql/expression/literal/LiteralVisitor.java rename src/main/java/com/exasol/sql/expression/{ => literal}/LongLiteral.java (82%) rename src/main/java/com/exasol/sql/expression/{ => literal}/NullLiteral.java (68%) rename src/main/java/com/exasol/sql/expression/{ => literal}/StringLiteral.java (84%) delete mode 100644 src/main/java/com/exasol/sql/expression/rendering/BooleanExpressionRenderer.java delete mode 100644 src/main/java/com/exasol/sql/expression/rendering/ComparisonRenderer.java delete mode 100644 src/main/java/com/exasol/util/AbstractBottomUpTreeNode.java delete mode 100644 src/main/java/com/exasol/util/AbstractTree.java delete mode 100644 src/main/java/com/exasol/util/AbstractTreeNode.java delete mode 100644 src/main/java/com/exasol/util/TreeNode.java delete mode 100644 src/test/java/com/exasol/hamcrest/BooleanExpressionRenderResultMatcher.java create mode 100644 src/test/java/com/exasol/hamcrest/ValueExpressionRenderResultMatcher.java rename src/test/java/com/exasol/sql/expression/{ => comparison}/TestComparisonOperator.java (88%) rename src/test/java/com/exasol/sql/expression/{ => literal}/DoubleLiteralTest.java (90%) rename src/test/java/com/exasol/sql/expression/{ => literal}/FloatLiteralTest.java (90%) rename src/test/java/com/exasol/sql/expression/{ => literal}/LongLiteralTest.java (91%) rename src/test/java/com/exasol/sql/expression/{ => literal}/TestBigDecimalLiteral.java (92%) rename src/test/java/com/exasol/sql/expression/{ => literal}/TestBooleanLiteral.java (97%) rename src/test/java/com/exasol/sql/expression/{ => literal}/TestIntegerLiteral.java (90%) rename src/test/java/com/exasol/sql/expression/{ => literal}/TestStringLiteral.java (87%) delete mode 100644 src/test/java/com/exasol/util/DummyBottomUpTreeNode.java delete mode 100644 src/test/java/com/exasol/util/DummyTreeNode.java delete mode 100644 src/test/java/com/exasol/util/TestAbstractBottomUpTreeNode.java delete mode 100644 src/test/java/com/exasol/util/TestAbstractTreeNode.java diff --git a/doc/changes/changes_4.3.1.md b/doc/changes/changes_4.3.1.md index 2eda4ffd..b247eec9 100644 --- a/doc/changes/changes_4.3.1.md +++ b/doc/changes/changes_4.3.1.md @@ -7,3 +7,4 @@ Code Name: Refactoring * #98: Refactored comparison and like class structure The refactoring changed the internal representation of the `Comparison`. The public API from `BooleanTerm` did however not change. +* #95: Refactored `ValueExpressionVisitor` diff --git a/doc/diagrams/interfaces.puml b/doc/diagrams/interfaces.puml new file mode 100644 index 00000000..82858337 --- /dev/null +++ b/doc/diagrams/interfaces.puml @@ -0,0 +1,13 @@ +@startuml +interface ValueExpression +interface BooleanExpression +interface Function +interface Comparison +interface Literal + +ValueExpression <|-- BooleanExpression +ValueExpression <|-- Function +ValueExpression <|-- Literal +BooleanExpression <|-- Comparison + +@enduml \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/UnnamedPlaceholder.java b/src/main/java/com/exasol/sql/UnnamedPlaceholder.java index c01d3fca..5337f0be 100644 --- a/src/main/java/com/exasol/sql/UnnamedPlaceholder.java +++ b/src/main/java/com/exasol/sql/UnnamedPlaceholder.java @@ -1,11 +1,12 @@ package com.exasol.sql; -import com.exasol.sql.expression.*; +import com.exasol.sql.expression.ValueExpression; +import com.exasol.sql.expression.ValueExpressionVisitor; /** * This class implements a nameless placeholder ("?") in an SQL statement */ -public class UnnamedPlaceholder extends AbstractValueExpression implements ValueExpression { +public class UnnamedPlaceholder implements ValueExpression { @Override public void accept(final ValueExpressionVisitor visitor) { visitor.visit(this); diff --git a/src/main/java/com/exasol/sql/ValueTableRow.java b/src/main/java/com/exasol/sql/ValueTableRow.java index 1c6b3887..e0e983f0 100644 --- a/src/main/java/com/exasol/sql/ValueTableRow.java +++ b/src/main/java/com/exasol/sql/ValueTableRow.java @@ -1,8 +1,11 @@ package com.exasol.sql; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; -import com.exasol.sql.expression.*; +import com.exasol.sql.expression.ValueExpression; +import com.exasol.sql.expression.literal.*; /** * This class represents a row in a {@link ValueTable}. @@ -14,7 +17,7 @@ public class ValueTableRow extends AbstractFragment { /** * Create a value table row from a list of expressions. * - * @param root root node of the SQL statement + * @param root root node of the SQL statement * @param expressions value expressions */ public ValueTableRow(final Fragment root, final ValueExpression... expressions) { @@ -25,7 +28,7 @@ public ValueTableRow(final Fragment root, final ValueExpression... expressions) /** * Create a value table row from a list of string literals. * - * @param root root node of the SQL statement + * @param root root node of the SQL statement * @param values sting literals */ public ValueTableRow(final Fragment root, final String... values) { diff --git a/src/main/java/com/exasol/sql/dml/merge/MergeUpdateClause.java b/src/main/java/com/exasol/sql/dml/merge/MergeUpdateClause.java index e7c45ff5..f2aab782 100644 --- a/src/main/java/com/exasol/sql/dml/merge/MergeUpdateClause.java +++ b/src/main/java/com/exasol/sql/dml/merge/MergeUpdateClause.java @@ -4,7 +4,9 @@ import java.util.List; import com.exasol.sql.Fragment; -import com.exasol.sql.expression.*; +import com.exasol.sql.expression.DefaultValue; +import com.exasol.sql.expression.ValueExpression; +import com.exasol.sql.expression.literal.*; /** * Represents the {@code MERGE} strategy of updating matched rows. @@ -24,7 +26,7 @@ public MergeUpdateClause(final Fragment root) { /** * Update a column with a value expression. * - * @param column column to be updated + * @param column column to be updated * @param expression value expression * @return {@code this} for fluent programming */ @@ -36,7 +38,7 @@ public MergeUpdateClause set(final String column, final ValueExpression expressi /** * Update a column with a string value. * - * @param column column to be updated + * @param column column to be updated * @param literal string literal * @return {@code this} for fluent programming */ @@ -47,7 +49,7 @@ public MergeUpdateClause set(final String column, final String literal) { /** * Update a column with a char value. * - * @param column column to be updated + * @param column column to be updated * @param literal char literal * @return {@code this} for fluent programming */ @@ -58,7 +60,7 @@ public MergeUpdateClause set(final String column, final char literal) { /** * Update a column with an integer value. * - * @param column column to be updated + * @param column column to be updated * @param literal integer literal * @return {@code this} for fluent programming */ @@ -69,7 +71,7 @@ public MergeUpdateClause set(final String column, final int literal) { /** * Update a column with a long value. * - * @param column column to be updated + * @param column column to be updated * @param literal long literal * @return {@code this} for fluent programming */ @@ -80,7 +82,7 @@ public MergeUpdateClause set(final String column, final long literal) { /** * Update a column with a double value. * - * @param column column to be updated + * @param column column to be updated * @param literal double literal * @return {@code this} for fluent programming */ @@ -91,7 +93,7 @@ public MergeUpdateClause set(final String column, final double literal) { /** * Update a column with a float value. * - * @param column column to be updated + * @param column column to be updated * @param literal float literal * @return {@code this} for fluent programming */ @@ -102,7 +104,7 @@ public MergeUpdateClause set(final String column, final float literal) { /** * Update a column with a boolean value. * - * @param column column to be updated + * @param column column to be updated * @param literal boolean literal * @return {@code this} for fluent programming */ diff --git a/src/main/java/com/exasol/sql/dml/merge/rendering/MergeRenderer.java b/src/main/java/com/exasol/sql/dml/merge/rendering/MergeRenderer.java index ae8593a4..bb559136 100644 --- a/src/main/java/com/exasol/sql/dml/merge/rendering/MergeRenderer.java +++ b/src/main/java/com/exasol/sql/dml/merge/rendering/MergeRenderer.java @@ -1,6 +1,9 @@ package com.exasol.sql.dml.merge.rendering; -import com.exasol.sql.*; +import com.exasol.sql.DerivedColumn; +import com.exasol.sql.Table; +import com.exasol.sql.ValueTable; +import com.exasol.sql.ValueTableRow; import com.exasol.sql.dml.insert.InsertFields; import com.exasol.sql.dml.insert.rendering.InsertRenderer; import com.exasol.sql.dml.merge.*; @@ -47,7 +50,7 @@ public void visit(final UsingClause using) { @Override public void visit(final OnClause onClause) { appendKeyWord(" ON "); - appendRenderedBooleanExpression(onClause.getCondition()); + appendRenderedValueExpression(onClause.getCondition()); setLastVisited(onClause); } @@ -155,7 +158,7 @@ public void leave(final ValueTableRow valueTableRow) { @Override public void visit(final WhereClause whereClause) { appendKeyWord(" WHERE "); - appendRenderedBooleanExpression(whereClause.getExpression()); + appendRenderedValueExpression(whereClause.getExpression()); setLastVisited(whereClause); } } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/dql/select/rendering/SelectRenderer.java b/src/main/java/com/exasol/sql/dql/select/rendering/SelectRenderer.java index 54ca7f68..474e7353 100644 --- a/src/main/java/com/exasol/sql/dql/select/rendering/SelectRenderer.java +++ b/src/main/java/com/exasol/sql/dql/select/rendering/SelectRenderer.java @@ -2,7 +2,10 @@ import java.util.List; -import com.exasol.sql.*; +import com.exasol.sql.DerivedColumn; +import com.exasol.sql.Table; +import com.exasol.sql.ValueTable; +import com.exasol.sql.ValueTableRow; import com.exasol.sql.dql.select.*; import com.exasol.sql.expression.BooleanExpression; import com.exasol.sql.rendering.AbstractFragmentRenderer; @@ -84,7 +87,7 @@ public void visit(final Join join) { @Override public void visit(final WhereClause whereClause) { appendKeyWord(" WHERE "); - appendRenderedBooleanExpression(whereClause.getExpression()); + appendRenderedValueExpression(whereClause.getExpression()); setLastVisited(whereClause); } @@ -95,7 +98,7 @@ public void visit(final GroupByClause groupByClause) { final BooleanExpression having = groupByClause.getHavingBooleanExpression(); if (having != null) { appendKeyWord(" HAVING "); - appendRenderedBooleanExpression(having); + appendRenderedValueExpression(having); } setLastVisited(groupByClause); } diff --git a/src/main/java/com/exasol/sql/expression/AbstractBooleanExpression.java b/src/main/java/com/exasol/sql/expression/AbstractBooleanExpression.java index d78fbe18..cb135788 100644 --- a/src/main/java/com/exasol/sql/expression/AbstractBooleanExpression.java +++ b/src/main/java/com/exasol/sql/expression/AbstractBooleanExpression.java @@ -1,46 +1,9 @@ package com.exasol.sql.expression; -import com.exasol.util.AbstractBottomUpTreeNode; -import com.exasol.util.TreeNode; - /** * Abstract base class for all types of BooleanExpressions. */ -public abstract class AbstractBooleanExpression extends AbstractBottomUpTreeNode implements BooleanExpression { - protected AbstractBooleanExpression() { - super(); - } - - protected AbstractBooleanExpression(final BooleanExpression expression) { - super(expression); - } - - protected AbstractBooleanExpression(final BooleanExpression... expressions) { - super(expressions); - } - - @Override - public void accept(final BooleanExpressionVisitor visitor) { - acceptConcrete(visitor); - for (final TreeNode child : this.getChildren()) { - ((BooleanExpression) child).accept(visitor); - } - dismissConcrete(visitor); - } - - /** - * Sub-classes must override this method so that the visitor knows the type of the visited class at compile time. - * - * @param visitor visitor to accept - */ - public abstract void acceptConcrete(final BooleanExpressionVisitor visitor); - - /** - * Sub-classes must override this method so that the visitor knows the type of the visited class at compile time. - * - * @param visitor visitor to accept - */ - public abstract void dismissConcrete(final BooleanExpressionVisitor visitor); +public abstract class AbstractBooleanExpression implements BooleanExpression { @Override public void accept(final ValueExpressionVisitor visitor) { diff --git a/src/main/java/com/exasol/sql/expression/AbstractValueExpression.java b/src/main/java/com/exasol/sql/expression/AbstractValueExpression.java deleted file mode 100644 index fcf1f26f..00000000 --- a/src/main/java/com/exasol/sql/expression/AbstractValueExpression.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.exasol.sql.expression; - -import com.exasol.util.AbstractBottomUpTreeNode; - -/** - * Abstract base class for all types of value expressions - */ -public abstract class AbstractValueExpression extends AbstractBottomUpTreeNode implements ValueExpression { - /** - * Create a new instance of a {@link AbstractValueExpression} - */ - public AbstractValueExpression() { - super(); - } -} \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/And.java b/src/main/java/com/exasol/sql/expression/And.java index 5b550a52..71207200 100644 --- a/src/main/java/com/exasol/sql/expression/And.java +++ b/src/main/java/com/exasol/sql/expression/And.java @@ -1,16 +1,23 @@ package com.exasol.sql.expression; +import java.util.Arrays; +import java.util.List; + +import com.exasol.sql.expression.literal.BooleanLiteral; + /** * This class represents a logical AND predicate. */ public class And extends AbstractBooleanExpression { + private final List operands; + /** * Create a new {@link And} instance * - * @param expressions boolean expressions to be connected by a logical AND + * @param operands boolean expressions to be connected by a logical AND */ - public And(final BooleanExpression... expressions) { - super(expressions); + public And(final BooleanExpression... operands) { + this.operands = Arrays.asList(operands); } /** @@ -22,13 +29,17 @@ public And(final boolean... values) { this(BooleanLiteral.toBooleanExpressions(values)); } - @Override - public void acceptConcrete(final BooleanExpressionVisitor visitor) { - visitor.visit(this); + /** + * Get the operands of this AND. + * + * @return operands of this AND + */ + public List getOperands() { + return this.operands; } @Override - public void dismissConcrete(final BooleanExpressionVisitor visitor) { - visitor.leave(this); + public void accept(final BooleanExpressionVisitor visitor) { + visitor.visit(this); } -} \ No newline at end of file +} diff --git a/src/main/java/com/exasol/sql/expression/BinaryArithmeticExpression.java b/src/main/java/com/exasol/sql/expression/BinaryArithmeticExpression.java index 82f0c68f..49c7cef1 100644 --- a/src/main/java/com/exasol/sql/expression/BinaryArithmeticExpression.java +++ b/src/main/java/com/exasol/sql/expression/BinaryArithmeticExpression.java @@ -1,14 +1,12 @@ package com.exasol.sql.expression; -import com.exasol.util.AbstractTreeNode; - /** * This class represents a binary arithmetic expression. *

* Examples: +, -, *, / *

*/ -public class BinaryArithmeticExpression extends AbstractTreeNode implements ValueExpression { +public class BinaryArithmeticExpression implements ValueExpression { private final BinaryArithmeticOperator arithmeticOperator; private final ValueExpression left; private final ValueExpression right; @@ -18,16 +16,14 @@ private BinaryArithmeticExpression(final BinaryArithmeticOperator arithmeticOper this.arithmeticOperator = arithmeticOperator; this.left = left; this.right = right; - addChild(left); - addChild(right); } /** * Create a new {@link BinaryArithmeticExpression} instance. * * @param operator arithmetic operator represented by {@link BinaryArithmeticOperator} - * @param left left part of the expression - * @param right right part of the expression + * @param left left part of the expression + * @param right right part of the expression * @return new {@link BinaryArithmeticExpression} instance */ public static BinaryArithmeticExpression of(final BinaryArithmeticOperator operator, final ValueExpression left, diff --git a/src/main/java/com/exasol/sql/expression/BooleanExpressionVisitor.java b/src/main/java/com/exasol/sql/expression/BooleanExpressionVisitor.java index 6251809f..f04889d9 100644 --- a/src/main/java/com/exasol/sql/expression/BooleanExpressionVisitor.java +++ b/src/main/java/com/exasol/sql/expression/BooleanExpressionVisitor.java @@ -1,6 +1,7 @@ package com.exasol.sql.expression; import com.exasol.sql.expression.comparison.Comparison; +import com.exasol.sql.expression.literal.BooleanLiteral; /** * Visitor interface for a {@link BooleanTerm} @@ -12,13 +13,7 @@ public interface BooleanExpressionVisitor { public void visit(And and); - public void leave(Not not); - - public void leave(And and); - public void visit(Or or); - public void leave(Or or); - public void visit(Comparison comparison); } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/BooleanTerm.java b/src/main/java/com/exasol/sql/expression/BooleanTerm.java index b401cb08..583fcacf 100644 --- a/src/main/java/com/exasol/sql/expression/BooleanTerm.java +++ b/src/main/java/com/exasol/sql/expression/BooleanTerm.java @@ -3,6 +3,7 @@ import com.exasol.sql.expression.comparison.LikeComparison; import com.exasol.sql.expression.comparison.SimpleComparison; import com.exasol.sql.expression.comparison.SimpleComparisonOperator; +import com.exasol.sql.expression.literal.BooleanLiteral; // [impl->dsn~boolean-operators~1] public abstract class BooleanTerm extends AbstractBooleanExpression { diff --git a/src/main/java/com/exasol/sql/expression/ColumnReference.java b/src/main/java/com/exasol/sql/expression/ColumnReference.java index fe24a0cd..feac3dfa 100644 --- a/src/main/java/com/exasol/sql/expression/ColumnReference.java +++ b/src/main/java/com/exasol/sql/expression/ColumnReference.java @@ -3,7 +3,7 @@ /** * This class represents column reference. */ -public final class ColumnReference extends AbstractValueExpression { +public final class ColumnReference implements ValueExpression { private final String columnName; private final String tableName; @@ -15,7 +15,7 @@ private ColumnReference(final String columnName, final String tableName) { /** * Create a new {@link ColumnReference} from a column name and a table name. * - * @param tableName table name + * @param tableName table name * @param columnName column name * * @return new {@link ColumnReference} @@ -40,7 +40,7 @@ public static ColumnReference of(final String columnName) { * @return column name */ public String getColumnName() { - return columnName; + return this.columnName; } /** @@ -49,16 +49,16 @@ public String getColumnName() { * @return table name */ public String getTableName() { - return tableName; + return this.tableName; } public String toString() { final StringBuilder stringBuilder = new StringBuilder(); - if ((tableName != null) && !tableName.isEmpty()) { - stringBuilder.append(tableName); + if ((this.tableName != null) && !this.tableName.isEmpty()) { + stringBuilder.append(this.tableName); stringBuilder.append("."); } - stringBuilder.append(columnName); + stringBuilder.append(this.columnName); return stringBuilder.toString(); } diff --git a/src/main/java/com/exasol/sql/expression/DefaultValue.java b/src/main/java/com/exasol/sql/expression/DefaultValue.java index c941c6d6..07f1dff9 100644 --- a/src/main/java/com/exasol/sql/expression/DefaultValue.java +++ b/src/main/java/com/exasol/sql/expression/DefaultValue.java @@ -8,7 +8,7 @@ *

*/ // [impl->dsn~literal-values~2] -public final class DefaultValue extends AbstractValueExpression { +public final class DefaultValue implements ValueExpression { private static final DefaultValue instance = new DefaultValue(); public static ValueExpression defaultValue() { diff --git a/src/main/java/com/exasol/sql/expression/ExpressionTerm.java b/src/main/java/com/exasol/sql/expression/ExpressionTerm.java index 2f570bd3..fbad880e 100644 --- a/src/main/java/com/exasol/sql/expression/ExpressionTerm.java +++ b/src/main/java/com/exasol/sql/expression/ExpressionTerm.java @@ -5,13 +5,14 @@ import com.exasol.sql.expression.function.FunctionName; import com.exasol.sql.expression.function.exasol.ExasolFunction; import com.exasol.sql.expression.function.exasol.ExasolUdf; +import com.exasol.sql.expression.literal.*; /** * Static factory methods for SQL expressions. */ -public abstract class ExpressionTerm extends AbstractValueExpression { +public class ExpressionTerm { private ExpressionTerm() { - super(); + // constructor hidden on purpose } /** @@ -97,7 +98,7 @@ public static ColumnReference column(final String column) { /** * Create a reference to a column in a specific table. * - * @param table table name + * @param table table name * @param column column name * * @return column reference @@ -109,7 +110,7 @@ public static ColumnReference column(final String table, final String column) { /** * Create a binary arithmetic expression with ADD operator. * - * @param left left operand + * @param left left operand * @param right right operand * @return binary arithmetic expression */ @@ -120,7 +121,7 @@ public static BinaryArithmeticExpression plus(final ValueExpression left, final /** * Create a binary arithmetic expression with SUBTRACT operator. * - * @param left left operand + * @param left left operand * @param right right operand * @return binary arithmetic expression */ @@ -131,7 +132,7 @@ public static BinaryArithmeticExpression minus(final ValueExpression left, final /** * Create a binary arithmetic expression with DIVIDE operator. * - * @param left left operand + * @param left left operand * @param right right operand * @return binary arithmetic expression */ @@ -142,7 +143,7 @@ public static BinaryArithmeticExpression multiply(final ValueExpression left, fi /** * Create a binary arithmetic expression with DIVIDE operator. * - * @param left left operand + * @param left left operand * @param right right operand * @return binary arithmetic expression */ @@ -163,7 +164,7 @@ public static Function function(final FunctionName functionName) { /** * Create an Exasol function. * - * @param functionName a name of function + * @param functionName a name of function * @param valueExpressions zero or more value expressions * @return this instance for fluent programming */ @@ -174,9 +175,9 @@ public static Function function(final FunctionName functionName, final ValueExpr /** * Create a User Defined Function. * - * @param functionName a name of function + * @param functionName a name of function * @param emitsColumnsDefinition column definitions for emits - * @param valueExpressions zero or more value expressions + * @param valueExpressions zero or more value expressions * @return UDF */ public static Function udf(final String functionName, final ColumnsDefinition emitsColumnsDefinition, @@ -187,7 +188,7 @@ public static Function udf(final String functionName, final ColumnsDefinition em /** * Create a User Defined Function. * - * @param functionName a name of function + * @param functionName a name of function * @param valueExpressions zero or more value expressions * @return UDF */ @@ -203,4 +204,4 @@ public static Function udf(final String functionName, final ValueExpression... v public static NullLiteral nullLiteral() { return NullLiteral.nullLiteral(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/exasol/sql/expression/Not.java b/src/main/java/com/exasol/sql/expression/Not.java index c52e9752..f63fa5a2 100644 --- a/src/main/java/com/exasol/sql/expression/Not.java +++ b/src/main/java/com/exasol/sql/expression/Not.java @@ -1,16 +1,20 @@ package com.exasol.sql.expression; +import com.exasol.sql.expression.literal.BooleanLiteral; + /** * This class implements the logical unary NOT predicate. */ public class Not extends AbstractBooleanExpression { + private final BooleanExpression operand; + /** * Create a new instance of a unary {@link Not} from a boolean literal * * @param value boolean literal to be negated */ public Not(final boolean value) { - super(BooleanLiteral.of(value)); + this(BooleanLiteral.of(value)); } /** @@ -19,25 +23,29 @@ public Not(final boolean value) { * @param value string literal to be negated */ public Not(final String value) { - super(BooleanLiteral.of(value)); + this(BooleanLiteral.of(value)); } /** * Create a new instance of a unary {@link Not} from a boolean expression * - * @param expression boolean expression literal to be negated + * @param operand boolean expression literal to be negated */ - public Not(final BooleanExpression expression) { - super(expression); + public Not(final BooleanExpression operand) { + this.operand = operand; } - @Override - public void acceptConcrete(final BooleanExpressionVisitor visitor) { - visitor.visit(this); + /** + * Get the boolean expression literal to be negated. + * + * @return boolean expression literal to be negated + */ + public BooleanExpression getOperand() { + return this.operand; } @Override - public void dismissConcrete(final BooleanExpressionVisitor visitor) { - visitor.leave(this); + public void accept(final BooleanExpressionVisitor visitor) { + visitor.visit(this); } } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/Or.java b/src/main/java/com/exasol/sql/expression/Or.java index 193028c6..5bc53732 100644 --- a/src/main/java/com/exasol/sql/expression/Or.java +++ b/src/main/java/com/exasol/sql/expression/Or.java @@ -1,16 +1,23 @@ package com.exasol.sql.expression; +import java.util.Arrays; +import java.util.List; + +import com.exasol.sql.expression.literal.BooleanLiteral; + /** * This class represents a logical OR predicate. */ public class Or extends AbstractBooleanExpression { + private final List operands; + /** * Create a new {@link Or} instance * - * @param expressions boolean expressions to be connected by a logical Or + * @param operands boolean expressions to be connected by a logical Or */ - public Or(final BooleanExpression... expressions) { - super(expressions); + public Or(final BooleanExpression... operands) { + this.operands = Arrays.asList(operands); } /** @@ -22,13 +29,17 @@ public Or(final boolean... values) { this(BooleanLiteral.toBooleanExpressions(values)); } - @Override - public void acceptConcrete(final BooleanExpressionVisitor visitor) { - visitor.visit(this); + /** + * Get the operands of this OR. + * + * @return operands of this OR + */ + public List getOperands() { + return this.operands; } @Override - public void dismissConcrete(final BooleanExpressionVisitor visitor) { - visitor.leave(this); + public void accept(final BooleanExpressionVisitor visitor) { + visitor.visit(this); } } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/ValueExpression.java b/src/main/java/com/exasol/sql/expression/ValueExpression.java index f01fa1da..8b614237 100644 --- a/src/main/java/com/exasol/sql/expression/ValueExpression.java +++ b/src/main/java/com/exasol/sql/expression/ValueExpression.java @@ -1,11 +1,9 @@ package com.exasol.sql.expression; -import com.exasol.util.TreeNode; - /** * Common interface for all types of value expressions */ -public interface ValueExpression extends TreeNode { +public interface ValueExpression { /** * Accept a visitor * diff --git a/src/main/java/com/exasol/sql/expression/ValueExpressionVisitor.java b/src/main/java/com/exasol/sql/expression/ValueExpressionVisitor.java index 716fecbe..35fb845f 100644 --- a/src/main/java/com/exasol/sql/expression/ValueExpressionVisitor.java +++ b/src/main/java/com/exasol/sql/expression/ValueExpressionVisitor.java @@ -1,47 +1,25 @@ package com.exasol.sql.expression; import com.exasol.sql.UnnamedPlaceholder; -import com.exasol.sql.expression.function.exasol.CastExasolFunction; -import com.exasol.sql.expression.function.exasol.ExasolFunction; -import com.exasol.sql.expression.function.exasol.ExasolUdf; +import com.exasol.sql.expression.function.Function; +import com.exasol.sql.expression.literal.Literal; /** * Visitor interface for a {@link BooleanTerm}. */ public interface ValueExpressionVisitor { - public void visit(UnnamedPlaceholder unnamedPlaceholder); - - public void visit(StringLiteral literal); - - public void visit(IntegerLiteral literal); - - public void visit(LongLiteral literal); - - public void visit(DoubleLiteral literal); - - public void visit(FloatLiteral literal); + public void visit(final Literal literal); - public void visit(BigDecimalLiteral literal); + public void visit(final Function function); - public void visit(BooleanLiteral literal); + public void visit(UnnamedPlaceholder unnamedPlaceholder); public void visit(ColumnReference columnReference); public void visit(DefaultValue defaultValue); - public void visit(ExasolFunction function); - - public void leave(ExasolFunction function); - - public void visit(ExasolUdf function); - - public void leave(ExasolUdf function); - public void visit(BinaryArithmeticExpression expression); - public void visit(NullLiteral nullLiteral); - public void visit(BooleanExpression booleanExpression); - public void visit(CastExasolFunction castFunction); } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/comparison/AbstractComparison.java b/src/main/java/com/exasol/sql/expression/comparison/AbstractComparison.java index a63a97ce..e37370a5 100644 --- a/src/main/java/com/exasol/sql/expression/comparison/AbstractComparison.java +++ b/src/main/java/com/exasol/sql/expression/comparison/AbstractComparison.java @@ -26,16 +26,6 @@ protected AbstractComparison(final ComparisonOperator comparisonOperator, final this.rightOperand = rightOperand; } - @Override - public final void acceptConcrete(final BooleanExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public final void dismissConcrete(final BooleanExpressionVisitor visitor) { - // empty on purpose - } - /** * Get the left-hand side operator of the comparison * @@ -65,4 +55,9 @@ public ValueExpression getRightOperand() { public ComparisonOperator getOperator() { return this.operator; } + + @Override + public void accept(final BooleanExpressionVisitor visitor) { + visitor.visit(this); + } } diff --git a/src/main/java/com/exasol/sql/expression/function/AbstractFunction.java b/src/main/java/com/exasol/sql/expression/function/AbstractFunction.java index dd3fb9bf..1ff44e12 100644 --- a/src/main/java/com/exasol/sql/expression/function/AbstractFunction.java +++ b/src/main/java/com/exasol/sql/expression/function/AbstractFunction.java @@ -3,32 +3,42 @@ import java.util.List; import com.exasol.sql.expression.ValueExpression; -import com.exasol.util.AbstractTreeNode; +import com.exasol.sql.expression.ValueExpressionVisitor; /** * This is a base class for functions. */ -public abstract class AbstractFunction extends AbstractTreeNode implements Function { +public abstract class AbstractFunction implements Function { protected String functionName; - protected List valueExpressions; + protected List parameters; /** * Create a new instance using {@link AbstractFunction}. * * @param functionName name of a function - * @param valueExpressions zero or more value expressions + * @param parameters zero or more value expressions */ - protected AbstractFunction(final String functionName, final List valueExpressions) { + protected AbstractFunction(final String functionName, final List parameters) { this.functionName = functionName; - this.valueExpressions = valueExpressions; - for (final ValueExpression valueExpression : this.valueExpressions) { - addChild(valueExpression); - valueExpression.setParent(this); - } + this.parameters = parameters; } @Override public String getFunctionName() { return this.functionName; } + + /** + * Get the value expressions (parameters of the function) + * + * @return list of value expressions + */ + public List getParameters() { + return this.parameters; + } + + @Override + public final void accept(final ValueExpressionVisitor visitor) { + visitor.visit(this); + } } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/function/Function.java b/src/main/java/com/exasol/sql/expression/function/Function.java index e3eba8c3..47d34d02 100644 --- a/src/main/java/com/exasol/sql/expression/function/Function.java +++ b/src/main/java/com/exasol/sql/expression/function/Function.java @@ -18,5 +18,12 @@ public interface Function extends ValueExpression { * * @return true if function has parenthesis with parameters */ - boolean hasParenthesis(); + public boolean hasParenthesis(); + + /** + * Accept {@link FunctionVisitor}. + * + * @param visitor visitor to accept + */ + public void accept(final FunctionVisitor visitor); } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/function/FunctionVisitor.java b/src/main/java/com/exasol/sql/expression/function/FunctionVisitor.java new file mode 100644 index 00000000..77fb0dcf --- /dev/null +++ b/src/main/java/com/exasol/sql/expression/function/FunctionVisitor.java @@ -0,0 +1,16 @@ +package com.exasol.sql.expression.function; + +import com.exasol.sql.expression.function.exasol.CastExasolFunction; +import com.exasol.sql.expression.function.exasol.ExasolFunction; +import com.exasol.sql.expression.function.exasol.ExasolUdf; + +/** + * Visitor interface for {@link Function}. + */ +public interface FunctionVisitor { + public void visit(ExasolFunction function); + + public void visit(ExasolUdf function); + + public void visit(CastExasolFunction castFunction); +} diff --git a/src/main/java/com/exasol/sql/expression/function/exasol/CastExasolFunction.java b/src/main/java/com/exasol/sql/expression/function/exasol/CastExasolFunction.java index c6158ad3..c0af3fdc 100644 --- a/src/main/java/com/exasol/sql/expression/function/exasol/CastExasolFunction.java +++ b/src/main/java/com/exasol/sql/expression/function/exasol/CastExasolFunction.java @@ -4,17 +4,18 @@ import com.exasol.datatype.type.DataType; import com.exasol.sql.expression.ValueExpression; -import com.exasol.sql.expression.ValueExpressionVisitor; +import com.exasol.sql.expression.function.AbstractFunction; import com.exasol.sql.expression.function.FunctionName; +import com.exasol.sql.expression.function.FunctionVisitor; /** * This class represents the Exasol CAST function. */ -public class CastExasolFunction extends ExasolFunction { +public class CastExasolFunction extends AbstractFunction { private final DataType type; private CastExasolFunction(final ValueExpression value, final DataType type) { - super(ExasolScalarFunctionCast.CAST, List.of(value)); + super(ExasolScalarFunctionCast.CAST.toString(), List.of(value)); this.type = type; } @@ -35,7 +36,7 @@ public static CastExasolFunction of(final ValueExpression valueExpression, final * @return value to cast */ public ValueExpression getValue() { - return this.valueExpressions.get(0); + return this.parameters.get(0); } /** @@ -53,7 +54,7 @@ public boolean hasParenthesis() { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final FunctionVisitor visitor) { visitor.visit(this); } diff --git a/src/main/java/com/exasol/sql/expression/function/exasol/ExasolFunction.java b/src/main/java/com/exasol/sql/expression/function/exasol/ExasolFunction.java index af065b90..c0a0211a 100644 --- a/src/main/java/com/exasol/sql/expression/function/exasol/ExasolFunction.java +++ b/src/main/java/com/exasol/sql/expression/function/exasol/ExasolFunction.java @@ -5,9 +5,9 @@ import java.util.List; import com.exasol.sql.expression.ValueExpression; -import com.exasol.sql.expression.ValueExpressionVisitor; import com.exasol.sql.expression.function.AbstractFunction; import com.exasol.sql.expression.function.FunctionName; +import com.exasol.sql.expression.function.FunctionVisitor; /** * This class represents a function in the Exasol database. @@ -47,11 +47,7 @@ public boolean hasParenthesis() { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final FunctionVisitor visitor) { visitor.visit(this); - for (final ValueExpression valueExpression : this.valueExpressions) { - valueExpression.accept(visitor); - } - visitor.leave(this); } } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/function/exasol/ExasolUdf.java b/src/main/java/com/exasol/sql/expression/function/exasol/ExasolUdf.java index 20cbc3f0..4e43cd53 100644 --- a/src/main/java/com/exasol/sql/expression/function/exasol/ExasolUdf.java +++ b/src/main/java/com/exasol/sql/expression/function/exasol/ExasolUdf.java @@ -1,11 +1,13 @@ package com.exasol.sql.expression.function.exasol; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; import com.exasol.sql.ColumnsDefinition; import com.exasol.sql.expression.ValueExpression; -import com.exasol.sql.expression.ValueExpressionVisitor; import com.exasol.sql.expression.function.AbstractFunction; +import com.exasol.sql.expression.function.FunctionVisitor; /** * This class represents a User Defined Function in the Exasol database. @@ -22,9 +24,9 @@ private ExasolUdf(final String functionName, final Optional e /** * Create a new {@link ExasolUdf} instance. * - * @param functionName name of the function + * @param functionName name of the function * @param emitsColumnsDefinition column definitions for emits - * @param valueExpressions zero or more value expressions + * @param valueExpressions zero or more value expressions * @return new {@link ExasolUdf} */ public static ExasolUdf of(final String functionName, final ColumnsDefinition emitsColumnsDefinition, @@ -35,7 +37,7 @@ public static ExasolUdf of(final String functionName, final ColumnsDefinition em /** * Create a new {@link ExasolUdf} instance. * - * @param functionName name of the function + * @param functionName name of the function * @param valueExpressions zero or more value expressions * @return new {@link ExasolUdf} */ @@ -48,6 +50,11 @@ public boolean hasParenthesis() { return true; } + @Override + public void accept(final FunctionVisitor visitor) { + visitor.visit(this); + } + /** * Check if the EMITS part is required. * @@ -65,13 +72,4 @@ public boolean hasEmitsColumnsDefinition() { public Optional getEmitsColumnsDefinition() { return this.emitsColumnsDefinition; } - - @Override - public void accept(final ValueExpressionVisitor visitor) { - visitor.visit(this); - for (final ValueExpression valueExpression : this.valueExpressions) { - valueExpression.accept(visitor); - } - visitor.leave(this); - } } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/literal/AbstractLiteral.java b/src/main/java/com/exasol/sql/expression/literal/AbstractLiteral.java new file mode 100644 index 00000000..c14a2ce1 --- /dev/null +++ b/src/main/java/com/exasol/sql/expression/literal/AbstractLiteral.java @@ -0,0 +1,14 @@ +package com.exasol.sql.expression.literal; + +import com.exasol.sql.expression.ValueExpression; +import com.exasol.sql.expression.ValueExpressionVisitor; + +/** + * Abstract basis for {@link Literal}s. + */ +public abstract class AbstractLiteral implements Literal, ValueExpression { + @Override + public final void accept(final ValueExpressionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/src/main/java/com/exasol/sql/expression/BigDecimalLiteral.java b/src/main/java/com/exasol/sql/expression/literal/BigDecimalLiteral.java similarity index 65% rename from src/main/java/com/exasol/sql/expression/BigDecimalLiteral.java rename to src/main/java/com/exasol/sql/expression/literal/BigDecimalLiteral.java index 0a258c48..178f1942 100644 --- a/src/main/java/com/exasol/sql/expression/BigDecimalLiteral.java +++ b/src/main/java/com/exasol/sql/expression/literal/BigDecimalLiteral.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; import java.math.BigDecimal; @@ -6,10 +6,10 @@ * This class represents BigDecimal literals. */ // [impl->dsn~literal-values~2] -public class BigDecimalLiteral extends AbstractValueExpression { +public class BigDecimalLiteral extends AbstractLiteral { private final BigDecimal literal; - private BigDecimalLiteral(BigDecimal literal) { + private BigDecimalLiteral(final BigDecimal literal) { this.literal = literal; } @@ -19,7 +19,7 @@ private BigDecimalLiteral(BigDecimal literal) { * @param literal content * @return new {@link StringLiteral} */ - public static BigDecimalLiteral of(BigDecimal literal) { + public static BigDecimalLiteral of(final BigDecimal literal) { return new BigDecimalLiteral(literal); } @@ -29,16 +29,16 @@ public static BigDecimalLiteral of(BigDecimal literal) { * @return BigDecimal value */ public BigDecimal getValue() { - return literal; + return this.literal; } @Override - public void accept(ValueExpressionVisitor visitor) { + public void accept(final LiteralVisitor visitor) { visitor.visit(this); } @Override public String toString() { - return literal.toString(); + return this.literal.toString(); } } diff --git a/src/main/java/com/exasol/sql/expression/BooleanLiteral.java b/src/main/java/com/exasol/sql/expression/literal/BooleanLiteral.java similarity index 86% rename from src/main/java/com/exasol/sql/expression/BooleanLiteral.java rename to src/main/java/com/exasol/sql/expression/literal/BooleanLiteral.java index 6ddde03c..2ff6a4ff 100644 --- a/src/main/java/com/exasol/sql/expression/BooleanLiteral.java +++ b/src/main/java/com/exasol/sql/expression/literal/BooleanLiteral.java @@ -1,10 +1,13 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; + +import com.exasol.sql.expression.BooleanExpression; +import com.exasol.sql.expression.BooleanExpressionVisitor; /** * This class represents boolean literals (read "true" and "false") */ // [impl->dsn~boolean-literals~1] -public final class BooleanLiteral extends AbstractBooleanExpression implements ValueExpression { +public final class BooleanLiteral extends AbstractLiteral implements BooleanExpression { private static final String FALSE = "FALSE"; private static final String TRUE = "TRUE"; private final boolean value; @@ -69,16 +72,6 @@ public boolean toBoolean() { return this.value; } - @Override - public void acceptConcrete(final BooleanExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public void dismissConcrete(final BooleanExpressionVisitor visitor) { - // empty on purpose - } - /** * Map an array of booleans to and array of BooleanExpressions * @@ -94,7 +87,12 @@ public static BooleanExpression[] toBooleanExpressions(final boolean[] values) { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final LiteralVisitor visitor) { + visitor.visit(this); + } + + @Override + public void accept(final BooleanExpressionVisitor visitor) { visitor.visit(this); } } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/DoubleLiteral.java b/src/main/java/com/exasol/sql/expression/literal/DoubleLiteral.java similarity index 82% rename from src/main/java/com/exasol/sql/expression/DoubleLiteral.java rename to src/main/java/com/exasol/sql/expression/literal/DoubleLiteral.java index 3a879776..fb85969b 100644 --- a/src/main/java/com/exasol/sql/expression/DoubleLiteral.java +++ b/src/main/java/com/exasol/sql/expression/literal/DoubleLiteral.java @@ -1,10 +1,10 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; /** * This class represents double literals. */ // [impl->dsn~literal-values~2] -public class DoubleLiteral extends AbstractValueExpression { +public class DoubleLiteral extends AbstractLiteral { private final double value; private DoubleLiteral(final double value) { @@ -31,7 +31,7 @@ public double getValue() { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final LiteralVisitor visitor) { visitor.visit(this); } diff --git a/src/main/java/com/exasol/sql/expression/FloatLiteral.java b/src/main/java/com/exasol/sql/expression/literal/FloatLiteral.java similarity index 82% rename from src/main/java/com/exasol/sql/expression/FloatLiteral.java rename to src/main/java/com/exasol/sql/expression/literal/FloatLiteral.java index 944b94de..2861d700 100644 --- a/src/main/java/com/exasol/sql/expression/FloatLiteral.java +++ b/src/main/java/com/exasol/sql/expression/literal/FloatLiteral.java @@ -1,10 +1,10 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; /** * This class represents float literals. */ // [impl->dsn~literal-values~2] -public class FloatLiteral extends AbstractValueExpression { +public class FloatLiteral extends AbstractLiteral { private final float value; private FloatLiteral(final float value) { @@ -31,7 +31,7 @@ public float getValue() { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final LiteralVisitor visitor) { visitor.visit(this); } diff --git a/src/main/java/com/exasol/sql/expression/IntegerLiteral.java b/src/main/java/com/exasol/sql/expression/literal/IntegerLiteral.java similarity index 82% rename from src/main/java/com/exasol/sql/expression/IntegerLiteral.java rename to src/main/java/com/exasol/sql/expression/literal/IntegerLiteral.java index 28bf6c10..e1b169a6 100644 --- a/src/main/java/com/exasol/sql/expression/IntegerLiteral.java +++ b/src/main/java/com/exasol/sql/expression/literal/IntegerLiteral.java @@ -1,10 +1,10 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; /** * This class represents integer literals. */ // [impl->dsn~literal-values~2] -public final class IntegerLiteral extends AbstractValueExpression { +public final class IntegerLiteral extends AbstractLiteral { private final int value; private IntegerLiteral(final int value) { @@ -31,7 +31,7 @@ public int getValue() { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final LiteralVisitor visitor) { visitor.visit(this); } diff --git a/src/main/java/com/exasol/sql/expression/literal/Literal.java b/src/main/java/com/exasol/sql/expression/literal/Literal.java new file mode 100644 index 00000000..a4b78992 --- /dev/null +++ b/src/main/java/com/exasol/sql/expression/literal/Literal.java @@ -0,0 +1,15 @@ +package com.exasol.sql.expression.literal; + +import com.exasol.sql.expression.ValueExpression; + +/** + * Interface for classes that represent literal values. + */ +public interface Literal extends ValueExpression { + /** + * Accept a {@link LiteralVisitor}. + * + * @param visitor visitor to accept + */ + public void accept(final LiteralVisitor visitor); +} diff --git a/src/main/java/com/exasol/sql/expression/literal/LiteralVisitor.java b/src/main/java/com/exasol/sql/expression/literal/LiteralVisitor.java new file mode 100644 index 00000000..cfca8430 --- /dev/null +++ b/src/main/java/com/exasol/sql/expression/literal/LiteralVisitor.java @@ -0,0 +1,23 @@ +package com.exasol.sql.expression.literal; + +/** + * Visitor for {@link Literal}. + */ +public interface LiteralVisitor { + public void visit(final NullLiteral nullLiteral); + + public void visit(final StringLiteral literal); + + public void visit(final IntegerLiteral literal); + + public void visit(final LongLiteral literal); + + public void visit(final DoubleLiteral literal); + + public void visit(final FloatLiteral literal); + + public void visit(final BigDecimalLiteral literal); + + public void visit(final BooleanLiteral literal); + +} diff --git a/src/main/java/com/exasol/sql/expression/LongLiteral.java b/src/main/java/com/exasol/sql/expression/literal/LongLiteral.java similarity index 82% rename from src/main/java/com/exasol/sql/expression/LongLiteral.java rename to src/main/java/com/exasol/sql/expression/literal/LongLiteral.java index e2b18c7d..c7f3d07a 100644 --- a/src/main/java/com/exasol/sql/expression/LongLiteral.java +++ b/src/main/java/com/exasol/sql/expression/literal/LongLiteral.java @@ -1,10 +1,10 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; /** * This class represents long literals. */ // [impl->dsn~literal-values~2] -public class LongLiteral extends AbstractValueExpression { +public class LongLiteral extends AbstractLiteral { private final long value; private LongLiteral(final long value) { @@ -31,7 +31,7 @@ public long getValue() { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final LiteralVisitor visitor) { visitor.visit(this); } diff --git a/src/main/java/com/exasol/sql/expression/NullLiteral.java b/src/main/java/com/exasol/sql/expression/literal/NullLiteral.java similarity index 68% rename from src/main/java/com/exasol/sql/expression/NullLiteral.java rename to src/main/java/com/exasol/sql/expression/literal/NullLiteral.java index 2e7bf1bb..8f8d038c 100644 --- a/src/main/java/com/exasol/sql/expression/NullLiteral.java +++ b/src/main/java/com/exasol/sql/expression/literal/NullLiteral.java @@ -1,10 +1,10 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; /** * This class represents a null literal. */ // [impl->dsn~literal-values~2] -public final class NullLiteral extends AbstractValueExpression { +public final class NullLiteral extends AbstractLiteral { private static final NullLiteral instance = new NullLiteral(); public static NullLiteral nullLiteral() { @@ -16,7 +16,7 @@ private NullLiteral() { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final LiteralVisitor visitor) { visitor.visit(this); } } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/StringLiteral.java b/src/main/java/com/exasol/sql/expression/literal/StringLiteral.java similarity index 84% rename from src/main/java/com/exasol/sql/expression/StringLiteral.java rename to src/main/java/com/exasol/sql/expression/literal/StringLiteral.java index e572cf14..74975b1f 100644 --- a/src/main/java/com/exasol/sql/expression/StringLiteral.java +++ b/src/main/java/com/exasol/sql/expression/literal/StringLiteral.java @@ -1,10 +1,10 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; /** * This class represents string literals (or character literals in SQL terms). */ // [impl->dsn~literal-values~2] -public final class StringLiteral extends AbstractValueExpression { +public final class StringLiteral extends AbstractLiteral { private final String literal; private StringLiteral(final String literal) { @@ -32,7 +32,7 @@ public static StringLiteral of(final char literal) { } @Override - public void accept(final ValueExpressionVisitor visitor) { + public void accept(final LiteralVisitor visitor) { visitor.visit(this); } diff --git a/src/main/java/com/exasol/sql/expression/rendering/AbstractExpressionRenderer.java b/src/main/java/com/exasol/sql/expression/rendering/AbstractExpressionRenderer.java index 5b628599..f782bce3 100644 --- a/src/main/java/com/exasol/sql/expression/rendering/AbstractExpressionRenderer.java +++ b/src/main/java/com/exasol/sql/expression/rendering/AbstractExpressionRenderer.java @@ -1,9 +1,6 @@ package com.exasol.sql.expression.rendering; -import java.util.ArrayDeque; -import java.util.Deque; - -import com.exasol.sql.expression.*; +import com.exasol.sql.expression.literal.BooleanLiteral; import com.exasol.sql.rendering.StringRendererConfig; import com.exasol.util.QuotesApplier; @@ -13,13 +10,10 @@ public abstract class AbstractExpressionRenderer { protected final StringRendererConfig config; protected final StringBuilder builder = new StringBuilder(); - protected final Deque connectorDeque = new ArrayDeque<>(); private final QuotesApplier quotesApplier; - private ValueExpression lastVisited; public AbstractExpressionRenderer(final StringRendererConfig config) { this.config = config; - this.lastVisited = null; this.quotesApplier = new QuotesApplier(config); } @@ -27,18 +21,6 @@ protected void appendKeyword(final String keyword) { this.builder.append(this.config.useLowerCase() ? keyword.toLowerCase() : keyword); } - protected void connect(final BooleanExpression expression) { - if (expression.isChild() && !expression.isFirstSibling()) { - appendConnector(); - } - } - - private void appendConnector() { - if (!this.connectorDeque.isEmpty()) { - appendKeyword(this.connectorDeque.peek()); - } - } - protected void appendBooleanLiteral(final BooleanLiteral literal) { this.builder.append(this.config.useLowerCase() ? literal.toString().toLowerCase() : literal.toString()); } @@ -60,18 +42,6 @@ protected void appendAutoQuoted(final String identifier) { append(autoQuotedIdentifier); } - protected void appendCommaWhenNeeded(final ValueExpression valueExpression) { - if ((this.lastVisited != null && !(valueExpression.getParent() instanceof BinaryArithmeticExpression)) - && (this.lastVisited.isSibling(valueExpression) || (valueExpression.getParent() != this.lastVisited - && this.lastVisited.getClass().equals(valueExpression.getClass())))) { - append(", "); - } - } - - protected void setLastVisited(final ValueExpression valueExpression) { - this.lastVisited = valueExpression; - } - /** * Render expression to a string * diff --git a/src/main/java/com/exasol/sql/expression/rendering/BooleanExpressionRenderer.java b/src/main/java/com/exasol/sql/expression/rendering/BooleanExpressionRenderer.java deleted file mode 100644 index 3a3f417c..00000000 --- a/src/main/java/com/exasol/sql/expression/rendering/BooleanExpressionRenderer.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.exasol.sql.expression.rendering; - -import com.exasol.sql.expression.*; -import com.exasol.sql.expression.comparison.Comparison; -import com.exasol.sql.rendering.StringRendererConfig; - -/** - * Renderer for {@link BooleanExpression}s. - */ -public class BooleanExpressionRenderer extends AbstractExpressionRenderer implements BooleanExpressionVisitor { - public BooleanExpressionRenderer(final StringRendererConfig config) { - super(config); - } - - public BooleanExpressionRenderer() { - this(StringRendererConfig.builder().build()); - } - - @Override - public void visit(final Not not) { - connect(not); - appendKeyword("NOT"); - startParenthesis(); - } - - @Override - public void leave(final Not not) { - endParenthesis(); - } - - @Override - public void visit(final And and) { - connect(and); - this.connectorDeque.push(" AND "); - if (!and.isRoot()) { - startParenthesis(); - } - } - - @Override - public void leave(final And and) { - if (!and.isRoot()) { - endParenthesis(); - } - this.connectorDeque.pop(); - } - - @Override - public void visit(final Or or) { - connect(or); - this.connectorDeque.push(" OR "); - if (!or.isRoot()) { - startParenthesis(); - } - } - - @Override - public void leave(final Or or) { - if (!or.isRoot()) { - endParenthesis(); - } - this.connectorDeque.pop(); - } - - @Override - public void visit(final BooleanLiteral literal) { - connect(literal); - appendBooleanLiteral(literal); - } - - @Override - public void visit(final Comparison comparison) { - connect(comparison); - final ComparisonRenderer comparisonRenderer = new ComparisonRenderer(this.config); - comparison.accept(comparisonRenderer); - append(comparisonRenderer.render()); - } -} \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/rendering/ComparisonRenderer.java b/src/main/java/com/exasol/sql/expression/rendering/ComparisonRenderer.java deleted file mode 100644 index 72a7dc2f..00000000 --- a/src/main/java/com/exasol/sql/expression/rendering/ComparisonRenderer.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.exasol.sql.expression.rendering; - -import com.exasol.sql.expression.ValueExpression; -import com.exasol.sql.expression.comparison.Comparison; -import com.exasol.sql.expression.comparison.ComparisonVisitor; -import com.exasol.sql.expression.comparison.LikeComparison; -import com.exasol.sql.expression.comparison.SimpleComparison; -import com.exasol.sql.rendering.StringRendererConfig; - -/** - * Renderer for {@link Comparison}s; - */ -public class ComparisonRenderer extends AbstractExpressionRenderer implements ComparisonVisitor { - - /** - * Create a new instance of {@link ComparisonRenderer}. - * - * @param config render configuration - */ - public ComparisonRenderer(final StringRendererConfig config) { - super(config); - } - - @Override - public void visit(final SimpleComparison simpleComparison) { - openComparison(simpleComparison); - closeComparison(simpleComparison); - } - - @Override - public void visit(final LikeComparison like) { - openComparison(like); - if (like.hasEscape()) { - this.builder.append(" ESCAPE "); - this.builder.append("'"); - this.builder.append(like.getEscape()); - this.builder.append("'"); - } - closeComparison(like); - } - - private void openComparison(final Comparison comparison) { - connect(comparison); - if (!comparison.isRoot()) { - startParenthesis(); - } - appendOperand(comparison.getLeftOperand()); - this.builder.append(" "); - this.builder.append(comparison.getOperator().toString()); - this.builder.append(" "); - appendOperand(comparison.getRightOperand()); - } - - private void closeComparison(final Comparison comparison) { - if (!comparison.isRoot()) { - endParenthesis(); - } - } - - private void appendOperand(final ValueExpression leftOperand) { - final ValueExpressionRenderer leftExpressionRenderer = new ValueExpressionRenderer(this.config); - leftOperand.accept(leftExpressionRenderer); - append(leftExpressionRenderer.render()); - } -} diff --git a/src/main/java/com/exasol/sql/expression/rendering/ValueExpressionRenderer.java b/src/main/java/com/exasol/sql/expression/rendering/ValueExpressionRenderer.java index ee8d753c..4610001b 100644 --- a/src/main/java/com/exasol/sql/expression/rendering/ValueExpressionRenderer.java +++ b/src/main/java/com/exasol/sql/expression/rendering/ValueExpressionRenderer.java @@ -1,127 +1,239 @@ package com.exasol.sql.expression.rendering; +import java.util.List; + import com.exasol.datatype.type.DataType; import com.exasol.sql.ColumnsDefinition; import com.exasol.sql.UnnamedPlaceholder; import com.exasol.sql.expression.*; +import com.exasol.sql.expression.comparison.Comparison; +import com.exasol.sql.expression.comparison.ComparisonVisitor; +import com.exasol.sql.expression.comparison.LikeComparison; +import com.exasol.sql.expression.comparison.SimpleComparison; +import com.exasol.sql.expression.function.AbstractFunction; import com.exasol.sql.expression.function.Function; +import com.exasol.sql.expression.function.FunctionVisitor; import com.exasol.sql.expression.function.exasol.CastExasolFunction; import com.exasol.sql.expression.function.exasol.ExasolFunction; import com.exasol.sql.expression.function.exasol.ExasolUdf; +import com.exasol.sql.expression.literal.*; import com.exasol.sql.rendering.ColumnsDefinitionRenderer; import com.exasol.sql.rendering.StringRendererConfig; /** * Renderer for common value expressions. */ -public class ValueExpressionRenderer extends AbstractExpressionRenderer implements ValueExpressionVisitor { +public class ValueExpressionRenderer extends AbstractExpressionRenderer implements BooleanExpressionVisitor, + ComparisonVisitor, ValueExpressionVisitor, LiteralVisitor, FunctionVisitor { + int nestedLevel = 0; + + /** + * Create a new instance of {@link ValueExpressionRenderer}. + * + * @param config render configuration + */ public ValueExpressionRenderer(final StringRendererConfig config) { super(config); } @Override - public void visit(final StringLiteral literal) { - appendCommaWhenNeeded(literal); - append("'"); - append(literal.toString()); - append("'"); - setLastVisited(literal); + public void visit(final Not not) { + appendKeyword("NOT"); + startParenthesis(); + not.getOperand().accept((BooleanExpressionVisitor) this); + endParenthesis(); } @Override - public void visit(final IntegerLiteral literal) { - appendCommaWhenNeeded(literal); - append(literal.toString()); - setLastVisited(literal); + public void visit(final And and) { + startParenthesisIfNested(); + append(" AND ", and.getOperands()); + endParenthesisIfNested(); + } + + private void append(final String separator, final List expressions) { + boolean isFirst = true; + for (final BooleanExpression expression : expressions) { + if (!isFirst) { + appendKeyword(separator); + } + isFirst = false; + expression.accept((BooleanExpressionVisitor) this); + } } @Override - public void visit(final LongLiteral literal) { - appendCommaWhenNeeded(literal); - append(literal.toString()); - setLastVisited(literal); + public void visit(final Or or) { + startParenthesisIfNested(); + append(" OR ", or.getOperands()); + endParenthesisIfNested(); } @Override - public void visit(final DoubleLiteral literal) { - appendCommaWhenNeeded(literal); - append(literal.toString()); - setLastVisited(literal); + public void visit(final BooleanLiteral literal) { + appendBooleanLiteral(literal); } @Override - public void visit(final FloatLiteral literal) { - appendCommaWhenNeeded(literal); - append(literal.toString()); - setLastVisited(literal); + public void visit(final Comparison comparison) { + comparison.accept((ComparisonVisitor) this); } + /* + * Comparison renderer + */ @Override - public void visit(final BigDecimalLiteral literal) { - appendCommaWhenNeeded(literal); - append(literal.toString()); - setLastVisited(literal); + public void visit(final SimpleComparison simpleComparison) { + openComparison(simpleComparison); + closeComparison(); } @Override - public void visit(final BooleanLiteral literal) { - appendCommaWhenNeeded(literal); - append(literal.toString()); - setLastVisited(literal); + public void visit(final LikeComparison like) { + openComparison(like); + if (like.hasEscape()) { + appendKeyword(" ESCAPE "); + append("'"); + this.builder.append(like.getEscape()); + append("'"); + } + closeComparison(); + } + + private void openComparison(final Comparison comparison) { + startParenthesisIfNested(); + appendOperand(comparison.getLeftOperand()); + this.builder.append(" "); + this.builder.append(comparison.getOperator().toString()); + this.builder.append(" "); + + appendOperand(comparison.getRightOperand()); + } + + private void closeComparison() { + endParenthesisIfNested(); + } + + /* Value expression visitor */ + + public void visit(final ValueExpression... valueExpression) { + boolean isFirst = true; + for (final ValueExpression parameter : valueExpression) { + if (!isFirst) { + append(", "); + } + isFirst = false; + parameter.accept(this); + } } @Override public void visit(final ColumnReference columnReference) { - appendCommaWhenNeeded(columnReference); appendAutoQuoted(columnReference.toString()); - setLastVisited(columnReference); + } + + @Override + public void visit(final Literal literal) { + literal.accept((LiteralVisitor) this); + } + + @Override + public void visit(final Function function) { + function.accept((FunctionVisitor) this); + } + + @Override + public void visit(final BooleanExpression booleanExpression) { + booleanExpression.accept((BooleanExpressionVisitor) this); } @Override public void visit(final UnnamedPlaceholder unnamedPlaceholder) { append("?"); - setLastVisited(unnamedPlaceholder); } @Override public void visit(final DefaultValue defaultValue) { appendKeyword("DEFAULT"); - setLastVisited(defaultValue); + } + + /** Literal visitor **/ + @Override + public void visit(final StringLiteral literal) { + append("'"); + append(literal.toString()); + append("'"); + } + + @Override + public void visit(final IntegerLiteral literal) { + append(literal.toString()); + } + + @Override + public void visit(final LongLiteral literal) { + append(literal.toString()); + } + + @Override + public void visit(final DoubleLiteral literal) { + append(literal.toString()); + } + + @Override + public void visit(final FloatLiteral literal) { + append(literal.toString()); + } + + @Override + public void visit(final BigDecimalLiteral literal) { + append(literal.toString()); } + @Override + public void visit(final NullLiteral nullLiteral) { + appendKeyword("NULL"); + } + + /** Function visitor */ + @Override public void visit(final ExasolFunction function) { - visitFunction(function); + renderFunction(function); } - private void visitFunction(final Function function) { - appendCommaWhenNeeded(function); + private void renderFunction(final AbstractFunction function) { appendKeyword(function.getFunctionName()); if (function.hasParenthesis()) { startParenthesis(); } - } - - @Override - public void leave(final ExasolFunction function) { + ++this.nestedLevel; + this.visit(function.getParameters().toArray(ValueExpression[]::new)); + --this.nestedLevel; if (function.hasParenthesis()) { endParenthesis(); } - setLastVisited(function); } @Override public void visit(final ExasolUdf function) { - visitFunction(function); + renderFunction(function); + appendEmitsWhenNecessary(function); } @Override - public void leave(final ExasolUdf function) { - if (function.hasParenthesis()) { - endParenthesis(); - } - appendEmitsWhenNecessary(function); - setLastVisited(function); + public void visit(final CastExasolFunction castFunction) { + appendKeyword("CAST"); + startParenthesis(); + ++this.nestedLevel; + castFunction.getValue().accept(this); + appendKeyword(" AS "); + final DataType type = castFunction.getType(); + final ColumnsDefinitionRenderer columnsDefinitionRenderer = getColumnsDefinitionRenderer(); + type.accept(columnsDefinitionRenderer); + append(columnsDefinitionRenderer.render()); + --this.nestedLevel; + endParenthesis(); } @SuppressWarnings("squid:S3655") @@ -139,49 +251,34 @@ private void appendEmitsWhenNecessary(final ExasolUdf function) { @Override public void visit(final BinaryArithmeticExpression expression) { - appendCommaWhenNeeded(expression); startParenthesis(); + ++this.nestedLevel; appendOperand(expression.getLeft()); append(expression.getStringOperatorRepresentation()); appendOperand(expression.getRight()); + --this.nestedLevel; endParenthesis(); - setLastVisited(expression); - } - - protected void appendOperand(final ValueExpression operand) { - final ValueExpressionRenderer expressionRenderer = new ValueExpressionRenderer(this.config); - operand.accept(expressionRenderer); - this.builder.append(expressionRenderer.render()); } - @Override - public void visit(final NullLiteral nullLiteral) { - appendCommaWhenNeeded(nullLiteral); - appendKeyword("NULL"); - setLastVisited(nullLiteral); + private void appendOperand(final ValueExpression operand) { + operand.accept(this); } - @Override - public void visit(final BooleanExpression booleanExpression) { - final BooleanExpressionRenderer expressionRenderer = new BooleanExpressionRenderer(this.config); - booleanExpression.accept(expressionRenderer); - append(expressionRenderer.render()); + private ColumnsDefinitionRenderer getColumnsDefinitionRenderer() { + return new ColumnsDefinitionRenderer(this.config); } - @Override - public void visit(final CastExasolFunction castFunction) { - appendKeyword("CAST"); - startParenthesis(); - castFunction.getValue().accept(this); - appendKeyword(" AS"); - final DataType type = castFunction.getType(); - final ColumnsDefinitionRenderer columnsDefinitionRenderer = getColumnsDefinitionRenderer(); - type.accept(columnsDefinitionRenderer); - append(columnsDefinitionRenderer.render()); - endParenthesis(); + private void startParenthesisIfNested() { + if (this.nestedLevel > 0) { + startParenthesis(); + } + ++this.nestedLevel; } - private ColumnsDefinitionRenderer getColumnsDefinitionRenderer() { - return new ColumnsDefinitionRenderer(this.config); + private void endParenthesisIfNested() { + --this.nestedLevel; + if (this.nestedLevel > 0) { + endParenthesis(); + } } -} \ No newline at end of file +} diff --git a/src/main/java/com/exasol/sql/rendering/AbstractFragmentRenderer.java b/src/main/java/com/exasol/sql/rendering/AbstractFragmentRenderer.java index 4c1fac6c..424ab921 100644 --- a/src/main/java/com/exasol/sql/rendering/AbstractFragmentRenderer.java +++ b/src/main/java/com/exasol/sql/rendering/AbstractFragmentRenderer.java @@ -4,9 +4,7 @@ import com.exasol.sql.Fragment; import com.exasol.sql.ValueTableRow; -import com.exasol.sql.expression.BooleanExpression; import com.exasol.sql.expression.ValueExpression; -import com.exasol.sql.expression.rendering.BooleanExpressionRenderer; import com.exasol.sql.expression.rendering.ValueExpressionRenderer; import com.exasol.util.QuotesApplier; @@ -43,12 +41,16 @@ protected void endParenthesis() { this.builder.append(")"); } + protected void appendRenderedValueExpression(final ValueExpression expression) { + final ValueExpressionRenderer renderer = new ValueExpressionRenderer(this.config); + expression.accept(renderer); + append(renderer.render()); + } + protected void appendListOfValueExpressions(final List valueExpressions) { if ((valueExpressions != null) && !valueExpressions.isEmpty()) { final ValueExpressionRenderer valueExpressionRenderer = new ValueExpressionRenderer(this.config); - for (final ValueExpression valueExpression : valueExpressions) { - valueExpression.accept(valueExpressionRenderer); - } + valueExpressionRenderer.visit(valueExpressions.toArray(ValueExpression[]::new)); this.builder.append(valueExpressionRenderer.render()); } } @@ -71,22 +73,10 @@ protected void appendCommaWhenNeeded(final Fragment fragment) { } } - protected void appendRenderedBooleanExpression(final BooleanExpression expression) { - final BooleanExpressionRenderer expressionRenderer = new BooleanExpressionRenderer(this.config); - expression.accept(expressionRenderer); - append(expressionRenderer.render()); - } - protected void append(final int number) { this.builder.append(number); } - protected void appendRenderedValueExpression(final ValueExpression expression) { - final ValueExpressionRenderer renderer = new ValueExpressionRenderer(this.config); - expression.accept(renderer); - append(renderer.render()); - } - protected void appendAutoQuoted(final String identifier) { final String autoQuotedIdentifier = this.quotesApplier.getAutoQuoted(identifier); append(autoQuotedIdentifier); diff --git a/src/main/java/com/exasol/util/AbstractBottomUpTreeNode.java b/src/main/java/com/exasol/util/AbstractBottomUpTreeNode.java deleted file mode 100644 index 4806f966..00000000 --- a/src/main/java/com/exasol/util/AbstractBottomUpTreeNode.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.exasol.util; - -import java.util.Arrays; -import java.util.List; - -/** - * This is an abstract base class for nodes in a tree structure. - */ -public abstract class AbstractBottomUpTreeNode extends AbstractTree { - /** - * Create a new instance of a {@link AbstractBottomUpTreeNode}. - * - * @param children child nodes to be linked to this node. - */ - public AbstractBottomUpTreeNode(final List children) { - this.children = children; - for (final TreeNode child : children) { - assignThisAsParentTo(child); - } - } - - /** - * Create a new instance of a {@link AbstractBottomUpTreeNode}. - * - * @param children child nodes to be linked to this node. - */ - public AbstractBottomUpTreeNode(final TreeNode... children) { - this(Arrays.asList(children)); - } - - private void assignThisAsParentTo(final TreeNode child) { - assertChildType(child); - assertChildDoesNotAlreadyHaveAParent(child); - ((AbstractBottomUpTreeNode) child).parent = this; - } - - private void assertChildType(final TreeNode child) { - if (!(child instanceof AbstractBottomUpTreeNode)) { - throw new IllegalArgumentException("A bottom up tree can only be constructed from nodes of type \"" - + AbstractBottomUpTreeNode.class.getName() + "\" but got an object of type \"" - + child.getClass().getName() + "\""); - } - } - - private void assertChildDoesNotAlreadyHaveAParent(final TreeNode child) { - if (child.getParent() != null) { - throw new IllegalStateException( - "Tried to link node \"" + child.toString() + "\" in bottom-up tree to parent \"" + this.toString() - + "\" which already has a parent \"" + child.getParent() + "\""); - } - } - - @Override - public TreeNode getRoot() { - if (getParent() == null) { - return this; - } else { - return getParent().getRoot(); - } - } - - @Override - public void addChild(final TreeNode child) { - throw new UnsupportedOperationException("Node \"" + child.toString() - + "\" can only be added as child node in parent constructor in a bottom-up tree."); - } - - @Override - public void setParent(final TreeNode parent) { - this.parent = parent; - } -} \ No newline at end of file diff --git a/src/main/java/com/exasol/util/AbstractTree.java b/src/main/java/com/exasol/util/AbstractTree.java deleted file mode 100644 index 6a5f41fa..00000000 --- a/src/main/java/com/exasol/util/AbstractTree.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.exasol.util; - -import java.util.ArrayList; -import java.util.List; - -/** - * An abstract base for {@link TreeNode} implementations. - */ -public abstract class AbstractTree implements TreeNode { - protected TreeNode parent = null; - protected List children = new ArrayList<>(); - - @Override - public TreeNode getParent() { - return this.parent; - } - - @Override - public List getChildren() { - return this.children; - } - - @Override - public TreeNode getChild(final int index) { - return this.children.get(index); - } - - @Override - public boolean isRoot() { - return (this == getRoot()); - } - - @Override - public boolean isChild() { - return (this.parent != null); - } - - @Override - public boolean isFirstSibling() { - return (this.parent != null) && (this.getParent().getChild(0) == this); - } - - @Override - public boolean isSibling(final TreeNode node) { - return (this.parent != null) && (this.getParent().getChildren().contains(node)); - } -} diff --git a/src/main/java/com/exasol/util/AbstractTreeNode.java b/src/main/java/com/exasol/util/AbstractTreeNode.java deleted file mode 100644 index 070b8106..00000000 --- a/src/main/java/com/exasol/util/AbstractTreeNode.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.exasol.util; - -/** - * This is an abstract base class for nodes in a tree structure. - */ -public abstract class AbstractTreeNode extends AbstractTree { - private TreeNode root; - - /** - * Create a new instance of a {@link AbstractTreeNode} that serves as root for a tree. - */ - public AbstractTreeNode() { - this.root = this; - this.parent = null; - } - - /** - * Link to a parent node - * - * @param parent the parent to which this node will be linked as a child - * - * @throws IllegalArgumentException if parent is null or parent and child are identical - */ - @Override - public void setParent(final TreeNode parent) { - if (parent == null) { - throw new IllegalArgumentException("Parent tree node cannot be NULL."); - } else if (parent == this) { - throw new IllegalArgumentException("Parent tree node cannot be the same as child tree node."); - } else { - this.parent = parent; - this.root = this.parent.getRoot(); - } - } - - @Override - public TreeNode getRoot() { - return this.root; - } - - @Override - public void addChild(final TreeNode child) { - this.children.add(child); - child.setParent(this); - } -} \ No newline at end of file diff --git a/src/main/java/com/exasol/util/TreeNode.java b/src/main/java/com/exasol/util/TreeNode.java deleted file mode 100644 index 014d9eb8..00000000 --- a/src/main/java/com/exasol/util/TreeNode.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.exasol.util; - -import java.util.List; - -/** - * This class represents a node in a tree structure. - */ -public interface TreeNode { - /** - * Get the root of the tree - * - * @return root node - */ - public TreeNode getRoot(); - - /** - * Get the parent of this node - * - * @return parent node - */ - public TreeNode getParent(); - - /** - * Add a child node below this node. Children are registered in the order in which they are added. - *

- * Important: this also automatically creates a link in the opposite direction. All implementations - * must adhere to this rule. - * - * @param child child node - */ - public void addChild(TreeNode child); - - /** - * Get all child nodes of this node - * - * @return child nodes - */ - public List getChildren(); - - /** - * Get child node by position in the list of siblings. The position depends on the order in which the children were - * added. - * - * @param index position in the list of siblings - * @return child node at position - * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index ≥ size()) - */ - public TreeNode getChild(int index); - - /** - * Check whether this node is the root of the tree. - * - * @return true if this node is the root - */ - public boolean isRoot(); - - /** - * Check whether this node is a child node - * - * @return true if the node is a child of another node - */ - public boolean isChild(); - - /** - * Check whether a child is the first in the list of siblings - * - * @return true if the child is the first in the list of siblings - */ - public boolean isFirstSibling(); - - /** - * Check whether this node is a sibling of the second node. - * - * @param node second node - * @return true if two nodes are siblings - */ - public boolean isSibling(TreeNode node); - - /** - * Set a parent for this node. - * - * @param parent a node to set as a parent - */ - public void setParent(TreeNode parent); -} \ No newline at end of file diff --git a/src/test/java/com/exasol/hamcrest/BooleanExpressionRenderResultMatcher.java b/src/test/java/com/exasol/hamcrest/BooleanExpressionRenderResultMatcher.java deleted file mode 100644 index 7bee09fd..00000000 --- a/src/test/java/com/exasol/hamcrest/BooleanExpressionRenderResultMatcher.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.exasol.hamcrest; - -import org.hamcrest.Description; - -import com.exasol.sql.dql.select.rendering.SelectRenderer; -import com.exasol.sql.expression.BooleanExpression; -import com.exasol.sql.expression.rendering.BooleanExpressionRenderer; -import com.exasol.sql.rendering.StringRendererConfig; - -/** - * This class implements a matcher for the results of rendering boolean expressions to text. - */ -public class BooleanExpressionRenderResultMatcher extends AbstractRenderResultMatcher { - private final BooleanExpressionRenderer renderer; - - private BooleanExpressionRenderResultMatcher(final String expectedText) { - super(expectedText); - this.renderer = new BooleanExpressionRenderer(); - } - - private BooleanExpressionRenderResultMatcher(final StringRendererConfig config, final String expectedText) { - super(expectedText); - this.renderer = new BooleanExpressionRenderer(config); - } - - /** - * Factory method for {@link BooleanExpressionRenderResultMatcher} - * - * @param expectedText text that represents the expected rendering result - * @return the matcher - */ - public static BooleanExpressionRenderResultMatcher rendersTo(final String expectedText) { - return new BooleanExpressionRenderResultMatcher(expectedText); - } - - /** - * Factory method for {@link BooleanExpressionRenderResultMatcher} - * - * @param config configuration settings for the {@link SelectRenderer} - * @param expectedText text that represents the expected rendering result - * @return the matcher - */ - public static BooleanExpressionRenderResultMatcher rendersWithConfigTo(final StringRendererConfig config, - final String expectedText) { - return new BooleanExpressionRenderResultMatcher(config, expectedText); - } - - /** - * Match the rendered result against original text. - * - * @param expression expression to be matched against the original text. - */ - @Override - public boolean matchesSafely(final BooleanExpression expression) { - expression.accept(this.renderer); - this.renderedText = this.renderer.render(); - return this.renderedText.equals(this.expectedText); - } - - @Override - protected void describeMismatchSafely(final BooleanExpression expression, final Description mismatchDescription) { - mismatchDescription.appendText(this.renderedText); - } -} \ No newline at end of file diff --git a/src/test/java/com/exasol/hamcrest/ValueExpressionRenderResultMatcher.java b/src/test/java/com/exasol/hamcrest/ValueExpressionRenderResultMatcher.java new file mode 100644 index 00000000..da8ea317 --- /dev/null +++ b/src/test/java/com/exasol/hamcrest/ValueExpressionRenderResultMatcher.java @@ -0,0 +1,64 @@ +package com.exasol.hamcrest; + +import org.hamcrest.Description; + +import com.exasol.sql.dql.select.rendering.SelectRenderer; +import com.exasol.sql.expression.ValueExpression; +import com.exasol.sql.expression.rendering.ValueExpressionRenderer; +import com.exasol.sql.rendering.StringRendererConfig; + +/** + * This class implements a matcher for the results of rendering boolean expressions to text. + */ +public class ValueExpressionRenderResultMatcher extends AbstractRenderResultMatcher { + private final ValueExpressionRenderer renderer; + + private ValueExpressionRenderResultMatcher(final String expectedText) { + super(expectedText); + this.renderer = new ValueExpressionRenderer(StringRendererConfig.createDefault()); + } + + private ValueExpressionRenderResultMatcher(final StringRendererConfig config, final String expectedText) { + super(expectedText); + this.renderer = new ValueExpressionRenderer(config); + } + + /** + * Factory method for {@link ValueExpressionRenderResultMatcher} + * + * @param expectedText text that represents the expected rendering result + * @return the matcher + */ + public static ValueExpressionRenderResultMatcher rendersTo(final String expectedText) { + return new ValueExpressionRenderResultMatcher(expectedText); + } + + /** + * Factory method for {@link ValueExpressionRenderResultMatcher} + * + * @param config configuration settings for the {@link SelectRenderer} + * @param expectedText text that represents the expected rendering result + * @return the matcher + */ + public static ValueExpressionRenderResultMatcher rendersWithConfigTo(final StringRendererConfig config, + final String expectedText) { + return new ValueExpressionRenderResultMatcher(config, expectedText); + } + + /** + * Match the rendered result against original text. + * + * @param expression expression to be matched against the original text. + */ + @Override + public boolean matchesSafely(final ValueExpression expression) { + expression.accept(this.renderer); + this.renderedText = this.renderer.render(); + return this.renderedText.equals(this.expectedText); + } + + @Override + protected void describeMismatchSafely(final ValueExpression expression, final Description mismatchDescription) { + mismatchDescription.appendText(this.renderedText); + } +} \ No newline at end of file diff --git a/src/test/java/com/exasol/sql/dml/merge/MergeMethodDefinitionTest.java b/src/test/java/com/exasol/sql/dml/merge/MergeMethodDefinitionTest.java index 0a3dd29c..f71568d0 100644 --- a/src/test/java/com/exasol/sql/dml/merge/MergeMethodDefinitionTest.java +++ b/src/test/java/com/exasol/sql/dml/merge/MergeMethodDefinitionTest.java @@ -11,7 +11,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import com.exasol.sql.Fragment; -import com.exasol.sql.expression.BooleanLiteral; +import com.exasol.sql.expression.literal.BooleanLiteral; @ExtendWith(MockitoExtension.class) class MergeMethodDefinitionTest { diff --git a/src/test/java/com/exasol/sql/expression/TestComparisonOperator.java b/src/test/java/com/exasol/sql/expression/comparison/TestComparisonOperator.java similarity index 88% rename from src/test/java/com/exasol/sql/expression/TestComparisonOperator.java rename to src/test/java/com/exasol/sql/expression/comparison/TestComparisonOperator.java index d659c555..57ea01c6 100644 --- a/src/test/java/com/exasol/sql/expression/TestComparisonOperator.java +++ b/src/test/java/com/exasol/sql/expression/comparison/TestComparisonOperator.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.comparison; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; @@ -6,8 +6,6 @@ import org.junit.jupiter.api.Test; -import com.exasol.sql.expression.comparison.SimpleComparisonOperator; - class TestComparisonOperator { @Test void testToString() { diff --git a/src/test/java/com/exasol/sql/expression/function/exasol/CastExasolFunctionTest.java b/src/test/java/com/exasol/sql/expression/function/exasol/CastExasolFunctionTest.java index 7a1c167a..bfb34bca 100644 --- a/src/test/java/com/exasol/sql/expression/function/exasol/CastExasolFunctionTest.java +++ b/src/test/java/com/exasol/sql/expression/function/exasol/CastExasolFunctionTest.java @@ -8,20 +8,20 @@ import com.exasol.datatype.type.Varchar; import com.exasol.sql.StatementFactory; import com.exasol.sql.dql.select.Select; -import com.exasol.sql.expression.NullLiteral; +import com.exasol.sql.expression.literal.NullLiteral; class CastExasolFunctionTest { @Test void testRendering() { final Select select = StatementFactory.getInstance().select() .function(CastExasolFunction.of(NullLiteral.nullLiteral(), new Varchar(254))); - assertThat(select, rendersTo("SELECT CAST(NULL AS VARCHAR(254))")); + assertThat(select, rendersTo("SELECT CAST(NULL AS VARCHAR(254))")); } @Test void testRenderingWithName() { final Select select = StatementFactory.getInstance().select() .function(CastExasolFunction.of(NullLiteral.nullLiteral(), new Varchar(254)), "TEST"); - assertThat(select, rendersTo("SELECT CAST(NULL AS VARCHAR(254)) TEST")); + assertThat(select, rendersTo("SELECT CAST(NULL AS VARCHAR(254)) TEST")); } } \ No newline at end of file diff --git a/src/test/java/com/exasol/sql/expression/DoubleLiteralTest.java b/src/test/java/com/exasol/sql/expression/literal/DoubleLiteralTest.java similarity index 90% rename from src/test/java/com/exasol/sql/expression/DoubleLiteralTest.java rename to src/test/java/com/exasol/sql/expression/literal/DoubleLiteralTest.java index eeea3b9c..ccf4a2fd 100644 --- a/src/test/java/com/exasol/sql/expression/DoubleLiteralTest.java +++ b/src/test/java/com/exasol/sql/expression/literal/DoubleLiteralTest.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; diff --git a/src/test/java/com/exasol/sql/expression/FloatLiteralTest.java b/src/test/java/com/exasol/sql/expression/literal/FloatLiteralTest.java similarity index 90% rename from src/test/java/com/exasol/sql/expression/FloatLiteralTest.java rename to src/test/java/com/exasol/sql/expression/literal/FloatLiteralTest.java index 0e8dd602..20edb852 100644 --- a/src/test/java/com/exasol/sql/expression/FloatLiteralTest.java +++ b/src/test/java/com/exasol/sql/expression/literal/FloatLiteralTest.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; diff --git a/src/test/java/com/exasol/sql/expression/LongLiteralTest.java b/src/test/java/com/exasol/sql/expression/literal/LongLiteralTest.java similarity index 91% rename from src/test/java/com/exasol/sql/expression/LongLiteralTest.java rename to src/test/java/com/exasol/sql/expression/literal/LongLiteralTest.java index 31e13db8..4cf65c24 100644 --- a/src/test/java/com/exasol/sql/expression/LongLiteralTest.java +++ b/src/test/java/com/exasol/sql/expression/literal/LongLiteralTest.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; diff --git a/src/test/java/com/exasol/sql/expression/TestBigDecimalLiteral.java b/src/test/java/com/exasol/sql/expression/literal/TestBigDecimalLiteral.java similarity index 92% rename from src/test/java/com/exasol/sql/expression/TestBigDecimalLiteral.java rename to src/test/java/com/exasol/sql/expression/literal/TestBigDecimalLiteral.java index 39c2ede0..a95e09c6 100644 --- a/src/test/java/com/exasol/sql/expression/TestBigDecimalLiteral.java +++ b/src/test/java/com/exasol/sql/expression/literal/TestBigDecimalLiteral.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; diff --git a/src/test/java/com/exasol/sql/expression/TestBooleanLiteral.java b/src/test/java/com/exasol/sql/expression/literal/TestBooleanLiteral.java similarity index 97% rename from src/test/java/com/exasol/sql/expression/TestBooleanLiteral.java rename to src/test/java/com/exasol/sql/expression/literal/TestBooleanLiteral.java index c06b5953..67a115f2 100644 --- a/src/test/java/com/exasol/sql/expression/TestBooleanLiteral.java +++ b/src/test/java/com/exasol/sql/expression/literal/TestBooleanLiteral.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; diff --git a/src/test/java/com/exasol/sql/expression/TestIntegerLiteral.java b/src/test/java/com/exasol/sql/expression/literal/TestIntegerLiteral.java similarity index 90% rename from src/test/java/com/exasol/sql/expression/TestIntegerLiteral.java rename to src/test/java/com/exasol/sql/expression/literal/TestIntegerLiteral.java index 6f0d71bf..ea714a56 100644 --- a/src/test/java/com/exasol/sql/expression/TestIntegerLiteral.java +++ b/src/test/java/com/exasol/sql/expression/literal/TestIntegerLiteral.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; diff --git a/src/test/java/com/exasol/sql/expression/TestStringLiteral.java b/src/test/java/com/exasol/sql/expression/literal/TestStringLiteral.java similarity index 87% rename from src/test/java/com/exasol/sql/expression/TestStringLiteral.java rename to src/test/java/com/exasol/sql/expression/literal/TestStringLiteral.java index 8145133b..65c8d948 100644 --- a/src/test/java/com/exasol/sql/expression/TestStringLiteral.java +++ b/src/test/java/com/exasol/sql/expression/literal/TestStringLiteral.java @@ -1,4 +1,4 @@ -package com.exasol.sql.expression; +package com.exasol.sql.expression.literal; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; diff --git a/src/test/java/com/exasol/sql/expression/rendering/TestBooleanExpressionRenderer.java b/src/test/java/com/exasol/sql/expression/rendering/TestBooleanExpressionRenderer.java index 3e578eef..d72758ba 100644 --- a/src/test/java/com/exasol/sql/expression/rendering/TestBooleanExpressionRenderer.java +++ b/src/test/java/com/exasol/sql/expression/rendering/TestBooleanExpressionRenderer.java @@ -1,7 +1,7 @@ package com.exasol.sql.expression.rendering; -import static com.exasol.hamcrest.BooleanExpressionRenderResultMatcher.rendersTo; -import static com.exasol.hamcrest.BooleanExpressionRenderResultMatcher.rendersWithConfigTo; +import static com.exasol.hamcrest.ValueExpressionRenderResultMatcher.rendersTo; +import static com.exasol.hamcrest.ValueExpressionRenderResultMatcher.rendersWithConfigTo; import static com.exasol.sql.expression.BooleanTerm.*; import static com.exasol.sql.expression.ExpressionTerm.*; import static org.hamcrest.MatcherAssert.assertThat; @@ -11,9 +11,9 @@ import org.junit.jupiter.api.Test; -import com.exasol.sql.expression.BigDecimalLiteral; import com.exasol.sql.expression.BooleanExpression; import com.exasol.sql.expression.comparison.SimpleComparisonOperator; +import com.exasol.sql.expression.literal.BigDecimalLiteral; import com.exasol.sql.rendering.StringRendererConfig; class TestBooleanExpressionRenderer { diff --git a/src/test/java/com/exasol/util/DummyBottomUpTreeNode.java b/src/test/java/com/exasol/util/DummyBottomUpTreeNode.java deleted file mode 100644 index 77a4d426..00000000 --- a/src/test/java/com/exasol/util/DummyBottomUpTreeNode.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.exasol.util; - -public class DummyBottomUpTreeNode extends AbstractBottomUpTreeNode { - public DummyBottomUpTreeNode() { - super(); - } - - public DummyBottomUpTreeNode(final TreeNode... children) { - super(children); - } -} diff --git a/src/test/java/com/exasol/util/DummyTreeNode.java b/src/test/java/com/exasol/util/DummyTreeNode.java deleted file mode 100644 index 9ef5afb7..00000000 --- a/src/test/java/com/exasol/util/DummyTreeNode.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.exasol.util; - -public class DummyTreeNode extends AbstractTreeNode { - public DummyTreeNode() { - super(); - } -} diff --git a/src/test/java/com/exasol/util/TestAbstractBottomUpTreeNode.java b/src/test/java/com/exasol/util/TestAbstractBottomUpTreeNode.java deleted file mode 100644 index 6cceef77..00000000 --- a/src/test/java/com/exasol/util/TestAbstractBottomUpTreeNode.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.exasol.util; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.junit.jupiter.api.Assertions.*; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class TestAbstractBottomUpTreeNode { - private TreeNode node; - - @BeforeEach - void beforeEach() { - this.node = new DummyBottomUpTreeNode(); - } - - @Test - void testIsRootOnRootNode() { - assertTrue(this.node.isRoot()); - } - - @Test - void testIsChildOnRootNode() { - assertFalse(this.node.isChild()); - } - - @Test - void testIsFirstSiblingOnRootNode() { - assertFalse(this.node.isFirstSibling()); - } - - @Test - void testIsRootOnChild() { - new DummyBottomUpTreeNode(this.node); - assertFalse(this.node.isRoot()); - } - - @Test - void testIsChildOnChild() { - new DummyBottomUpTreeNode(this.node); - assertTrue(this.node.isChild()); - } - - @Test - void testIsFirstSiblingOnChild() { - new DummyBottomUpTreeNode(this.node); - assertTrue(this.node.isFirstSibling()); - } - - @Test - void testIsFirstSiblingOnFirstChild() { - new DummyBottomUpTreeNode(this.node, new DummyBottomUpTreeNode()); - assertTrue(this.node.isFirstSibling()); - } - - @Test - void testIsFirstSiblingOnSecondChild() { - new DummyBottomUpTreeNode(new DummyBottomUpTreeNode(), this.node); - assertFalse(this.node.isFirstSibling()); - } - - @Test - void testAddingChildAfterConstructorThrowsException() { - final DummyBottomUpTreeNode child = new DummyBottomUpTreeNode(); - assertThrows(UnsupportedOperationException.class, () -> this.node.addChild(child)); - } - - @Test - void testGetChildren() { - final TreeNode otherNode = new DummyBottomUpTreeNode(); - final TreeNode parent = new DummyBottomUpTreeNode(this.node, otherNode); - assertThat(parent.getChildren(), contains(this.node, otherNode)); - } - - @Test - void testAddingChildToTwoParentsThrowsException() { - new DummyBottomUpTreeNode(this.node); - assertThrows(IllegalStateException.class, () -> new DummyBottomUpTreeNode(this.node)); - } - - @Test - void testAddingWrongChildTypeThrowsException() { - final TreeNode wrongChild = new WrongNodeType(); - assertThrows(IllegalArgumentException.class, () -> new DummyBottomUpTreeNode(wrongChild)); - } - - private static class WrongNodeType implements TreeNode { - @Override - public TreeNode getRoot() { - return null; - } - - @Override - public TreeNode getParent() { - return null; - } - - @Override - public void addChild(final TreeNode child) { - } - - @Override - public List getChildren() { - return null; - } - - @Override - public TreeNode getChild(final int index) throws IndexOutOfBoundsException { - return null; - } - - @Override - public boolean isRoot() { - return false; - } - - @Override - public boolean isChild() { - return false; - } - - @Override - public boolean isFirstSibling() { - return false; - } - - @Override - public boolean isSibling(final TreeNode node) { - return false; - } - - @Override - public void setParent(final TreeNode parent) { - } - } -} \ No newline at end of file diff --git a/src/test/java/com/exasol/util/TestAbstractTreeNode.java b/src/test/java/com/exasol/util/TestAbstractTreeNode.java deleted file mode 100644 index d2028c65..00000000 --- a/src/test/java/com/exasol/util/TestAbstractTreeNode.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.exasol.util; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class TestAbstractTreeNode { - private TreeNode node; - - @BeforeEach - void beforeEach() { - this.node = new DummyTreeNode(); - } - - @Test - void testIsRootOnRootNode() { - assertTrue(this.node.isRoot()); - } - - @Test - void testIsChildOnRootNode() { - assertFalse(this.node.isChild()); - } - - @Test - void testIsFirstSiblingOnRootNode() { - assertFalse(this.node.isFirstSibling()); - } - - @Test - void testIsRootOnChild() { - final TreeNode child = new DummyTreeNode(); - this.node.addChild(child); - assertFalse(child.isRoot()); - } - - @Test - void testIsChildOnChild() { - final TreeNode child = new DummyTreeNode(); - this.node.addChild(child); - assertTrue(child.isChild()); - } - - @Test - void testIsFirstSiblingOnChild() { - final TreeNode child = new DummyTreeNode(); - this.node.addChild(child); - assertTrue(child.isFirstSibling()); - } - - @Test - void testIsFirstSiblingOnFirstChild() { - final TreeNode child = new DummyTreeNode(); - final TreeNode otherChild = new DummyTreeNode(); - this.node.addChild(child); - this.node.addChild(otherChild); - assertTrue(child.isFirstSibling()); - } - - @Test - void testIsFirstSiblingOnSecondChild() { - final TreeNode child = new DummyTreeNode(); - final TreeNode otherChild = new DummyTreeNode(); - this.node.addChild(child); - this.node.addChild(otherChild); - assertFalse(otherChild.isFirstSibling()); - } - - @Test - void testGetChildren() { - final TreeNode child = new DummyTreeNode(); - final TreeNode otherChild = new DummyTreeNode(); - this.node.addChild(child); - this.node.addChild(otherChild); - assertThat(this.node.getChildren(), contains(child, otherChild)); - } - - @Test - void testGetChild() { - final TreeNode child = new DummyTreeNode(); - final TreeNode otherChild = new DummyTreeNode(); - this.node.addChild(child); - this.node.addChild(otherChild); - assertThat(this.node.getChild(1), equalTo(otherChild)); - } - - @Test - void testGetParent() { - final TreeNode child = new DummyTreeNode(); - this.node.addChild(child); - assertThat(child.getParent(), equalTo(this.node)); - } - - @Test - void testSetParentToNullThrowsException() { - final DummyTreeNode dummyTreeNode = new DummyTreeNode(); - assertThrows(IllegalArgumentException.class, () -> dummyTreeNode.setParent(null)); - } - - @Test - void testSetParentToSelfThrowsException() { - final DummyTreeNode abstractNode = new DummyTreeNode(); - assertThrows(IllegalArgumentException.class, () -> abstractNode.setParent(abstractNode)); - } -} \ No newline at end of file