/******************************************************************************* * 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 java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.persistence.jpa.jpql.LiteralType; import org.eclipse.persistence.jpa.jpql.LiteralVisitor; import org.eclipse.persistence.jpa.jpql.parser.AbsExpression; import org.eclipse.persistence.jpa.jpql.parser.AbstractExpression; import org.eclipse.persistence.jpa.jpql.parser.AbstractExpressionVisitor; import org.eclipse.persistence.jpa.jpql.parser.AbstractSchemaName; import org.eclipse.persistence.jpa.jpql.parser.AbstractTraverseChildrenVisitor; 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.AnonymousExpressionVisitor; import org.eclipse.persistence.jpa.jpql.parser.ArithmeticFactor; 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.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.ConcatExpression; import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression; import org.eclipse.persistence.jpa.jpql.parser.CountFunction; import org.eclipse.persistence.jpa.jpql.parser.DateTime; 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.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.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.Join; import org.eclipse.persistence.jpa.jpql.parser.KeyExpression; 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.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.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.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.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.TreatExpression; import org.eclipse.persistence.jpa.jpql.parser.TrimExpression; import org.eclipse.persistence.jpa.jpql.parser.TypeExpression; 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.ValueExpression; 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.AbstractFromClauseStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractIdentificationVariableDeclarationStateObject; 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.AbstractStateObjectVisitor; import org.eclipse.persistence.jpa.jpql.tools.model.query.AdditionExpressionStateObject; 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.CollectionExpressionStateObject; 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.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.DeleteStatementStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.DerivedPathIdentificationVariableDeclarationStateObject; 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.EntityTypeLiteralStateObject; import org.eclipse.persistence.jpa.jpql.tools.model.query.EntryExpressionStateObject; 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.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.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.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.StateObjectVisitor; 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; import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedTypeProvider; import org.eclipse.persistence.jpa.jpql.utility.CollectionTools; /** * The default implementation of a {@link IBuilder}, which creates a {@link StateObject} * representation of the {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression} being * visited. * <p> * Provisional API: This interface is part of an interim API that is still under development and * expected to change significantly before reaching stability. It is available at this early stage * to solicit feedback from pioneering adopters on the understanding that any code that uses this * API will almost certainly be broken (repeatedly) as the API evolves. * * @see Expression * @see StateObject * * @version 2.5 * @since 2.4 * @author Pascal Filion */ @SuppressWarnings("nls") public abstract class BasicStateObjectBuilder extends AbstractExpressionVisitor { /** * */ private IBuilder<CollectionMemberDeclarationStateObject, AbstractFromClauseStateObject> collectionDeclarationBuilder; /** * */ private CollectionExpressionVisitor collectionExpressionVisitor; /** * */ private IBuilder<DeleteStatementStateObject, JPQLQueryStateObject> deleteStatementBuilder; /** * This {@link IBuilder} is responsible to build an <code><b>DELETE</b></code> statement, * which populates the <code><b>DELETE</b></code> clause and the optional <code><b>WHERE</b></code> * clause by converting the information contained in the parsed JPQL query. */ private IBuilder<JoinStateObject, AbstractIdentificationVariableDeclarationStateObject> joinBuilder; /** * */ IJPQLQueryBuilder jpqlQueryBuilder; /** * This visitor is used to retrieve a variable name from various type of an {@link Expression}. */ private LiteralVisitor literalVisitor; /** * */ protected IManagedTypeProvider managedTypeProvider; /** * The parent {@link StateObject} of the {@link StateObject} to create. */ protected JPQLQueryStateObject parent; /** * */ private IBuilder<AbstractIdentificationVariableDeclarationStateObject, FromClauseStateObject> rangeDeclarationBuilder; /** * */ private IBuilder<StateObject, SelectClauseStateObject> selectItemBuilder; /** * This {@link IBuilder} is responsible to build a top-level <code><b>SELECT</b></code> statement, * which populates the various clauses by converting the information contained in the parsed JPQL * query. */ private IBuilder<SelectStatementStateObject, JPQLQueryStateObject> selectStatementBuilder; /** * */ private IBuilder<AbstractIdentificationVariableDeclarationStateObject, SimpleFromClauseStateObject> simpleRangeDeclarationBuilder; /** * This {@link IBuilder} is responsible to build a subquery <code><b>SELECT</b></code> statement, * which populates the various clauses by converting the information contained in the parsed JPQL * query. */ private IBuilder<SimpleSelectStatementStateObject, StateObject> simpleSelectStatementBuilder; /** * The {@link StateObject} that was created based on the visited {@link Expression}. */ protected StateObject stateObject; /** * This {@link IBuilder} is responsible to build an <code><b>UPDATE</b></code> statement, * which populates the <code><b>UPDATE</b></code> clause and the optional <code><b>WHERE</b></code> * clause by converting the information contained in the parsed JPQL query. */ private IBuilder<UpdateStatementStateObject, JPQLQueryStateObject> updateStatementBuilder; /** * This {@link IBuilder} is responsible to build a <code><b>WHEN</b></code> clause for the * <code><b>CASE</b></code> expression by converting the information contained in the parsed * JPQL query. */ private IBuilder<CaseExpressionStateObject, CaseExpressionStateObject> whenClauseBuilder; /** * Creates a new <code>StateObjectBuilder</code>. */ protected BasicStateObjectBuilder() { super(); } @SuppressWarnings("unchecked") protected <T extends StateObject> List<T> buildChildren(Expression expression) { StateObject oldStateObject = stateObject; List<T> stateObjects = new ArrayList<T>(); for (Expression child : children(expression)) { child.accept(this); stateObjects.add((T) stateObject); stateObject = oldStateObject; } return stateObjects; } protected IBuilder<CollectionMemberDeclarationStateObject, AbstractFromClauseStateObject> buildCollectionDeclarationBuilder() { return new CollectionMemberDeclarationBuilder(); } protected IBuilder<DeleteStatementStateObject, JPQLQueryStateObject> buildDeleteStatementBuilder() { return new DeleteStatementBuilder(); } protected IBuilder<JoinStateObject, AbstractIdentificationVariableDeclarationStateObject> buildJoinBuilder() { return new JoinBuilder(); } /** * Creates the visitor that can retrieve the "literal" value from a given {@link Expression} * based on the desired {@link LiteralType}. * * @return A new concrete instance of {@link LiteralVisitor} */ protected abstract LiteralVisitor buildLiteralVisitor(); protected IBuilder<AbstractIdentificationVariableDeclarationStateObject, FromClauseStateObject> buildRangeDeclarationBuilder() { return new RangeDeclarationBuilder(); } protected IBuilder<StateObject, SelectClauseStateObject> buildSelectItemBuilder() { return new SelectItemBuilder(); } protected IBuilder<SelectStatementStateObject, JPQLQueryStateObject> buildSelectStatementBuilder() { return new SelectStatementBuilder(); } protected IBuilder<AbstractIdentificationVariableDeclarationStateObject, SimpleFromClauseStateObject> buildSimpleRangeDeclarationBuilder() { return new SimpleRangeDeclarationBuilder(); } protected IBuilder<SimpleSelectStatementStateObject, StateObject> buildSimpleSelectStatementBuilder() { return new SimpleSelectStatementBuilder(); } /** * Visits the given {@link Expression} and returned its {@link StateObject}. * * @param expression The {@link Expression} to be visited by this builder * @return The {@link StateObject} representation of the given {@link Expression} or <code>null</code> * if nothing could be created */ protected final StateObject buildStateObjectImp(Expression expression) { expression.accept(this); return stateObject; } protected IBuilder<UpdateStatementStateObject, JPQLQueryStateObject> buildUpdateStatementBuilder() { return new UpdateStatementBuilder(); } protected IBuilder<CaseExpressionStateObject, CaseExpressionStateObject> buildWhenClauseBuilder() { return new WhenClauseBuilder(); } @SuppressWarnings("unchecked") protected <T extends Expression> List<T> children(Expression expression) { CollectionExpressionVisitor visitor = getCollectionExpressionVisitor(); try { expression.accept(visitor); return (List<T>) visitor.children; } finally { visitor.reset(); } } protected IBuilder<CollectionMemberDeclarationStateObject, AbstractFromClauseStateObject> getCollectionDeclarationBuilder() { if (collectionDeclarationBuilder == null) { collectionDeclarationBuilder = buildCollectionDeclarationBuilder(); } return collectionDeclarationBuilder; } protected CollectionExpressionVisitor getCollectionExpressionVisitor() { if (collectionExpressionVisitor == null) { collectionExpressionVisitor = new CollectionExpressionVisitor(); } return collectionExpressionVisitor; } protected IBuilder<DeleteStatementStateObject, JPQLQueryStateObject> getDeleteStatementBuilder() { if (deleteStatementBuilder == null) { deleteStatementBuilder = buildDeleteStatementBuilder(); } return deleteStatementBuilder; } protected IBuilder<JoinStateObject, AbstractIdentificationVariableDeclarationStateObject> getJoinBuilder() { if (joinBuilder == null) { joinBuilder = buildJoinBuilder(); } return joinBuilder; } protected LiteralVisitor getLiteralVisitor() { if (literalVisitor == null) { literalVisitor = buildLiteralVisitor(); } return literalVisitor; } protected IBuilder<AbstractIdentificationVariableDeclarationStateObject, FromClauseStateObject> getRangeDeclarationBuilder() { if (rangeDeclarationBuilder == null) { rangeDeclarationBuilder = buildRangeDeclarationBuilder(); } return rangeDeclarationBuilder; } protected IBuilder<StateObject, SelectClauseStateObject> getSelectItemBuilder() { if (selectItemBuilder == null) { selectItemBuilder = buildSelectItemBuilder(); } return selectItemBuilder; } protected IBuilder<SelectStatementStateObject, JPQLQueryStateObject> getSelectStatementBuilder() { if (selectStatementBuilder == null) { selectStatementBuilder = buildSelectStatementBuilder(); } return selectStatementBuilder; } protected IBuilder<AbstractIdentificationVariableDeclarationStateObject, SimpleFromClauseStateObject> getSimpleRangeDeclarationBuilder() { if (simpleRangeDeclarationBuilder == null) { simpleRangeDeclarationBuilder = buildSimpleRangeDeclarationBuilder(); } return simpleRangeDeclarationBuilder; } protected IBuilder<SimpleSelectStatementStateObject, StateObject> getSimpleSelectStatementBuilder() { if (simpleSelectStatementBuilder == null) { simpleSelectStatementBuilder = buildSimpleSelectStatementBuilder(); } return simpleSelectStatementBuilder; } /** * Returns the {@link StateObject} that was created based on the visited {@link Expression}. * * @return The {@link StateObject} that was created based on the visited {@link Expression} */ public StateObject getStateObject() { return stateObject; } protected IBuilder<UpdateStatementStateObject, JPQLQueryStateObject> getUpdateStatementBuilder() { if (updateStatementBuilder == null) { updateStatementBuilder = buildUpdateStatementBuilder(); } return updateStatementBuilder; } /** * Retrieves the "literal" from the given {@link Expression}. The literal to retrieve depends on * the given {@link LiteralType type}. The literal is basically a string value like an * identification variable name, an input parameter, a path expression, an abstract schema name, * etc. * * @param expression The {@link Expression} to visit * @param type The {@link LiteralType} helps to determine what to retrieve from the visited * {@link Expression} * @return A value from the given {@link Expression} or an empty string if the given {@link * Expression} and the {@link LiteralType} do not match */ protected String literal(Expression expression, LiteralType type) { LiteralVisitor visitor = getLiteralVisitor(); try { visitor.setType(type); visitor.literal = null; expression.accept(visitor); return visitor.literal; } finally { visitor.literal = null; } } /** * {@inheritDoc} */ @Override public void visit(AbsExpression expression) { expression.getExpression().accept(this); AbsExpressionStateObject stateObject = new AbsExpressionStateObject(parent, this.stateObject); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(AbstractSchemaName expression) { AbstractSchemaNameStateObject stateObject = new AbstractSchemaNameStateObject( parent, expression.getText() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(AdditionExpression expression) { expression.getLeftExpression().accept(this); StateObject leftStateObject = stateObject; expression.getRightExpression().accept(this); StateObject rightStateObject = stateObject; AdditionExpressionStateObject stateObject = new AdditionExpressionStateObject( parent, leftStateObject, rightStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(AllOrAnyExpression expression) { expression.getExpression().accept(this); AllOrAnyExpressionStateObject stateObject = new AllOrAnyExpressionStateObject( parent, expression.getIdentifier(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(AndExpression expression) { expression.getLeftExpression().accept(this); StateObject leftStateObject = stateObject; expression.getRightExpression().accept(this); StateObject rightStateObject = stateObject; AndExpressionStateObject stateObject = new AndExpressionStateObject( parent, leftStateObject, rightStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(ArithmeticFactor expression) { expression.getExpression().accept(this); ArithmeticFactorStateObject stateObject = new ArithmeticFactorStateObject( parent, expression.isPositive(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(AvgFunction expression) { expression.getExpression().accept(this); AvgFunctionStateObject stateObject = new AvgFunctionStateObject( parent, expression.hasDistinct(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(BadExpression expression) { BadExpressionStateObject stateObject = new BadExpressionStateObject( parent, expression.getExpression().toActualText() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(BetweenExpression expression) { expression.getExpression().accept(this); StateObject betweenStateObject = stateObject; expression.getLowerBoundExpression().accept(this); StateObject lowerBoundStateObject = stateObject; expression.getUpperBoundExpression().accept(this); StateObject upperBoundStateObject = stateObject; BetweenExpressionStateObject stateObject = new BetweenExpressionStateObject( parent, betweenStateObject, expression.hasNot(), lowerBoundStateObject, upperBoundStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(CaseExpression expression) { expression.getCaseOperand().accept(this); StateObject caseOperand = stateObject; expression.getElseExpression().accept(this); StateObject elseStateObject = stateObject; CaseExpressionStateObject caseExpressionStateObject = new CaseExpressionStateObject( parent, caseOperand, Collections.<WhenClauseStateObject>emptyList(), elseStateObject ); whenClauseBuilder().buildStateObject(caseExpressionStateObject, expression); caseExpressionStateObject.setExpression(expression); this.stateObject = caseExpressionStateObject; } /** * {@inheritDoc} */ @Override public void visit(CoalesceExpression expression) { CoalesceExpressionStateObject stateObject = new CoalesceExpressionStateObject( parent, buildChildren(expression.getExpression()) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(CollectionExpression expression) { List<StateObject> stateObjects = buildChildren(expression); CollectionExpressionStateObject stateObject = new CollectionExpressionStateObject( parent, stateObjects ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(CollectionMemberDeclaration expression) { // Not done here stateObject = null; } /** * {@inheritDoc} */ @Override public void visit(CollectionMemberExpression expression) { expression.getEntityExpression().accept(this); StateObject entityExpression = stateObject; CollectionMemberExpressionStateObject stateObject = new CollectionMemberExpressionStateObject( parent, entityExpression, expression.hasNot(), expression.hasOf(), literal(expression.getCollectionValuedPathExpression(), LiteralType.PATH_EXPRESSION_ALL_PATH) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(CollectionValuedPathExpression expression) { CollectionValuedPathExpressionStateObject stateObject = new CollectionValuedPathExpressionStateObject( parent, expression.toActualText() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(ComparisonExpression expression) { expression.getLeftExpression().accept(this); StateObject leftStateObject = stateObject; expression.getRightExpression().accept(this); StateObject rightStateObject = stateObject; ComparisonExpressionStateObject stateObject = new ComparisonExpressionStateObject( parent, leftStateObject, expression.getComparisonOperator(), rightStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(ConcatExpression expression) { ConcatExpressionStateObject stateObject = new ConcatExpressionStateObject( parent, buildChildren(expression.getExpression()) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(ConstructorExpression expression) { ConstructorExpressionStateObject stateObject = new ConstructorExpressionStateObject( parent, expression.getClassName(), buildChildren(expression.getConstructorItems()) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(CountFunction expression) { expression.getExpression().accept(this); CountFunctionStateObject stateObject = new CountFunctionStateObject( parent, expression.hasDistinct(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(DateTime expression) { DateTimeStateObject stateObject = new DateTimeStateObject(parent, expression.getText()); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(DeleteClause expression) { // Done via DeleteStatementBuilder stateObject = null; } /** * {@inheritDoc} */ @Override public void visit(DeleteStatement expression) { stateObject = getDeleteStatementBuilder().buildStateObject(parent, expression); } /** * {@inheritDoc} */ @Override public void visit(DivisionExpression expression) { expression.getLeftExpression().accept(this); StateObject leftStateObject = stateObject; expression.getRightExpression().accept(this); StateObject rightStateObject = stateObject; DivisionExpressionStateObject stateObject = new DivisionExpressionStateObject( parent, leftStateObject, rightStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(EmptyCollectionComparisonExpression expression) { EmptyCollectionComparisonExpressionStateObject stateObject = new EmptyCollectionComparisonExpressionStateObject( parent, expression.hasNot(), literal(expression.getExpression(), LiteralType.PATH_EXPRESSION_ALL_PATH) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(EntityTypeLiteral expression) { EntityTypeLiteralStateObject stateObject = new EntityTypeLiteralStateObject( parent, expression.getEntityTypeName() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(EntryExpression expression) { EntryExpressionStateObject stateObject = new EntryExpressionStateObject( parent, literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(ExistsExpression expression) { expression.getExpression().accept(this); ExistsExpressionStateObject stateObject = new ExistsExpressionStateObject( parent, expression.hasNot(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public final void visit(FromClause expression) { // Not done here stateObject = null; } /** * {@inheritDoc} */ @Override public void visit(FunctionExpression expression) { FunctionExpressionStateObject stateObject = new FunctionExpressionStateObject( parent, expression.getIdentifier(), expression.getUnquotedFunctionName(), buildChildren(expression.getExpression()) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public final void visit(GroupByClause expression) { // Not done here stateObject = null; } /** * {@inheritDoc} */ @Override public void visit(HavingClause expression) { expression.getConditionalExpression().accept(this); } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariable expression) { IdentificationVariableStateObject stateObject = new IdentificationVariableStateObject( parent, expression.getText() ); stateObject.setVirtual(expression.isVirtual()); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public final void visit(final IdentificationVariableDeclaration expression) { StateObjectVisitor visitor = new AbstractStateObjectVisitor() { @Override public void visit(FromClauseStateObject stateObject) { getRangeDeclarationBuilder().buildStateObject(stateObject, expression); } @Override public void visit(SimpleFromClauseStateObject stateObject) { getSimpleRangeDeclarationBuilder().buildStateObject(stateObject, expression); } }; stateObject.accept(visitor); } /** * {@inheritDoc} */ @Override public void visit(IndexExpression expression) { IndexExpressionStateObject stateObject = new IndexExpressionStateObject( parent, literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(InExpression expression) { expression.getExpression().accept(this); InExpressionStateObject stateObject = new InExpressionStateObject( parent, this.stateObject, expression.hasNot(), buildChildren(expression.getInItems()) ); stateObject.setSingleInputParameter(expression.isSingleInputParameter()); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(InputParameter expression) { InputParameterStateObject stateObject = new InputParameterStateObject( parent, expression.getParameter() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public final void visit(Join expression) { stateObject = getJoinBuilder().buildStateObject( (IdentificationVariableDeclarationStateObject) stateObject, expression ); } /** * {@inheritDoc} */ @Override public void visit(JPQLExpression expression) { parent = new JPQLQueryStateObject(jpqlQueryBuilder, managedTypeProvider); parent.setExpression(expression); expression.getQueryStatement().accept(this); parent.setQueryStatement(stateObject); } /** * {@inheritDoc} */ @Override public void visit(KeyExpression expression) { KeyExpressionStateObject stateObject = new KeyExpressionStateObject( parent, literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(KeywordExpression expression) { KeywordExpressionStateObject stateObject = new KeywordExpressionStateObject( parent, expression.getText() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(LengthExpression expression) { expression.getExpression().accept(this); LengthExpressionStateObject stateObject = new LengthExpressionStateObject( parent, this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(LikeExpression expression) { expression.getStringExpression().accept(this); StateObject stringStateObject = stateObject; expression.getPatternValue().accept(this); StateObject patternValue = stateObject; LikeExpressionStateObject stateObject = new LikeExpressionStateObject( parent, stringStateObject, expression.hasNot(), patternValue, literal(expression.getEscapeCharacter(), LiteralType.STRING_LITERAL) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(LocateExpression expression) { expression.getFirstExpression().accept(this); StateObject firstStateObject = stateObject; expression.getSecondExpression().accept(this); StateObject secondStateObject = stateObject; expression.getThirdExpression().accept(this); StateObject thirdStateObject = stateObject; LocateExpressionStateObject stateObject = new LocateExpressionStateObject( parent, firstStateObject, secondStateObject, thirdStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(LowerExpression expression) { expression.getExpression().accept(this); LowerExpressionStateObject stateObject = new LowerExpressionStateObject( parent, this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(MaxFunction expression) { expression.getExpression().accept(this); MaxFunctionStateObject stateObject = new MaxFunctionStateObject( parent, expression.hasDistinct(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(MinFunction expression) { expression.getExpression().accept(this); MinFunctionStateObject stateObject = new MinFunctionStateObject( parent, expression.hasDistinct(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(ModExpression expression) { expression.getFirstExpression().accept(this); StateObject firstStateObject = stateObject; expression.getSecondExpression().accept(this); StateObject secondStateObject = stateObject; ModExpressionStateObject stateObject = new ModExpressionStateObject( parent, firstStateObject, secondStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(MultiplicationExpression expression) { expression.getLeftExpression().accept(this); StateObject leftStateObject = stateObject; expression.getRightExpression().accept(this); StateObject rightStateObject = stateObject; MultiplicationExpressionStateObject stateObject = new MultiplicationExpressionStateObject( parent, leftStateObject, rightStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(NotExpression expression) { expression.getExpression().accept(this); NotExpressionStateObject stateObject = new NotExpressionStateObject( parent, this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(NullComparisonExpression expression) { expression.getExpression().accept(this); NullComparisonExpressionStateObject stateObject = new NullComparisonExpressionStateObject( parent, expression.hasNot(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(NullExpression expression) { stateObject = null; } /** * {@inheritDoc} */ @Override public void visit(NullIfExpression expression) { expression.getFirstExpression().accept(this); StateObject firstStateObject = stateObject; expression.getSecondExpression().accept(this); StateObject secondStateObject = stateObject; NullIfExpressionStateObject stateObject = new NullIfExpressionStateObject( parent, firstStateObject, secondStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(NumericLiteral expression) { NumericLiteralStateObject stateObject = new NumericLiteralStateObject( parent, expression.getText() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(ObjectExpression expression) { ObjectExpressionStateObject stateObject = new ObjectExpressionStateObject( parent, literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(OnClause expression) { expression.getConditionalExpression().accept(this); } /** * {@inheritDoc} */ @Override public final void visit(OrderByClause expression) { // Not done here stateObject = null; } /** * {@inheritDoc} */ @Override public final void visit(OrderByItem expression) { OrderByClauseStateObject orderByClause = (OrderByClauseStateObject) stateObject; OrderByItemStateObject orderByItem = orderByClause.addItem(expression.getOrdering()); orderByItem.setExpression(expression); expression.getExpression().accept(this); orderByItem.setStateObject(stateObject); } /** * {@inheritDoc} */ @Override public void visit(OrExpression expression) { expression.getLeftExpression().accept(this); StateObject leftStateObject = stateObject; expression.getRightExpression().accept(this); StateObject rightStateObject = stateObject; OrExpressionStateObject stateObject = new OrExpressionStateObject( parent, leftStateObject, rightStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public final void visit(RangeVariableDeclaration expression) { // Not done here stateObject = null; } /** * {@inheritDoc} */ @Override public final void visit(final ResultVariable expression) { StateObjectVisitor visitor = new AbstractStateObjectVisitor() { @Override public void visit(SelectClauseStateObject stateObject) { BasicStateObjectBuilder.this.stateObject = getSelectItemBuilder().buildStateObject( stateObject, expression ); } }; stateObject.accept(visitor); } /** * {@inheritDoc} */ @Override public final void visit(SelectClause expression) { // Not done here stateObject = null; } /** * {@inheritDoc} */ @Override public void visit(SelectStatement expression) { stateObject = getSelectStatementBuilder().buildStateObject(parent, expression); } /** * {@inheritDoc} */ @Override public final void visit(SimpleFromClause expression) { // Done via SimpleSelectStatementBuilder stateObject = null; } /** * {@inheritDoc} */ @Override public final void visit(SimpleSelectClause expression) { // Done via SimpleSelectStatementBuilder stateObject = null; } /** * {@inheritDoc} */ @Override public void visit(SimpleSelectStatement expression) { stateObject = getSimpleSelectStatementBuilder().buildStateObject(parent, expression); } /** * {@inheritDoc} */ @Override public void visit(SizeExpression expression) { expression.getExpression().accept(this); SizeExpressionStateObject stateObject = new SizeExpressionStateObject( parent, this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(SqrtExpression expression) { expression.getExpression().accept(this); SqrtExpressionStateObject stateObject = new SqrtExpressionStateObject( parent, this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(StateFieldPathExpression expression) { StateFieldPathExpressionStateObject stateObject = new StateFieldPathExpressionStateObject( parent, expression.toActualText() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(StringLiteral expression) { StringLiteralStateObject stateObject = new StringLiteralStateObject( parent, expression.getText() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(SubExpression expression) { expression.getExpression().accept(this); SubExpressionStateObject stateObject = new SubExpressionStateObject( parent, this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(SubstringExpression expression) { expression.getFirstExpression().accept(this); StateObject firstExpression = stateObject; expression.getSecondExpression().accept(this); StateObject secondExpression = stateObject; expression.getThirdExpression().accept(this); StateObject thirdExpression = stateObject; SubstringExpressionStateObject stateObject = new SubstringExpressionStateObject( parent, firstExpression, secondExpression, thirdExpression ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(SubtractionExpression expression) { expression.getLeftExpression().accept(this); StateObject leftStateObject = stateObject; expression.getRightExpression().accept(this); StateObject rightStateObject = stateObject; SubtractionExpressionStateObject stateObject = new SubtractionExpressionStateObject( parent, leftStateObject, rightStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(SumFunction expression) { expression.getExpression().accept(this); SumFunctionStateObject stateObject = new SumFunctionStateObject( parent, expression.hasDistinct(), this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(TreatExpression expression) { // Done by JoinBuilder } /** * {@inheritDoc} */ @Override public void visit(TrimExpression expression) { expression.getExpression().accept(this); StateObject trimStateObject = stateObject; expression.getTrimCharacter().accept(this); StateObject trimCharacter = stateObject; TrimExpressionStateObject stateObject = new TrimExpressionStateObject( parent, expression.getSpecification(), trimCharacter, trimStateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(TypeExpression expression) { expression.getExpression().accept(this); TypeExpressionStateObject stateObject = new TypeExpressionStateObject( parent, this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(UnknownExpression expression) { UnknownExpressionStateObject stateObject = new UnknownExpressionStateObject( parent, expression.getText() ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public final void visit(UpdateClause expression) { // Done via UpdateStatementBuilder } /** * {@inheritDoc} */ @Override public final void visit(UpdateItem expression) { // Done via UpdateStatementBuilder } /** * {@inheritDoc} */ @Override public void visit(UpdateStatement expression) { stateObject = getUpdateStatementBuilder().buildStateObject(parent, expression); } /** * {@inheritDoc} */ @Override public void visit(UpperExpression expression) { expression.getExpression().accept(this); UpperExpressionStateObject stateObject = new UpperExpressionStateObject( parent, this.stateObject ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public void visit(ValueExpression expression) { ValueExpressionStateObject stateObject = new ValueExpressionStateObject( parent, literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE) ); stateObject.setExpression(expression); this.stateObject = stateObject; } /** * {@inheritDoc} */ @Override public final void visit(WhenClause expression) { // Done throw WhenClauseBuilder stateObject = null; } /** * {@inheritDoc} */ @Override public void visit(WhereClause expression) { expression.getConditionalExpression().accept(this); } /** * Returns the {@link IBuilder} that is responsible to visit each {@link WhenClause} and to * create the corresponding {@link WhenClauseStateObject}. The new state objects have to be added * to {@link CaseExpressionStateObject} by the builder. * * @return The builder of the <code><b>WHEN</b></code> clauses */ protected IBuilder<CaseExpressionStateObject, CaseExpressionStateObject> whenClauseBuilder() { if (whenClauseBuilder == null) { whenClauseBuilder = buildWhenClauseBuilder(); } return whenClauseBuilder; } /** * This builder is responsible to create a new identification variable declaration and to add it * to the state object representing the <code><b>FROM</b></code> clause. */ protected abstract class AbstractRangeDeclarationBuilder<S extends AbstractFromClauseStateObject> extends AbstractTraverseChildrenVisitor implements IBuilder<AbstractIdentificationVariableDeclarationStateObject, S> { /** * The concrete instance of {@link AbstractFromClauseStateObject} where the new identification * variable declaration is added. */ protected S parent; /** * The concrete instance of {@link IdentificationVariableDeclarationStateObject} * that represents the visited {@link IdentificationVariableDeclaration}. */ protected AbstractIdentificationVariableDeclarationStateObject stateObject; /** * Creates the concrete instance of an {@link AbstractIdentificationVariableDeclarationStateObject} * for the given {@link IdentificationVariableDeclaration}. * * @param expression The {@link IdentificationVariableDeclaration} to convert into a * {@link StateObject} * @return A new {@link StateObject} representing an identification variable declaration */ protected abstract AbstractIdentificationVariableDeclarationStateObject addRangeDeclaration(IdentificationVariableDeclaration expression); /** * {@inheritDoc} */ @Override public AbstractIdentificationVariableDeclarationStateObject buildStateObject(S parent, Expression expression) { try { this.parent = parent; expression.accept(this); return stateObject; } finally { this.parent = null; this.stateObject = null; } } /** * {@inheritDoc} */ @Override public void visit(AbstractSchemaName expression) { stateObject.setRootPath(expression.getText()); } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariable expression) { stateObject.setIdentificationVariable(expression.getText()); IdentificationVariableStateObject variable = stateObject.getRangeVariableDeclaration().getIdentificationVariableStateObject(); variable.setVirtual(expression.isVirtual()); variable.setExpression(expression); } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariableDeclaration expression) { stateObject = addRangeDeclaration(expression); stateObject.setExpression(expression); getJoinBuilder().buildStateObject(stateObject, expression.getJoins()); expression.getRangeVariableDeclaration().accept(this); } /** * {@inheritDoc} */ @Override public void visit(RangeVariableDeclaration expression) { AbstractRangeVariableDeclarationStateObject declaration = stateObject.getRangeVariableDeclaration(); declaration.setAs(expression.hasAs()); declaration.setExpression(expression); super.visit(expression); } } /** * The abstract definition of the builder that is responsible to create the {@link StateObject} * representation of the <code><b>SELECT</b></code> statement. */ protected abstract class AbstractSelectStatementBuilder<T extends AbstractSelectStatementStateObject, P extends StateObject> extends AbstractTraverseChildrenVisitor implements IBuilder<T, P> { /** * The parent of the <code><b>SELECT</b></code> statement. */ protected P parent; /** * The concrete class of {@link AbstractSelectStatementStateObject}. */ protected T stateObject; /** * {@inheritDoc} */ @Override public T buildStateObject(P parent, Expression expression) { try { this.parent = parent; expression.accept(this); return stateObject; } finally { this.parent = null; } } /** * {@inheritDoc} */ @Override public void visit(CollectionMemberDeclaration expression) { getCollectionDeclarationBuilder().buildStateObject(stateObject.getFromClause(), expression); } /** * {@inheritDoc} */ @Override public void visit(GroupByClause expression) { GroupByClauseStateObject groupByClause = stateObject.addGroupByClause(); groupByClause.setExpression(expression); groupByClause.addItems(buildChildren(expression.getGroupByItems())); } /** * {@inheritDoc} */ @Override public void visit(HavingClause expression) { HavingClauseStateObject havingClause = stateObject.addHavingClause(); havingClause.setConditional(buildStateObjectImp(expression)); havingClause.setExpression(expression); } /** * {@inheritDoc} */ @Override public abstract void visit(IdentificationVariableDeclaration expression); /** * {@inheritDoc} */ @Override public void visit(WhereClause expression) { WhereClauseStateObject whereClause = stateObject.addWhereClause(); whereClause.setConditional(buildStateObjectImp(expression)); whereClause.setExpression(expression); } } protected static class CollectionExpressionVisitor extends AnonymousExpressionVisitor { List<Expression> children; CollectionExpressionVisitor() { super(); reset(); } void reset() { children = new ArrayList<Expression>(); } /** * {@inheritDoc} */ @Override public void visit(CollectionExpression expression) { CollectionTools.addAll(children, expression.children()); } /** * {@inheritDoc} */ @Override protected void visit(Expression expression) { children.add(expression); } } protected static class CollectionMemberDeclarationBuilder extends AbstractTraverseChildrenVisitor implements IBuilder<CollectionMemberDeclarationStateObject, AbstractFromClauseStateObject> { protected AbstractFromClauseStateObject parent; protected CollectionMemberDeclarationStateObject stateObject; /** * {@inheritDoc} */ @Override public CollectionMemberDeclarationStateObject buildStateObject(AbstractFromClauseStateObject parent, Expression expression) { try { this.parent = parent; expression.accept(this); return stateObject; } finally { this.parent = null; this.stateObject = null; } } /** * {@inheritDoc} */ @Override public void visit(CollectionMemberDeclaration expression) { stateObject = parent.addCollectionDeclaration(); stateObject.setAs(expression.hasAs()); stateObject.setExpression(expression); stateObject.setDerived(expression.isDerived()); super.visit(expression); } /** * {@inheritDoc} */ @Override public void visit(CollectionValuedPathExpression expression) { CollectionValuedPathExpressionStateObject path = stateObject.getCollectionValuedPath(); path.setPaths(expression.paths().iterator()); path.setExpression(expression); } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariable expression) { IdentificationVariableStateObject variable = stateObject.getIdentificationVariable(); variable.setExpression(expression); variable.setText(expression.getText()); variable.setVirtual(expression.isVirtual()); } } /** * This builder is responsible to create the {@link StateObject} representation of the * <code><b>DELETE</b></code> query statement. */ protected class DeleteStatementBuilder extends AbstractTraverseChildrenVisitor implements IBuilder<DeleteStatementStateObject, JPQLQueryStateObject> { protected JPQLQueryStateObject parent; protected DeleteStatementStateObject stateObject; /** * {@inheritDoc} */ @Override public DeleteStatementStateObject buildStateObject(JPQLQueryStateObject parent, Expression expression) { try { this.parent = parent; expression.accept(this); return stateObject; } finally { this.parent = null; } } /** * {@inheritDoc} */ @Override public void visit(AbstractSchemaName expression) { AbstractSchemaNameStateObject entityStateObject = stateObject.getAbstractSchemaNameStateObject(); entityStateObject.setText(expression.getText()); entityStateObject.setExpression(expression); } /** * {@inheritDoc} */ @Override public void visit(DeleteClause expression) { stateObject.getModifyClause().setExpression(expression); super.visit(expression); } /** * {@inheritDoc} */ @Override public void visit(DeleteStatement expression) { stateObject = parent.addDeleteStatement(); stateObject.setExpression(expression); super.visit(expression); } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariable expression) { IdentificationVariableStateObject variable = stateObject.getIdentificationVariableStateObject(); variable.setExpression(expression); variable.setText(expression.getText()); variable.setVirtual(expression.isVirtual()); } /** * {@inheritDoc} */ @Override public void visit(RangeVariableDeclaration expression) { stateObject.getModifyClause().getRangeVariableDeclaration().setExpression(expression); super.visit(expression); } /** * {@inheritDoc} */ @Override public void visit(WhereClause expression) { WhereClauseStateObject whereClause = stateObject.addWhereClause(); whereClause.setExpression(expression); expression.getConditionalExpression().accept(BasicStateObjectBuilder.this); StateObject conditionalStateObject = BasicStateObjectBuilder.this.stateObject; whereClause.setConditional(conditionalStateObject); } } protected class JoinBuilder extends AbstractExpressionVisitor implements IBuilder<JoinStateObject, AbstractIdentificationVariableDeclarationStateObject> { protected AbstractIdentificationVariableDeclarationStateObject parent; protected JoinStateObject stateObject; /** * {@inheritDoc} */ @Override public JoinStateObject buildStateObject(AbstractIdentificationVariableDeclarationStateObject parent, Expression expression) { try { this.parent = parent; expression.accept(this); return stateObject; } finally { this.parent = null; this.stateObject = null; } } /** * {@inheritDoc} */ @Override public void visit(CollectionExpression expression) { expression.acceptChildren(this); } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariableDeclaration expression) { expression.getRangeVariableDeclaration().accept(this); expression.getJoins().accept(this); } /** * {@inheritDoc} */ @Override public void visit(Join expression) { stateObject = parent.addJoin( expression.getIdentifier(), literal(expression.getJoinAssociationPath(), LiteralType.PATH_EXPRESSION_ALL_PATH), literal(expression.getIdentificationVariable(), LiteralType.IDENTIFICATION_VARIABLE) ); stateObject.setAs(expression.hasAs()); stateObject.setExpression(expression); expression.getJoinAssociationPath().accept(this); expression.getIdentificationVariable().accept(this); } /** * {@inheritDoc} */ @Override public void visit(TreatExpression expression) { TreatExpressionStateObject treatStateObject = new TreatExpressionStateObject( stateObject, expression.hasAs(), literal(expression.getEntityType(), LiteralType.ENTITY_TYPE) ); treatStateObject.setExpression(expression); stateObject.getJoinAssociationPathStateObject().decorate(treatStateObject); expression.getCollectionValuedPathExpression().accept(this); } } /** * This builder is responsible to create a new identification variable declaration and to add it * to the state object representing the <code><b>FROM</b></code> clause of the top-level query. */ protected class RangeDeclarationBuilder extends AbstractRangeDeclarationBuilder<FromClauseStateObject> { /** * {@inheritDoc} */ @Override protected AbstractIdentificationVariableDeclarationStateObject addRangeDeclaration(IdentificationVariableDeclaration expression) { return parent.addRangeDeclaration(); } /** * {@inheritDoc} */ @Override public void visit(AbstractSchemaName expression) { super.visit(expression); IdentificationVariableDeclarationStateObject stateObject = (IdentificationVariableDeclarationStateObject) this.stateObject; stateObject.getRootStateObject().setExpression(expression); } } /** * This builder is responsible to create the items owned by the top-level * <code><b>SELECT</b></code> clause. */ protected class SelectItemBuilder extends AnonymousExpressionVisitor implements IBuilder<StateObject, SelectClauseStateObject> { protected SelectClauseStateObject parent; protected StateObject stateObject; /** * {@inheritDoc} */ @Override public StateObject buildStateObject(SelectClauseStateObject parent, Expression expression) { try { this.parent = parent; expression.accept(this); return this.stateObject; } finally { this.parent = null; this.stateObject = null; } } /** * {@inheritDoc} */ @Override protected void visit(Expression expression) { expression.accept(BasicStateObjectBuilder.this); stateObject = BasicStateObjectBuilder.this.stateObject; } /** * {@inheritDoc} */ @Override public void visit(ResultVariable expression) { expression.getSelectExpression().accept(BasicStateObjectBuilder.this); ResultVariableStateObject stateObject = new ResultVariableStateObject( parent, BasicStateObjectBuilder.this.stateObject, expression.hasAs(), literal(expression.getResultVariable(), LiteralType.RESULT_VARIABLE) ); stateObject.setExpression(expression); this.stateObject = stateObject; } } /** * This builder is responsible to create the {@link StateObject} representation of the * <code><b>SELECT</b></code> query statement. */ protected class SelectStatementBuilder extends AbstractSelectStatementBuilder<SelectStatementStateObject, JPQLQueryStateObject> { /** * {@inheritDoc} */ @Override public void visit(FromClause expression) { stateObject.getFromClause().setExpression(expression); for (Expression child : children(expression.getDeclaration())) { child.accept(this); } } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariableDeclaration expression) { getRangeDeclarationBuilder().buildStateObject(stateObject.getFromClause(), expression); } /** * {@inheritDoc} */ @Override public void visit(OrderByClause expression) { OrderByClauseStateObject orderByClause = stateObject.addOrderByClause(); orderByClause.setExpression(expression); super.visit(expression); } /** * {@inheritDoc} */ @Override public void visit(OrderByItem expression) { OrderByClauseStateObject orderByClause = stateObject.getOrderByClause(); OrderByItemStateObject orderByItem = orderByClause.addItem(expression.getOrdering()); orderByItem.setExpression(expression); expression.getExpression().accept(BasicStateObjectBuilder.this); orderByItem.setStateObject(BasicStateObjectBuilder.this.stateObject); } /** * {@inheritDoc} */ @Override public void visit(SelectClause expression) { SelectClauseStateObject selectClause = stateObject.getSelectClause(); selectClause.setExpression(expression); selectClause.setDistinct(expression.hasDistinct()); for (Expression child : children(expression.getSelectExpression())) { StateObject stateObject = getSelectItemBuilder().buildStateObject(selectClause, child); if (stateObject != null) { selectClause.addItem(stateObject); } } } /** * {@inheritDoc} */ @Override public void visit(SelectStatement expression) { SelectStatementStateObject stateObject = parent.addSelectStatement(); stateObject.setExpression(expression); this.stateObject = stateObject; super.visit(expression); } } /** * This builder is responsible to create a new identification variable declaration and to add it * to the state object representing the <code><b>FROM</b></code> clause of a subquery. */ protected class SimpleRangeDeclarationBuilder extends AbstractRangeDeclarationBuilder<SimpleFromClauseStateObject> { /** * {@inheritDoc} */ @Override protected AbstractIdentificationVariableDeclarationStateObject addRangeDeclaration(IdentificationVariableDeclaration expression) { String root = expression.getRangeVariableDeclaration().toActualText(); int index = root.indexOf(AbstractExpression.SPACE); if (index > 0) { root = root.substring(0, index); } if (root.indexOf(AbstractExpression.DOT) > 0) { return parent.addDerivedPathDeclaration(); } return parent.addRangeDeclaration(); } /** * {@inheritDoc} */ @Override public void visit(CollectionValuedPathExpression expression) { DerivedPathIdentificationVariableDeclarationStateObject stateObject = (DerivedPathIdentificationVariableDeclarationStateObject) this.stateObject; stateObject.setRootPath(expression.toActualText()); stateObject.getRootStateObject().setExpression(expression); } } /** * This builder is responsible to create the {@link StateObject} representation of the * <code><b>SELECT</b></code> subquery. */ protected class SimpleSelectStatementBuilder extends AbstractSelectStatementBuilder<SimpleSelectStatementStateObject, StateObject> { /** * {@inheritDoc} */ @Override public void visit(IdentificationVariableDeclaration expression) { getSimpleRangeDeclarationBuilder().buildStateObject(stateObject.getFromClause(), expression); } /** * {@inheritDoc} */ @Override public void visit(SimpleFromClause expression) { stateObject.getFromClause().setExpression(expression); for (Expression child : children(expression.getDeclaration())) { child.accept(this); } } /** * {@inheritDoc} */ @Override public void visit(SimpleSelectClause expression) { SimpleSelectClauseStateObject selectClause = stateObject.getSelectClause(); selectClause.setDistinct(expression.hasDistinct()); selectClause.setExpression(expression); List<StateObject> children = buildChildren(expression.getSelectExpression()); if (!children.isEmpty()) { selectClause.setSelectItem(children.get(0)); } } /** * {@inheritDoc} */ @Override public void visit(SimpleSelectStatement expression) { stateObject = new SimpleSelectStatementStateObject(parent); stateObject.setExpression(expression); stateObject.setParent(parent); super.visit(expression); } } /** * This builder is responsible to create the {@link StateObject} representation of the * <code><b>UPDATE</b></code> query statement. */ protected class UpdateStatementBuilder extends AbstractTraverseChildrenVisitor implements IBuilder<UpdateStatementStateObject, JPQLQueryStateObject> { protected JPQLQueryStateObject parent; protected UpdateStatementStateObject stateObject; protected UpdateItemStateObject updateItem; /** * {@inheritDoc} */ @Override public UpdateStatementStateObject buildStateObject(JPQLQueryStateObject parent, Expression expression) { try { this.parent = parent; expression.accept(this); return stateObject; } finally { this.parent = null; this.stateObject = null; } } /** * {@inheritDoc} */ @Override public void visit(AbstractSchemaName expression) { stateObject.setEntityName(expression.getText()); stateObject.getModifyClause().getAbstractSchemaNameStateObject().setExpression(expression); } /** * {@inheritDoc} */ @Override public void visit(IdentificationVariable expression) { if (updateItem == null) { IdentificationVariableStateObject variable = stateObject.getIdentificationVariableStateObject(); variable.setText(expression.getText()); variable.setVirtual(expression.isVirtual()); variable.setExpression(expression); } } /** * {@inheritDoc} */ @Override public void visit(RangeVariableDeclaration expression) { stateObject.getModifyClause().getRangeVariableDeclaration().setExpression(expression); super.visit(expression); } /** * {@inheritDoc} */ @Override public void visit(StateFieldPathExpression expression) { updateItem.getStateFieldPath().setPaths(expression.paths().iterator()); updateItem.getStateFieldPath().setExpression(expression); } /** * {@inheritDoc} */ @Override public void visit(UpdateClause expression) { stateObject.getModifyClause().setExpression(expression); super.visit(expression); } /** * {@inheritDoc} */ @Override public void visit(UpdateItem expression) { UpdateClauseStateObject updateClause = stateObject.getModifyClause(); String identificationVariable = updateClause.getIdentificationVariable(); updateItem = updateClause.addItem(); updateItem.setExpression(expression); try { // Retrieve the state field path expression String path = literal( expression.getStateFieldPathExpression(), LiteralType.PATH_EXPRESSION_ALL_PATH ); if (!path.startsWith(identificationVariable + ".")) { updateItem.setPath(identificationVariable + "." + path); } else { updateItem.setPath(path); } // Set the virtual identification variable if (!updateClause.isIdentificationVariableDefined()) { updateItem.setVirtualIdentificationVariable(updateClause.getIdentificationVariable()); } // Create the new value StateObject stateObject = buildStateObjectImp(expression.getNewValue()); updateItem.setNewValue(stateObject); } finally { updateItem = null; } } /** * {@inheritDoc} */ @Override public void visit(UpdateStatement expression) { UpdateStatementStateObject stateObject = parent.addUpdateStatement(); stateObject.setExpression(expression); this.stateObject = stateObject; super.visit(expression); } /** * {@inheritDoc} */ @Override public void visit(WhereClause expression) { WhereClauseStateObject whereClause = stateObject.addWhereClause(); whereClause.setExpression(expression); StateObject stateObject = buildStateObjectImp(expression.getConditionalExpression()); whereClause.setConditional(stateObject); } } /** * This builder is responsible to create the <code><b>WHEN</b></code> clauses for a * <code><b>CASE</b></code> expression. */ protected class WhenClauseBuilder extends AbstractTraverseChildrenVisitor implements IBuilder<CaseExpressionStateObject, CaseExpressionStateObject> { /** * The {@link CaseExpressionStateObject} for which its {@link WhenClauseStateObject * WhenClauseStateObjects} are created by this builder. */ private CaseExpressionStateObject parent; /** * {@inheritDoc} */ @Override public CaseExpressionStateObject buildStateObject(CaseExpressionStateObject parent, Expression expression) { try { this.parent = parent; expression.accept(this); return parent; } finally { this.parent = null; } } /** * {@inheritDoc} */ @Override public void visit(WhenClause expression) { StateObject whenStateObject = buildStateObjectImp(expression.getWhenExpression()); StateObject thenStateObject = buildStateObjectImp(expression.getThenExpression()); WhenClauseStateObject stateObject = parent.addWhenClause(whenStateObject, thenStateObject); stateObject.setExpression(expression); } } }