| /* | |
| * 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 <b>FROM</b> clause of a query. | |
| * <p> | |
| * Requirements: | |
| * <ul> | |
| * <li>All identification variables must be declared in the <b>FROM</b> clause. Identification | |
| * variables cannot be declared in other clauses. | |
| * <li>An identification variable must not be a reserved identifier or have the same name as any | |
| * entity in the same persistence unit. | |
| * <li>Identification variables are case insensitive. | |
| * <li>An identification variable evaluates to a value of the type of the expression used in | |
| * declaring the variable. | |
| * </ul> | |
| * <p> | |
| * 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. | |
| * <p> | |
| * 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. | |
| * <p> | |
| * An identification variable always designates a reference to a single value. It is declared in one | |
| * of three ways: | |
| * <ul> | |
| * <li>In a range variable declaration; | |
| * <li>In a join clause; | |
| * <li>In a collection member declaration. | |
| * </ul> | |
| * The identification variable declarations are evaluated from left to right in the <b>FROM</b> | |
| * clause, and an identification variable declaration can use the result of a preceding | |
| * identification variable declaration of the query string. | |
| * <p> | |
| * All identification variables used in the <b>SELECT</b>, <b>WHERE</b>, <b>ORDER BY</b>, | |
| * <b>GROUP BY</b>, or <b>HAVING</b> clause of a <b>SELECT</b> or <b>DELETE</b> statement must be | |
| * declared in the <b>FROM</b> clause. The identification variables used in the <b>WHERE</b> clause | |
| * of an <b>UPDATE</b> statement must be declared in the <b>UPDATE</b> clause. | |
| * <p> | |
| * 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 <code>IdentificationVariable</code>. | |
| * | |
| * @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 <code>IdentificationVariable</code>. | |
| * | |
| * @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<Expression> 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 <code>true</code>. This is valid in an <b>UPDATE</b> and | |
| * <b>DELETE</b> 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 <b>UPDATE</b> and <b>DELETE</b> 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()); | |
| } | |
| } |