/*
 * Copyright (c) 2006, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.tests.jpql.parser;

import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.JPAVersion;
import org.eclipse.persistence.jpa.jpql.parser.AbsExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractConditionalClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractDoubleEncapsulatedExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractEncapsulatedExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractFromClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractOrderByClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSchemaName;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSelectClause;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.AbstractSingleEncapsulatedExpression;
import org.eclipse.persistence.jpa.jpql.parser.AbstractTripleEncapsulatedExpression;
import org.eclipse.persistence.jpa.jpql.parser.AdditionExpression;
import org.eclipse.persistence.jpa.jpql.parser.AllOrAnyExpression;
import org.eclipse.persistence.jpa.jpql.parser.AndExpression;
import org.eclipse.persistence.jpa.jpql.parser.ArithmeticFactor;
import org.eclipse.persistence.jpa.jpql.parser.AsOfClause;
import org.eclipse.persistence.jpa.jpql.parser.AvgFunction;
import org.eclipse.persistence.jpa.jpql.parser.BadExpression;
import org.eclipse.persistence.jpa.jpql.parser.BetweenExpression;
import org.eclipse.persistence.jpa.jpql.parser.CaseExpression;
import org.eclipse.persistence.jpa.jpql.parser.CastExpression;
import org.eclipse.persistence.jpa.jpql.parser.CoalesceExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionMemberDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.CollectionMemberExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionValuedPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.ComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.CompoundExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConcatExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConnectByClause;
import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression;
import org.eclipse.persistence.jpa.jpql.parser.CountFunction;
import org.eclipse.persistence.jpa.jpql.parser.DatabaseType;
import org.eclipse.persistence.jpa.jpql.parser.DateTime;
import org.eclipse.persistence.jpa.jpql.parser.DefaultEclipseLinkJPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.DefaultJPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.DeleteClause;
import org.eclipse.persistence.jpa.jpql.parser.DeleteStatement;
import org.eclipse.persistence.jpa.jpql.parser.DivisionExpression;
import org.eclipse.persistence.jpa.jpql.parser.EmptyCollectionComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.EntityTypeLiteral;
import org.eclipse.persistence.jpa.jpql.parser.EntryExpression;
import org.eclipse.persistence.jpa.jpql.parser.ExistsExpression;
import org.eclipse.persistence.jpa.jpql.parser.Expression;
import org.eclipse.persistence.jpa.jpql.parser.ExtractExpression;
import org.eclipse.persistence.jpa.jpql.parser.FromClause;
import org.eclipse.persistence.jpa.jpql.parser.FunctionExpression;
import org.eclipse.persistence.jpa.jpql.parser.GroupByClause;
import org.eclipse.persistence.jpa.jpql.parser.HavingClause;
import org.eclipse.persistence.jpa.jpql.parser.HierarchicalQueryClause;
import org.eclipse.persistence.jpa.jpql.parser.IdentificationVariable;
import org.eclipse.persistence.jpa.jpql.parser.IdentificationVariableDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.InExpression;
import org.eclipse.persistence.jpa.jpql.parser.IndexExpression;
import org.eclipse.persistence.jpa.jpql.parser.InputParameter;
import org.eclipse.persistence.jpa.jpql.parser.JPQLExpression;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.JPQLStatementBNF;
import org.eclipse.persistence.jpa.jpql.parser.Join;
import org.eclipse.persistence.jpa.jpql.parser.KeywordExpression;
import org.eclipse.persistence.jpa.jpql.parser.LengthExpression;
import org.eclipse.persistence.jpa.jpql.parser.LikeExpression;
import org.eclipse.persistence.jpa.jpql.parser.LocateExpression;
import org.eclipse.persistence.jpa.jpql.parser.LogicalExpression;
import org.eclipse.persistence.jpa.jpql.parser.LowerExpression;
import org.eclipse.persistence.jpa.jpql.parser.MaxFunction;
import org.eclipse.persistence.jpa.jpql.parser.MinFunction;
import org.eclipse.persistence.jpa.jpql.parser.ModExpression;
import org.eclipse.persistence.jpa.jpql.parser.MultiplicationExpression;
import org.eclipse.persistence.jpa.jpql.parser.NotExpression;
import org.eclipse.persistence.jpa.jpql.parser.NullComparisonExpression;
import org.eclipse.persistence.jpa.jpql.parser.NullExpression;
import org.eclipse.persistence.jpa.jpql.parser.NullIfExpression;
import org.eclipse.persistence.jpa.jpql.parser.NumericLiteral;
import org.eclipse.persistence.jpa.jpql.parser.ObjectExpression;
import org.eclipse.persistence.jpa.jpql.parser.OnClause;
import org.eclipse.persistence.jpa.jpql.parser.OrExpression;
import org.eclipse.persistence.jpa.jpql.parser.OrderByClause;
import org.eclipse.persistence.jpa.jpql.parser.OrderByItem;
import org.eclipse.persistence.jpa.jpql.parser.OrderByItem.NullOrdering;
import org.eclipse.persistence.jpa.jpql.parser.OrderByItem.Ordering;
import org.eclipse.persistence.jpa.jpql.parser.OrderSiblingsByClause;
import org.eclipse.persistence.jpa.jpql.parser.RangeVariableDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.RegexpExpression;
import org.eclipse.persistence.jpa.jpql.parser.ResultVariable;
import org.eclipse.persistence.jpa.jpql.parser.SelectClause;
import org.eclipse.persistence.jpa.jpql.parser.SelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.SimpleFromClause;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectClause;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.SizeExpression;
import org.eclipse.persistence.jpa.jpql.parser.SqrtExpression;
import org.eclipse.persistence.jpa.jpql.parser.StartWithClause;
import org.eclipse.persistence.jpa.jpql.parser.StateFieldPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.StringLiteral;
import org.eclipse.persistence.jpa.jpql.parser.SubExpression;
import org.eclipse.persistence.jpa.jpql.parser.SubstringExpression;
import org.eclipse.persistence.jpa.jpql.parser.SubtractionExpression;
import org.eclipse.persistence.jpa.jpql.parser.SumFunction;
import org.eclipse.persistence.jpa.jpql.parser.TableExpression;
import org.eclipse.persistence.jpa.jpql.parser.TableVariableDeclaration;
import org.eclipse.persistence.jpa.jpql.parser.TreatExpression;
import org.eclipse.persistence.jpa.jpql.parser.TrimExpression;
import org.eclipse.persistence.jpa.jpql.parser.TrimExpression.Specification;
import org.eclipse.persistence.jpa.jpql.parser.TypeExpression;
import org.eclipse.persistence.jpa.jpql.parser.UnionClause;
import org.eclipse.persistence.jpa.jpql.parser.UnknownExpression;
import org.eclipse.persistence.jpa.jpql.parser.UpdateClause;
import org.eclipse.persistence.jpa.jpql.parser.UpdateItem;
import org.eclipse.persistence.jpa.jpql.parser.UpdateStatement;
import org.eclipse.persistence.jpa.jpql.parser.UpperExpression;
import org.eclipse.persistence.jpa.jpql.parser.WhenClause;
import org.eclipse.persistence.jpa.jpql.parser.WhereClause;
import org.eclipse.persistence.jpa.tests.jpql.JPQLBasicTest;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.*;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.*;
import static org.eclipse.persistence.jpa.tests.jpql.parser.JPQLParserTester.*;
import static org.eclipse.persistence.jpa.tests.jpql.parser.JPQLQueryBuilder.*;
import static org.junit.Assert.*;

/**
 * This abstract class provides the functionality to test the parsed tree representation of a JPQL
 * query by traversing the tree and comparing each node.
 * <p>
 * Note: This class provides the {@link ExpressionTester} for all JPQL grammars (1.0, 2.0 and 2.1),
 * as well as for EclipseLink (all versions).
 *
 * @version 2.6
 * @since 2.3
 * @author Pascal Filion
 */
@SuppressWarnings({"nls", "unused" /* For the extra import statement, see bug 330740 */ })
public abstract class JPQLParserTest extends JPQLBasicTest {

    @JPQLGrammarTestHelper
    private JPQLGrammar jpqlGrammar;

    protected JPQLGrammar getGrammar() {
        return jpqlGrammar;
    }

    protected final boolean isEclipseLinkProvider() {
        return DefaultEclipseLinkJPQLGrammar.PROVIDER_NAME == jpqlGrammar.getProvider();
    }

    protected final boolean isGenericProvider() {
        return DefaultJPQLGrammar.PROVIDER_NAME == jpqlGrammar.getProvider();
    }

    protected final boolean isJPA1_0() {
        return jpqlGrammar.getJPAVersion() == JPAVersion.VERSION_1_0;
    }

    protected final boolean isJPA2_0() {
        return jpqlGrammar.getJPAVersion() == JPAVersion.VERSION_2_0;
    }

    protected final boolean isJPA2_1() {
        return jpqlGrammar.getJPAVersion() == JPAVersion.VERSION_2_1;
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned on.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     */
    protected void testInvalidQuery(String jpqlQuery, ExpressionTester expressionTester) {
        testQuery(jpqlQuery, expressionTester, JPQLStatementBNF.ID, JPQLQueryStringFormatter.DEFAULT, true);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned on.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param jpqlGrammar The {@link JPQLGrammar} used to determine how to parse the JPQL query
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testInvalidQuery(String jpqlQuery,
                                    ExpressionTester expressionTester,
                                    JPQLGrammar jpqlGrammar) {

        testQuery(jpqlQuery, expressionTester, jpqlGrammar, JPQLStatementBNF.ID, JPQLQueryStringFormatter.DEFAULT, true);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned on.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testInvalidQuery(String jpqlQuery,
                                    ExpressionTester expressionTester,
                                    JPQLQueryStringFormatter formatter) {

        testQuery(jpqlQuery, expressionTester, JPQLStatementBNF.ID, formatter, true);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned on.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     */
    protected void testInvalidQuery(String jpqlQuery,
                                    ExpressionTester expressionTester,
                                    String jpqlQueryBNFId) {

        testQuery(jpqlQuery, expressionTester, jpqlQueryBNFId, JPQLQueryStringFormatter.DEFAULT, true);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned on.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testInvalidQuery(String jpqlQuery,
                                    ExpressionTester expressionTester,
                                    String jpqlQueryBNFId,
                                    JPQLQueryStringFormatter formatter) {

        testQuery(jpqlQuery, expressionTester, jpqlQueryBNFId, formatter, true);
    }

    /**
     * Tests parsing the given JPQL query by comparing the parsed tree ({@link JPQLExpression}) with
     * the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * This method test both parsing modes: tolerant and non-tolerant. When the tolerant mode is
     * turned on, it means it will parse valid/complete and invalid/incomplete JPQL queries. When the
     * tolerant mode is turned off, it means the JPQL query has to be complete and has to be
     * grammatically valid.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     */
    protected void testQuery(String jpqlQuery, ExpressionTester expressionTester) {
        testQuery(jpqlQuery, expressionTester, JPQLStatementBNF.ID, JPQLQueryStringFormatter.DEFAULT, true);
        testQuery(jpqlQuery, expressionTester, JPQLStatementBNF.ID, JPQLQueryStringFormatter.DEFAULT, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * This method test both parsing modes: tolerant and non-tolerant. When the tolerant mode is
     * turned on, it means it will parse valid/complete and invalid/incomplete JPQL queries. When the
     * tolerant mode is turned off, it means the JPQL query has to be complete and has to be
     * grammatically valid.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param jpqlGrammar The {@link JPQLGrammar} used to determine how to parse the JPQL query
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testQuery(String jpqlQuery,
                             ExpressionTester expressionTester,
                             JPQLGrammar jpqlGrammar) {

        testQuery(jpqlQuery, expressionTester, jpqlGrammar, JPQLStatementBNF.ID, JPQLQueryStringFormatter.DEFAULT, true);
        testQuery(jpqlQuery, expressionTester, jpqlGrammar, JPQLStatementBNF.ID, JPQLQueryStringFormatter.DEFAULT, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * This method test both parsing modes: tolerant and non-tolerant. When the tolerant mode is
     * turned on, it means it will parse valid/complete and invalid/incomplete JPQL queries. When the
     * tolerant mode is turned off, it means the JPQL query has to be complete and has to be
     * grammatically valid.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param jpqlGrammar The {@link JPQLGrammar} used to determine how to parse the JPQL query
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testQuery(String jpqlQuery,
                             ExpressionTester expressionTester,
                             JPQLGrammar jpqlGrammar,
                             JPQLQueryStringFormatter formatter) {

        testQuery(jpqlQuery, expressionTester, jpqlGrammar, JPQLStatementBNF.ID, formatter, true);
        testQuery(jpqlQuery, expressionTester, jpqlGrammar, JPQLStatementBNF.ID, formatter, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * This method test both parsing modes: tolerant and non-tolerant. When the tolerant mode is
     * turned on, it means it will parse valid/complete and invalid/incomplete JPQL queries. When the
     * tolerant mode is turned off, it means the JPQL query has to be complete and has to be
     * grammatically valid.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testQuery(String jpqlQuery,
                             ExpressionTester expressionTester,
                             JPQLGrammar jpqlGrammar,
                             String jpqlQueryBNFId,
                             JPQLQueryStringFormatter formatter) {

        testQuery(jpqlQuery, expressionTester, jpqlGrammar, jpqlQueryBNFId, formatter, true);
        testQuery(jpqlQuery, expressionTester, jpqlGrammar, jpqlQueryBNFId, formatter, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param jpqlGrammar The {@link JPQLGrammar} used to determine how to parse the JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse grammatically invalid or incomplete queries
     */
    protected void testQuery(String jpqlQuery,
                             ExpressionTester expressionTester,
                             JPQLGrammar jpqlGrammar,
                             String jpqlQueryBNFId,
                             JPQLQueryStringFormatter formatter,
                             boolean tolerant) {

        JPQLExpression jpqlExpression = buildQuery(jpqlQuery, jpqlGrammar, jpqlQueryBNFId, formatter, tolerant);

        if (expressionTester.getClass() != JPQLExpressionTester.class) {
            expressionTester = jpqlExpression(expressionTester);
        }

        expressionTester.test(jpqlExpression);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * This method test both parsing modes: tolerant and non-tolerant. When the tolerant mode is
     * turned on, it means it will parse valid/complete and invalid/incomplete JPQL queries. When the
     * tolerant mode is turned off, it means the JPQL query has to be complete and has to be
     * grammatically valid.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testQuery(String jpqlQuery,
                             ExpressionTester expressionTester,
                             JPQLQueryStringFormatter formatter) {

        testQuery(jpqlQuery, expressionTester, JPQLStatementBNF.ID, formatter, true);
        testQuery(jpqlQuery, expressionTester, JPQLStatementBNF.ID, formatter, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * This method test both parsing modes: tolerant and non-tolerant. When the tolerant mode is
     * turned on, it means it will parse valid/complete and invalid/incomplete JPQL queries. When the
     * tolerant mode is turned off, it means the JPQL query has to be complete and has to be
     * grammatically valid.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     */
    protected void testQuery(String jpqlQuery,
                             ExpressionTester expressionTester,
                             String jpqlQueryBNFId) {

        testQuery(jpqlQuery, expressionTester, jpqlQueryBNFId, JPQLQueryStringFormatter.DEFAULT, true);
        testQuery(jpqlQuery, expressionTester, jpqlQueryBNFId, JPQLQueryStringFormatter.DEFAULT, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * This method test both parsing modes: tolerant and non-tolerant. When the tolerant mode is
     * turned on, it means it will parse valid/complete and invalid/incomplete JPQL queries. When the
     * tolerant mode is turned off, it means the JPQL query has to be complete and has to be
     * grammatically valid.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testQuery(String jpqlQuery,
                             ExpressionTester expressionTester,
                             String jpqlQueryBNFId,
                             JPQLQueryStringFormatter formatter) {

        testQuery(jpqlQuery, expressionTester, jpqlQueryBNFId, formatter, true);
        testQuery(jpqlQuery, expressionTester, jpqlQueryBNFId, formatter, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse grammatically invalid or incomplete queries
     */
    protected void testQuery(String jpqlQuery,
                             ExpressionTester expressionTester,
                             String jpqlQueryBNFId,
                             JPQLQueryStringFormatter formatter,
                             boolean tolerant) {

        testQuery(jpqlQuery, expressionTester, jpqlGrammar, jpqlQueryBNFId, formatter, tolerant);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned off.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     */
    protected void testValidQuery(String jpqlQuery, ExpressionTester expressionTester) {
        testQuery(jpqlQuery, expressionTester, JPQLStatementBNF.ID, JPQLQueryStringFormatter.DEFAULT, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned off.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testValidQuery(String jpqlQuery,
                                  ExpressionTester expressionTester,
                                  JPQLQueryStringFormatter formatter) {

        testQuery(jpqlQuery, expressionTester, JPQLStatementBNF.ID, formatter, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned off.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     */
    protected void testValidQuery(String jpqlQuery,
                                  ExpressionTester expressionTester,
                                  String jpqlQueryBNFId) {

        testQuery(jpqlQuery, expressionTester, jpqlQueryBNFId, JPQLQueryStringFormatter.DEFAULT, false);
    }

    /**
     * Tests the parsing of the given JPQL query by comparing the parsed tree ({@link JPQLExpression})
     * with the given tester, which is an equivalent representation of the parsed tree.
     * <p>
     * The parsing system will have the tolerance turned off.
     *
     * @param jpqlQuery The JPQL query to parse and to test the parsed tree representation
     * @param expressionTester The tester used to verify the parsed tree is correctly representing the
     * JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.
     * JPQLQueryBNF JPQLQueryBNF}
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     */
    protected void testValidQuery(String jpqlQuery,
                                  ExpressionTester expressionTester,
                                  String jpqlQueryBNFId,
                                  JPQLQueryStringFormatter formatter) {

        testQuery(jpqlQuery, expressionTester, jpqlQueryBNFId, formatter, false);
    }

    public static final class AbsExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected AbsExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return AbsExpression.class;
        }

        @Override
        protected String identifier() {
            return ABS;
        }
    }

    public static abstract class AbstractConditionalClauseTester extends AbstractExpressionTester {

        private ExpressionTester conditionalExpression;
        public boolean hasSpaceAfterIdentifier;

        protected AbstractConditionalClauseTester(ExpressionTester conditionalExpression) {
            super();
            this.conditionalExpression   = conditionalExpression;
            this.hasSpaceAfterIdentifier = !conditionalExpression.isNull();
        }

        protected abstract Class<? extends AbstractConditionalClause> expressionType();

        protected abstract String identifier();

        public void test(Expression expression) {

            assertInstance(expression, expressionType());

            AbstractConditionalClause conditionalClause = (AbstractConditionalClause) expression;
            assertEquals(toString(),                      conditionalClause.toParsedText());
            assertEquals(!conditionalExpression.isNull(), conditionalClause.hasConditionalExpression());
            assertEquals(hasSpaceAfterIdentifier,         conditionalClause.hasSpaceAfterIdentifier());

            conditionalExpression.test(conditionalClause.getConditionalExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(identifier());
            if (hasSpaceAfterIdentifier) {
                sb.append(SPACE);
            }
            sb.append(conditionalExpression);
            return sb.toString();
        }
    }

    public static abstract class AbstractDoubleEncapsulatedExpressionTester extends AbstractEncapsulatedExpressionTester {

        private ExpressionTester firstExpression;
        public boolean hasComma;
        public boolean hasSpaceAfterComma;
        private ExpressionTester secondExpression;

        protected AbstractDoubleEncapsulatedExpressionTester(ExpressionTester firstExpression,
                                                             ExpressionTester secondExpression) {

            super();
            this.hasComma           = true;
            this.hasSpaceAfterComma = true;
            this.firstExpression    = firstExpression;
            this.secondExpression   = secondExpression;
        }

        @Override
        protected abstract Class<? extends AbstractDoubleEncapsulatedExpression> expressionType();

        @Override
        protected boolean hasEncapsulatedExpression() {
            return !firstExpression.isNull() || hasComma || !secondExpression.isNull();
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);

            AbstractDoubleEncapsulatedExpression abstractDoubleEncapsulatedExpression = (AbstractDoubleEncapsulatedExpression) expression;
            assertEquals(!firstExpression.isNull(),  abstractDoubleEncapsulatedExpression.hasFirstExpression());
            assertEquals(!secondExpression.isNull(), abstractDoubleEncapsulatedExpression.hasSecondExpression());
            assertEquals(hasComma,                   abstractDoubleEncapsulatedExpression.hasComma());
            assertEquals(hasSpaceAfterComma,         abstractDoubleEncapsulatedExpression.hasSpaceAfterComma());

            firstExpression .test(abstractDoubleEncapsulatedExpression.getFirstExpression());
            secondExpression.test(abstractDoubleEncapsulatedExpression.getSecondExpression());
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {
            sb.append(firstExpression);
            if (hasComma) {
                sb.append(COMMA);
            }
            if (hasSpaceAfterComma) {
                sb.append(SPACE);
            }
            sb.append(secondExpression);
        }
    }

    public static abstract class AbstractEncapsulatedExpressionTester extends AbstractExpressionTester {

        public boolean hasLeftParenthesis;
        public boolean hasRightParenthesis;

        protected AbstractEncapsulatedExpressionTester() {
            super();
            this.hasLeftParenthesis  = true;
            this.hasRightParenthesis = true;
        }

        protected abstract Class<? extends AbstractEncapsulatedExpression> expressionType();

        protected abstract boolean hasEncapsulatedExpression();

        protected abstract String identifier();

        public void test(Expression expression) {
            assertInstance(expression, expressionType());

            AbstractEncapsulatedExpression abstractEncapsulatedExpression = (AbstractEncapsulatedExpression) expression;
            assertEquals(toString(),                  abstractEncapsulatedExpression.toParsedText());
            assertEquals(hasLeftParenthesis,          abstractEncapsulatedExpression.hasLeftParenthesis());
            assertEquals(hasRightParenthesis,         abstractEncapsulatedExpression.hasRightParenthesis());
            assertEquals(hasEncapsulatedExpression(), abstractEncapsulatedExpression.hasEncapsulatedExpression());
        }

        @Override
        public final String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(identifier());
            if (hasLeftParenthesis) {
                sb.append(LEFT_PARENTHESIS);
            }
            else if (hasEncapsulatedExpression()) {
                sb.append(SPACE);
            }
            toStringEncapsulatedExpression(sb);
            if (hasRightParenthesis) {
                sb.append(RIGHT_PARENTHESIS);
            }
            return sb.toString();
        }

        protected abstract void toStringEncapsulatedExpression(StringBuilder sb);
    }

    /**
     * The abstract definition of an {@link ExpressionTester}.
     */
    public static abstract class AbstractExpressionTester implements ExpressionTester {

        public final AdditionExpressionTester add(ExpressionTester expression) {
            return JPQLParserTester.add(this, expression);
        }

        public final AndExpressionTester and(ExpressionTester expression) {
            return JPQLParserTester.and(this, expression);
        }

        protected final void assertInstance(Expression expression,
                                            Class<? extends Expression> expressionType) {

            Class<? extends Expression> expressionClass = expression.getClass();

            if (expressionClass != expressionType &&
               !expressionType.isAssignableFrom(expressionClass)) {

                StringBuilder sb = new StringBuilder();
                sb.append("Expecting ");
                sb.append(expressionType.getSimpleName());
                sb.append(" but was ");
                sb.append(expressionClass.getSimpleName());
                sb.append(" for [");
                sb.append(expression.toParsedText());
                sb.append("]");

                fail(sb.toString());
            }
        }

        public final BetweenExpressionTester between(ExpressionTester lowerBoundExpression,
                                                     ExpressionTester upperBoundExpression) {

            return JPQLParserTester.between(this, lowerBoundExpression, upperBoundExpression);
        }

        public final ComparisonExpressionTester different(ExpressionTester expression) {
            return JPQLParserTester.different(this, expression);
        }

        public final DivisionExpressionTester divide(ExpressionTester expression) {
            return JPQLParserTester.division(this, expression);
        }

        public final ComparisonExpressionTester equal(ExpressionTester expression) {
            return JPQLParserTester.equal(this, expression);
        }

        public final ComparisonExpressionTester greaterThan(ExpressionTester expression) {
            return JPQLParserTester.greaterThan(this, expression);
        }

        public final ComparisonExpressionTester greaterThanOrEqual(ExpressionTester expression) {
            return JPQLParserTester.greaterThanOrEqual(this, expression);
        }

        public final InExpressionTester in(ExpressionTester... inItems) {
            if (inItems.length == 1) {
                return JPQLParserTester.in(this, inItems[0]);
            }
            return JPQLParserTester.in(this, inItems);
        }

        public final InExpressionTester in(String inputParameter) {
            return JPQLParserTester.in(this, inputParameter);
        }

        public final EmptyCollectionComparisonExpressionTester isEmpty() {
            return JPQLParserTester.isEmpty(this);
        }

        public final EmptyCollectionComparisonExpressionTester isNotEmpty() {
            return JPQLParserTester.isNotEmpty(this);
        }

        public boolean isNull() {
            return false;
        }

        public final LikeExpressionTester like(ExpressionTester patternValue) {
            return JPQLParserTester.like(this, patternValue);
        }

        public final LikeExpressionTester like(ExpressionTester patternValue,
                                               ExpressionTester escapeCharacter) {

            return JPQLParserTester.like(this, patternValue, escapeCharacter);
        }

        public final ComparisonExpressionTester lowerThan(ExpressionTester expression) {
            return JPQLParserTester.lowerThan(this, expression);
        }

        public final ComparisonExpressionTester lowerThanOrEqual(ExpressionTester expression) {
            return JPQLParserTester.lowerThanOrEqual(this, expression);
        }

        public final CollectionMemberExpressionTester member(ExpressionTester collectionPath) {
            return JPQLParserTester.member(this, collectionPath);
        }

        public final CollectionMemberExpressionTester memberOf(ExpressionTester collectionPath) {
            return JPQLParserTester.memberOf(this, collectionPath);
        }

        public final MultiplicationExpressionTester multiply(ExpressionTester expression) {
            return JPQLParserTester.multiplication(this, expression);
        }

        public final BetweenExpressionTester notBetween(ExpressionTester lowerBoundExpression,
                                                        ExpressionTester upperBoundExpression) {

            return JPQLParserTester.notBetween(this, lowerBoundExpression, upperBoundExpression);
        }

        public final ComparisonExpressionTester notEqual(ExpressionTester expression) {
            return JPQLParserTester.notEqual(this, expression);
        }

        public final InExpressionTester notIn(ExpressionTester... inItems) {
            if (inItems.length == 1) {
                return JPQLParserTester.notIn(this, inItems[0]);
            }
            return JPQLParserTester.notIn(this, inItems);
        }

        public final InExpressionTester notIn(String inputParameter) {
            return JPQLParserTester.notIn(this, inputParameter);
        }

        public final LikeExpressionTester notLike(ExpressionTester expression) {
            return JPQLParserTester.notLike(this, expression);
        }

        public final LikeExpressionTester notLike(ExpressionTester expression,
                                                  ExpressionTester escapeCharacter) {

            return JPQLParserTester.notLike(this, expression, escapeCharacter);
        }

        public final ExpressionTester notMember(ExpressionTester collectionPath) {
            return JPQLParserTester.notMember(this, collectionPath);
        }

        public final ExpressionTester notMemberOf(ExpressionTester collectionPath) {
            return JPQLParserTester.notMemberOf(this, collectionPath);
        }

        public final OrExpressionTester or(ExpressionTester expression) {
            return JPQLParserTester.or(this, expression);
        }

        public final RegexpExpressionTester regexp(StringLiteralTester patternValue) {
            return JPQLParserTester.regexp(this, patternValue);
        }

        public final SubtractionExpressionTester subtract(ExpressionTester expression) {
            return JPQLParserTester.subtract(this, expression);
        }
    }

    public static abstract class AbstractFromClauseTester extends AbstractExpressionTester {

        private ExpressionTester asOfClause;
        private ExpressionTester declaration;
        private boolean hasSpaceAfterDeclaration;
        public boolean hasSpaceAfterFrom;
        private boolean hasSpaceAfterHierarchicalQueryClause;
        private ExpressionTester hierarchicalQueryClause;

        protected AbstractFromClauseTester(ExpressionTester declaration,
                                           ExpressionTester hierarchicalQueryClause,
                                           ExpressionTester asOfClause) {
            super();
            this.hasSpaceAfterFrom                    = true;
            this.asOfClause                           = asOfClause;
            this.declaration                          = declaration;
            this.hierarchicalQueryClause              = hierarchicalQueryClause;
            this.hasSpaceAfterDeclaration             = !declaration.isNull() && (!hierarchicalQueryClause.isNull() || !asOfClause.isNull());
            this.hasSpaceAfterHierarchicalQueryClause = !hierarchicalQueryClause.isNull() && !asOfClause.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, AbstractFromClause.class);

            AbstractFromClause fromClause = (AbstractFromClause) expression;
            assertEquals(toString(),                           fromClause.toParsedText());
            assertEquals(hasSpaceAfterFrom,                    fromClause.hasSpaceAfterFrom());
            assertEquals(!declaration.isNull(),                fromClause.hasDeclaration());
            assertEquals(hasSpaceAfterDeclaration,             fromClause.hasSpaceAfterDeclaration());
            assertEquals(!hierarchicalQueryClause.isNull(),    fromClause.hasHierarchicalQueryClause());
            assertEquals(hasSpaceAfterHierarchicalQueryClause, fromClause.hasSpaceAfterHierarchicalQueryClause());
            assertEquals(!asOfClause.isNull(),                 fromClause.hasAsOfClause());

            declaration.test(fromClause.getDeclaration());
            hierarchicalQueryClause.test(fromClause.getHierarchicalQueryClause());
            asOfClause.test(fromClause.getAsOfClause());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(FROM);
            if (hasSpaceAfterFrom) {
                sb.append(SPACE);
            }
            sb.append(declaration);
            if (hasSpaceAfterDeclaration) {
                sb.append(SPACE);
            }
            sb.append(hierarchicalQueryClause);
            if (hasSpaceAfterHierarchicalQueryClause) {
                sb.append(SPACE);
            }
            sb.append(asOfClause);
            return sb.toString();
        }
    }

    public static abstract class AbstractOrderByClauseTester extends AbstractExpressionTester {

        public boolean hasSpaceAfterIdentifier;
        private ExpressionTester orderByItems;

        protected AbstractOrderByClauseTester(ExpressionTester orderByItems) {
            super();
            this.orderByItems            = orderByItems;
            this.hasSpaceAfterIdentifier = !orderByItems.isNull();
        }

        protected abstract String identifier();

        public void test(Expression expression) {
            assertInstance(expression, AbstractOrderByClause.class);

            AbstractOrderByClause orderByClause = (AbstractOrderByClause) expression;
            assertEquals(toString(),              orderByClause.toParsedText());
            assertEquals(!orderByItems.isNull(),  orderByClause.hasOrderByItems());
            assertEquals(hasSpaceAfterIdentifier, orderByClause.hasSpaceAfterIdentifier());

            orderByItems.test(orderByClause.getOrderByItems());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(identifier());
            if (hasSpaceAfterIdentifier) {
                sb.append(SPACE);
            }
            sb.append(orderByItems);
            return sb.toString();
        }
    }

    public static abstract class AbstractPathExpressionTester extends AbstractExpressionTester {

        private boolean endsWithDot;
        private ExpressionTester identificationVariable;
        private boolean startsWithDot;
        private String value;

        protected AbstractPathExpressionTester(ExpressionTester identificationVariable, String value) {

            super();

            this.value                  = value;
            this.identificationVariable = identificationVariable;
            this.startsWithDot          = (identificationVariable.toString().length() == 0) && (value.indexOf(DOT) > -1);

            if (value.length() > 1) {
                endsWithDot = value.charAt(value.length() - 1) == DOT;
            }
        }

        public void test(Expression expression) {

            assertInstance(expression, AbstractPathExpression.class);

            AbstractPathExpression abstractPathExpression = (AbstractPathExpression) expression;
            assertEquals(toString(),                       abstractPathExpression.toParsedText());
            assertEquals(!identificationVariable.isNull(), abstractPathExpression.hasIdentificationVariable());
            assertEquals(endsWithDot,                      abstractPathExpression.endsWithDot());
            assertEquals(startsWithDot,                    abstractPathExpression.startsWithDot());

            identificationVariable.test(abstractPathExpression.getIdentificationVariable());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(identificationVariable);
            if (startsWithDot || (sb.length() > 0)) {
                sb.append(DOT);
            }
            sb.append(value);
            return sb.toString();
        }
    }

    public static final class AbstractSchemaNameTester extends AbstractExpressionTester {

        private String abstractSchemaName;

        protected AbstractSchemaNameTester(String abstractSchemaName) {
            super();
            this.abstractSchemaName = abstractSchemaName;
        }

        public void test(Expression expression) {
            assertInstance(expression, AbstractSchemaName.class);

            AbstractSchemaName abstractSchemaName = (AbstractSchemaName) expression;
            assertEquals(toString(), abstractSchemaName.toParsedText());
        }

        @Override
        public String toString() {
            return abstractSchemaName;
        }
    }

    public static abstract class AbstractSelectClauseTester extends AbstractExpressionTester {

        private boolean hasDistinct;
        public boolean hasSpaceAfterDistinct;
        public boolean hasSpaceAfterSelect;
        private ExpressionTester selectExpression;

        protected AbstractSelectClauseTester(ExpressionTester selectExpression, boolean hasDistinct) {
            super();
            this.hasDistinct           = hasDistinct;
            this.hasSpaceAfterDistinct = hasDistinct;
            this.hasSpaceAfterSelect   = hasDistinct || !selectExpression.isNull();
            this.selectExpression      = selectExpression;
        }

        public void test(Expression expression) {

            assertInstance(expression, AbstractSelectClause.class);
            AbstractSelectClause selectClause = (AbstractSelectClause) expression;

            assertEquals(toString(),                 selectClause.toParsedText());
            assertEquals(hasSpaceAfterSelect,        selectClause.hasSpaceAfterSelect());
            assertEquals(hasDistinct,                selectClause.hasDistinct());
            assertEquals(hasSpaceAfterDistinct,      selectClause.hasSpaceAfterDistinct());
            assertEquals(!selectExpression.isNull(), selectClause.hasSelectExpression());

            selectExpression.test(selectClause.getSelectExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(SELECT);
            if (hasSpaceAfterSelect) {
                sb.append(SPACE);
            }
            if (hasDistinct) {
                sb.append(DISTINCT);
            }
            if (hasSpaceAfterDistinct) {
                sb.append(SPACE);
            }
            sb.append(selectExpression);
            return sb.toString();
        }
    }

    public static abstract class AbstractSelectStatementTester extends AbstractExpressionTester {

        private ExpressionTester fromClause;
        private ExpressionTester groupByClause;
        public boolean hasSpaceAfterFrom;
        public boolean hasSpaceAfterGroupBy;
        public boolean hasSpaceAfterSelect;
        public boolean hasSpaceAfterWhere;
        private ExpressionTester havingClause;
        private ExpressionTester selectClause;
        private ExpressionTester whereClause;

        protected AbstractSelectStatementTester(ExpressionTester selectClause,
                                                ExpressionTester fromClause,
                                                ExpressionTester whereClause,
                                                ExpressionTester groupByClause,
                                                ExpressionTester havingClause) {

            super();

            this.selectClause            = selectClause;
            this.fromClause              = fromClause;
            this.whereClause             = whereClause;
            this.groupByClause           = groupByClause;
            this.havingClause            = havingClause;

            hasSpaceAfterSelect  = !fromClause.isNull();
            hasSpaceAfterFrom    = !fromClause.isNull() && (!whereClause.isNull() || !groupByClause.isNull() || !havingClause.isNull());
            hasSpaceAfterWhere   = !whereClause.isNull() && (!groupByClause.isNull() || !havingClause.isNull());
            hasSpaceAfterGroupBy = !groupByClause.isNull() && !havingClause.isNull();
        }

        protected abstract Class<? extends AbstractSelectStatement> expressionType();

        public void test(Expression expression) {
            assertInstance(expression, expressionType());

            AbstractSelectStatement selectStatement = (AbstractSelectStatement) expression;
            assertEquals(toString(),                        selectStatement.toParsedText());
            assertEquals(!selectClause .isNull(), selectStatement.hasSelectClause());
            assertEquals(!fromClause   .isNull(), selectStatement.hasFromClause());
            assertEquals(!whereClause  .isNull(), selectStatement.hasWhereClause());
            assertEquals(!groupByClause.isNull(), selectStatement.hasGroupByClause());
            assertEquals(!havingClause .isNull(), selectStatement.hasHavingClause());

            selectClause .test(selectStatement.getSelectClause());
            fromClause   .test(selectStatement.getFromClause());
            whereClause  .test(selectStatement.getWhereClause());
            groupByClause.test(selectStatement.getGroupByClause());
            havingClause .test(selectStatement.getHavingClause());
        }

        @Override
        public String toString() {

            StringBuilder sb = new StringBuilder();

            // SELECT
            sb.append(selectClause);

            if (hasSpaceAfterSelect && (sb.length() > 0) && (sb.charAt(sb.length() - 1) != ' ')) {
                sb.append(SPACE);
            }

            // FROM
            sb.append(fromClause);

            if (hasSpaceAfterFrom && sb.charAt(sb.length() - 1) != ' ') {
                sb.append(SPACE);
            }

            // WHERE
            sb.append(whereClause);

            if (hasSpaceAfterWhere && sb.charAt(sb.length() - 1) != ' ') {
                sb.append(SPACE);
            }

            // GROUP BY
            sb.append(groupByClause);

            if (hasSpaceAfterGroupBy && sb.charAt(sb.length() - 1) != ' ') {
                sb.append(SPACE);
            }

            // HAVING
            sb.append(havingClause);

            return sb.toString();
        }
    }

    public static abstract class AbstractSingleEncapsulatedExpressionTester extends AbstractEncapsulatedExpressionTester {

        private ExpressionTester expression;

        protected AbstractSingleEncapsulatedExpressionTester(ExpressionTester expression) {
            super();
            this.expression = expression;
        }

        @Override
        protected abstract Class<? extends AbstractSingleEncapsulatedExpression> expressionType();

        @Override
        protected boolean hasEncapsulatedExpression() {
            return !expression.isNull();
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);

            AbstractSingleEncapsulatedExpression encapsulatedExpression = (AbstractSingleEncapsulatedExpression) expression;
            this.expression.test(encapsulatedExpression.getExpression());
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {
            sb.append(expression);
        }
    }

    public static abstract class AbstractTripleEncapsulatedExpressionTester extends AbstractEncapsulatedExpressionTester {

        private ExpressionTester firstExpression;
        public boolean hasFirstComma;
        public boolean hasSecondComma;
        public boolean hasSpaceAfterFirstComma;
        public boolean hasSpaceAfterSecondComma;
        private ExpressionTester secondExpression;
        private ExpressionTester thirdExpression;

        protected AbstractTripleEncapsulatedExpressionTester(ExpressionTester firstExpression,
                                                             ExpressionTester secondExpression,
                                                             ExpressionTester thirdExpression) {

            super();

            this.firstExpression  = firstExpression;
            this.secondExpression = secondExpression;
            this.thirdExpression  = thirdExpression;

            hasFirstComma  = !secondExpression.isNull();
            hasSecondComma = !thirdExpression.isNull();

            hasSpaceAfterFirstComma  = hasFirstComma;
            hasSpaceAfterSecondComma = hasSecondComma;
        }

        @Override
        protected abstract Class<? extends AbstractTripleEncapsulatedExpression> expressionType();

        @Override
        protected boolean hasEncapsulatedExpression() {
            return !firstExpression.isNull() || hasFirstComma || !secondExpression.isNull() || hasSecondComma || !thirdExpression.isNull();
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, AbstractTripleEncapsulatedExpression.class);

            AbstractTripleEncapsulatedExpression tripleExpression = (AbstractTripleEncapsulatedExpression) expression;
            assertEquals(toString(), tripleExpression.toParsedText());

            assertEquals(hasFirstComma,  tripleExpression.hasFirstComma());
            assertEquals(hasSecondComma, tripleExpression.hasSecondComma());

            assertEquals(hasSpaceAfterFirstComma,  tripleExpression.hasSpaceAfterFirstComma());
            assertEquals(hasSpaceAfterSecondComma, tripleExpression.hasSpaceAfterSecondComma());

            assertEquals(!firstExpression.isNull(),  tripleExpression.hasFirstExpression());
            assertEquals(!secondExpression.isNull(), tripleExpression.hasSecondExpression());
            assertEquals(!thirdExpression.isNull(),  tripleExpression.hasThirdExpression());

            firstExpression.test(tripleExpression.getFirstExpression());
            secondExpression.test(tripleExpression.getSecondExpression());
            thirdExpression.test(tripleExpression.getThirdExpression());
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {
            sb.append(firstExpression);
            if (hasFirstComma) {
                sb.append(COMMA);
            }
            if (hasSpaceAfterFirstComma) {
                sb.append(SPACE);
            }
            sb.append(secondExpression);
            if (hasSecondComma) {
                sb.append(COMMA);
            }
            if (hasSpaceAfterSecondComma) {
                sb.append(SPACE);
            }
            sb.append(thirdExpression);
        }
    }

    public static final class AdditionExpressionTester extends CompoundExpressionTester {

        protected AdditionExpressionTester(ExpressionTester leftExpression,
                                           ExpressionTester rightExpression) {

            super(leftExpression, rightExpression);
        }

        @Override
        protected Class<? extends CompoundExpression> expressionType() {
            return AdditionExpression.class;
        }

        @Override
        protected String identifier() {
            return PLUS;
        }
    }

    public static abstract class AggregateFunctionTester extends AbstractSingleEncapsulatedExpressionTester {

        public boolean hasDistinct;
        public boolean hasSpaceAfterDistinct;

        protected AggregateFunctionTester(ExpressionTester expression, boolean hasDistinct) {
            super(expression);
            this.hasDistinct = hasDistinct;
            this.hasSpaceAfterDistinct = hasDistinct;
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {

            if (hasDistinct) {
                sb.append(DISTINCT);
            }

            if (hasSpaceAfterDistinct) {
                sb.append(SPACE);
            }

            super.toStringEncapsulatedExpression(sb);
        }
    }

    public static final class AllOrAnyExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        private String identifier;

        protected AllOrAnyExpressionTester(String identifier, ExpressionTester expression) {
            super(expression);
            this.identifier = identifier;
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return AllOrAnyExpression.class;
        }

        @Override
        protected String identifier() {
            return identifier;
        }
    }

    public static final class AndExpressionTester extends LogicalExpressionTester {

        protected AndExpressionTester(ExpressionTester leftExpression,
                                      ExpressionTester rightExpression) {

            super(leftExpression, rightExpression);
        }

        @Override
        protected Class<? extends CompoundExpression> expressionType() {
            return AndExpression.class;
        }

        @Override
        protected String identifier() {
            return AND;
        }
    }

    public static final class ArithmeticFactorTester extends AbstractExpressionTester {

        private ExpressionTester expression;
        private String sign;

        protected ArithmeticFactorTester(String sign, ExpressionTester expression) {
            super();
            this.sign = sign;
            this.expression = expression;
        }

        public void test(Expression expression) {
            assertInstance(expression, ArithmeticFactor.class);

            ArithmeticFactor factor = (ArithmeticFactor) expression;
            assertEquals(toString(),    factor.toParsedText());
            assertEquals(sign == MINUS, factor.isNegative());
            assertEquals(sign == PLUS,  factor.isPositive());

            this.expression.test(factor.getExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(sign);
            sb.append(expression);
            return sb.toString();
        }
    }

    protected final static class AsOfClauseTester extends AbstractExpressionTester {

        private String category;
        private ExpressionTester expression;
        public boolean hasSpaceAfterCategory;
        public boolean hasSpaceAfterIdentifier;

        protected AsOfClauseTester(String category, ExpressionTester expression) {
            super();
            this.category                = category;
            this.expression              = expression;
            this.hasSpaceAfterIdentifier = (category != null) || !expression.isNull();
            this.hasSpaceAfterCategory   = (category != null) && !expression.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, AsOfClause.class);

            AsOfClause asOfClause = (AsOfClause) expression;
            assertEquals(toString(),                asOfClause.toParsedText());
            assertEquals(!this.expression.isNull(), asOfClause.hasExpression());
            assertEquals(hasSpaceAfterIdentifier,   asOfClause.hasSpaceAfterIdentifier());
            assertEquals(hasSpaceAfterCategory,     asOfClause.hasSpaceAfterCategory());

            this.expression.test(asOfClause.getExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(AS_OF);
            if (hasSpaceAfterIdentifier) {
                sb.append(SPACE);
            }
            if (category != null) {
                sb.append(category);
            }
            if (hasSpaceAfterCategory) {
                sb.append(SPACE);
            }
            sb.append(expression);
            return sb.toString();
        }
    }

    public static final class AvgFunctionTester extends AggregateFunctionTester {

        protected AvgFunctionTester(ExpressionTester expression, boolean hasDistinct) {
            super(expression, hasDistinct);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return AvgFunction.class;
        }

        @Override
        protected String identifier() {
            return AVG;
        }
    }

    public static final class BadExpressionTester extends AbstractExpressionTester {

        private ExpressionTester expression;

        protected BadExpressionTester(ExpressionTester expression) {
            super();
            this.expression = expression;
        }

        public void test(Expression expression) {
            assertInstance(expression, BadExpression.class);

            BadExpression badExpression = (BadExpression) expression;
            assertEquals(toString(), badExpression.toParsedText());

            this.expression.test(badExpression.getExpression());
        }

        @Override
        public String toString() {
            return expression.toString();
        }
    }

    public static final class BetweenExpressionTester extends AbstractExpressionTester {

        private ExpressionTester expression;
        public boolean hasAnd;
        public boolean hasBetween;
        private boolean hasNot;
        public boolean hasSpaceAfterAnd;
        public boolean hasSpaceAfterBetween;
        public boolean hasSpaceAfterLowerBound;
        private ExpressionTester lowerBoundExpression;
        private ExpressionTester upperBoundExpression;

        protected BetweenExpressionTester(ExpressionTester expression,
                                          boolean hasNot,
                                          ExpressionTester lowerBoundExpression,
                                          ExpressionTester upperBoundExpression) {

            super();
            this.hasNot                  = hasNot;
            this.hasAnd                  = true;
            this.expression              = expression;
            this.hasSpaceAfterAnd        = true;
            this.hasSpaceAfterLowerBound = true;
            this.hasSpaceAfterBetween    = true;
            this.lowerBoundExpression    = lowerBoundExpression;
            this.upperBoundExpression    = upperBoundExpression;
        }

        public void test(Expression expression) {
            assertInstance(expression, BetweenExpression.class);

            BetweenExpression betweenExpression = (BetweenExpression) expression;
            assertEquals(toString(),                     betweenExpression.toParsedText());
            assertEquals(!this.expression.isNull(),      betweenExpression.hasExpression());
            assertEquals(hasNot,                         betweenExpression.hasNot());
            assertEquals(hasAnd,                         betweenExpression.hasAnd());
            assertEquals(!lowerBoundExpression.isNull(), betweenExpression.hasLowerBoundExpression());
            assertEquals(hasSpaceAfterAnd,               betweenExpression.hasSpaceAfterAnd());
            assertEquals(hasSpaceAfterBetween,           betweenExpression.hasSpaceAfterBetween());
            assertEquals(hasSpaceAfterLowerBound,        betweenExpression.hasSpaceAfterLowerBound());
            assertEquals(!upperBoundExpression.isNull(), betweenExpression.hasUpperBoundExpression());

            this.expression.test(betweenExpression.getExpression());
            lowerBoundExpression.test(betweenExpression.getLowerBoundExpression());
            upperBoundExpression.test(betweenExpression.getUpperBoundExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(expression);
            if (!expression.isNull()) {
                sb.append(SPACE);
            }
            if (hasNot) {
                sb.append(NOT);
                sb.append(SPACE);
            }
            sb.append(BETWEEN);
            if (hasSpaceAfterBetween) {
                sb.append(SPACE);
            }
            sb.append(lowerBoundExpression);
            if (hasSpaceAfterLowerBound) {
                sb.append(SPACE);
            }
            if (hasAnd) {
                sb.append(AND);
            }
            if (hasSpaceAfterAnd) {
                sb.append(SPACE);
            }
            sb.append(upperBoundExpression);
            return sb.toString();
        }
    }

    public static final class CaseExpressionTester extends AbstractExpressionTester {

        private ExpressionTester caseOperand;
        private ExpressionTester elseExpression;
        public boolean hasElse;
        public boolean hasEnd;
        public boolean hasSpaceAfterCase;
        public boolean hasSpaceAfterCaseOperand;
        public boolean hasSpaceAfterElse;
        public boolean hasSpaceAfterElseExpression;
        public boolean hasSpaceAfterWhenClauses;
        private ExpressionTester whenClauses;

        protected CaseExpressionTester(ExpressionTester caseOperand,
                                       ExpressionTester whenClauses,
                                       ExpressionTester elseExpression) {

            super();
            this.whenClauses                 = whenClauses;
            this.caseOperand                 = caseOperand;
            this.elseExpression              = elseExpression;
            this.hasElse                     = !elseExpression.isNull();
            this.hasEnd                      = true;
            this.hasSpaceAfterCase           = true;
            this.hasSpaceAfterElse           = hasElse;
            this.hasSpaceAfterElseExpression = hasElse;
            this.hasSpaceAfterCaseOperand    = !caseOperand.isNull();
            this.hasSpaceAfterWhenClauses    = !whenClauses.isNull();
        }

        public void test(Expression expression) {

            assertInstance(expression, CaseExpression.class);

            CaseExpression caseExpression = (CaseExpression) expression;
            assertEquals(toString(),                  caseExpression.toParsedText());
            assertEquals(!caseOperand.isNull(),       caseExpression.hasCaseOperand());
            assertEquals(hasElse,                     caseExpression.hasElse());
            assertEquals(hasEnd,                      caseExpression.hasEnd());
            assertEquals(hasSpaceAfterCase,           caseExpression.hasSpaceAfterCase());
            assertEquals(hasSpaceAfterCaseOperand,    caseExpression.hasSpaceAfterCaseOperand());
            assertEquals(hasSpaceAfterElse,           caseExpression.hasSpaceAfterElse());
            assertEquals(hasSpaceAfterElseExpression, caseExpression.hasSpaceAfterElseExpression());
            assertEquals(hasSpaceAfterWhenClauses,    caseExpression.hasSpaceAfterWhenClauses());
            assertEquals(!whenClauses.isNull(),       caseExpression.hasWhenClauses());

            caseOperand.test(caseExpression.getCaseOperand());
            whenClauses.test(caseExpression.getWhenClauses());
            elseExpression.test(caseExpression.getElseExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(CASE);
            if (hasSpaceAfterCase) {
                sb.append(SPACE);
            }
            sb.append(caseOperand);
            if (hasSpaceAfterCaseOperand) {
                sb.append(SPACE);
            }
            sb.append(whenClauses);
            if (hasSpaceAfterWhenClauses) {
                sb.append(SPACE);
            }
            if (hasElse) {
                sb.append(ELSE);
            }
            if (hasSpaceAfterElse) {
                sb.append(SPACE);
            }
            sb.append(elseExpression);
            if (hasSpaceAfterElseExpression) {
                sb.append(SPACE);
            }
            if (hasEnd) {
                sb.append(END);
            }
            return sb.toString();
        }
    }

    public static final class CastExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        private ExpressionTester databaseType;
        private boolean hasAs;
        public boolean hasSpaceAfterAs;
        public boolean hasSpaceAfterExpression;

        protected CastExpressionTester(ExpressionTester expression,
                                       boolean hasAs,
                                       ExpressionTester databaseType) {

            super(expression);
            this.hasAs                   = hasAs;
            this.databaseType            = databaseType;
            this.hasSpaceAfterAs         = hasAs && !databaseType.isNull();
            this.hasSpaceAfterExpression = !expression.isNull() && (hasAs || !databaseType.isNull());
        }

        @Override
        protected Class<CastExpression> expressionType() {
            return CastExpression.class;
        }

        @Override
        protected boolean hasEncapsulatedExpression() {
            return super.hasEncapsulatedExpression() || hasAs || !databaseType.isNull();
        }

        @Override
        protected String identifier() {
            return CAST;
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {
            super.toStringEncapsulatedExpression(sb);
            if (hasSpaceAfterExpression) {
                sb.append(SPACE);
            }
            if (hasAs) {
                sb.append(AS);
            }
            if (hasSpaceAfterAs) {
                sb.append(SPACE);
            }
            sb.append(databaseType);
        }
    }

    public static final class CoalesceExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected CoalesceExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return CoalesceExpression.class;
        }

        @Override
        protected String identifier(){
            return COALESCE;
        }
    }

    public static final class CollectionExpressionTester extends AbstractExpressionTester {

        public Boolean[] commas;
        private ExpressionTester[] expressionTesters;
        public Boolean[] spaces;

        protected CollectionExpressionTester(ExpressionTester[] expressionTesters,
                                             Boolean[] commas,
                                             Boolean[] spaces) {

            super();
            this.expressionTesters = expressionTesters;
            this.spaces            = spaces;
            this.commas            = commas;
        }

        public void test(Expression expression) {
            assertInstance(expression, CollectionExpression.class);

            CollectionExpression collectionExpression = (CollectionExpression) expression;
            assertEquals(toString(), collectionExpression.toParsedText());
            assertEquals(spaces.length, collectionExpression.childrenSize());
            assertEquals(commas.length, collectionExpression.childrenSize());
            assertEquals(expressionTesters.length, collectionExpression.childrenSize());

            // Expressions
            for (int index = expressionTesters.length; --index >= 0; ) {
                expressionTesters[index].test(collectionExpression.getChild(index));
            }

            // Spaces
            for (int index = 0, count = spaces.length; index < count; index++) {
                assertEquals(
                    "The flag for a space at " + index + " does not match",
                    spaces[index],
                    collectionExpression.hasSpace(index)
                );
            }

            // Commas
            for (int index = 0, count = commas.length; index < count; index++) {
                assertEquals(
                    "The flag for a comma at " + index + " does not match",
                    commas[index],
                    collectionExpression.hasComma(index)
                );
            }
        }

        @Override
        public String toString() {

            StringBuilder sb = new StringBuilder();

            for (int index = 0, count = expressionTesters.length; index < count; index++) {
                sb.append(expressionTesters[index]);

                if ((index < commas.length) && commas[index]) {
                    sb.append(COMMA);
                }

                if ((index < spaces.length) && spaces[index]) {
                    sb.append(SPACE);
                }
            }

            return sb.toString();
        }
    }

    public static final class CollectionMemberDeclarationTester extends AbstractExpressionTester {

        private ExpressionTester collectionValuedPath;
        public boolean hasAs;
        public boolean hasLeftParenthesis;
        public boolean hasRightParenthesis;
        public boolean hasSpaceAfterAs;
        public boolean hasSpaceAfterIn;
        public boolean hasSpaceAfterRightParenthesis;
        private ExpressionTester identificationVariable;

        protected CollectionMemberDeclarationTester(ExpressionTester collectionValuedPath,
                                                    boolean hasAs,
                                                    ExpressionTester identificationVariable) {

            super();
            this.hasAs                         = hasAs;
            this.hasSpaceAfterAs               = hasAs;
            this.hasLeftParenthesis            = true;
            this.hasRightParenthesis           = true;
            this.collectionValuedPath          = collectionValuedPath;
            this.identificationVariable        = identificationVariable;
            this.hasSpaceAfterRightParenthesis = hasAs || !identificationVariable.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, CollectionMemberDeclaration.class);

            CollectionMemberDeclaration collectionMemberDeclaration = (CollectionMemberDeclaration) expression;
            assertEquals(toString(),                       collectionMemberDeclaration.toParsedText());
            assertEquals(hasAs,                            collectionMemberDeclaration.hasAs());
            assertEquals(!collectionValuedPath.isNull(),   collectionMemberDeclaration.hasCollectionValuedPathExpression());
            assertEquals(!identificationVariable.isNull(), collectionMemberDeclaration.hasIdentificationVariable());
            assertEquals(hasLeftParenthesis,               collectionMemberDeclaration.hasLeftParenthesis());
            assertEquals(hasRightParenthesis,              collectionMemberDeclaration.hasRightParenthesis());
            assertEquals(hasSpaceAfterAs,                  collectionMemberDeclaration.hasSpaceAfterAs());
            assertEquals(hasSpaceAfterIn,                  collectionMemberDeclaration.hasSpaceAfterIn());
            assertEquals(hasSpaceAfterRightParenthesis,    collectionMemberDeclaration.hasSpaceAfterRightParenthesis());

            collectionValuedPath.test(collectionMemberDeclaration.getCollectionValuedPathExpression());
            identificationVariable.test(collectionMemberDeclaration.getIdentificationVariable());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(IN);
            if (hasSpaceAfterIn) {
                sb.append(SPACE);
            }
            else if (hasLeftParenthesis) {
                sb.append(LEFT_PARENTHESIS);
            }
            sb.append(collectionValuedPath);
            if (hasRightParenthesis) {
                sb.append(RIGHT_PARENTHESIS);
            }
            if (hasSpaceAfterRightParenthesis) {
                sb.append(SPACE);
            }
            if (hasAs) {
                sb.append(AS);
            }
            if (hasSpaceAfterAs) {
                sb.append(SPACE);
            }
            sb.append(identificationVariable);
            return sb.toString();
        }
    }

    public static final class CollectionMemberExpressionTester extends AbstractExpressionTester {

        private ExpressionTester collectionPath;
        private ExpressionTester entityExpression;
        private boolean hasNot;
        private boolean hasOf;
        public boolean hasSpaceAfterMember;
        public boolean hasSpaceAfterOf;

        protected CollectionMemberExpressionTester(ExpressionTester entityExpression,
                                                   boolean hasNot,
                                                   boolean hasOf,
                                                   ExpressionTester collectionPath) {

            super();
            this.hasNot                         = hasNot;
            this.hasOf                          = hasOf;
            this.hasSpaceAfterMember            = true;
            this.hasSpaceAfterOf                = hasOf;
            this.entityExpression               = entityExpression;
            this.collectionPath = collectionPath;
        }

        public void test(Expression expression) {
            assertInstance(expression, CollectionMemberExpression.class);

            CollectionMemberExpression collectionMemberExpression = (CollectionMemberExpression) expression;
            assertEquals(toString(),                               collectionMemberExpression.toParsedText());
            assertEquals(!collectionPath.isNull(), collectionMemberExpression.hasCollectionValuedPathExpression());
            assertEquals(!entityExpression.isNull(),               collectionMemberExpression.hasEntityExpression());
            assertEquals(hasNot,                                   collectionMemberExpression.hasNot());
            assertEquals(hasSpaceAfterMember,                      collectionMemberExpression.hasSpaceAfterMember());
            assertEquals(hasOf,                                    collectionMemberExpression.hasOf());
            assertEquals(hasSpaceAfterOf,                          collectionMemberExpression.hasSpaceAfterOf());

            entityExpression.test(collectionMemberExpression.getEntityExpression());
            collectionPath.test(collectionMemberExpression.getCollectionValuedPathExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(entityExpression);
            if (!entityExpression.isNull()) {
                sb.append(SPACE);
            }
            if (hasNot) {
                sb.append(NOT);
                sb.append(SPACE);
            }
            if (hasOf) {
                sb.append(MEMBER_OF);
                if (hasSpaceAfterOf) {
                    sb.append(SPACE);
                }
            }
            else {
                sb.append(MEMBER);
                if (hasSpaceAfterMember) {
                    sb.append(SPACE);
                }
            }
            sb.append(collectionPath);
            return sb.toString();
        }
    }

    public static final class CollectionValuedPathExpressionTester extends AbstractPathExpressionTester {

        protected CollectionValuedPathExpressionTester(ExpressionTester identificationVariable,
                                                       String value) {

            super(identificationVariable, value);
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, CollectionValuedPathExpression.class);
        }
    }

    public static final class ComparisonExpressionTester extends AbstractExpressionTester {

        private String comparator;
        public boolean hasSpaceAfterIdentifier;
        private ExpressionTester leftExpression;
        private ExpressionTester rightExpression;

        protected ComparisonExpressionTester(String comparator,
                                             ExpressionTester leftExpression,
                                             ExpressionTester rightExpression) {

            super();
            this.comparator              = comparator;
            this.leftExpression          = leftExpression;
            this.rightExpression         = rightExpression;
            this.hasSpaceAfterIdentifier = true;
        }

        public void test(Expression expression) {
            assertInstance(expression, ComparisonExpression.class);

            ComparisonExpression comparisonExpression = (ComparisonExpression) expression;
            assertEquals(toString(),                comparisonExpression.toParsedText());
            assertEquals(!leftExpression.isNull(),  comparisonExpression.hasLeftExpression());
            assertEquals(!rightExpression.isNull(), comparisonExpression.hasRightExpression());
            assertEquals(hasSpaceAfterIdentifier,   comparisonExpression.hasSpaceAfterIdentifier());

            leftExpression .test(comparisonExpression.getLeftExpression());
            rightExpression.test(comparisonExpression.getRightExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(leftExpression);
            if (!leftExpression.isNull()) {
                sb.append(SPACE);
            }
            sb.append(comparator);
            if (hasSpaceAfterIdentifier) {
                sb.append(SPACE);
            }
            sb.append(rightExpression);
            return sb.toString();
        }
    }

    public static abstract class CompoundExpressionTester extends AbstractExpressionTester {

        public boolean hasSpaceAfterIdentifier;
        private ExpressionTester leftExpression;
        private ExpressionTester rightExpression;

        protected CompoundExpressionTester(ExpressionTester leftExpression,
                                           ExpressionTester rightExpression) {

            super();
            this.leftExpression          = leftExpression;
            this.rightExpression         = rightExpression;
            this.hasSpaceAfterIdentifier = !rightExpression.isNull();
        }

        protected abstract Class<? extends CompoundExpression> expressionType();

        protected abstract String identifier();

        public void test(Expression expression) {
            assertInstance(expression, expressionType());

            CompoundExpression compoundExpression = (CompoundExpression) expression;
            assertEquals(toString(),                compoundExpression.toParsedText());
            assertEquals(!leftExpression.isNull(),  compoundExpression.hasLeftExpression());
            assertEquals(!rightExpression.isNull(), compoundExpression.hasRightExpression());
            assertEquals(hasSpaceAfterIdentifier,   compoundExpression.hasSpaceAfterIdentifier());

            leftExpression .test(compoundExpression.getLeftExpression());
            rightExpression.test(compoundExpression.getRightExpression());
        }

        @Override
        public String toString() {

            StringBuilder sb = new StringBuilder();

            if (!leftExpression.isNull()) {
                sb.append(leftExpression);
                if (sb.charAt(sb.length() - 1) != SPACE) {
                    sb.append(SPACE);
                }
            }

            sb.append(identifier());

            if (hasSpaceAfterIdentifier) {
                sb.append(SPACE);
            }

            sb.append(rightExpression);
            return sb.toString();
        }
    }

    public static final class ConcatExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected ConcatExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return ConcatExpression.class;
        }

        @Override
        protected String identifier() {
            return CONCAT;
        }
    }

    public static final class ConnectByClauseTester extends AbstractExpressionTester {

        private ExpressionTester expression;
        public boolean hasSpaceAfterConnectBy;

        protected ConnectByClauseTester(ExpressionTester expression) {
            super();
            this.expression             = expression;
            this.hasSpaceAfterConnectBy = !expression.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, ConnectByClause.class);

            ConnectByClause priorExpression = (ConnectByClause) expression;
            assertEquals(toString(),                priorExpression.toParsedText());
            assertEquals(hasSpaceAfterConnectBy,    priorExpression.hasSpaceAfterConnectBy());
            assertEquals(!this.expression.isNull(), priorExpression.hasExpression());

            this.expression.test(priorExpression.getExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(CONNECT_BY);
            if (hasSpaceAfterConnectBy) {
                sb.append(SPACE);
            }
            sb.append(expression);
            return sb.toString();
        }
    }

    public static final class ConstructorExpressionTester extends AbstractExpressionTester {

        private String className;
        private ExpressionTester constructorItems;
        public boolean hasLeftParenthesis;
        public boolean hasRightParenthesis;
        public boolean hasSpaceAfterNew;

        protected ConstructorExpressionTester(String className, ExpressionTester constructorItems) {
            super();
            this.className           = className;
            this.constructorItems    = constructorItems;
            this.hasSpaceAfterNew    = true;
            this.hasLeftParenthesis  = true;
            this.hasRightParenthesis = true;
        }

        public void test(Expression expression) {
            assertInstance(expression, ConstructorExpression.class);

            ConstructorExpression constructorExpression = (ConstructorExpression) expression;
            assertEquals(toString(),                 constructorExpression.toParsedText());
            assertEquals(!constructorItems.isNull(), constructorExpression.hasConstructorItems());
            assertEquals(hasSpaceAfterNew,           constructorExpression.hasSpaceAfterNew());
            assertEquals(hasLeftParenthesis,         constructorExpression.hasLeftParenthesis());
            assertEquals(hasRightParenthesis,        constructorExpression.hasRightParenthesis());

            constructorItems.test(constructorExpression.getConstructorItems());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(NEW);
            if (hasSpaceAfterNew) {
                sb.append(SPACE);
            }
            sb.append(className);
            if (hasLeftParenthesis) {
                sb.append(LEFT_PARENTHESIS);
            }
            sb.append(constructorItems);
            if (hasRightParenthesis) {
                sb.append(RIGHT_PARENTHESIS);
            }
            return sb.toString();
        }
    }

    public static final class CountFunctionTester extends AggregateFunctionTester {

        protected CountFunctionTester(ExpressionTester expression, boolean hasDistinct) {
            super(expression, hasDistinct);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return CountFunction.class;
        }

        @Override
        protected String identifier() {
            return COUNT;
        }
    }

    public static final class DatabaseTypeTester extends AbstractDoubleEncapsulatedExpressionTester {

        private String databaseType;

        protected DatabaseTypeTester(String databaseType,
                                     ExpressionTester size,
                                     ExpressionTester precision) {

            super(size, precision);
            this.databaseType = databaseType;
        }

        @Override
        protected Class<DatabaseType> expressionType() {
            return DatabaseType.class;
        }

        @Override
        protected String identifier() {
            return databaseType;
        }
    }

    public static final class DateTimeTester extends AbstractExpressionTester {

        private String dateTime;

        protected DateTimeTester(String dateTime) {
            super();
            this.dateTime = dateTime;
        }

        public void test(Expression expression) {
            assertInstance(expression, DateTime.class);

            DateTime dateTime = (DateTime) expression;
            assertEquals(toString(), dateTime.toParsedText());
        }

        @Override
        public String toString() {
            return dateTime;
        }
    }

    /**
     * Tester for {@link DeleteClause}.
     */
    public static final class DeleteClauseTester extends AbstractExpressionTester {

        public boolean hasFrom;
        public boolean hasSpaceAfterDelete;
        public boolean hasSpaceAfterFrom;
        private ExpressionTester rangeVariableDeclaration;

        protected DeleteClauseTester(ExpressionTester rangeVariableDeclaration) {
            super();
            this.hasFrom                  = true;
            this.hasSpaceAfterFrom        = true;
            this.hasSpaceAfterDelete      = true;
            this.rangeVariableDeclaration = rangeVariableDeclaration;
        }

        public void test(Expression expression) {

            assertInstance(expression, DeleteClause.class);

            DeleteClause deleteClause = (DeleteClause) expression;
            assertEquals(toString(),                         deleteClause.toParsedText());
            assertEquals(hasSpaceAfterDelete,                deleteClause.hasSpaceAfterDelete());
            assertEquals(hasFrom,                            deleteClause.hasFrom());
            assertEquals(hasSpaceAfterFrom,                  deleteClause.hasSpaceAfterFrom());
            assertEquals(!rangeVariableDeclaration.isNull(), deleteClause.hasRangeVariableDeclaration());

            rangeVariableDeclaration.test(deleteClause.getRangeVariableDeclaration());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(DELETE);
            if (hasSpaceAfterDelete) {
                sb.append(SPACE);
            }
            if (hasFrom) {
                sb.append(FROM);
            }
            if (hasSpaceAfterFrom) {
                sb.append(SPACE);
            }
            sb.append(rangeVariableDeclaration);
            return sb.toString();
        }
    }

    public static final class DeleteStatementTester extends AbstractExpressionTester {

        private ExpressionTester deleteClause;
        public boolean hasSpaceAfterDeleteClause;
        private ExpressionTester whereClause;

        protected DeleteStatementTester(ExpressionTester deleteClause, ExpressionTester whereClause) {
            super();
            this.deleteClause              = deleteClause;
            this.whereClause               = whereClause;
            this.hasSpaceAfterDeleteClause = !whereClause.isNull();
        }

        public void test(Expression expression) {

            assertInstance(expression, DeleteStatement.class);

            DeleteStatement deleteStatement = (DeleteStatement) expression;
            assertEquals(toString(),                deleteStatement.toParsedText());
            assertEquals(hasSpaceAfterDeleteClause, deleteStatement.hasSpaceAfterDeleteClause());
            assertEquals(!whereClause.isNull(),     deleteStatement.hasWhereClause());

            deleteClause.test(deleteStatement.getDeleteClause());
            whereClause .test(deleteStatement.getWhereClause());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(deleteClause);
            if (hasSpaceAfterDeleteClause) {
                sb.append(SPACE);
            }
            sb.append(whereClause);
            return sb.toString();
        }
    }

    public static final class DivisionExpressionTester extends CompoundExpressionTester {

        protected DivisionExpressionTester(ExpressionTester leftExpression,
                                           ExpressionTester rightExpression) {

            super(leftExpression, rightExpression);
        }

        @Override
        protected Class<? extends CompoundExpression> expressionType() {
            return DivisionExpression.class;
        }

        @Override
        protected String identifier() {
            return DIVISION;
        }
    }

    public static final class EmptyCollectionComparisonExpressionTester extends AbstractExpressionTester {

        private ExpressionTester collectionPath;
        private boolean hasNot;
        public boolean hasSpaceAfterIs;

        protected EmptyCollectionComparisonExpressionTester(ExpressionTester collectionPath,
                                                            boolean hasNot) {

            super();
            this.hasNot = hasNot;
            this.hasSpaceAfterIs = true;
            this.collectionPath = collectionPath;
        }

        public void test(Expression expression) {
            assertInstance(expression, EmptyCollectionComparisonExpression.class);

            EmptyCollectionComparisonExpression emptyCollection = (EmptyCollectionComparisonExpression) expression;
            assertEquals(toString(),                               emptyCollection.toParsedText());
            assertEquals(!collectionPath.isNull(), emptyCollection.hasExpression());
            assertEquals(hasNot,                                   emptyCollection.hasNot());
            assertEquals(hasSpaceAfterIs,                          emptyCollection.hasSpaceAfterIs());

            collectionPath.test(emptyCollection.getExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(collectionPath);
            if (!collectionPath.isNull()) {
                sb.append(SPACE);
            }
            sb.append(IS);
            if (hasSpaceAfterIs) {
                sb.append(SPACE);
            }
            if (hasNot) {
                sb.append(NOT);
                sb.append(SPACE);
            }
            sb.append(EMPTY);
            return sb.toString();
        }
    }

    public static final class EntityTypeLiteralTester extends AbstractExpressionTester {

        private String entityType;

        protected EntityTypeLiteralTester(String entityType) {
            super();
            this.entityType = entityType;
        }

        public void test(Expression expression) {
            assertInstance(expression, EntityTypeLiteral.class);

            EntityTypeLiteral entityTypeLiteral = (EntityTypeLiteral) expression;
            assertEquals(toString(), entityTypeLiteral.toParsedText());
        }

        @Override
        public String toString() {
            return entityType;
        }
    }

    public static final class EntryExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected EntryExpressionTester(ExpressionTester identificationVariable) {
            super(identificationVariable);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return EntryExpression.class;
        }

        @Override
        protected String identifier() {
            return ENTRY;
        }
    }

    public static final class ExistsExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        private boolean hasNot;

        protected ExistsExpressionTester(ExpressionTester subquery, boolean hasNot) {
            super(subquery);
            this.hasNot = hasNot;
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return ExistsExpression.class;
        }

        @Override
        protected String identifier() {
            return hasNot ? NOT_EXISTS : EXISTS;
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, ExistsExpression.class);

            ExistsExpression existsExpression = (ExistsExpression) expression;
            assertEquals(hasNot, existsExpression.hasNot());
        }
    }

    /**
     * This tester tests an {@link Expression} information to make sure it correctly parsed a section
     * of the query. This interface also adds helper method for easily creating a parsed tree
     * representation of the actual query parsed tree.
     */
    public static interface ExpressionTester {

        AdditionExpressionTester add(ExpressionTester expression);
        AndExpressionTester and(ExpressionTester expression);
        BetweenExpressionTester between(ExpressionTester lowerBoundExpression, ExpressionTester upperBoundExpression);
        ComparisonExpressionTester different(ExpressionTester expression);
        DivisionExpressionTester divide(ExpressionTester expression);
        ComparisonExpressionTester equal(ExpressionTester expression);
        ComparisonExpressionTester greaterThan(ExpressionTester expression);
        ComparisonExpressionTester greaterThanOrEqual(ExpressionTester expression);
        InExpressionTester in(ExpressionTester... inItems);
        InExpressionTester in(String inputParameter);
        EmptyCollectionComparisonExpressionTester isEmpty();
        EmptyCollectionComparisonExpressionTester isNotEmpty();

        /**
         * Determines whether this tester represents the {@link NullExpression}.
         *
         * @return <code>true</code> if this tester represents a <code>null</code> object;
         * <code>false</code> otherwise
         */
        boolean isNull();

        LikeExpressionTester like(ExpressionTester patternValue);
        LikeExpressionTester like(ExpressionTester patternValue, ExpressionTester escapeCharacter);
        ComparisonExpressionTester lowerThan(ExpressionTester expression);
        ComparisonExpressionTester lowerThanOrEqual(ExpressionTester expression);
        ExpressionTester member(ExpressionTester collectionPath);
        ExpressionTester memberOf(ExpressionTester collectionPath);
        MultiplicationExpressionTester multiply(ExpressionTester expression);
        BetweenExpressionTester notBetween(ExpressionTester lowerBoundExpression, ExpressionTester upperBoundExpression);
        ComparisonExpressionTester notEqual(ExpressionTester expression);
        InExpressionTester notIn(ExpressionTester... inItems);
        InExpressionTester notIn(String inputParameter);
        LikeExpressionTester notLike(ExpressionTester expression);
        LikeExpressionTester notLike(ExpressionTester expression, ExpressionTester escapeCharacter);
        ExpressionTester notMember(ExpressionTester collectionPath);
        ExpressionTester notMemberOf(ExpressionTester collectionPath);
        OrExpressionTester or(ExpressionTester expression);
        RegexpExpressionTester regexp(StringLiteralTester patternValue);
        SubtractionExpressionTester subtract(ExpressionTester expression);

        /**
         * Tests the given {@link Expression} internal data.
         */
        void test(Expression expression);
    }

    public static final class ExtractExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        private boolean hasFrom;
        public boolean hasSpaceAfterFrom;
        public boolean hasSpaceAfterPart;
        private String part;

        protected ExtractExpressionTester(String part, boolean hasFom, ExpressionTester expression) {
            super(expression);
            this.hasFrom           = hasFom;
            this.part              = (part != null) ? part : ExpressionTools.EMPTY_STRING;
            this.hasSpaceAfterPart = (part != null) && (hasFrom || !expression.isNull());
            this.hasSpaceAfterFrom = hasFom && !expression.isNull();
        }

        @Override
        protected Class<ExtractExpression> expressionType() {
            return ExtractExpression.class;
        }

        @Override
        protected boolean hasEncapsulatedExpression() {
            return super.hasEncapsulatedExpression() || hasFrom || ExpressionTools.stringIsNotEmpty(part);
        }

        @Override
        protected String identifier() {
            return EXTRACT;
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);

            ExtractExpression extractExpression = (ExtractExpression) expression;
            assertEquals(part,              extractExpression.getDatePart());
            assertEquals(hasFrom,           extractExpression.hasFrom());
            assertSame  (hasSpaceAfterFrom, extractExpression.hasSpaceAfterFrom());
            assertSame  (hasSpaceAfterPart, extractExpression.hasSpaceAfterDatePart());
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {

            sb.append(part);

            if (hasSpaceAfterPart) {
                sb.append(SPACE);
            }

            if (hasFrom) {
                sb.append(FROM);
            }

            if (hasSpaceAfterFrom) {
                sb.append(SPACE);
            }

            super.toStringEncapsulatedExpression(sb);
        }
    }

    public static final class FromClauseTester extends AbstractFromClauseTester {

        protected FromClauseTester(ExpressionTester declarations,
                                   ExpressionTester hierarchicalQueryClause,
                                   ExpressionTester asOfClause) {

            super(declarations, hierarchicalQueryClause, asOfClause);
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, FromClause.class);
        }
    }

    public static final class FunctionExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        private String functionName;
        public boolean hasComma;
        public boolean hasSpaceAfterComma;
        private String identifier;

        protected FunctionExpressionTester(String identifier,
                                           String functionName,
                                           ExpressionTester funcItems) {

            super(funcItems);
            this.identifier = identifier;
            this.functionName = functionName;
            this.hasSpaceAfterComma = !funcItems.isNull();
            this.hasComma = !funcItems.isNull();
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return FunctionExpression.class;
        }

        @Override
        protected boolean hasEncapsulatedExpression() {
            return functionName.length() > 0 ||
                   hasComma                  ||
                   hasSpaceAfterComma        ||
                   super.hasEncapsulatedExpression();
        }

        @Override
        protected String identifier() {
            return identifier;
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);

            FunctionExpression funcExpression = (FunctionExpression) expression;
            assertEquals(identifier,         funcExpression.getIdentifier());
            assertEquals(functionName,       funcExpression.getFunctionName());
            assertEquals(hasComma,           funcExpression.hasComma());
            assertEquals(hasSpaceAfterComma, funcExpression.hasSpaceAfterComma());
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {
            if (functionName != null) {
                sb.append(functionName);
            }
            if (hasComma) {
                sb.append(COMMA);
            }
            if (hasSpaceAfterComma) {
                sb.append(SPACE);
            }
            super.toStringEncapsulatedExpression(sb);
        }
    }

    public static final class GroupByClauseTester extends AbstractExpressionTester {

        private ExpressionTester groupByItems;
        public boolean hasSpaceAfterGroupBy;

        protected GroupByClauseTester(ExpressionTester groupByItems) {
            super();
            this.groupByItems         = groupByItems;
            this.hasSpaceAfterGroupBy = !groupByItems.isNull();
        }

        public void test(Expression expression) {

            assertInstance(expression, GroupByClause.class);

            GroupByClause groupByClause = (GroupByClause) expression;
            assertEquals(toString(),             groupByClause.toParsedText());
            assertEquals(!groupByItems.isNull(), groupByClause.hasGroupByItems());
            assertEquals(hasSpaceAfterGroupBy,   groupByClause.hasSpaceAfterGroupBy());

            groupByItems.test(groupByClause.getGroupByItems());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(GROUP_BY);
            if (hasSpaceAfterGroupBy) {
                sb.append(SPACE);
            }
            sb.append(groupByItems);
            return sb.toString();
        }
    }

    public static final class HavingClauseTester extends AbstractConditionalClauseTester {

        protected HavingClauseTester(ExpressionTester conditionalExpression) {
            super(conditionalExpression);
        }

        @Override
        protected Class<? extends AbstractConditionalClause> expressionType() {
            return HavingClause.class;
        }

        @Override
        protected String identifier() {
            return HAVING;
        }
    }

    public static final class HierarchicalQueryClauseTester extends AbstractExpressionTester {

        private ExpressionTester connectByClause;
        public boolean hasSpaceAfterConnectByClause;
        public boolean hasSpaceAfterStartWithClause;
        private ExpressionTester orderSiblingsByClause;
        private ExpressionTester startWithClause;

        protected HierarchicalQueryClauseTester(ExpressionTester startWithClause,
                                                ExpressionTester connectByClause,
                                                ExpressionTester orderSiblingsByClause) {
            super();
            this.startWithClause              = startWithClause;
            this.connectByClause              = connectByClause;
            this.orderSiblingsByClause        = orderSiblingsByClause;
            this.hasSpaceAfterStartWithClause = !startWithClause.isNull() && !connectByClause.isNull();
            this.hasSpaceAfterConnectByClause = !connectByClause.isNull() && !orderSiblingsByClause.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, HierarchicalQueryClause.class);

            HierarchicalQueryClause clause = (HierarchicalQueryClause) expression;
            assertEquals(toString(),                      clause.toString());
            assertEquals(!startWithClause.isNull(),       clause.hasStartWithClause());
            assertEquals(!connectByClause.isNull(),       clause.hasConnectByClause());
            assertEquals(!orderSiblingsByClause.isNull(), clause.hasOrderSiblingsByClause());
            assertEquals(hasSpaceAfterStartWithClause,    clause.hasSpaceAfterStartWithClause());
            assertEquals(hasSpaceAfterConnectByClause,    clause.hasSpaceAfterConnectByClause());

            startWithClause.test(clause.getStartWithClause());
            connectByClause.test(clause.getConnectByClause());
            orderSiblingsByClause.test(clause.getOrderSiblingsByClause());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(startWithClause);
            if (hasSpaceAfterStartWithClause) {
                sb.append(SPACE);
            }
            sb.append(connectByClause);
            if (hasSpaceAfterConnectByClause) {
                sb.append(SPACE);
            }
            sb.append(orderSiblingsByClause);
            return sb.toString();
        }
    }

    public static final class IdentificationVariableDeclarationTester extends AbstractExpressionTester {

        public boolean hasSpace;
        private ExpressionTester joins;
        private ExpressionTester rangeVariableDeclaration;

        protected IdentificationVariableDeclarationTester(ExpressionTester rangeVariableDeclaration,
                                                          ExpressionTester joins) {

            super();
            this.rangeVariableDeclaration = rangeVariableDeclaration;
            this.hasSpace                 = !joins.isNull();
            this.joins                    = joins;
        }

        public void test(Expression expression) {

            assertInstance(expression, IdentificationVariableDeclaration.class);

            IdentificationVariableDeclaration identificationVariableDeclaration = (IdentificationVariableDeclaration) expression;
            assertEquals(toString(),                         identificationVariableDeclaration.toParsedText());
            assertEquals(!rangeVariableDeclaration.isNull(), identificationVariableDeclaration.hasRangeVariableDeclaration());
            assertEquals(hasSpace,                           identificationVariableDeclaration.hasSpace());
            assertEquals(!joins.isNull(),                    identificationVariableDeclaration.hasJoins());

            rangeVariableDeclaration.test(identificationVariableDeclaration.getRangeVariableDeclaration());
            joins.test(identificationVariableDeclaration.getJoins());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(rangeVariableDeclaration);
            if (hasSpace) {
                sb.append(SPACE);
            }
            sb.append(joins);
            return sb.toString();
        }
    }

    public static final class IdentificationVariableTester extends AbstractExpressionTester {

        private String identificationVariable;
        private boolean virtual;
        private ExpressionTester virtualPathExpression;

        protected IdentificationVariableTester(String identificationVariable,
                                               boolean virtual,
                                               ExpressionTester virtualPathExpression) {
            super();
            this.virtual                = virtual;
            this.identificationVariable = identificationVariable;
            this.virtualPathExpression  = virtualPathExpression;
        }

        @Override
        public boolean isNull() {
            return virtual && virtualPathExpression.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, IdentificationVariable.class);

            IdentificationVariable identificationVariable = (IdentificationVariable) expression;
            assertEquals(this.identificationVariable, identificationVariable.toParsedText());
            assertEquals(virtual,                     identificationVariable.isVirtual());

            if (virtual) {
                StateFieldPathExpression pathExpression = identificationVariable.getStateFieldPathExpression();
                assertEquals(virtualPathExpression.isNull(), pathExpression == null);
                if (pathExpression != null) {
                    virtualPathExpression.test(pathExpression);
                }
            }
        }

        @Override
        public String toString() {
            return virtual ? virtualPathExpression.toString() : identificationVariable;
        }
    }

    public static final class IndexExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected IndexExpressionTester(ExpressionTester identificationVariable) {
            super(identificationVariable);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return IndexExpression.class;
        }

        @Override
        protected String identifier() {
            return INDEX;
        }
    }

    public static final class InExpressionTester extends AbstractExpressionTester {

        public boolean hasLeftParenthesis;
        private boolean hasNot;
        public boolean hasRightParenthesis;
        public boolean hasSpaceAfterIn;
        private ExpressionTester inItems;
        private ExpressionTester stateFieldPathExpression;

        protected InExpressionTester(ExpressionTester stateFieldPathExpression,
                                     boolean hasNot,
                                     ExpressionTester inItems) {

            super();
            this.stateFieldPathExpression = stateFieldPathExpression;
            this.hasLeftParenthesis       = !inItems.isNull();
            this.hasRightParenthesis      = !inItems.isNull();
            this.hasNot                   = hasNot;
            this.inItems                  = inItems;
            this.hasSpaceAfterIn          = !hasLeftParenthesis && !inItems.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, InExpression.class);

            InExpression inExpression = (InExpression) expression;
            assertEquals(toString(),                         inExpression.toParsedText());
            assertEquals(hasLeftParenthesis,                 inExpression.hasLeftParenthesis());
            assertEquals(hasRightParenthesis,                inExpression.hasRightParenthesis());
            assertEquals(hasNot,                             inExpression.hasNot());
            assertEquals(!inItems.isNull(),                  inExpression.hasInItems());
            assertEquals(!stateFieldPathExpression.isNull(), inExpression.hasExpression());

            stateFieldPathExpression.test(inExpression.getExpression());
            inItems.test(inExpression.getInItems());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(stateFieldPathExpression);
            if (!stateFieldPathExpression.isNull()) {
                sb.append(SPACE);
            }
            sb.append(hasNot ? NOT_IN : IN);
            if (hasSpaceAfterIn) {
                sb.append(SPACE);
            }
            if (hasLeftParenthesis) {
                sb.append(LEFT_PARENTHESIS);
            }
            sb.append(inItems);
            if (hasRightParenthesis) {
                sb.append(RIGHT_PARENTHESIS);
            }
            return sb.toString();
        }
    }

    public static final class InputParameterTester extends AbstractExpressionTester {

        private String inputParameter;

        protected InputParameterTester(String inputParameter) {
            super();
            this.inputParameter = inputParameter;
        }

        public void test(Expression expression) {
            assertInstance(expression, InputParameter.class);

            InputParameter inputParameter = (InputParameter) expression;
            assertEquals(toString(),                           inputParameter.toParsedText());
            assertEquals(this.inputParameter.charAt(0) == '?', inputParameter.isPositional());
            assertEquals(this.inputParameter.charAt(0) == ':', inputParameter.isNamed());
            assertEquals(this.inputParameter.substring(1),     inputParameter.getParameterName());
        }

        @Override
        public String toString() {
            return inputParameter;
        }
    }

    public static final class JoinTester extends AbstractExpressionTester {

        private boolean hasAs;
        public boolean hasSpaceAfterAs;
        public boolean hasSpaceAfterIdentificationVariable;
        public boolean hasSpaceAfterJoin;
        public boolean hasSpaceAfterJoinAssociation;
        private ExpressionTester identificationVariable;
        private ExpressionTester joinAssociationPath;
        private ExpressionTester joinCondition;
        private String joinType;

        protected JoinTester(String joinType,
                             ExpressionTester joinAssociationPath,
                             boolean hasAs,
                             ExpressionTester identificationVariable,
                             ExpressionTester joinCondition) {

            super();
            this.joinType                            = joinType;
            this.hasSpaceAfterJoin                   = true;
            this.joinAssociationPath                 = joinAssociationPath;
            this.hasAs                               = hasAs;
            this.hasSpaceAfterAs                     = hasAs;
            this.identificationVariable              = identificationVariable;
            this.hasSpaceAfterJoinAssociation        = !joinAssociationPath.isNull();
            this.hasSpaceAfterIdentificationVariable = !identificationVariable.isNull() && !joinCondition.isNull();
            this.joinCondition                       = joinCondition;
        }

        public void test(Expression expression) {
            assertInstance(expression, Join.class);

            Join join = (Join) expression;
            assertEquals(toString(), join.toParsedText());
            assertEquals(joinType, join.getIdentifier());

            assertEquals(hasSpaceAfterJoin,                   join.hasSpaceAfterJoin());
            assertEquals(!joinAssociationPath.isNull(),       join.hasJoinAssociationPath());
            assertEquals(hasAs,                               join.hasAs());
            assertEquals(hasSpaceAfterAs,                     join.hasSpaceAfterAs());
            assertEquals(hasSpaceAfterJoinAssociation,        join.hasSpaceAfterJoinAssociation());
            assertEquals(!identificationVariable.isNull(),    join.hasIdentificationVariable());
            assertEquals(hasSpaceAfterIdentificationVariable, join.hasSpaceAfterIdentificationVariable());

            joinAssociationPath.test(join.getJoinAssociationPath());
            identificationVariable.test(join.getIdentificationVariable());
            joinCondition.test(join.getOnClause());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(joinType);
            if (hasSpaceAfterJoin) {
                sb.append(SPACE);
            }
            sb.append(joinAssociationPath);
            if (hasSpaceAfterJoinAssociation) {
                sb.append(SPACE);
            }
            if (hasAs) {
                sb.append(AS);
            }
            if (hasSpaceAfterAs) {
                sb.append(SPACE);
            }
            sb.append(identificationVariable);
            if (hasSpaceAfterIdentificationVariable) {
                sb.append(SPACE);
            }
            sb.append(joinCondition);
            return sb.toString();
        }
    }

    public static final class JPQLExpressionTester extends AbstractExpressionTester {

        private ExpressionTester queryStatement;
        private ExpressionTester unknownExpression;

        protected JPQLExpressionTester(ExpressionTester queryStatement,
                                       ExpressionTester unknownExpression) {

            super();
            this.queryStatement    = queryStatement;
            this.unknownExpression = unknownExpression;
        }

        public void test(Expression expression) {

            JPQLExpression jpqlExpression = (JPQLExpression) expression;

            assertEquals(toString(),                  jpqlExpression.toParsedText());
            assertEquals(!queryStatement.isNull(),    jpqlExpression.hasQueryStatement());
            assertEquals(!unknownExpression.isNull(), jpqlExpression.hasUnknownEndingStatement());

            queryStatement   .test(jpqlExpression.getQueryStatement());
            unknownExpression.test(jpqlExpression.getUnknownEndingStatement());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(queryStatement);
            sb.append(unknownExpression);
            return sb.toString();
        }
    }

    public static final class KeywordExpressionTester extends AbstractExpressionTester {

        private String keyword;

        protected KeywordExpressionTester(String keyword) {
            super();
            this.keyword = keyword;
        }

        public void test(Expression expression) {
            assertInstance(expression, KeywordExpression.class);

            KeywordExpression keywordExpression = (KeywordExpression) expression;
            assertEquals(toString(), keywordExpression.toParsedText());
        }

        @Override
        public String toString() {
            return keyword;
        }
    }

    public static final class LengthExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected LengthExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return LengthExpression.class;
        }

        @Override
        protected String identifier() {
            return LENGTH;
        }
    }

    public static final class LikeExpressionTester extends AbstractExpressionTester {

        private ExpressionTester escapeCharacter;
        public boolean hasEscape;
        private boolean hasNot;
        public boolean hasSpaceAfterEscape;
        public boolean hasSpaceAfterLike;
        public boolean hasSpaceAfterPatternValue;
        private ExpressionTester patternValue;
        private ExpressionTester stringExpression;

        protected LikeExpressionTester(ExpressionTester stringExpression,
                                       boolean hasNot,
                                       ExpressionTester patternValue,
                                       ExpressionTester escapeCharacter) {

            super();
            this.hasNot              = hasNot;
            this.hasSpaceAfterLike   = true;
            this.stringExpression    = stringExpression;
            this.patternValue        = patternValue;
            this.escapeCharacter     = escapeCharacter;
            this.hasEscape           = !escapeCharacter.isNull();
            this.hasSpaceAfterEscape = hasEscape;
            this.hasSpaceAfterPatternValue = !patternValue.isNull() && hasEscape;
        }

        public void test(Expression expression) {
            assertInstance(expression, LikeExpression.class);

            LikeExpression likeExpression = (LikeExpression) expression;
            assertEquals(toString(),                likeExpression.toParsedText());
            assertEquals(hasNot,                    likeExpression.hasNot());
            assertEquals(hasSpaceAfterLike,         likeExpression.hasSpaceAfterLike());
            assertEquals(hasEscape,                 likeExpression.hasEscape());
            assertEquals(!escapeCharacter.isNull(), likeExpression.hasEscapeCharacter());
            assertEquals(hasSpaceAfterEscape,       likeExpression.hasSpaceAfterEscape());
            assertEquals(hasSpaceAfterPatternValue, likeExpression.hasSpaceAfterPatternValue());
            assertEquals(!patternValue.isNull(),    likeExpression.hasPatternValue());

            stringExpression.test(likeExpression.getStringExpression());
            patternValue.test(likeExpression.getPatternValue());
            escapeCharacter.test(likeExpression.getEscapeCharacter());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(stringExpression);
            if (!stringExpression.isNull()) {
                sb.append(SPACE);
            }
            sb.append(hasNot ? NOT_LIKE : LIKE);
            if (hasSpaceAfterLike) {
                sb.append(SPACE);
            }
            sb.append(patternValue);
            if (hasSpaceAfterPatternValue) {
                sb.append(SPACE);
            }
            if (hasEscape) {
                sb.append(ESCAPE);
            }
            if (hasSpaceAfterEscape) {
                sb.append(SPACE);
            }
            sb.append(escapeCharacter);
            return sb.toString();
        }
    }

    public static final class LocateExpressionTester extends AbstractTripleEncapsulatedExpressionTester {

        protected LocateExpressionTester(ExpressionTester firstExpression,
                                         ExpressionTester secondExpression,
                                         ExpressionTester thirdExpression) {

            super(firstExpression, secondExpression, thirdExpression);
        }

        @Override
        protected Class<? extends AbstractTripleEncapsulatedExpression> expressionType() {
            return LocateExpression.class;
        }

        @Override
        protected String identifier() {
            return LOCATE;
        }
    }

    public static abstract class LogicalExpressionTester extends CompoundExpressionTester {

        protected LogicalExpressionTester(ExpressionTester leftExpression,
                                          ExpressionTester rightExpression) {

            super(leftExpression, rightExpression);
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, LogicalExpression.class);
        }
    }

    public static final class LowerExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected LowerExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return LowerExpression.class;
        }

        @Override
        protected String identifier() {
            return LOWER;
        }
    }

    public static final class MaxFunctionTester extends AggregateFunctionTester {

        protected MaxFunctionTester(ExpressionTester expression, boolean hasDistinct) {
            super(expression, hasDistinct);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return MaxFunction.class;
        }

        @Override
        protected String identifier() {
            return MAX;
        }
    }

    public static final class MinFunctionTester extends AggregateFunctionTester {

        protected MinFunctionTester(ExpressionTester expression, boolean hasDistinct) {
            super(expression, hasDistinct);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return MinFunction.class;
        }

        @Override
        protected String identifier() {
            return MIN;
        }
    }

    public static final class ModExpressionTester extends AbstractDoubleEncapsulatedExpressionTester {

        protected ModExpressionTester(ExpressionTester firstExpression, ExpressionTester secondExpression) {
            super(firstExpression, secondExpression);
        }

        @Override
        protected Class<? extends AbstractDoubleEncapsulatedExpression> expressionType() {
            return ModExpression.class;
        }

        @Override
        protected String identifier() {
            return MOD;
        }
    }

    public static final class MultiplicationExpressionTester extends CompoundExpressionTester {

        protected MultiplicationExpressionTester(ExpressionTester leftExpression,
                                                 ExpressionTester rightExpression) {

            super(leftExpression, rightExpression);
        }

        @Override
        protected Class<? extends CompoundExpression> expressionType() {
            return MultiplicationExpression.class;
        }

        @Override
        protected String identifier() {
            return MULTIPLICATION;
        }
    }

    public static final class NotExpressionTester extends AbstractExpressionTester {

        private ExpressionTester expression;
        public boolean hasSpaceAfterNot;

        protected NotExpressionTester(ExpressionTester expression) {
            super();
            this.expression       = expression;
            this.hasSpaceAfterNot = true;
        }

        public void test(Expression expression) {
            assertInstance(expression, NotExpression.class);

            NotExpression notExpression = (NotExpression) expression;
            assertEquals(toString(),                notExpression.toParsedText());
            assertEquals(hasSpaceAfterNot,          notExpression.hasSpaceAfterNot());
            assertEquals(!this.expression.isNull(), notExpression.hasExpression());

            this.expression.test(notExpression.getExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(NOT);
            if (hasSpaceAfterNot) {
                sb.append(SPACE);
            }
            sb.append(expression);
            return sb.toString();
        }
    }

    public static final class NullComparisonExpressionTester extends AbstractExpressionTester {

        private ExpressionTester expression;
        private boolean hasNot;

        protected NullComparisonExpressionTester(ExpressionTester expression, boolean hasNot) {
            super();
            this.hasNot     = hasNot;
            this.expression = expression;
        }

        public void test(Expression expression) {
            assertInstance(expression, NullComparisonExpression.class);

            NullComparisonExpression nullComparisonExpression = (NullComparisonExpression) expression;
            assertEquals(toString(),                nullComparisonExpression.toParsedText());
            assertEquals(hasNot,                    nullComparisonExpression.hasNot());
            assertEquals(!this.expression.isNull(), nullComparisonExpression.hasExpression());

            this.expression.test(nullComparisonExpression.getExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(expression);
            if (!expression.isNull()) {
                sb.append(SPACE);
            }
            sb.append(hasNot ? IS_NOT_NULL : IS_NULL);
            return sb.toString();
        }
    }

    public static final class NullExpressionTester extends AbstractExpressionTester {

        @Override
        public boolean isNull() {
            return true;
        }

        public void test(Expression expression) {
            assertInstance(expression, NullExpression.class);
        }

        @Override
        public String toString() {
            return ExpressionTools.EMPTY_STRING;
        }
    }

    public static final class NullIfExpressionTester extends AbstractDoubleEncapsulatedExpressionTester {

        protected NullIfExpressionTester(ExpressionTester firstExpression,
                                         ExpressionTester secondExpression) {

            super(firstExpression, secondExpression);
      }

        @Override
        protected Class<? extends AbstractDoubleEncapsulatedExpression> expressionType() {
            return NullIfExpression.class;
        }

        @Override
        protected String identifier() {
            return NULLIF;
        }
    }

    public static final class NumericLiteralTester extends AbstractExpressionTester {

        private String number;

        protected NumericLiteralTester(String number) {
            super();
            this.number = number;
        }

        public void test(Expression expression) {
            assertInstance(expression, NumericLiteral.class);

            assertEquals(toString(), expression.toParsedText());
        }

        @Override
        public String toString() {
            return number;
        }
    }

    public static final class ObjectExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected ObjectExpressionTester(ExpressionTester identificationVariable) {
            super(identificationVariable);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return ObjectExpression.class;
        }

        @Override
        protected String identifier() {
            return OBJECT;
        }
    }

    public static final class OnClauseTester extends AbstractConditionalClauseTester {

        protected OnClauseTester(ExpressionTester conditionalExpression) {
            super(conditionalExpression);
        }

        @Override
        protected Class<? extends AbstractConditionalClause> expressionType() {
            return OnClause.class;
        }

        @Override
        protected String identifier() {
            return ON;
        }
    }

    public static final class OrderByClauseTester extends AbstractOrderByClauseTester {

        protected OrderByClauseTester(ExpressionTester orderByItems) {
            super(orderByItems);
        }

        @Override
        protected String identifier() {
            return ORDER_BY;
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, OrderByClause.class);
        }
    }

    public static final class OrderByItemTester extends AbstractExpressionTester {

        public boolean hasSpaceAfterExpression;
        public boolean hasSpaceAfterNulls;
        public boolean hasSpaceAfterOrdering;
        private NullOrdering nullOrdering;
        public String nulls;
        private ExpressionTester orderByItem;
        private Ordering ordering;

        protected OrderByItemTester(ExpressionTester orderByItem,
                                    Ordering ordering,
                                    NullOrdering nullOrdering) {

            super();
            this.ordering     = ordering;
            this.orderByItem  = orderByItem;
            this.nullOrdering = nullOrdering;
            this.hasSpaceAfterExpression = ordering != Ordering.DEFAULT ||
                                           nullOrdering != NullOrdering.DEFAULT;
            this.hasSpaceAfterOrdering = ordering != Ordering.DEFAULT &&
                                         nullOrdering != NullOrdering.DEFAULT;
        }

        public void test(Expression expression) {
            assertInstance(expression, OrderByItem.class);

            OrderByItem orderByItem = (OrderByItem) expression;
            assertEquals(toString(), orderByItem.toParsedText());
            assertEquals(!this.orderByItem.isNull(), orderByItem.hasExpression());
            assertEquals(hasSpaceAfterExpression,    orderByItem.hasSpaceAfterExpression());
            assertEquals(hasSpaceAfterOrdering,      orderByItem.hasSpaceAfterOrdering());
            assertSame  (ordering, orderByItem.getOrdering());

            if (nulls != null) {
                assertEquals(nulls, orderByItem.getActualNullOrdering().toUpperCase());
            }
            else {
                assertSame(nullOrdering, orderByItem.getNullOrdering());
            }

            this.orderByItem.test(orderByItem.getExpression());
        }

        @Override
        public String toString() {

            StringBuilder sb = new StringBuilder();
            sb.append(orderByItem);

            if (hasSpaceAfterExpression) {
                sb.append(SPACE);
            }

            if (ordering != Ordering.DEFAULT) {
                sb.append(ordering.name());
            }

            if (hasSpaceAfterOrdering) {
                sb.append(SPACE);
            }

            if (nulls != null) {
                sb.append(nulls);
                if (hasSpaceAfterNulls) {
                    sb.append(SPACE);
                }
            }
            else if (nullOrdering != NullOrdering.DEFAULT) {
                sb.append(nullOrdering.getIdentifier());
            }

            return sb.toString();
        }
    }

    public static final class OrderSiblingsByClauseTester extends AbstractOrderByClauseTester {

        protected OrderSiblingsByClauseTester(ExpressionTester orderByItems) {
            super(orderByItems);
        }

        @Override
        protected String identifier() {
            return ORDER_SIBLINGS_BY;
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, OrderSiblingsByClause.class);
        }
    }

    public static final class OrExpressionTester extends LogicalExpressionTester {

        protected OrExpressionTester(ExpressionTester leftExpression,
                                     ExpressionTester rightExpression) {

            super(leftExpression, rightExpression);
        }

        @Override
        protected Class<? extends CompoundExpression> expressionType() {
            return OrExpression.class;
        }

        @Override
        protected String identifier() {
            return OR;
        }
    }

    public static final class RangeVariableDeclarationTester extends AbstractExpressionTester {

        private ExpressionTester abstractSchemaName;
        private boolean hasAs;
        public boolean hasSpaceAfterAbstractSchemaName;
        public boolean hasSpaceAfterAs;
        private ExpressionTester identificationVariable;

        protected RangeVariableDeclarationTester(ExpressionTester abstractSchemaName,
                                                 boolean hasAs,
                                                 ExpressionTester identificationVariable) {

            super();
            this.hasAs                           = hasAs;
            this.abstractSchemaName              = abstractSchemaName;
            this.identificationVariable          = identificationVariable;
            this.hasSpaceAfterAbstractSchemaName = hasAs || !identificationVariable.isNull();
            this.hasSpaceAfterAs                 = hasAs;

            if (identificationVariable instanceof IdentificationVariableTester &&
                identificationVariable.isNull()) {

                this.hasSpaceAfterAbstractSchemaName = true;
            }
        }

        public void test(Expression expression) {
            assertInstance(expression, RangeVariableDeclaration.class);

            RangeVariableDeclaration rangeVariableDeclaration = (RangeVariableDeclaration) expression;
            assertEquals(toString(),                       rangeVariableDeclaration.toParsedText());
            assertEquals(hasAs,                            rangeVariableDeclaration.hasAs());
            assertEquals(hasSpaceAfterAs,                  rangeVariableDeclaration.hasSpaceAfterAs());
            assertEquals(!identificationVariable.isNull(), rangeVariableDeclaration.hasIdentificationVariable());
            assertEquals(hasSpaceAfterAbstractSchemaName,  rangeVariableDeclaration.hasSpaceAfterRootObject());

            abstractSchemaName.test(rangeVariableDeclaration.getRootObject());
            identificationVariable.test(rangeVariableDeclaration.getIdentificationVariable());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(abstractSchemaName);
            if (hasSpaceAfterAbstractSchemaName) {
                sb.append(SPACE);
            }
            if (hasAs) {
                sb.append(AS);
            }
            if (hasSpaceAfterAs) {
                sb.append(SPACE);
            }
            sb.append(identificationVariable);
            return sb.toString();
        }
    }

    public static final class RegexpExpressionTester extends AbstractExpressionTester {

        public boolean hasSpaceAfterIdentifier;
        private ExpressionTester patternValue;
        private ExpressionTester stringExpression;

        protected RegexpExpressionTester(ExpressionTester stringExpression,
                                         ExpressionTester patternValue) {

            super();
            this.stringExpression        = stringExpression;
            this.patternValue            = patternValue;
            this.hasSpaceAfterIdentifier = !patternValue.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, RegexpExpression.class);

            RegexpExpression regexpExpression = (RegexpExpression) expression;
            assertEquals(toString(),                 regexpExpression.toParsedText());
            assertEquals(!patternValue.isNull(),     regexpExpression.hasPatternValue());
            assertEquals(hasSpaceAfterIdentifier,    regexpExpression.hasSpaceAfterIdentifier());
            assertEquals(!stringExpression.isNull(), regexpExpression.hasSpaceAfterStringExpression());
            assertEquals(!stringExpression.isNull(), regexpExpression.hasStringExpression());

            stringExpression.test(regexpExpression.getStringExpression());
            patternValue    .test(regexpExpression.getPatternValue());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(stringExpression);
            if (!stringExpression.isNull()) {
                sb.append(SPACE);
            }
            sb.append(REGEXP);
            if (hasSpaceAfterIdentifier) {
                sb.append(SPACE);
            }
            sb.append(patternValue);
            return sb.toString();
        }
    }

    public static final class ResultVariableTester extends AbstractExpressionTester {

        private boolean hasAs;
        public boolean hasSpaceAfterAs;
        private ExpressionTester resultVariable;
        private ExpressionTester selectExpression;

        protected ResultVariableTester(ExpressionTester selectExpression,
                                       boolean hasAs,
                                       ExpressionTester resultVariable) {

            super();
            this.hasAs            = hasAs;
            this.hasSpaceAfterAs  = hasAs;
            this.selectExpression = selectExpression;
            this.resultVariable   = resultVariable;
        }

        public void test(Expression expression) {

            assertInstance(expression, ResultVariable.class);
            ResultVariable resultVariable = (ResultVariable) expression;

            assertEquals(toString(),                    resultVariable.toParsedText());
            assertEquals(hasAs,                         resultVariable.hasAs());
            assertEquals(hasSpaceAfterAs,               resultVariable.hasSpaceAfterAs());
            assertEquals(!this.resultVariable.isNull(), resultVariable.hasResultVariable());
            assertEquals(!selectExpression.isNull(),    resultVariable.hasSelectExpression());

            this.selectExpression.test(resultVariable.getSelectExpression());
            this.resultVariable  .test(resultVariable.getResultVariable());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(selectExpression);
            if (!selectExpression.isNull()) {
                sb.append(SPACE);
            }
            if (hasAs) {
                sb.append(AS);
            }
            if (hasSpaceAfterAs) {
                sb.append(SPACE);
            }
            sb.append(resultVariable);
            return sb.toString();
        }
    }

    public static final class SelectClauseTester extends AbstractSelectClauseTester {

        protected SelectClauseTester(ExpressionTester selectExpressions, boolean hasDistinct) {
            super(selectExpressions, hasDistinct);
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, SelectClause.class);
        }
    }

    public static final class SelectStatementTester extends AbstractSelectStatementTester {

        public boolean hasSpaceBeforeOrderByClause;
        public boolean hasSpaceBeforeUnionClauses;
        private ExpressionTester orderByClause;
        private ExpressionTester unionClauses;

        protected SelectStatementTester(ExpressionTester selectClause,
                                        ExpressionTester fromClause,
                                        ExpressionTester whereClause,
                                        ExpressionTester groupByClause,
                                        ExpressionTester havingClause,
                                        ExpressionTester orderByClause,
                                        ExpressionTester unionClauses) {

            super(selectClause,
                  fromClause,
                  whereClause,
                  groupByClause,
                  havingClause);

            this.orderByClause = orderByClause;
            this.unionClauses  = unionClauses;

            this.hasSpaceBeforeOrderByClause = !orderByClause.isNull();
            this.hasSpaceBeforeUnionClauses  = !unionClauses .isNull();

//            hasSpaceAfterFrom                    |= (!fromClause   .isNull() && (!whereClause.isNull() || !groupByClause.isNull() &&  havingClause .isNull() && !orderByClause.isNull() && !unionClauses.isNull());
//            hasSpaceAfterWhere                   |= (!whereClause  .isNull() && groupByClause.isNull() && !havingClause .isNull() && !orderByClause.isNull() && !unionClauses .isNull());
//            hasSpaceAfterHierarchicalQueryClause |= (!whereClause  .isNull() && groupByClause.isNull() && !havingClause .isNull() && !orderByClause.isNull() && !unionClauses .isNull());
//            hasSpaceAfterGroupBy                 |= (!groupByClause.isNull() && havingClause .isNull() && !orderByClause.isNull() && !unionClauses.isNull());
        }

        @Override
        protected Class<? extends AbstractSelectStatement> expressionType() {
            return SelectStatement.class;
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);

            SelectStatement selectStatement = (SelectStatement) expression;
            assertEquals(!orderByClause.isNull(), selectStatement.hasOrderByClause());
//            assertEquals(hasSpaceBeforeOrderByClause, selectStatement.hasSpaceBeforeOrderBy());

            orderByClause.test(selectStatement.getOrderByClause());
            unionClauses .test(selectStatement.getUnionClauses());
        }

        @Override
        public String toString() {

            StringBuilder sb = new StringBuilder();
            sb.append(super.toString());
            if (hasSpaceBeforeOrderByClause && sb.charAt(sb.length() - 1) != ' ') {
                sb.append(SPACE);
            }
            sb.append(orderByClause);
            if (hasSpaceBeforeUnionClauses && sb.charAt(sb.length() - 1) != ' ') {
                sb.append(SPACE);
            }
            sb.append(unionClauses);
            return sb.toString();
        }
    }

    public static final class SimpleFromClauseTester extends AbstractFromClauseTester {

        protected SimpleFromClauseTester(ExpressionTester declaration,
                                           ExpressionTester hierarchicalQueryClause,
                                           ExpressionTester asOfClause) {

            super(declaration, hierarchicalQueryClause, asOfClause);
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, SimpleFromClause.class);
        }
    }

    public static final class SimpleSelectClauseTester extends AbstractSelectClauseTester {

        protected SimpleSelectClauseTester(ExpressionTester selectExpressions, boolean hasDistinct) {
            super(selectExpressions, hasDistinct);
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, SimpleSelectClause.class);
        }
    }

    public static final class SimpleSelectStatementTester extends AbstractSelectStatementTester {

        protected SimpleSelectStatementTester(ExpressionTester selectClause,
                                              ExpressionTester fromClause,
                                              ExpressionTester whereClause,
                                              ExpressionTester groupByClause,
                                              ExpressionTester havingClause) {

            super(selectClause, fromClause, whereClause, groupByClause, havingClause);
        }

        @Override
        protected Class<? extends AbstractSelectStatement> expressionType() {
            return SimpleSelectStatement.class;
        }
    }

    public static final class SizeExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected SizeExpressionTester(ExpressionTester collectionPath) {
            super(collectionPath);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return SizeExpression.class;
        }

        @Override
        protected String identifier() {
            return SIZE;
        }
    }

    public static final class SqrtExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected SqrtExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return SqrtExpression.class;
        }

        @Override
        protected String identifier() {
            return SQRT;
        }
    }

    public static final class StartWithClauseTester extends AbstractConditionalClauseTester {

        protected StartWithClauseTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<StartWithClause> expressionType() {
            return StartWithClause.class;
        }

        @Override
        protected String identifier() {
            return START_WITH;
        }
    }

    public static final class StateFieldPathExpressionTester extends AbstractPathExpressionTester {

        protected StateFieldPathExpressionTester(ExpressionTester identificationVariable,
                                               String value) {

            super(identificationVariable, value);
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);
            assertInstance(expression, StateFieldPathExpression.class);
        }
    }

    public static final class StringLiteralTester extends AbstractExpressionTester {

        private boolean hasCloseQuote;
        private String literal;

        protected StringLiteralTester(String literal) {

            super();
            this.literal = literal;

            if (literal.length() > 1) {
                char lastChar = literal.charAt(literal.length() - 1);
                hasCloseQuote = (lastChar == SINGLE_QUOTE) || (lastChar == DOUBLE_QUOTE);
            }
        }

        public void test(Expression expression) {
            assertInstance(expression, StringLiteral.class);

            StringLiteral stringLiteral = (StringLiteral) expression;
            assertEquals(toString(),    stringLiteral.toString());
            assertEquals(hasCloseQuote, stringLiteral.hasCloseQuote());
        }

        @Override
        public String toString() {
            return literal;
        }
    }

    public static final class SubExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected SubExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return SubExpression.class;
        }

        @Override
        protected String identifier() {
            return ExpressionTools.EMPTY_STRING;
        }
    }

    public static final class SubstringExpressionTester extends AbstractTripleEncapsulatedExpressionTester {

        protected SubstringExpressionTester(ExpressionTester firstExpression,
                                            ExpressionTester firstArithmeticExpression,
                                            ExpressionTester secondArithmeticExpression) {

            super(firstExpression, firstArithmeticExpression, secondArithmeticExpression);
        }

        @Override
        protected Class<? extends AbstractTripleEncapsulatedExpression> expressionType() {
            return SubstringExpression.class;
        }

        @Override
        protected String identifier() {
            return SubstringExpression.SUBSTRING;
        }
    }

    public static final class SubtractionExpressionTester extends CompoundExpressionTester {

        protected SubtractionExpressionTester(ExpressionTester leftExpression,
                                              ExpressionTester rightExpression) {

            super(leftExpression, rightExpression);
        }

        @Override
        protected Class<? extends CompoundExpression> expressionType() {
            return SubtractionExpression.class;
        }

        @Override
        protected String identifier() {
            return MINUS;
        }
    }

    public static final class SumFunctionTester extends AggregateFunctionTester {

        protected SumFunctionTester(ExpressionTester expression, boolean hasDistinct) {
            super(expression, hasDistinct);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return SumFunction.class;
        }

        @Override
        protected String identifier() {
            return SUM;
        }
    }

    public static final class TableExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected TableExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<TableExpression> expressionType() {
            return TableExpression.class;
        }

        @Override
        protected String identifier() {
            return TABLE;
        }
    }

    public static final class TableVariableDeclarationTester extends AbstractExpressionTester {


        private boolean hasAs;
        public boolean hasSpaceAfterAs;
        public boolean hasSpaceAfterTableExpression;
        private ExpressionTester identificationVariable;
        private TableExpressionTester tableExpression;

        protected TableVariableDeclarationTester(TableExpressionTester tableExpression,
                                                 boolean hasAs,
                                                 ExpressionTester identificationVariable) {
            super();
            this.tableExpression              = tableExpression;
            this.hasAs                        = hasAs;
            this.identificationVariable       = identificationVariable;
            this.hasSpaceAfterTableExpression = hasAs || !identificationVariable.isNull();
            this.hasSpaceAfterAs              = hasAs && !identificationVariable.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, Expression.class);

            TableVariableDeclaration tableVariableDeclaration = (TableVariableDeclaration) expression;
            assertEquals(toString(), tableVariableDeclaration.toParsedText());
            assertEquals(!identificationVariable.isNull(), tableVariableDeclaration.hasIdentificationVariable());
            assertEquals(hasAs,                            tableVariableDeclaration.hasAs());
            assertEquals(hasSpaceAfterAs,                  tableVariableDeclaration.hasSpaceAfterAs());
            assertEquals(hasSpaceAfterTableExpression,     tableVariableDeclaration.hasSpaceAfterTableExpression());

            tableExpression       .test(tableVariableDeclaration.getTableExpression());
            identificationVariable.test(tableVariableDeclaration.getIdentificationVariable());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(tableExpression);
            if (hasSpaceAfterTableExpression) {
                sb.append(SPACE);
            }
            if (hasAs) {
                sb.append(AS);
            }
            if (hasSpaceAfterAs) {
                sb.append(SPACE);
            }
            sb.append(identificationVariable);
            return sb.toString();
        }
    }

    public static final class TreatExpressionTester extends AbstractEncapsulatedExpressionTester {

        private ExpressionTester collectionValuedPathExpression;
        private ExpressionTester entityTypeName;
        private boolean hasAs;
        public boolean hasSpaceAfterAs;
        public boolean hasSpaceAfterCollectionValuedPathExpression;

        protected TreatExpressionTester(ExpressionTester collectionValuedPathExpression,
                                        boolean hasAs,
                                        ExpressionTester entityTypeName) {
            super();
            this.hasAs           = hasAs;
            this.entityTypeName  = entityTypeName;
            this.hasSpaceAfterAs = hasAs;
            this.hasSpaceAfterCollectionValuedPathExpression = true;
            this.collectionValuedPathExpression              = collectionValuedPathExpression;
        }

        @Override
        protected Class<? extends AbstractEncapsulatedExpression> expressionType() {
            return TreatExpression.class;
        }

        @Override
        protected boolean hasEncapsulatedExpression() {
            return !collectionValuedPathExpression.isNull() || !entityTypeName.isNull() || hasAs;
        }

        @Override
        protected String identifier() {
            return TREAT;
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {
            sb.append(collectionValuedPathExpression);
            if (hasSpaceAfterCollectionValuedPathExpression) {
                sb.append(SPACE);
            }
            if (hasAs) {
                sb.append(AS);
            }
            if (hasSpaceAfterAs) {
                sb.append(SPACE);
            }
            sb.append(entityTypeName);
        }
    }

    public static final class TrimExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        private boolean hasFrom;
        public boolean hasSpaceAfterFrom;
        public boolean hasSpaceAfterSpecification;
        public boolean hasSpaceAfterTrimCharacter;
        private Specification specification;
        private ExpressionTester trimCharacter;

        protected TrimExpressionTester(Specification specification,
                                       ExpressionTester stringPrimary,
                                       ExpressionTester trimCharacter,
                                       boolean hasFrom) {

            super(stringPrimary);
            this.specification              = specification;
            this.trimCharacter              = trimCharacter;
            this.hasFrom                    = hasFrom;
            this.hasSpaceAfterFrom          = hasFrom;
            this.hasSpaceAfterTrimCharacter = !trimCharacter.isNull();
            this.hasSpaceAfterSpecification = specification != Specification.DEFAULT;
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return TrimExpression.class;
        }

        @Override
        protected String identifier() {
            return TRIM;
        }

        @Override
        public void test(Expression expression) {
            super.test(expression);

            TrimExpression trimExpression = (TrimExpression) expression;
            assertEquals(hasFrom,                                trimExpression.hasFrom());
            assertEquals(hasSpaceAfterFrom,                      trimExpression.hasSpaceAfterFrom());
            assertEquals(hasSpaceAfterTrimCharacter,             trimExpression.hasSpaceAfterTrimCharacter());
            assertEquals(!trimCharacter.isNull(),                trimExpression.hasTrimCharacter());
            assertEquals(specification != Specification.DEFAULT, trimExpression.hasSpecification());
            assertEquals(hasSpaceAfterSpecification,             trimExpression.hasSpaceAfterSpecification());

            trimCharacter.test(trimExpression.getTrimCharacter());
        }

        @Override
        protected void toStringEncapsulatedExpression(StringBuilder sb) {
            if (specification != Specification.DEFAULT) {
                sb.append(specification);
            }
            if (hasSpaceAfterSpecification) {
                sb.append(SPACE);
            }
            sb.append(trimCharacter);
            if (hasSpaceAfterTrimCharacter) {
                sb.append(SPACE);
            }
            if (hasFrom) {
                sb.append(FROM);
            }
            if (hasSpaceAfterFrom) {
                sb.append(SPACE);
            }
            super.toStringEncapsulatedExpression(sb);
        }
    }

    public static final class TypeExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected TypeExpressionTester(ExpressionTester identificationVariable) {
            super(identificationVariable);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return TypeExpression.class;
        }

        @Override
        protected String identifier() {
            return TYPE;
        }
    }

    public static final class UnionClauseTester extends AbstractExpressionTester {

        private boolean hasAll;
        public boolean hasSpaceAfterAll;
        public boolean hasSpaceAfterIdentifier;
        private String identifier;
        private ExpressionTester subquery;

        protected UnionClauseTester(String identifier, boolean hasAll, ExpressionTester subquery) {
            super();
            this.identifier = identifier;
            this.hasAll     = hasAll;
            this.subquery   = subquery;
            this.hasSpaceAfterIdentifier = hasAll || !subquery.isNull();
            this.hasSpaceAfterAll        = hasAll && !subquery.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, UnionClause.class);

            UnionClause unionClause = (UnionClause) expression;
            assertEquals(toString(),              unionClause.toParsedText());
            assertEquals(identifier,              unionClause.getIdentifier());
            assertEquals(hasSpaceAfterIdentifier, unionClause.hasSpaceAfterIdentifier());
            assertEquals(hasAll,                  unionClause.hasAll());
            assertEquals(!subquery.isNull(),      unionClause.hasQuery());
            assertEquals(hasSpaceAfterAll,        unionClause.hasSpaceAfterAll());

            subquery.test(unionClause.getQuery());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(identifier);
            if (hasSpaceAfterIdentifier) {
                sb.append(SPACE);
            }
            if (hasAll) {
                sb.append(ALL);
            }
            if (hasSpaceAfterAll) {
                sb.append(SPACE);
            }
            sb.append(subquery);
            return sb.toString();
        }
    }

    public static final class UnknownExpressionTester extends AbstractExpressionTester {

        private final String unknownText;

        protected UnknownExpressionTester(String unknownText) {
            super();
            this.unknownText = unknownText;
        }

        public void test(Expression expression) {
            assertInstance(expression, UnknownExpression.class);

            UnknownExpression unknownExpression = (UnknownExpression) expression;
            assertEquals(toString(), unknownExpression.toParsedText());
        }

        @Override
        public String toString() {
            return unknownText;
        }
    }

    public static final class UpdateClauseTester extends AbstractExpressionTester {

        public boolean hasSet;
        public boolean hasSpaceAfterRangeVariableDeclaration;
        public boolean hasSpaceAfterSet;
        public boolean hasSpaceAfterUpdate;
        private ExpressionTester rangeVariableDeclaration;
        private ExpressionTester updateItems;

        protected UpdateClauseTester(ExpressionTester rangeVariableDeclaration,
                                     ExpressionTester updateItems) {

            super();
            this.hasSet                                = true;
            this.hasSpaceAfterSet                      = true;
            this.hasSpaceAfterUpdate                   = true;
            this.updateItems                           = updateItems;
            this.rangeVariableDeclaration              = rangeVariableDeclaration;
            this.hasSpaceAfterRangeVariableDeclaration = !rangeVariableDeclaration.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, UpdateClause.class);

            UpdateClause updateClause = (UpdateClause) expression;
            assertEquals(toString(),                            updateClause.toParsedText());
            assertEquals(!rangeVariableDeclaration.isNull(),    updateClause.hasRangeVariableDeclaration());
            assertEquals(hasSet,                                updateClause.hasSet());
            assertEquals(hasSpaceAfterSet,                      updateClause.hasSpaceAfterSet());
            assertEquals(hasSpaceAfterUpdate,                   updateClause.hasSpaceAfterUpdate());
            assertEquals(!updateItems.isNull(),                 updateClause.hasUpdateItems());
            assertEquals(hasSpaceAfterRangeVariableDeclaration, updateClause.hasSpaceAfterRangeVariableDeclaration());

            rangeVariableDeclaration.test(updateClause.getRangeVariableDeclaration());
            updateItems.test(updateClause.getUpdateItems());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(UPDATE);
            if (hasSpaceAfterUpdate) {
                sb.append(SPACE);
            }
            sb.append(rangeVariableDeclaration);
            if (hasSpaceAfterRangeVariableDeclaration) {
                sb.append(SPACE);
            }
            if (hasSet) {
                sb.append(SET);
            }
            if (hasSpaceAfterSet) {
                sb.append(SPACE);
            }
            sb.append(updateItems);
            return sb.toString();
        }
    }

    public static final class UpdateItemTester extends AbstractExpressionTester {

        public boolean hasEqualSign;
        public boolean hasSpaceAfterEqualSign;
        public boolean hasSpaceAfterStateFieldPathExpression;
        private ExpressionTester newValue;
        private ExpressionTester stateFieldPathExpression;

        protected UpdateItemTester(ExpressionTester stateFieldPathExpression,
                                   ExpressionTester newValue) {

            super();
            this.stateFieldPathExpression = stateFieldPathExpression;
            this.newValue = newValue;
            this.hasSpaceAfterStateFieldPathExpression = true;
            this.hasSpaceAfterEqualSign = true;
            this.hasEqualSign = true;
        }

        public void test(Expression expression) {
            assertInstance(expression, UpdateItem.class);

            UpdateItem updateItem = (UpdateItem) expression;
            assertEquals(toString(),                            updateItem.toParsedText());
            assertEquals(hasEqualSign,                          updateItem.hasEqualSign());
            assertEquals(!newValue.isNull(),                    updateItem.hasNewValue());
            assertEquals(hasSpaceAfterEqualSign,                updateItem.hasSpaceAfterEqualSign());
            assertEquals(hasSpaceAfterStateFieldPathExpression, updateItem.hasSpaceAfterStateFieldPathExpression());
            assertEquals(!stateFieldPathExpression.isNull(),    updateItem.hasStateFieldPathExpression());

            stateFieldPathExpression.test(updateItem.getStateFieldPathExpression());
            newValue.test(updateItem.getNewValue());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(stateFieldPathExpression);
            if (hasSpaceAfterStateFieldPathExpression) {
                sb.append(SPACE);
            }
            if (hasEqualSign) {
                sb.append(EQUAL);
            }
            if (hasSpaceAfterEqualSign) {
                sb.append(SPACE);
            }
            sb.append(newValue);
            return sb.toString();
        }
    }

    public static final class UpdateStatementTester extends AbstractExpressionTester {

        public boolean hasSpaceAfterUpdateClause;
        private ExpressionTester updateClause;
        private ExpressionTester whereClause;

        protected UpdateStatementTester(ExpressionTester updateClause, ExpressionTester whereClause) {
            super();
            this.updateClause = updateClause;
            this.whereClause  = whereClause;
            this.hasSpaceAfterUpdateClause = !whereClause.isNull();
        }

        public void test(Expression expression) {
            assertInstance(expression, UpdateStatement.class);

            UpdateStatement updateStatement = (UpdateStatement) expression;
            assertEquals(toString(), updateStatement.toParsedText());
            assertEquals(hasSpaceAfterUpdateClause, updateStatement.hasSpaceAfterUpdateClause());
            assertEquals(!whereClause.isNull(),     updateStatement.hasWhereClause());

            updateClause.test(updateStatement.getUpdateClause());
            whereClause .test(updateStatement.getWhereClause());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(updateClause);

            if (hasSpaceAfterUpdateClause) {
                sb.append(SPACE);
            }

            sb.append(whereClause);
            return sb.toString();
        }
    }

    public static final class UpperExpressionTester extends AbstractSingleEncapsulatedExpressionTester {

        protected UpperExpressionTester(ExpressionTester expression) {
            super(expression);
        }

        @Override
        protected Class<? extends AbstractSingleEncapsulatedExpression> expressionType() {
            return UpperExpression.class;
        }

        @Override
        protected String identifier() {
            return UPPER;
        }
    }

    public static final class WhenClauseTester extends AbstractExpressionTester {

        public boolean hasSpaceAfterThen;
        public boolean hasSpaceAfterWhen;
        public boolean hasSpaceAfterWhenExpression;
        public boolean hasThen;
        private ExpressionTester thenExpression;
        private ExpressionTester whenExpression;

        protected WhenClauseTester(ExpressionTester whenExpression, ExpressionTester thenExpression) {
            super();
            this.hasSpaceAfterWhenExpression = true;
            this.hasSpaceAfterThen           = true;
            this.hasSpaceAfterWhen           = true;
            this.hasThen                     = true;
            this.thenExpression              = thenExpression;
            this.whenExpression              = whenExpression;
        }

        public void test(Expression expression) {
            assertInstance(expression, WhenClause.class);

            WhenClause whenClause = (WhenClause) expression;
            assertEquals(toString(),                  whenClause.toParsedText());
            assertEquals(!whenExpression.isNull(),    whenClause.hasWhenExpression());
            assertEquals(hasSpaceAfterWhenExpression, whenClause.hasSpaceAfterWhenExpression());
            assertEquals(hasSpaceAfterThen,           whenClause.hasSpaceAfterThen());
            assertEquals(hasSpaceAfterWhen,           whenClause.hasSpaceAfterWhen());
            assertEquals(hasThen,                     whenClause.hasThen());
            assertEquals(!thenExpression.isNull(),    whenClause.hasThenExpression());

            whenExpression.test(whenClause.getWhenExpression());
            thenExpression.test(whenClause.getThenExpression());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(WHEN);
            if (hasSpaceAfterWhen) {
                sb.append(SPACE);
            }
            sb.append(whenExpression);
            if (hasSpaceAfterWhenExpression) {
                sb.append(SPACE);
            }
            if (hasThen) {
                sb.append(THEN);
            }
            if (hasSpaceAfterWhen) {
                sb.append(SPACE);
            }
            sb.append(thenExpression);
            return sb.toString();
        }
    }

    public static final class WhereClauseTester extends AbstractConditionalClauseTester {

        protected WhereClauseTester(ExpressionTester conditionalExpression) {
            super(conditionalExpression);
        }

        @Override
        protected Class<? extends AbstractConditionalClause> expressionType() {
            return WhereClause.class;
        }

        @Override
        protected String identifier() {
            return WHERE;
        }
    }
}
