
org.eclipse.persistence.jpa.jpql.parser.UpdateClause Maven / Gradle / Ivy
/*
* Copyright (c) 2006, 2018 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.parser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.WordParser;
/**
* This is the update clause of the update statement.
*
* An UPDATE statement provides bulk operations over sets of entities of a single entity
* class (together with its subclasses, if any). Only one entity abstract schema type may be
* specified in the UPDATE clause.
*
*
BNF: update_clause ::= UPDATE abstract_schema_name [[AS] identification_variable] SET update_item {, update_item}*
*
* @see UpdateStatement
* @see UpdateItem
*
* @version 2.5
* @since 2.3
* @author Pascal Filion
*/
public final class UpdateClause extends AbstractExpression {
/**
* Determines whether a whitespace was parsed after the abstract schema name declaration.
*/
private boolean hasSpaceAfterRangeVariableDeclaration;
/**
* Determines whether a whitespace was parsed after SET.
*/
private boolean hasSpaceAfterSet;
/**
* Determines whether a whitespace was parsed after UPDATE.
*/
private boolean hasSpaceAfterUpdate;
/**
* The {@link Expression} representing the range variable declaration.
*/
private AbstractExpression rangeVariableDeclaration;
/**
* The actual SET identifier found in the string representation of the JPQL query.
*/
private String setIdentifier;
/**
* The actual UPDATE identifier found in the string representation of the JPQL query.
*/
private String updateIdentifier;
/**
* The expression containing the update items.
*/
private AbstractExpression updateItems;
/**
* Creates a new UpdateClause
.
*
* @param parent The parent of this expression
*/
public UpdateClause(AbstractExpression parent) {
super(parent, UPDATE);
}
/**
* {@inheritDoc}
*/
public void accept(ExpressionVisitor visitor) {
visitor.visit(this);
}
/**
* {@inheritDoc}
*/
public void acceptChildren(ExpressionVisitor visitor) {
getRangeVariableDeclaration().accept(visitor);
getUpdateItems().accept(visitor);
}
/**
* {@inheritDoc}
*/
@Override
protected void addChildrenTo(Collection children) {
children.add(getRangeVariableDeclaration());
children.add(getUpdateItems());
}
/**
* {@inheritDoc}
*/
@Override
protected void addOrderedChildrenTo(List children) {
// 'UPDATE'
children.add(buildStringExpression(UPDATE));
if (hasSpaceAfterUpdate) {
children.add(buildStringExpression(SPACE));
}
// Range variable declaration
if (rangeVariableDeclaration != null) {
children.add(rangeVariableDeclaration);
}
if (hasSpaceAfterRangeVariableDeclaration) {
children.add(buildStringExpression(SPACE));
}
// 'SET'
if (setIdentifier != null) {
children.add(buildStringExpression(SET));
}
if (hasSpaceAfterSet) {
children.add(buildStringExpression(SPACE));
}
// Update items
if (updateItems != null) {
children.add(updateItems);
}
}
/**
* Creates a new {@link CollectionExpression} that will wrap the single update item.
*
* @return The single update item represented by a temporary collection
*/
public CollectionExpression buildCollectionExpression() {
List children = new ArrayList(1);
children.add((AbstractExpression) getUpdateItems());
List commas = new ArrayList(1);
commas.add(Boolean.FALSE);
List spaces = new ArrayList(1);
spaces.add(Boolean.FALSE);
return new CollectionExpression(this, children, commas, spaces, true);
}
/**
* {@inheritDoc}
*/
@Override
public JPQLQueryBNF findQueryBNF(Expression expression) {
if ((rangeVariableDeclaration != null) && rangeVariableDeclaration.isAncestor(expression)) {
return getQueryBNF(RangeVariableDeclarationBNF.ID);
}
if ((updateItems != null) && updateItems.isAncestor(expression)) {
return getQueryBNF(InternalUpdateClauseBNF.ID);
}
return super.findQueryBNF(expression);
}
/**
* Returns the actual SET found in the string representation of the JPQL query, which has
* the actual case that was used.
*
* @return The SET identifier that was actually parsed, or an empty string if it was not parsed
*/
public String getActualSetIdentifier() {
return (setIdentifier != null) ? setIdentifier : ExpressionTools.EMPTY_STRING;
}
/**
* Returns the actual UPDATE found in the string representation of the JPQL query, which
* has the actual case that was used.
*
* @return The UPDATE identifier that was actually parsed
*/
public String getActualUpdateIdentifier() {
return updateIdentifier;
}
/**
* {@inheritDoc}
*/
public JPQLQueryBNF getQueryBNF() {
return getQueryBNF(UpdateClauseBNF.ID);
}
/**
* Returns the {@link Expression} representing the range variable declaration.
*
* @return The expression that was parsed representing the range variable declaration
*/
public Expression getRangeVariableDeclaration() {
if (rangeVariableDeclaration == null) {
rangeVariableDeclaration = buildNullExpression();
}
return rangeVariableDeclaration;
}
/**
* Returns the {@link Expression} representing the single update item or the collection of update items.
*
* @return The expression that was parsed representing the single or multiple update items
*/
public Expression getUpdateItems() {
if (updateItems == null) {
updateItems = buildNullExpression();
}
return updateItems;
}
/**
* Determines whether the range variable declaration was parsed.
*
* @return true
if the range variable declaration was parsed; false
otherwise
*/
public boolean hasRangeVariableDeclaration() {
return rangeVariableDeclaration != null &&
!rangeVariableDeclaration.isNull();
}
/**
* Determines whether SET was parsed or not.
*
* @return true
if SET was part of the query; false
otherwise
*/
public boolean hasSet() {
return setIdentifier != null;
}
/**
* Determines whether a whitespace was found after the abstract schema name declaration.
*
* @return true
if there was a whitespace after the abstract schema name declaration;
* false
otherwise
*/
public boolean hasSpaceAfterRangeVariableDeclaration() {
return hasSpaceAfterRangeVariableDeclaration;
}
/**
* Determines whether a whitespace was found after SET.
*
* @return true
if there was a whitespace after SET; false
otherwise
*/
public boolean hasSpaceAfterSet() {
return hasSpaceAfterSet;
}
/**
* Determines whether a whitespace was found after the identifier UPDATE.
*
* @return true
if there was a whitespace after the identifier UPDATE;
* false
otherwise
*/
public boolean hasSpaceAfterUpdate() {
return hasSpaceAfterUpdate;
}
/**
* Determines whether the update items section of the query was parsed.
*
* @return true
if something was parsed after SET even if it was a malformed
* expression; false
if nothing was parsed
*/
public boolean hasUpdateItems() {
return updateItems != null &&
!updateItems.isNull();
}
/**
* {@inheritDoc}
*/
@Override
protected boolean isParsingComplete(WordParser wordParser, String word, Expression expression) {
return word.equalsIgnoreCase(SET) ||
super.isParsingComplete(wordParser, word, expression);
}
/**
* {@inheritDoc}
*/
@Override
protected void parse(WordParser wordParser, boolean tolerant) {
// Parse 'UPDATE'
updateIdentifier = wordParser.moveForward(UPDATE);
hasSpaceAfterUpdate = wordParser.skipLeadingWhitespace() > 0;
// Parse the abstract schema name
if (tolerant && !wordParser.startsWithIdentifier(SET)) {
rangeVariableDeclaration = parse(
wordParser,
RangeVariableDeclarationBNF.ID,
tolerant
);
}
else if (!tolerant) {
rangeVariableDeclaration = new RangeVariableDeclaration(this);
rangeVariableDeclaration.parse(wordParser, tolerant);
}
hasSpaceAfterRangeVariableDeclaration = wordParser.skipLeadingWhitespace() > 0;
// Parse 'SET'
if (!tolerant || wordParser.startsWithIdentifier(SET)) {
setIdentifier = wordParser.moveForward(SET);
hasSpaceAfterSet = wordParser.skipLeadingWhitespace() > 0;
}
// Parse update items
updateItems = parse(wordParser, InternalUpdateClauseBNF.ID, tolerant);
}
/**
* {@inheritDoc}
*/
@Override
protected void toParsedText(StringBuilder writer, boolean actual) {
// 'UPDATE'
writer.append(actual ? updateIdentifier : UPDATE);
if (hasSpaceAfterUpdate) {
writer.append(SPACE);
}
// Range variable declaration
if (rangeVariableDeclaration != null) {
rangeVariableDeclaration.toParsedText(writer, actual);
}
if (hasSpaceAfterRangeVariableDeclaration) {
writer.append(SPACE);
}
// 'SET'
if (setIdentifier != null) {
writer.append(actual ? setIdentifier : SET);
}
if (hasSpaceAfterSet) {
writer.append(SPACE);
}
// Update items
if (updateItems != null) {
updateItems.toParsedText(writer, actual);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy