org.eclipse.persistence.jpa.jpql.parser.IdentificationVariable Maven / Gradle / Ivy
Show all versions of eclipselink Show documentation
/*
* 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
//
// 09/02/2019-3.0 Alexandre Jacob
// - 527415: Fix code when locale is tr, az or lt
package org.eclipse.persistence.jpa.jpql.parser;
import java.util.List;
import java.util.Locale;
import org.eclipse.persistence.jpa.jpql.WordParser;
/**
* An identification variable is a valid identifier declared in the FROM clause of a query.
*
* Requirements:
*
* - All identification variables must be declared in the FROM clause. Identification
* variables cannot be declared in other clauses.
*
- An identification variable must not be a reserved identifier or have the same name as any
* entity in the same persistence unit.
*
- Identification variables are case insensitive.
*
- An identification variable evaluates to a value of the type of the expression used in
* declaring the variable.
*
*
* An identification variable can range over an entity, embeddable, or basic abstract schema type.
* An identification variable designates an instance of an abstract schema type or an element of a
* collection of abstract schema type instances.
*
* Note that for identification variables referring to an instance of an association or collection
* represented as a {@link java.util.Map}, the identification variable is of the abstract schema
* type of the map value.
*
* An identification variable always designates a reference to a single value. It is declared in one
* of three ways:
*
* - In a range variable declaration;
*
- In a join clause;
*
- In a collection member declaration.
*
* The identification variable declarations are evaluated from left to right in the FROM
* clause, and an identification variable declaration can use the result of a preceding
* identification variable declaration of the query string.
*
* All identification variables used in the SELECT, WHERE, ORDER BY,
* GROUP BY, or HAVING clause of a SELECT or DELETE statement must be
* declared in the FROM clause. The identification variables used in the WHERE clause
* of an UPDATE statement must be declared in the UPDATE clause.
*
* An identification variable is scoped to the query (or subquery) in which it is defined and is
* also visible to any subqueries within that query scope that do not define an identification
* variable of the same name.
*
* @version 2.4
* @since 2.3
* @author Pascal Filion
*/
public final class IdentificationVariable extends AbstractExpression {
/**
* The virtual state field path expression having
*/
private StateFieldPathExpression stateFieldPathExpression;
/**
* The uppercase version of the identification variable.
*/
private String variableName;
/**
* Determines whether this identification variable is virtual, meaning it's not part of the query
* but is required for proper navigability.
*/
private boolean virtual;
/**
* Creates a new IdentificationVariable
.
*
* @param parent The parent of this expression
* @param identificationVariable The actual identification variable
*/
public IdentificationVariable(AbstractExpression parent, String identificationVariable) {
super(parent, identificationVariable);
}
/**
* Creates a new IdentificationVariable
.
*
* @param parent The parent of this expression
* @param identificationVariable The actual identification variable
* @param virtual Determines whether this identification variable is virtual, meaning it's not
* part of the query but is required for proper navigability
*/
public IdentificationVariable(AbstractExpression parent, String identificationVariable, boolean virtual) {
super(parent, identificationVariable);
this.virtual = virtual;
}
@Override
public void accept(ExpressionVisitor visitor) {
visitor.visit(this);
}
@Override
public void acceptChildren(ExpressionVisitor visitor) {
// Nothing to traverse
}
@Override
protected void addOrderedChildrenTo(List children) {
children.add(buildStringExpression(getText()));
}
@Override
public JPQLQueryBNF getQueryBNF() {
return getQueryBNF(IdentificationVariableBNF.ID);
}
/**
* Returns the actual representation of the parsed information. This method should only be called
* if {@link #isVirtual()} returns true
. This is valid in an UPDATE and
* DELETE queries where the identification variable is not specified.
*
* @return The path expression that is qualified by the virtual identification variable
* @throws IllegalAccessError If this expression does not have a virtual identification variable
*/
@SuppressWarnings("nls")
public StateFieldPathExpression getStateFieldPathExpression() {
if (!virtual) {
throw new IllegalAccessError("IdentificationVariable.getStateFieldPathExpression() can only be accessed when it represents an attribute that is not fully qualified, which can be present in an UPDATE or DELETE query.");
}
return stateFieldPathExpression;
}
@Override
public String getText() {
return super.getText();
}
/**
* Returns the identification variable, which has been changed to be upper case.
*
* @return The uppercase version of the identification variable
* @since 2.4
*/
public String getVariableName() {
if (variableName == null) {
variableName = getText().toUpperCase(Locale.ROOT).intern();
}
return variableName;
}
@Override
public boolean isVirtual() {
return virtual;
}
@Override
protected void parse(WordParser wordParser, boolean tolerant) {
wordParser.moveForward(getText());
}
/**
* Sets a virtual identification variable because the abstract schema name was parsed without
* one. This is valid in an UPDATE and DELETE queries. This internally transforms
* the what was thought to be an identification variable to a path expression.
*
* @param variableName The identification variable that was generated to identify the "root" object
*/
public void setVirtualIdentificationVariable(String variableName) {
virtual = true;
stateFieldPathExpression = new StateFieldPathExpression(getParent(), getText());
stateFieldPathExpression.setVirtualIdentificationVariable(variableName);
rebuildActualText();
rebuildParsedText();
}
@Override
public String toParsedText() {
return getText();
}
@Override
protected void toParsedText(StringBuilder writer, boolean actual) {
writer.append(getText());
}
}