blob: fd568764adde85bb12b3065504c484d337ad44f6 [file] [log] [blame]
/*
* Copyright (c) 2006, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.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;
}
}
@Override
public void visit(AbsExpression expression) {
expression.getExpression().accept(this);
AbsExpressionStateObject stateObject = new AbsExpressionStateObject(parent, this.stateObject);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(AbstractSchemaName expression) {
AbstractSchemaNameStateObject stateObject = new AbstractSchemaNameStateObject(
parent,
expression.getText()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@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;
}
@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;
}
@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;
}
@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;
}
@Override
public void visit(BadExpression expression) {
BadExpressionStateObject stateObject = new BadExpressionStateObject(
parent,
expression.getExpression().toActualText()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@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;
}
@Override
public void visit(CoalesceExpression expression) {
CoalesceExpressionStateObject stateObject = new CoalesceExpressionStateObject(
parent,
buildChildren(expression.getExpression())
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(CollectionExpression expression) {
List<StateObject> stateObjects = buildChildren(expression);
CollectionExpressionStateObject stateObject = new CollectionExpressionStateObject(
parent,
stateObjects
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(CollectionMemberDeclaration expression) {
// Not done here
stateObject = null;
}
@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;
}
@Override
public void visit(CollectionValuedPathExpression expression) {
CollectionValuedPathExpressionStateObject stateObject = new CollectionValuedPathExpressionStateObject(
parent,
expression.toActualText()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@Override
public void visit(ConcatExpression expression) {
ConcatExpressionStateObject stateObject = new ConcatExpressionStateObject(
parent,
buildChildren(expression.getExpression())
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(ConstructorExpression expression) {
ConstructorExpressionStateObject stateObject = new ConstructorExpressionStateObject(
parent,
expression.getClassName(),
buildChildren(expression.getConstructorItems())
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@Override
public void visit(DateTime expression) {
DateTimeStateObject stateObject = new DateTimeStateObject(parent, expression.getText());
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(DeleteClause expression) {
// Done via DeleteStatementBuilder
stateObject = null;
}
@Override
public void visit(DeleteStatement expression) {
stateObject = getDeleteStatementBuilder().buildStateObject(parent, expression);
}
@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;
}
@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;
}
@Override
public void visit(EntityTypeLiteral expression) {
EntityTypeLiteralStateObject stateObject = new EntityTypeLiteralStateObject(
parent,
expression.getEntityTypeName()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(EntryExpression expression) {
EntryExpressionStateObject stateObject = new EntryExpressionStateObject(
parent,
literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE)
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@Override
public final void visit(FromClause expression) {
// Not done here
stateObject = null;
}
@Override
public void visit(FunctionExpression expression) {
FunctionExpressionStateObject stateObject = new FunctionExpressionStateObject(
parent,
expression.getIdentifier(),
expression.getUnquotedFunctionName(),
buildChildren(expression.getExpression())
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public final void visit(GroupByClause expression) {
// Not done here
stateObject = null;
}
@Override
public void visit(HavingClause expression) {
expression.getConditionalExpression().accept(this);
}
@Override
public void visit(IdentificationVariable expression) {
IdentificationVariableStateObject stateObject = new IdentificationVariableStateObject(
parent,
expression.getText()
);
stateObject.setVirtual(expression.isVirtual());
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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);
}
@Override
public void visit(IndexExpression expression) {
IndexExpressionStateObject stateObject = new IndexExpressionStateObject(
parent,
literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE)
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@Override
public void visit(InputParameter expression) {
InputParameterStateObject stateObject = new InputParameterStateObject(
parent,
expression.getParameter()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public final void visit(Join expression) {
stateObject = getJoinBuilder().buildStateObject(
(IdentificationVariableDeclarationStateObject) stateObject,
expression
);
}
@Override
public void visit(JPQLExpression expression) {
parent = new JPQLQueryStateObject(jpqlQueryBuilder, managedTypeProvider);
parent.setExpression(expression);
expression.getQueryStatement().accept(this);
parent.setQueryStatement(stateObject);
}
@Override
public void visit(KeyExpression expression) {
KeyExpressionStateObject stateObject = new KeyExpressionStateObject(
parent,
literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE)
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(KeywordExpression expression) {
KeywordExpressionStateObject stateObject = new KeywordExpressionStateObject(
parent,
expression.getText()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(LengthExpression expression) {
expression.getExpression().accept(this);
LengthExpressionStateObject stateObject = new LengthExpressionStateObject(
parent,
this.stateObject
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@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;
}
@Override
public void visit(LowerExpression expression) {
expression.getExpression().accept(this);
LowerExpressionStateObject stateObject = new LowerExpressionStateObject(
parent,
this.stateObject
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@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;
}
@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;
}
@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;
}
@Override
public void visit(NotExpression expression) {
expression.getExpression().accept(this);
NotExpressionStateObject stateObject = new NotExpressionStateObject(
parent,
this.stateObject
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@Override
public void visit(NullExpression expression) {
stateObject = null;
}
@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;
}
@Override
public void visit(NumericLiteral expression) {
NumericLiteralStateObject stateObject = new NumericLiteralStateObject(
parent,
expression.getText()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(ObjectExpression expression) {
ObjectExpressionStateObject stateObject = new ObjectExpressionStateObject(
parent,
literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE)
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(OnClause expression) {
expression.getConditionalExpression().accept(this);
}
@Override
public final void visit(OrderByClause expression) {
// Not done here
stateObject = null;
}
@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);
}
@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;
}
@Override
public final void visit(RangeVariableDeclaration expression) {
// Not done here
stateObject = null;
}
@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);
}
@Override
public final void visit(SelectClause expression) {
// Not done here
stateObject = null;
}
@Override
public void visit(SelectStatement expression) {
stateObject = getSelectStatementBuilder().buildStateObject(parent, expression);
}
@Override
public final void visit(SimpleFromClause expression) {
// Done via SimpleSelectStatementBuilder
stateObject = null;
}
@Override
public final void visit(SimpleSelectClause expression) {
// Done via SimpleSelectStatementBuilder
stateObject = null;
}
@Override
public void visit(SimpleSelectStatement expression) {
stateObject = getSimpleSelectStatementBuilder().buildStateObject(parent, expression);
}
@Override
public void visit(SizeExpression expression) {
expression.getExpression().accept(this);
SizeExpressionStateObject stateObject = new SizeExpressionStateObject(
parent,
this.stateObject
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(SqrtExpression expression) {
expression.getExpression().accept(this);
SqrtExpressionStateObject stateObject = new SqrtExpressionStateObject(
parent,
this.stateObject
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(StateFieldPathExpression expression) {
StateFieldPathExpressionStateObject stateObject = new StateFieldPathExpressionStateObject(
parent,
expression.toActualText()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(StringLiteral expression) {
StringLiteralStateObject stateObject = new StringLiteralStateObject(
parent,
expression.getText()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(SubExpression expression) {
expression.getExpression().accept(this);
SubExpressionStateObject stateObject = new SubExpressionStateObject(
parent,
this.stateObject
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@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;
}
@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;
}
@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;
}
@Override
public void visit(TreatExpression expression) {
// Done by JoinBuilder
}
@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;
}
@Override
public void visit(TypeExpression expression) {
expression.getExpression().accept(this);
TypeExpressionStateObject stateObject = new TypeExpressionStateObject(
parent,
this.stateObject
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(UnknownExpression expression) {
UnknownExpressionStateObject stateObject = new UnknownExpressionStateObject(
parent,
expression.getText()
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public final void visit(UpdateClause expression) {
// Done via UpdateStatementBuilder
}
@Override
public final void visit(UpdateItem expression) {
// Done via UpdateStatementBuilder
}
@Override
public void visit(UpdateStatement expression) {
stateObject = getUpdateStatementBuilder().buildStateObject(parent, expression);
}
@Override
public void visit(UpperExpression expression) {
expression.getExpression().accept(this);
UpperExpressionStateObject stateObject = new UpperExpressionStateObject(
parent,
this.stateObject
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public void visit(ValueExpression expression) {
ValueExpressionStateObject stateObject = new ValueExpressionStateObject(
parent,
literal(expression.getExpression(), LiteralType.IDENTIFICATION_VARIABLE)
);
stateObject.setExpression(expression);
this.stateObject = stateObject;
}
@Override
public final void visit(WhenClause expression) {
// Done throw WhenClauseBuilder
stateObject = null;
}
@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);
@Override
public AbstractIdentificationVariableDeclarationStateObject buildStateObject(S parent, Expression expression) {
try {
this.parent = parent;
expression.accept(this);
return stateObject;
}
finally {
this.parent = null;
this.stateObject = null;
}
}
@Override
public void visit(AbstractSchemaName expression) {
stateObject.setRootPath(expression.getText());
}
@Override
public void visit(IdentificationVariable expression) {
stateObject.setIdentificationVariable(expression.getText());
IdentificationVariableStateObject variable = stateObject.getRangeVariableDeclaration().getIdentificationVariableStateObject();
variable.setVirtual(expression.isVirtual());
variable.setExpression(expression);
}
@Override
public void visit(IdentificationVariableDeclaration expression) {
stateObject = addRangeDeclaration(expression);
stateObject.setExpression(expression);
getJoinBuilder().buildStateObject(stateObject, expression.getJoins());
expression.getRangeVariableDeclaration().accept(this);
}
@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;
@Override
public T buildStateObject(P parent, Expression expression) {
try {
this.parent = parent;
expression.accept(this);
return stateObject;
}
finally {
this.parent = null;
}
}
@Override
public void visit(CollectionMemberDeclaration expression) {
getCollectionDeclarationBuilder().buildStateObject(stateObject.getFromClause(), expression);
}
@Override
public void visit(GroupByClause expression) {
GroupByClauseStateObject groupByClause = stateObject.addGroupByClause();
groupByClause.setExpression(expression);
groupByClause.addItems(buildChildren(expression.getGroupByItems()));
}
@Override
public void visit(HavingClause expression) {
HavingClauseStateObject havingClause = stateObject.addHavingClause();
havingClause.setConditional(buildStateObjectImp(expression));
havingClause.setExpression(expression);
}
@Override
public abstract void visit(IdentificationVariableDeclaration expression);
@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>();
}
@Override
public void visit(CollectionExpression expression) {
CollectionTools.addAll(children, expression.children());
}
@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;
@Override
public CollectionMemberDeclarationStateObject buildStateObject(AbstractFromClauseStateObject parent,
Expression expression) {
try {
this.parent = parent;
expression.accept(this);
return stateObject;
}
finally {
this.parent = null;
this.stateObject = null;
}
}
@Override
public void visit(CollectionMemberDeclaration expression) {
stateObject = parent.addCollectionDeclaration();
stateObject.setAs(expression.hasAs());
stateObject.setExpression(expression);
stateObject.setDerived(expression.isDerived());
super.visit(expression);
}
@Override
public void visit(CollectionValuedPathExpression expression) {
CollectionValuedPathExpressionStateObject path = stateObject.getCollectionValuedPath();
path.setPaths(expression.paths().iterator());
path.setExpression(expression);
}
@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;
@Override
public DeleteStatementStateObject buildStateObject(JPQLQueryStateObject parent,
Expression expression) {
try {
this.parent = parent;
expression.accept(this);
return stateObject;
}
finally {
this.parent = null;
}
}
@Override
public void visit(AbstractSchemaName expression) {
AbstractSchemaNameStateObject entityStateObject = stateObject.getAbstractSchemaNameStateObject();
entityStateObject.setText(expression.getText());
entityStateObject.setExpression(expression);
}
@Override
public void visit(DeleteClause expression) {
stateObject.getModifyClause().setExpression(expression);
super.visit(expression);
}
@Override
public void visit(DeleteStatement expression) {
stateObject = parent.addDeleteStatement();
stateObject.setExpression(expression);
super.visit(expression);
}
@Override
public void visit(IdentificationVariable expression) {
IdentificationVariableStateObject variable = stateObject.getIdentificationVariableStateObject();
variable.setExpression(expression);
variable.setText(expression.getText());
variable.setVirtual(expression.isVirtual());
}
@Override
public void visit(RangeVariableDeclaration expression) {
stateObject.getModifyClause().getRangeVariableDeclaration().setExpression(expression);
super.visit(expression);
}
@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;
@Override
public JoinStateObject buildStateObject(AbstractIdentificationVariableDeclarationStateObject parent,
Expression expression) {
try {
this.parent = parent;
expression.accept(this);
return stateObject;
}
finally {
this.parent = null;
this.stateObject = null;
}
}
@Override
public void visit(CollectionExpression expression) {
expression.acceptChildren(this);
}
@Override
public void visit(IdentificationVariableDeclaration expression) {
expression.getRangeVariableDeclaration().accept(this);
expression.getJoins().accept(this);
}
@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);
}
@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> {
@Override
protected AbstractIdentificationVariableDeclarationStateObject addRangeDeclaration(IdentificationVariableDeclaration expression) {
return parent.addRangeDeclaration();
}
@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;
@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;
}
}
@Override
protected void visit(Expression expression) {
expression.accept(BasicStateObjectBuilder.this);
stateObject = BasicStateObjectBuilder.this.stateObject;
}
@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> {
@Override
public void visit(FromClause expression) {
stateObject.getFromClause().setExpression(expression);
for (Expression child : children(expression.getDeclaration())) {
child.accept(this);
}
}
@Override
public void visit(IdentificationVariableDeclaration expression) {
getRangeDeclarationBuilder().buildStateObject(stateObject.getFromClause(), expression);
}
@Override
public void visit(OrderByClause expression) {
OrderByClauseStateObject orderByClause = stateObject.addOrderByClause();
orderByClause.setExpression(expression);
super.visit(expression);
}
@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);
}
@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);
}
}
}
@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> {
@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();
}
@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> {
@Override
public void visit(IdentificationVariableDeclaration expression) {
getSimpleRangeDeclarationBuilder().buildStateObject(stateObject.getFromClause(), expression);
}
@Override
public void visit(SimpleFromClause expression) {
stateObject.getFromClause().setExpression(expression);
for (Expression child : children(expression.getDeclaration())) {
child.accept(this);
}
}
@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));
}
}
@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;
@Override
public UpdateStatementStateObject buildStateObject(JPQLQueryStateObject parent,
Expression expression) {
try {
this.parent = parent;
expression.accept(this);
return stateObject;
}
finally {
this.parent = null;
this.stateObject = null;
}
}
@Override
public void visit(AbstractSchemaName expression) {
stateObject.setEntityName(expression.getText());
stateObject.getModifyClause().getAbstractSchemaNameStateObject().setExpression(expression);
}
@Override
public void visit(IdentificationVariable expression) {
if (updateItem == null) {
IdentificationVariableStateObject variable = stateObject.getIdentificationVariableStateObject();
variable.setText(expression.getText());
variable.setVirtual(expression.isVirtual());
variable.setExpression(expression);
}
}
@Override
public void visit(RangeVariableDeclaration expression) {
stateObject.getModifyClause().getRangeVariableDeclaration().setExpression(expression);
super.visit(expression);
}
@Override
public void visit(StateFieldPathExpression expression) {
updateItem.getStateFieldPath().setPaths(expression.paths().iterator());
updateItem.getStateFieldPath().setExpression(expression);
}
@Override
public void visit(UpdateClause expression) {
stateObject.getModifyClause().setExpression(expression);
super.visit(expression);
}
@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;
}
}
@Override
public void visit(UpdateStatement expression) {
UpdateStatementStateObject stateObject = parent.addUpdateStatement();
stateObject.setExpression(expression);
this.stateObject = stateObject;
super.visit(expression);
}
@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;
@Override
public CaseExpressionStateObject buildStateObject(CaseExpressionStateObject parent,
Expression expression) {
try {
this.parent = parent;
expression.accept(this);
return parent;
}
finally {
this.parent = null;
}
}
@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);
}
}
}