org.eclipse.persistence.jpa.jpql.tools.model.AbstractJPQLQueryBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction 180e602
/*******************************************************************************
* Copyright (c) 2011, 2014 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 org.eclipse.persistence.jpa.jpql.parser.*;
import org.eclipse.persistence.jpa.jpql.tools.model.query.JPQLQueryStateObject;
import org.eclipse.persistence.jpa.jpql.tools.model.query.StateObject;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedTypeProvider;
/**
* An abstract implementation of {@link IJPQLQueryBuilder} that parses a JPQL query or any JPQL
* fragments and creates the {@link StateObject} representation by delegating the creation to an
* instance of {@link BasicStateObjectBuilder}.
*
* @see DefaultJPQLQueryBuilder
* @see EclipseLinkJPQLQueryBuilder
*
* @version 2.4
* @since 2.4
* @author Pascal Filion
*/
public abstract class AbstractJPQLQueryBuilder implements IJPQLQueryBuilder {
/**
* Keeps a reference for future use.
*/
private BasicStateObjectBuilder builder;
/**
* Creates a new AbstractJPQLQueryBuilder
.
*/
protected AbstractJPQLQueryBuilder() {
super();
}
/**
* {@inheritDoc}
*/
public ICaseExpressionStateObjectBuilder buildCaseExpressionStateObjectBuilder(StateObject parent) {
return new DefaultCaseExpressionStateObjectBuilder(parent);
}
/**
* {@inheritDoc}
*/
public JPQLQueryStateObject buildStateObject(IManagedTypeProvider provider,
CharSequence jpqlQuery,
boolean tolerant) {
return buildStateObject(provider, jpqlQuery, JPQLStatementBNF.ID, tolerant);
}
/**
* {@inheritDoc}
*/
public JPQLQueryStateObject buildStateObject(IManagedTypeProvider provider,
CharSequence jpqlQuery,
String queryBNFId,
boolean tolerant) {
// First parse the JPQL query
JPQLExpression jpqlExpression = parse(jpqlQuery, getGrammar(), tolerant);
// Now visit the parsed expression and create the state object hierarchy
BasicStateObjectBuilder builder = getStateObjectBuilder();
try {
builder.jpqlQueryBuilder = this;
builder.managedTypeProvider = provider;
jpqlExpression.accept(wrap(builder));
return builder.parent;
}
finally {
builder.jpqlQueryBuilder = null;
builder.managedTypeProvider = null;
builder.parent = null;
builder.stateObject = null;
}
}
/**
* {@inheritDoc}
*/
public StateObject buildStateObject(StateObject parent,
CharSequence jpqlFragment,
String queryBNFId) {
// First parse the JPQL fragment
JPQLExpression jpqlExpression = parse(jpqlFragment, parent.getGrammar(), queryBNFId);
// We keep track of the old stuff because during the creation of a JPQLQueryStateObject,
// it is possible the state model uses this builder to create some objects
BasicStateObjectBuilder builder = getStateObjectBuilder();
IJPQLQueryBuilder oldBuilder = builder.jpqlQueryBuilder;
IManagedTypeProvider oldProvider = builder.managedTypeProvider;
JPQLQueryStateObject oldParent = builder.parent;
StateObject oldStateObject = builder.stateObject;
try {
builder.jpqlQueryBuilder = this;
builder.managedTypeProvider = parent.getManagedTypeProvider();
builder.parent = parent.getRoot();
builder.stateObject = parent;
// Visit the Expression for which a StateObject is needed
jpqlExpression.getQueryStatement().accept(wrap(builder));
return builder.stateObject;
}
finally {
builder.jpqlQueryBuilder = oldBuilder;
builder.managedTypeProvider = oldProvider;
builder.parent = oldParent;
builder.stateObject = oldStateObject;
}
}
/**
* Creates the builder that creates the {@link StateObject} for each {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression}.
*
* @return The builder that will be visiting the {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression}
*/
protected abstract BasicStateObjectBuilder buildStateObjectBuilder();
/**
* Returns the builder that creates the {@link StateObject} for each {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression}.
*
* @return The builder that will be visiting the {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression}
*/
protected final BasicStateObjectBuilder getStateObjectBuilder() {
if (builder == null) {
builder = buildStateObjectBuilder();
}
return builder;
}
/**
* Parses the given JPQL query with tolerant mode turned on.
*
* @param jpqlQuery The string representation of the JPQL query to parse
* @param jpqlGrammar The JPQL grammar that defines how to parse a JPQL query
* @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
* to parse invalid or incomplete queries
* @return The root of the parsed tree representation of the JPQL query
*/
protected JPQLExpression parse(CharSequence jpqlQuery, JPQLGrammar jpqlGrammar, boolean tolerant) {
return new JPQLExpression(jpqlQuery, jpqlGrammar, tolerant);
}
/**
* Parses the given JPQL fragment with tolerant mode turned on.
*
* @param jpqFragment The string representation of the portion of a JPQL query to parse
* @param jpqlGrammar The JPQL grammar that defines how to parse a JPQL query
* @param queryBNFId The unique identifier of the {@link JPQLQueryBNF}
* @return The root of the parsed tree representation of the JPQL fragment
*/
protected JPQLExpression parse(CharSequence jpqFragment,
JPQLGrammar jpqlGrammar,
String queryBNFId) {
return new JPQLExpression(jpqFragment, jpqlGrammar, queryBNFId, true);
}
/**
* If a subclass needs to wrap the given {@link BasicStateObjectBuilder} with another visitor can
* do so by simply overriding this method. {@link #buildStateObjectBuilder()} can't be easily
* overridden with an {@link ExpressionVisitor} due to the constraint on the return type.
*
* @param builder The builder to wrap
* @return By default the given builder is returned
*/
protected ExpressionVisitor wrap(BasicStateObjectBuilder builder) {
return builder;
}
}