/******************************************************************************* * Copyright (c) 2006, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation * ******************************************************************************/ package org.eclipse.persistence.jpa.jpql.tools.model; import static org.eclipse.persistence.jpa.jpql.parser.Expression.AND; import static org.eclipse.persistence.jpa.jpql.parser.Expression.AS; import static org.eclipse.persistence.jpa.jpql.parser.Expression.BETWEEN; import static org.eclipse.persistence.jpa.jpql.parser.Expression.CASE; import static org.eclipse.persistence.jpa.jpql.parser.Expression.COALESCE; import static org.eclipse.persistence.jpa.jpql.parser.Expression.CONCAT; import static org.eclipse.persistence.jpa.jpql.parser.Expression.DELETE; import static org.eclipse.persistence.jpa.jpql.parser.Expression.DISTINCT; import static org.eclipse.persistence.jpa.jpql.parser.Expression.DIVISION; import static org.eclipse.persistence.jpa.jpql.parser.Expression.ELSE; import static org.eclipse.persistence.jpa.jpql.parser.Expression.EMPTY; import static org.eclipse.persistence.jpa.jpql.parser.Expression.END; import static org.eclipse.persistence.jpa.jpql.parser.Expression.EQUAL; import static org.eclipse.persistence.jpa.jpql.parser.Expression.ESCAPE; import static org.eclipse.persistence.jpa.jpql.parser.Expression.EXISTS; import static org.eclipse.persistence.jpa.jpql.parser.Expression.FROM; import static org.eclipse.persistence.jpa.jpql.parser.Expression.FUNC; import static org.eclipse.persistence.jpa.jpql.parser.Expression.GROUP_BY; import static org.eclipse.persistence.jpa.jpql.parser.Expression.HAVING; import static org.eclipse.persistence.jpa.jpql.parser.Expression.IN; import static org.eclipse.persistence.jpa.jpql.parser.Expression.IS; import static org.eclipse.persistence.jpa.jpql.parser.Expression.LIKE; import static org.eclipse.persistence.jpa.jpql.parser.Expression.MEMBER; import static org.eclipse.persistence.jpa.jpql.parser.Expression.MINUS; import static org.eclipse.persistence.jpa.jpql.parser.Expression.MULTIPLICATION; import static org.eclipse.persistence.jpa.jpql.parser.Expression.NEW; import static org.eclipse.persistence.jpa.jpql.parser.Expression.NOT; import static org.eclipse.persistence.jpa.jpql.parser.Expression.NULL; import static org.eclipse.persistence.jpa.jpql.parser.Expression.OF; import static org.eclipse.persistence.jpa.jpql.parser.Expression.OR; import static org.eclipse.persistence.jpa.jpql.parser.Expression.ORDER_BY; import static org.eclipse.persistence.jpa.jpql.parser.Expression.PLUS; import static org.eclipse.persistence.jpa.jpql.parser.Expression.SELECT; import static org.eclipse.persistence.jpa.jpql.parser.Expression.SET; import static org.eclipse.persistence.jpa.jpql.parser.Expression.THEN; import static org.eclipse.persistence.jpa.jpql.parser.Expression.TREAT; import static org.eclipse.persistence.jpa.jpql.parser.Expression.UPDATE; import static org.eclipse.persistence.jpa.jpql.parser.Expression.WHEN; import static org.eclipse.persistence.jpa.jpql.parser.Expression.WHERE; import java.util.ListIterator; import org.eclipse.persistence.jpa.jpql.ExpressionTools; import org.eclipse.persistence.jpa.jpql.parser.AbstractDoubleEncapsulatedExpression; import org.eclipse.persistence.jpa.jpql.parser.AbstractFromClause; 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.AggregateFunction; import org.eclipse.persistence.jpa.jpql.parser.BetweenExpression; import org.eclipse.persistence.jpa.jpql.parser.CaseExpression; import org.eclipse.persistence.jpa.jpql.parser.CoalesceExpression; import org.eclipse.persistence.jpa.jpql.parser.CollectionMemberDeclaration; import org.eclipse.persistence.jpa.jpql.parser.CollectionMemberExpression; import org.eclipse.persistence.jpa.jpql.parser.CompoundExpression; import org.eclipse.persistence.jpa.jpql.parser.ConcatExpression; import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression; import org.eclipse.persistence.jpa.jpql.parser.DateTime; import org.eclipse.persistence.jpa.jpql.parser.DeleteClause; import org.eclipse.persistence.jpa.jpql.parser.EmptyCollectionComparisonExpression; import org.eclipse.persistence.jpa.jpql.parser.EncapsulatedIdentificationVariableExpression; import org.eclipse.persistence.jpa.jpql.parser.ExistsExpression; import org.eclipse.persistence.jpa.jpql.parser.Expression; 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.IdentificationVariableDeclaration; import org.eclipse.persistence.jpa.jpql.parser.InExpression; import org.eclipse.persistence.jpa.jpql.parser.Join; import org.eclipse.persistence.jpa.jpql.parser.KeywordExpression; import org.eclipse.persistence.jpa.jpql.parser.LikeExpression; import org.eclipse.persistence.jpa.jpql.parser.NotExpression; import org.eclipse.persistence.jpa.jpql.parser.NullComparisonExpression; import org.eclipse.persistence.jpa.jpql.parser.OrderByClause; import org.eclipse.persistence.jpa.jpql.parser.OrderByItem; import org.eclipse.persistence.jpa.jpql.parser.RangeVariableDeclaration; 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.SimpleSelectClause; import org.eclipse.persistence.jpa.jpql.parser.TreatExpression; import org.eclipse.persistence.jpa.jpql.parser.TrimExpression; import org.eclipse.persistence.jpa.jpql.parser.UpdateClause; import org.eclipse.persistence.jpa.jpql.parser.UpdateItem; import org.eclipse.persistence.jpa.jpql.parser.WhenClause; import org.eclipse.persistence.jpa.jpql.parser.WhereClause; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbsExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractDoubleEncapsulatedExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractFromClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractIdentificationVariableDeclarationStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractModifyStatementStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractPathExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractRangeVariableDeclarationStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractSchemaNameStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractSelectStatementStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractSingleEncapsulatedExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractTripleEncapsulatedExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AdditionExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AggregateFunctionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AllOrAnyExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AndExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ArithmeticFactorStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AvgFunctionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.BadExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.BetweenExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.CaseExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.CoalesceExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.CollectionMemberDeclarationStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.CollectionMemberExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.CollectionValuedPathExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ComparisonExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.CompoundExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ConcatExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ConstructorExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.CountFunctionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.DateTimeStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.DeleteClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.DeleteStatementStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.DerivedPathIdentificationVariableDeclarationStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.DerivedPathVariableDeclarationStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.DivisionExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.EmptyCollectionComparisonExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.EncapsulatedIdentificationVariableExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.EntityTypeLiteralStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.EntryExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.EnumTypeStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ExistsExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.FromClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.FunctionExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.GroupByClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.HavingClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.IdentificationVariableDeclarationStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.IdentificationVariableStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.InExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.IndexExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.InputParameterStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.JPQLQueryStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.JoinStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.KeyExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.KeywordExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.LengthExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.LikeExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ListHolderStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.LocateExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.LowerExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.MaxFunctionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.MinFunctionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ModExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.MultiplicationExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.NotExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.NullComparisonExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.NullIfExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.NumericLiteralStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ObjectExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.OrExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.OrderByClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.OrderByItemStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.RangeVariableDeclarationStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ResultVariableStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SelectClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SelectStatementStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SimpleFromClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SimpleSelectClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SimpleSelectStatementStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SimpleStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SizeExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SqrtExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.StateFieldPathExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.StateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.StringLiteralStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SubExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SubstringExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SubtractionExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.SumFunctionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.TreatExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.TrimExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.TypeExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.UnknownExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.UpdateClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.UpdateItemStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.UpdateStatementStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.UpperExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.ValueExpressionStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.WhenClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.WhereClauseStateObject; /** * This {@link IJPQLQueryFormatter} is used to generate a string representation of a {@link * StateObject} based on how it was parsed, which means this formatter can only be used when the * {@link StateObject} was created by parsing a JPQL query because it needs to retrieve parsing * information from the corresponding {@link Expression}. * <p> * It is possible to partially match the JPQL query that was parsed, the value of <em>exactMatch</em> * will determine whether the string representation of any given {@link StateObject} should reflect * the exact string that was parsed. <code>true</code> will use every bit of information contained * in the corresponding {@link Expression} to perfectly match what was parsed (case of JPQL * identifiers and the presence of whitespace); <code>false</code> will only match the case * sensitivity of the JPQL identifiers. * * @version 2.5 * @since 2.4 * @author Pascal Filion */ @SuppressWarnings("null") public abstract class AbstractActualJPQLQueryFormatter extends BaseJPQLQueryFormatter { /** * Determines whether the string representation of any given {@link StateObject} should reflect * the exact string that was parsed: <code>true</code> will use every bit of information * contained in the corresponding {@link Expression} to perfectly match what was parsed; * <code>false</code> will only match the case sensitivity of the JPQL identifiers. */ protected final boolean exactMatch; /** * Creates a new <code>AbstractActualJPQLQueryFormatter</code>. * * @param exactMatch Determines whether the string representation of any given {@link StateObject} * should reflect the exact string that was parsed: <code>true</code> will use every bit of * information contained in the corresponding {@link Expression} to perfectly match what was * parsed (case of JPQL identifiers and the presence of whitespace); <code>false</code> will only * match the case sensitivity of the JPQL identifiers */ protected AbstractActualJPQLQueryFormatter(boolean exactMatch) { super(IdentifierStyle.UPPERCASE); this.exactMatch = exactMatch; } /** * Creates a new <code>AbstractActualJPQLQueryFormatter</code>. * * @param exactMatch Determines whether the string representation of any given {@link StateObject} * should reflect the exact string that was parsed: <code>true</code> will use every bit of * information contained in the corresponding {@link Expression} to perfectly match what was * parsed (case of JPQL identifiers and the presence of whitespace); <code>false</code> will only * match the case sensitivity of the JPQL identifiers * @param style Determines how the JPQL identifiers are written out, which is used if the * {@link StateObject} was modified after its creation * @exception NullPointerException The IdentifierStyle cannot be <code>null</code> */ protected AbstractActualJPQLQueryFormatter(boolean exactMatch, IdentifierStyle style) { super(style); this.exactMatch = exactMatch; } /** * Appends the given actual identifier if it's not an empty string, otherwise the second * identifier will be appended. * * @param actualIdentifier The actual JPQL identifier to append to the writer if it's not an * empty string * @param identifier The uppercase constant of the JPQL identifier to append if the actual one is * an empty string */ protected void appendIdentifier(String actualIdentifier, String identifier) { if (!exactMatch || ExpressionTools.stringIsEmpty(actualIdentifier)) { actualIdentifier = formatIdentifier(identifier); } writer.append(actualIdentifier); } /** * Determines whether the string representation of any given {@link StateObject} should reflect * the exact string that was parsed. * * @return <code>true</code> will use every bit of information contained in the corresponding * {@link Expression} to perfectly match what was parsed; <code>false</code> will only match the * case sensitivity of the JPQL identifiers */ public boolean isUsingExactMatch() { return exactMatch; } protected boolean shouldOutput(Expression expression) { return !exactMatch || (expression == null); } protected void toStringAggregateFunction(AggregateFunctionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { AggregateFunction expression = stateObject.getExpression(); // Identifier appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getIdentifier(), stateObject.getIdentifier()); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(formatIdentifier(LEFT_PARENTHESIS)); } // 'DISTINCT' if (stateObject.hasDistinct()) { appendIdentifier((expression != null) ? expression.getActualDistinctIdentifier() : DISTINCT, DISTINCT); if (shouldOutput(expression) || expression.hasSpaceAfterDistinct()) { writer.append(SPACE); } } // Encapsulated expression if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); } // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(formatIdentifier(RIGHT_PARENTHESIS)); } } } protected void toStringChildren(ListHolderStateObject<? extends StateObject> stateObject, boolean comma) { for (ListIterator<? extends StateObject> iter = stateObject.items().iterator(); iter.hasNext(); ) { iter.next().accept(this); if (iter.hasNext()) { writer.append(comma ? COMMA_SPACE : SPACE); } } } protected void toStringCompound(CompoundExpressionStateObject stateObject, String identifier) { if (stateObject.isDecorated()) { toText(stateObject); } else { CompoundExpression expression = stateObject.getExpression(); // Left expression if (stateObject.hasLeft()) { stateObject.getLeft().accept(this); writer.append(SPACE); } // Identifier appendIdentifier((expression != null) ? expression.getActualIdentifier() : identifier, identifier); if (shouldOutput(expression) || expression.hasSpaceAfterIdentifier()) { writer.append(SPACE); } // Right expression if (stateObject.hasRight()) { stateObject.getRight().accept(this); } } } protected void toStringDoubleEncapsulated(AbstractDoubleEncapsulatedExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { AbstractDoubleEncapsulatedExpression expression = stateObject.getExpression(); // Identifier appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getIdentifier(), stateObject.getIdentifier()); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } else if (expression.hasSpaceAfterIdentifier()) { writer.append(COMMA); } // First expression if (stateObject.hasFirst()) { stateObject.getFirst().accept(this); } // ',' if (shouldOutput(expression) || expression.hasComma()) { writer.append(COMMA); } if (shouldOutput(expression) || expression.hasSpaceAfterComma()) { writer.append(SPACE); } // Second expression if (stateObject.hasSecond()) { stateObject.getSecond().accept(this); } // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } protected void toStringEncapsulatedIdentificationVariable(EncapsulatedIdentificationVariableExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { EncapsulatedIdentificationVariableExpression expression = stateObject.getExpression(); // Identifier appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getIdentifier(), stateObject.getIdentifier()); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } // Identification variable if (stateObject.hasIdentificationVariable()) { writer.append(stateObject.getIdentificationVariable()); } // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } protected void toStringFromClause(AbstractFromClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { AbstractFromClause expression = stateObject.getExpression(); // 'FROM' appendIdentifier((expression != null) ? expression.getActualIdentifier() : FROM, FROM); if (shouldOutput(expression) || expression.hasSpaceAfterFrom()) { writer.append(SPACE); } // declaration if (stateObject.hasItems()) { toStringChildren(stateObject, true); } } } protected void toStringIdentificationVariableDeclaration(AbstractIdentificationVariableDeclarationStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { IdentificationVariableDeclaration expression = stateObject.getExpression(); // Range variable declaration stateObject.getRangeVariableDeclaration().accept(this); // Join | Join Fetch if (stateObject.hasItems()) { if (shouldOutput(expression) || expression.hasSpace()) { writer.append(SPACE); } toStringChildren(stateObject, false); } } } protected void toStringModifyStatement(AbstractModifyStatementStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { stateObject.getModifyClause().accept(this); if (stateObject.hasWhereClause()) { // TODO: HANDLE SPACE writer.append(SPACE); stateObject.getWhereClause().accept(this); } } } protected void toStringPathExpression(AbstractPathExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { stateObject.toText(writer); } } protected void toStringRangeVariableDeclaration(AbstractRangeVariableDeclarationStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { RangeVariableDeclaration expression = stateObject.getExpression(); // "Root" object (abstract schema name or derived declaration) stateObject.getRootStateObject().accept(this); if (exactMatch && (expression != null) && expression.hasSpaceAfterRootObject()) { writer.append(SPACE); } // 'AS' if (stateObject.hasAs()) { if (!exactMatch || (expression == null)) { writer.append(SPACE); } appendIdentifier((expression != null) ? expression.getActualAsIdentifier() : AS, AS); } if (exactMatch && (expression != null) && expression.hasSpaceAfterAs()) { writer.append(SPACE); } // Identification variable if (stateObject.hasIdentificationVariable() && !stateObject.isIdentificationVariableVirtual()) { if (!exactMatch || (expression == null)) { writer.append(SPACE); } writer.append(stateObject.getIdentificationVariable()); } } } protected boolean toStringSelectStatement(AbstractSelectStatementStateObject stateObject) { AbstractSelectStatement expression = stateObject.getExpression(); boolean spaceAdded = false; // SELECT clause stateObject.getSelectClause().accept(this); // If no select items were parsed but they got added later, make sure a space is added if (shouldOutput(expression) || expression.hasSpaceAfterSelect() || // TODO (/*!expression.getSelectClause().hasSelectExpression() &&*/ stateObject.getSelectClause().hasSelectItem())) { writer.append(SPACE); } // FROM clause stateObject.getFromClause().accept(this); // If no WHERE clause was parsed but was added later, make sure a space is added if (exactMatch && (expression != null) && expression.hasSpaceAfterFrom() || stateObject.hasWhereClause()) { writer.append(SPACE); spaceAdded = true; } // WHERE clause if (stateObject.hasWhereClause()) { stateObject.getWhereClause().accept(this); spaceAdded = false; } // If no GROUP BY clause was parsed but was added later, make sure a space is added if (exactMatch && (expression != null) && expression.hasSpaceAfterWhere() || stateObject.hasGroupByClause()) { if (!spaceAdded) { writer.append(SPACE); spaceAdded = true; } } // GROUP BY clause if (stateObject.hasGroupByClause()) { stateObject.getGroupByClause().accept(this); spaceAdded = false; } // If no HAVING clause was parsed but was added later, make sure a space is added if (exactMatch && (expression != null) && expression.hasSpaceAfterGroupBy() || stateObject.hasHavingClause()) { if (!spaceAdded) { writer.append(SPACE); spaceAdded = true; } } // HAVING clause if (stateObject.hasHavingClause()) { stateObject.getHavingClause().accept(this); spaceAdded = true; } return spaceAdded; } protected void toStringSimpleStateObject(SimpleStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else if (stateObject.hasText()) { writer.append(stateObject.getText()); } } protected void toStringSingleEncapsulated(AbstractSingleEncapsulatedExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { AbstractSingleEncapsulatedExpression expression = stateObject.getExpression(); // Identifier appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getIdentifier(), stateObject.getIdentifier()); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); } // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } protected void toStringTripleEncapsulated(AbstractTripleEncapsulatedExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { AbstractTripleEncapsulatedExpression expression = stateObject.getExpression(); // Identifier appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getIdentifier(), stateObject.getIdentifier()); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } // First expression if (stateObject.hasFirst()) { stateObject.getFirst().accept(this); } if (shouldOutput(expression) || expression.hasFirstComma()) { writer.append(COMMA); } if (shouldOutput(expression) || expression.hasSpaceAfterFirstComma()) { writer.append(SPACE); } // Second expression if (stateObject.hasSecond()) { stateObject.getSecond().accept(this); } // Third expression if (stateObject.hasThird()) { if (shouldOutput(expression) || expression.hasSecondComma()) { writer.append(COMMA); } if (shouldOutput(expression) || expression.hasSpaceAfterSecondComma()) { writer.append(SPACE); } stateObject.getThird().accept(this); } // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } /** * {@inheritDoc} */ @Override public void visit(AbsExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(AbstractSchemaNameStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(AdditionExpressionStateObject stateObject) { toStringCompound(stateObject, PLUS); } /** * {@inheritDoc} */ @Override public void visit(AllOrAnyExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(AndExpressionStateObject stateObject) { toStringCompound(stateObject, AND); } /** * {@inheritDoc} */ @Override public void visit(ArithmeticFactorStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { writer.append(stateObject.getArithmeticSign()); if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(AvgFunctionStateObject stateObject) { toStringAggregateFunction(stateObject); } /** * {@inheritDoc} */ @Override public void visit(BadExpressionStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(BetweenExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { BetweenExpression expression = stateObject.getExpression(); // Expression if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); writer.append(SPACE); } // 'NOT if (stateObject.hasNot()) { appendIdentifier((expression != null) ? expression.getActualNotIdentifier() : NOT, NOT); writer.append(SPACE); } // 'BETWEEN' appendIdentifier((expression != null) ? expression.getActualBetweenIdentifier() : BETWEEN, BETWEEN); if (shouldOutput(expression) || expression.hasSpaceAfterBetween()) { writer.append(SPACE); } // Lower bound expression if (stateObject.hasLowerBound()) { stateObject.getLowerBound().accept(this); } if (shouldOutput(expression) || expression.hasSpaceAfterLowerBound()) { writer.append(SPACE); } // 'AND' if (shouldOutput(expression) || expression.hasAnd()) { appendIdentifier((expression != null) ? expression.getActualAndIdentifier() : AND, AND); } if (shouldOutput(expression) || expression.hasSpaceAfterAnd()) { writer.append(SPACE); } // Upper bound expression if (stateObject.hasUpperBound()) { stateObject.getUpperBound().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(CaseExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { CaseExpression expression = stateObject.getExpression(); // 'CASE' appendIdentifier((expression != null) ? expression.getActualCaseIdentifier() : CASE, CASE); if (shouldOutput(expression) || expression.hasSpaceAfterCase()) { writer.append(SPACE); } // Case operand if (stateObject.hasCaseOperand()) { stateObject.getCaseOperand().accept(this); if (shouldOutput(expression) || expression.hasSpaceAfterCaseOperand()) { writer.append(SPACE); } } // WHEN clauses if (stateObject.hasItems()) { toStringChildren(stateObject, false); } if (shouldOutput(expression) || expression.hasSpaceAfterWhenClauses()) { writer.append(SPACE); } // 'ELSE' if (shouldOutput(expression) || expression.hasElse()) { appendIdentifier((expression != null) ? expression.getActualElseIdentifier() : ELSE, ELSE); } if (shouldOutput(expression) || expression.hasSpaceAfterElse()) { writer.append(SPACE); } // Else expression if (stateObject.hasElse()) { stateObject.getElse().accept(this); } if (shouldOutput(expression) || expression.hasSpaceAfterElseExpression()) { writer.append(SPACE); } // END if (shouldOutput(expression) || expression.hasEnd()) { appendIdentifier((expression != null) ? expression.getActualEndIdentifier() : END, END); } } } /** * {@inheritDoc} */ @Override public void visit(CoalesceExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { CoalesceExpression expression = stateObject.getExpression(); // 'COALESCE' appendIdentifier((expression != null) ? expression.getActualIdentifier() : COALESCE, COALESCE); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } else if (expression.hasSpaceAfterIdentifier()) { writer.append(SPACE); } toStringChildren(stateObject, true); // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } /** * {@inheritDoc} */ @Override public void visit(CollectionMemberDeclarationStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { CollectionMemberDeclaration expression = stateObject.getExpression(); // 'IN' appendIdentifier((expression != null) ? expression.getActualInIdentifier() : IN, IN); // '(' if (!stateObject.isDerived() && (shouldOutput(expression) || expression.hasLeftParenthesis())) { writer.append(LEFT_PARENTHESIS); } else if (stateObject.isDerived() && (shouldOutput(expression) || expression.hasSpaceAfterIn())) { writer.append(SPACE); } // Collection-valued path expression stateObject.getCollectionValuedPath().accept(this); // ')' if (!stateObject.isDerived() && (shouldOutput(expression) || expression.hasRightParenthesis())) { writer.append(RIGHT_PARENTHESIS); if (shouldOutput(expression) || expression.hasSpaceAfterRightParenthesis()) { writer.append(SPACE); } } else if (stateObject.isDerived() && stateObject.hasAs() && (shouldOutput(expression) || expression.hasSpaceAfterRightParenthesis())) { writer.append(SPACE); } // 'AS' if (stateObject.hasAs()) { appendIdentifier((expression != null) ? expression.getActualAsIdentifier() : AS, AS); if (shouldOutput(expression) || expression.hasSpaceAfterAs()) { writer.append(SPACE); } } // Identification variable if (stateObject.hasIdentificationVariable()) { stateObject.getIdentificationVariable().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(CollectionMemberExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { CollectionMemberExpression expression = stateObject.getExpression(); // Entity or value expression if (stateObject.hasEntityStateObject()) { stateObject.getEntityStateObject().accept(this); writer.append(SPACE); } // 'NOT' if (stateObject.hasNot()) { appendIdentifier((expression != null) ? expression.getActualNotIdentifier() : NOT, NOT); writer.append(SPACE); } // 'MEMBER' appendIdentifier((expression != null) ? expression.getActualMemberIdentifier() : MEMBER, MEMBER); if (shouldOutput(expression) || expression.hasSpaceAfterMember()) { writer.append(SPACE); } // 'OF' if (stateObject.hasOf()) { appendIdentifier((expression != null) ? expression.getActualOfIdentifier() : OF, OF); if (shouldOutput(expression) || expression.hasSpaceAfterOf()) { writer.append(SPACE); } } // Collection-valued path expression stateObject.getCollectionValuedPath().accept(this); } } /** * {@inheritDoc} */ @Override public void visit(CollectionValuedPathExpressionStateObject stateObject) { toStringPathExpression(stateObject); } /** * {@inheritDoc} */ @Override public void visit(ComparisonExpressionStateObject stateObject) { toStringCompound(stateObject, stateObject.getIdentifier()); } /** * {@inheritDoc} */ @Override public void visit(ConcatExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { ConcatExpression expression = stateObject.getExpression(); // 'CONCAT' appendIdentifier((expression != null) ? expression.getActualIdentifier() : CONCAT, CONCAT); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } toStringChildren(stateObject, true); // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } /** * {@inheritDoc} */ @Override public void visit(ConstructorExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { ConstructorExpression expression = stateObject.getExpression(); // 'NEW' appendIdentifier((expression != null) ? expression.getActualIdentifier() : NEW, NEW); if (shouldOutput(expression) || expression.hasSpaceAfterNew()) { writer.append(SPACE); } // Class name writer.append(stateObject.getClassName()); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } toStringChildren(stateObject, true); // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } /** * {@inheritDoc} */ @Override public void visit(CountFunctionStateObject stateObject) { toStringAggregateFunction(stateObject); } /** * {@inheritDoc} */ @Override public void visit(DateTimeStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { DateTime expression = stateObject.getExpression(); appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getText(), stateObject.getText()); } } /** * {@inheritDoc} */ @Override public void visit(DeleteClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { DeleteClause expression = stateObject.getExpression(); // 'DELETE' appendIdentifier((expression != null) ? expression.getActualDeleteIdentifier() : DELETE, DELETE); if (shouldOutput(expression) || expression.hasSpaceAfterDelete()) { writer.append(SPACE); } // 'FROM' if (shouldOutput(expression) || expression.hasFrom()) { appendIdentifier((expression != null) ? expression.getActualFromIdentifier() : FROM, FROM); } if (shouldOutput(expression) || expression.hasSpaceAfterFrom()) { writer.append(SPACE); } // Range variable declaration stateObject.getRangeVariableDeclaration().accept(this); } } /** * {@inheritDoc} */ @Override public void visit(DeleteStatementStateObject stateObject) { toStringModifyStatement(stateObject); } /** * {@inheritDoc} */ @Override public void visit(DerivedPathIdentificationVariableDeclarationStateObject stateObject) { toStringIdentificationVariableDeclaration(stateObject); } /** * {@inheritDoc} */ @Override public void visit(DerivedPathVariableDeclarationStateObject stateObject) { toStringRangeVariableDeclaration(stateObject); } /** * {@inheritDoc} */ @Override public void visit(DivisionExpressionStateObject stateObject) { toStringCompound(stateObject, DIVISION); } /** * {@inheritDoc} */ @Override public void visit(EmptyCollectionComparisonExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { EmptyCollectionComparisonExpression expression = stateObject.getExpression(); stateObject.getStateObject().accept(this); writer.append(SPACE); // 'IS' appendIdentifier((expression != null) ? expression.getActualIsIdentifier() : IS, IS); writer.append(SPACE); // 'NOT' if (stateObject.hasNot()) { appendIdentifier((expression != null) ? expression.getActualNotIdentifier() : NOT, NOT); writer.append(SPACE); } // 'EMPTY' appendIdentifier((expression != null) ? expression.getActualEmptyIdentifier() : EMPTY, EMPTY); } } /** * {@inheritDoc} */ @Override public void visit(EntityTypeLiteralStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(EntryExpressionStateObject stateObject) { toStringEncapsulatedIdentificationVariable(stateObject); } /** * {@inheritDoc} */ @Override public void visit(EnumTypeStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(ExistsExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { ExistsExpression expression = stateObject.getExpression(); // 'NOT' if (stateObject.hasNot()) { appendIdentifier((expression != null) ? expression.getActualNotIdentifier() : NOT, NOT); writer.append(SPACE); } // 'EXISTS' String actualIdentifier = (expression != null) ? expression.getActualIdentifier() : null; if ((actualIdentifier != null) && actualIdentifier.startsWith(NOT)) { actualIdentifier = actualIdentifier.substring(4); } appendIdentifier(actualIdentifier, EXISTS); // '(' if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(formatIdentifier(LEFT_PARENTHESIS)); } // Subquery if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); } // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(formatIdentifier(RIGHT_PARENTHESIS)); } } } /** * {@inheritDoc} */ @Override public void visit(FromClauseStateObject stateObject) { toStringFromClause(stateObject); } /** * {@inheritDoc} */ @Override public void visit(FunctionExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { FunctionExpression expression = stateObject.getExpression(); // FUNC appendIdentifier((expression != null) ? expression.getActualIdentifier() : FUNC, FUNC); // ( if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } else if (exactMatch && expression.hasSpaceAfterIdentifier()) { writer.append(SPACE); } // Function name if (stateObject.hasFunctionName()) { writer.append(stateObject.getQuotedFunctionName()); if (shouldOutput(expression) || expression.hasComma()) { writer.append(COMMA); } if (shouldOutput(expression) || expression.hasSpaceAfterComma()) { writer.append(SPACE); } } // Arguments toStringChildren(stateObject, true); // ) if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } /** * {@inheritDoc} */ @Override public void visit(GroupByClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { GroupByClause expression = stateObject.getExpression(); // 'GROUP BY' appendIdentifier((expression != null) ? expression.getActualIdentifier() : GROUP_BY, GROUP_BY); if (shouldOutput(expression) || expression.hasSpaceAfterGroupBy()) { writer.append(SPACE); } // Group by items if (stateObject.hasItems()) { toStringChildren(stateObject, true); } } } /** * {@inheritDoc} */ @Override public void visit(HavingClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { HavingClause expression = stateObject.getExpression(); // 'HAVING' appendIdentifier((expression != null) ? expression.getActualIdentifier() : HAVING, HAVING); if (exactMatch && (expression != null) && expression.hasSpaceAfterIdentifier() || stateObject.hasConditional()) { writer.append(SPACE); } // Conditional expression if (stateObject.hasConditional()) { stateObject.getConditional().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariableDeclarationStateObject stateObject) { toStringIdentificationVariableDeclaration(stateObject); } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariableStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(IndexExpressionStateObject stateObject) { toStringEncapsulatedIdentificationVariable(stateObject); } /** * {@inheritDoc} */ @Override public void visit(InExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { InExpression expression = stateObject.getExpression(); if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); writer.append(SPACE); } // 'NOT' if (stateObject.hasNot()) { appendIdentifier((expression != null) ? expression.getActualNotIdentifier() : NOT, NOT); writer.append(SPACE); } // 'IN' appendIdentifier((expression != null) ? expression.getActualInIdentifier() : IN, IN); if (!stateObject.isSingleInputParameter()) { writer.append(LEFT_PARENTHESIS); } else if (shouldOutput(expression) || expression.hasSpaceAfterIn()) { writer.append(SPACE); } if (stateObject.hasItems()) { toStringChildren(stateObject, true); } if (!stateObject.isSingleInputParameter()) { writer.append(RIGHT_PARENTHESIS); } } } /** * {@inheritDoc} */ @Override public void visit(InputParameterStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(JoinStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { Join expression = stateObject.getExpression(); // JOIN appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getJoinType(), stateObject.getJoinType()); if (shouldOutput(expression) || expression.hasSpaceAfterJoin()) { writer.append(SPACE); } // Join association path stateObject.getJoinAssociationPathStateObject().accept(this); // Check first if the JOIN FETCH is allowed to have an identification variable if (stateObject.hasFetch()) { if (expression.hasAs()) { writer.append(SPACE); } } // JOIN always needs a whitespace else { if (shouldOutput(expression) || expression.hasSpaceAfterJoinAssociation()) { writer.append(SPACE); } } // AS if (stateObject.hasAs()) { appendIdentifier((expression != null) ? expression.getActualAsIdentifier() : AS, AS); if (shouldOutput(expression) || expression.hasSpaceAfterAs()) { writer.append(SPACE); } } // Identification variable stateObject.getIdentificationVariableStateObject().accept(this); } } /** * {@inheritDoc} */ @Override public void visit(JPQLQueryStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else if (stateObject.hasQueryStatement()) { stateObject.getQueryStatement().accept(this); } } /** * {@inheritDoc} */ @Override public void visit(KeyExpressionStateObject stateObject) { toStringEncapsulatedIdentificationVariable(stateObject); } /** * {@inheritDoc} */ @Override public void visit(KeywordExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { KeywordExpression expression = stateObject.getExpression(); appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getText(), stateObject.getText()); } } /** * {@inheritDoc} */ @Override public void visit(LengthExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(LikeExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { LikeExpression expression = stateObject.getExpression(); // String expression if (stateObject.hasStringStateObject()) { stateObject.getStringStateObject().accept(this); } if (shouldOutput(expression) || expression.hasSpaceAfterStringExpression()) { writer.append(SPACE); } // 'NOT' if (stateObject.hasNot()) { appendIdentifier((expression != null) ? expression.getActualNotIdentifier() : NOT, NOT); writer.append(SPACE); } // 'LIKE' appendIdentifier((expression != null) ? expression.getActualLikeIdentifier() : LIKE, LIKE); if (shouldOutput(expression) || expression.hasSpaceAfterLike()) { writer.append(SPACE); } // Pattern value if (stateObject.hasPatternValue()) { stateObject.getPatternValue().accept(this); } if (exactMatch && (expression != null) && expression.hasSpaceAfterPatternValue()) { writer.append(SPACE); } // Escape character if (stateObject.hasEscapeCharacter()) { if (!exactMatch) { writer.append(SPACE); } appendIdentifier((expression != null) ? expression.getActualEscapeIdentifier() : ESCAPE, ESCAPE); if (shouldOutput(expression) || expression.hasSpaceAfterEscape()) { writer.append(SPACE); } writer.append(stateObject.getEscapeCharacter()); } } } /** * {@inheritDoc} */ @Override public void visit(LocateExpressionStateObject stateObject) { toStringTripleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(LowerExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(MaxFunctionStateObject stateObject) { toStringAggregateFunction(stateObject); } /** * {@inheritDoc} */ @Override public void visit(MinFunctionStateObject stateObject) { toStringAggregateFunction(stateObject); } /** * {@inheritDoc} */ @Override public void visit(ModExpressionStateObject stateObject) { toStringDoubleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(MultiplicationExpressionStateObject stateObject) { toStringCompound(stateObject, MULTIPLICATION); } /** * {@inheritDoc} */ @Override public void visit(NotExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { NotExpression expression = stateObject.getExpression(); // 'NOT' appendIdentifier((expression != null) ? expression.getActualIdentifier() : NOT, NOT); if (shouldOutput(expression) || expression.hasSpaceAfterNot()) { writer.append(SPACE); } // Expression if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(NullComparisonExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { NullComparisonExpression expression = stateObject.getExpression(); // Expression if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); writer.append(SPACE); } // 'IS' appendIdentifier((expression != null) ? expression.getActualIsIdentifier() : IS, IS); writer.append(SPACE); // 'NOT' if (stateObject.hasNot()) { appendIdentifier((expression != null) ? expression.getActualNotIdentifier() : NOT, NOT); writer.append(SPACE); } // 'NULL' appendIdentifier((expression != null) ? expression.getActualNullIdentifier() : NULL, NULL); } } /** * {@inheritDoc} */ @Override public void visit(NullIfExpressionStateObject stateObject) { toStringDoubleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(NumericLiteralStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(ObjectExpressionStateObject stateObject) { toStringEncapsulatedIdentificationVariable(stateObject); } /** * {@inheritDoc} */ @Override public void visit(OrderByClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { OrderByClause expression = stateObject.getExpression(); // 'ORDER BY' appendIdentifier((expression != null) ? expression.getActualIdentifier() : ORDER_BY, ORDER_BY); if (shouldOutput(expression) || expression.hasSpaceAfterIdentifier()) { writer.append(SPACE); } // Order by items if (stateObject.hasItems()) { toStringChildren(stateObject, true); } } } /** * {@inheritDoc} */ @Override public void visit(OrderByItemStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { OrderByItem expression = stateObject.getExpression(); // Order by item if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); } // ASC/DESC if (!stateObject.isDefault()) { if (shouldOutput(expression) || expression.hasSpaceAfterExpression()) { writer.append(SPACE); } String ordering = stateObject.getOrdering().name(); String actualOrdering = (expression != null) ? expression.getActualOrdering() : null; if (!ordering.equalsIgnoreCase(actualOrdering)) { actualOrdering = ordering; } appendIdentifier(actualOrdering, ordering); } } } /** * {@inheritDoc} */ @Override public void visit(OrExpressionStateObject stateObject) { toStringCompound(stateObject, OR); } /** * {@inheritDoc} */ @Override public void visit(RangeVariableDeclarationStateObject stateObject) { toStringRangeVariableDeclaration(stateObject); } /** * {@inheritDoc} */ @Override public void visit(ResultVariableStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { ResultVariable expression = stateObject.getExpression(); // Select expression if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); } if (exactMatch && (expression != null) && expression.hasSelectExpression()) { writer.append(SPACE); } // 'AS' if (stateObject.hasAs()) { if (!exactMatch || (expression == null)) { writer.append(SPACE); } appendIdentifier((expression != null) ? expression.getActualAsIdentifier() : AS, AS); } if (exactMatch && (expression != null) && expression.hasSpaceAfterAs()) { writer.append(SPACE); } // Result variable if (stateObject.hasResultVariable()) { if (!exactMatch || (expression == null)) { writer.append(SPACE); } writer.append(stateObject.getResultVariable()); } } } /** * {@inheritDoc} */ @Override public void visit(SelectClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { SelectClause expression = stateObject.getExpression(); // SELECT appendIdentifier((expression != null) ? expression.getActualIdentifier() : SELECT, SELECT); if (shouldOutput(expression) || expression.hasSpaceAfterSelect()) { writer.append(SPACE); } // DISTINCT if (stateObject.hasDistinct()) { appendIdentifier((expression != null) ? expression.getActualDistinctIdentifier() : DISTINCT, DISTINCT); if (shouldOutput(expression) || expression.hasSpaceAfterDistinct()) { writer.append(SPACE); } } // Select expressions if (stateObject.hasItems()) { toStringChildren(stateObject, true); } } } /** * {@inheritDoc} */ @Override public void visit(SelectStatementStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { boolean endWithSpace = toStringSelectStatement(stateObject); SelectStatement expression = stateObject.getExpression(); // If no ORDER BY clause was parsed but was added later, make sure a space is added if (exactMatch && (expression != null) && expression.hasSpaceBeforeOrderBy() || stateObject.hasOrderByClause()) { if (!endWithSpace) { writer.append(SPACE); } } // ORDER BY clause if (stateObject.hasOrderByClause()) { stateObject.getOrderByClause().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(SimpleFromClauseStateObject stateObject) { toStringFromClause(stateObject); } /** * {@inheritDoc} */ @Override public void visit(SimpleSelectClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { SimpleSelectClause expression = stateObject.getExpression(); // SELECT appendIdentifier((expression != null) ? expression.getActualIdentifier() : SELECT, SELECT); if (shouldOutput(expression) || expression.hasSpaceAfterSelect()) { writer.append(SPACE); } // DISTINCT if (stateObject.hasDistinct()) { appendIdentifier((expression != null) ? expression.getActualDistinctIdentifier() : DISTINCT, DISTINCT); if (shouldOutput(expression) || expression.hasSpaceAfterDistinct()) { writer.append(SPACE); } } // Select expression if (stateObject.hasSelectItem()) { stateObject.getSelectItem().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(SimpleSelectStatementStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { toStringSelectStatement(stateObject); } } /** * {@inheritDoc} */ @Override public void visit(SizeExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(SqrtExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(StateFieldPathExpressionStateObject stateObject) { toStringPathExpression(stateObject); } /** * {@inheritDoc} */ @Override public void visit(StringLiteralStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(SubExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(SubstringExpressionStateObject stateObject) { toStringTripleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(SubtractionExpressionStateObject stateObject) { toStringCompound(stateObject, MINUS); } /** * {@inheritDoc} */ @Override public void visit(SumFunctionStateObject stateObject) { toStringAggregateFunction(stateObject); } /** * {@inheritDoc} */ @Override public void visit(TreatExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { TreatExpression expression = stateObject.getExpression(); // TREAT appendIdentifier((expression != null) ? expression.getActualIdentifier() : TREAT, TREAT); // ( if (shouldOutput(expression) || expression.hasLeftParenthesis()) { writer.append(LEFT_PARENTHESIS); } // Join association path expression stateObject.getJoinAssociationPathStateObject().accept(this); if (shouldOutput(expression) || expression.hasSpaceAfterCollectionValuedPathExpression()) { writer.append(SPACE); } // AS if (stateObject.hasAs()) { appendIdentifier((expression != null) ? expression.getActualAsIdentifier() : AS, AS); if (shouldOutput(expression) || expression.hasSpaceAfterAs()) { writer.append(SPACE); } } // Entity type name writer.append(stateObject.getEntityTypeName()); // ) if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } /** * {@inheritDoc} */ @Override public void visit(TrimExpressionStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { TrimExpression expression = stateObject.getExpression(); // 'TRIM' appendIdentifier((expression != null) ? expression.getActualIdentifier() : stateObject.getIdentifier(), stateObject.getIdentifier()); // '(' if (shouldOutput(expression) || ( expression != null && expression.hasLeftParenthesis())) { writer.append(LEFT_PARENTHESIS); } else if ((expression != null) && expression.hasSpaceAfterIdentifier()) { writer.append(SPACE); } // Trim specification if (stateObject.hasSpecification()) { String specification = stateObject.getSpecification().name(); String actualSpecification = (expression != null) ? expression.getActualSpecificationIdentifier() : null; if (!specification.equalsIgnoreCase(actualSpecification)) { actualSpecification = specification; } appendIdentifier(actualSpecification, specification); } if (shouldOutput(expression) || expression.hasSpaceAfterSpecification()) { writer.append(SPACE); } // Trim character if (stateObject.hasTrimCharacter()) { stateObject.getTrimCharacter().accept(this); if (shouldOutput(expression) || expression.hasSpaceAfterTrimCharacter()) { writer.append(SPACE); } } // 'FROM' if (stateObject.hasSpecification() || stateObject.hasTrimCharacter()) { appendIdentifier((expression != null) ? expression.getActualFromIdentifier() : FROM, FROM); if (shouldOutput(expression) || expression.hasSpaceAfterFrom()) { writer.append(SPACE); } } // String primary if (stateObject.hasStateObject()) { stateObject.getStateObject().accept(this); } // ')' if (shouldOutput(expression) || expression.hasRightParenthesis()) { writer.append(RIGHT_PARENTHESIS); } } } /** * {@inheritDoc} */ @Override public void visit(TypeExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(UnknownExpressionStateObject stateObject) { toStringSimpleStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(UpdateClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { UpdateClause expression = stateObject.getExpression(); // 'UPDATE' appendIdentifier((expression != null) ? expression.getActualUpdateIdentifier() : UPDATE, UPDATE); if (shouldOutput(expression) || expression.hasSpaceAfterUpdate()) { writer.append(SPACE); } // Range variable declaration stateObject.getRangeVariableDeclaration().accept(this); if (shouldOutput(expression) || expression.hasSpaceAfterRangeVariableDeclaration()) { writer.append(SPACE); } // 'SET' if (shouldOutput(expression) || expression.hasSet()) { appendIdentifier((expression != null) ? expression.getActualSetIdentifier() : SET, SET); if (shouldOutput(expression) || expression.hasSpaceAfterSet()) { writer.append(SPACE); } } // Update items if (stateObject.hasItems()) { toStringChildren(stateObject, true); } } } /** * {@inheritDoc} */ @Override public void visit(UpdateItemStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { UpdateItem expression = stateObject.getExpression(); // Update item stateObject.getStateFieldPath().accept(this); if (shouldOutput(expression) || expression.hasSpaceAfterStateFieldPathExpression()) { writer.append(SPACE); } // '=' if (shouldOutput(expression) || expression.hasEqualSign()) { writer.append(EQUAL); } if (shouldOutput(expression) || expression.hasSpaceAfterEqualSign()) { writer.append(SPACE); } // New value if (stateObject.hasNewValue()) { stateObject.getNewValue().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(UpdateStatementStateObject stateObject) { toStringModifyStatement(stateObject); } /** * {@inheritDoc} */ @Override public void visit(UpperExpressionStateObject stateObject) { toStringSingleEncapsulated(stateObject); } /** * {@inheritDoc} */ @Override public void visit(ValueExpressionStateObject stateObject) { toStringEncapsulatedIdentificationVariable(stateObject); } /** * {@inheritDoc} */ @Override public void visit(WhenClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { WhenClause expression = stateObject.getExpression(); // 'WHEN' appendIdentifier((expression != null) ? expression.getActualWhenIdentifier() : WHEN, WHEN); if (shouldOutput(expression) || expression.hasSpaceAfterWhen()) { writer.append(SPACE); } // WHEN expression if (stateObject.hasConditional()) { stateObject.getConditional().accept(this); } if (shouldOutput(expression) || expression.hasSpaceAfterWhenExpression()) { writer.append(SPACE); } // 'THEN' if (shouldOutput(expression) || expression.hasThen()) { appendIdentifier((expression != null) ? expression.getActualThenIdentifier() : THEN, THEN); } if (shouldOutput(expression) || expression.hasSpaceAfterThen()) { writer.append(SPACE); } // THEN expression if (stateObject.hasThen()) { stateObject.getThen().accept(this); } } } /** * {@inheritDoc} */ @Override public void visit(WhereClauseStateObject stateObject) { if (stateObject.isDecorated()) { toText(stateObject); } else { WhereClause expression = stateObject.getExpression(); // 'WHERE appendIdentifier((expression != null) ? expression.getActualIdentifier() : WHERE, WHERE); if (exactMatch && (expression != null) && expression.hasSpaceAfterIdentifier() || stateObject.hasConditional()) { writer.append(SPACE); } // Conditional expression if (stateObject.hasConditional()) { stateObject.getConditional().accept(this); } } } }