org.eclipse.persistence.jpa.jpql.parser.WhenClause 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 f2b9fc5
/*
* 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.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;
/**
* A WHEN predicate is used to calculate a condition and when it's true, its THEN will
* be executed.
*
* BNF: when_clause ::= WHEN conditional_expression THEN scalar_expression
* or
* BNF: simple_when_clause ::= WHEN scalar_expression THEN scalar_expression
*
* @version 2.5
* @since 2.3
* @author Pascal Filion
*/
public final class WhenClause extends AbstractExpression {
/**
* Determines whether a whitespace was parsed after the identifier THEN.
*/
private boolean hasSpaceAfterThen;
/**
* Determines whether a whitespace was parsed after the identifier WHEN.
*/
private boolean hasSpaceAfterWhen;
/**
* Determines whether a whitespace was parsed after the conditional expression.
*/
private boolean hasSpaceAfterWhenExpression;
/**
* The {@link Expression} representing the expression following the identifier THEN.
*/
private AbstractExpression thenExpression;
/**
* The actual THEN identifier found in the string representation of the JPQL query.
*/
private String thenIdentifier;
/**
* The {@link Expression} representing the conditional predicate of the clause.
*/
private AbstractExpression whenExpression;
/**
* The actual WHEN identifier found in the string representation of the JPQL query.
*/
private String whenIdentifier;
/**
* Creates a new WhenClause
.
*
* @param parent The parent of this expression
*/
public WhenClause(AbstractExpression parent) {
super(parent, WHEN);
}
@Override
public void accept(ExpressionVisitor visitor) {
visitor.visit(this);
}
@Override
public void acceptChildren(ExpressionVisitor visitor) {
getWhenExpression().accept(visitor);
getThenExpression().accept(visitor);
}
@Override
protected void addChildrenTo(Collection children) {
children.add(getWhenExpression());
children.add(getThenExpression());
}
@Override
protected void addOrderedChildrenTo(List children) {
// WHEN
children.add(buildStringExpression(WHEN));
if (hasSpaceAfterWhen) {
children.add(buildStringExpression(SPACE));
}
// WHEN Expression
if (whenExpression != null) {
children.add(whenExpression);
}
if (hasSpaceAfterWhenExpression) {
children.add(buildStringExpression(SPACE));
}
// THEN
if (thenIdentifier != null) {
children.add(buildStringExpression(THEN));
}
if (hasSpaceAfterThen) {
children.add(buildStringExpression(SPACE));
}
// THEN expression
if (thenExpression != null) {
children.add(thenExpression);
}
}
/**
* Creates a new {@link CollectionExpression} that will wrap the single WHEN
* expression.
*
* @return The single WHEN
expression represented by a temporary collection
*/
public CollectionExpression buildWhenCollectionExpression() {
List children = new ArrayList<>(1);
children.add(getWhenExpression());
List commas = new ArrayList<>(1);
commas.add(Boolean.FALSE);
List spaces = new ArrayList<>(1);
spaces.add(hasSpaceAfterWhenExpression);
return new CollectionExpression(this, children, commas, spaces, true);
}
@Override
public JPQLQueryBNF findQueryBNF(Expression expression) {
if ((whenExpression != null) && whenExpression.isAncestor(expression)) {
return getQueryBNF(InternalWhenClauseBNF.ID);
}
if ((thenExpression != null) && thenExpression.isAncestor(expression)) {
return getQueryBNF(ScalarExpressionBNF.ID);
}
return super.findQueryBNF(expression);
}
/**
* Returns the actual THEN found in the string representation of the JPQL query, which
* has the actual case that was used.
*
* @return The THEN identifier that was actually parsed, or an empty string if it was not parsed
*/
public String getActualThenIdentifier() {
return (thenIdentifier != null) ? thenIdentifier : ExpressionTools.EMPTY_STRING;
}
/**
* Returns the actual WHEN found in the string representation of the JPQL query, which
* has the actual case that was used.
*
* @return The WHEN identifier that was actually parsed
*/
public String getActualWhenIdentifier() {
return whenIdentifier;
}
@Override
public JPQLQueryBNF getQueryBNF() {
return getQueryBNF(WhenClauseBNF.ID);
}
/**
* Returns the {@link Expression} representing the expression following the identifier THEN.
*
* @return The expression representing the expression executed if the predicate is true
*/
public AbstractExpression getThenExpression() {
if (thenExpression == null) {
thenExpression = buildNullExpression();
}
return thenExpression;
}
/**
* Returns the {@link Expression} representing the conditional predicate of the clause.
*
* @return The expression following the WHEN identifier
*/
public AbstractExpression getWhenExpression() {
if (whenExpression == null) {
whenExpression = buildNullExpression();
}
return whenExpression;
}
/**
* Determines whether a whitespace was parsed after THEN.
*
* @return true
if there was a whitespace after THEN; false
otherwise
*/
public boolean hasSpaceAfterThen() {
return hasSpaceAfterThen;
}
/**
* Determines whether a whitespace was parsed after WHEN.
*
* @return true
if there was a whitespace after WHEN; false
otherwise
*/
public boolean hasSpaceAfterWhen() {
return hasSpaceAfterWhen;
}
/**
* Determines whether a whitespace was parsed after the conditional expression.
*
* @return true
if there was a whitespace after the conditional expression;
* false
otherwise
*/
public boolean hasSpaceAfterWhenExpression() {
return hasSpaceAfterWhenExpression;
}
/**
* Determines whether the identifier THEN was part of the query.
*
* @return true
if the identifier THEN was parsed; false
otherwise
*/
public boolean hasThen() {
return thenIdentifier != null;
}
/**
* Determines whether the THEN expression of the query was parsed.
*
* @return true
the THEN expression was parsed; false
if nothing
* was parsed
*/
public boolean hasThenExpression() {
return thenExpression != null &&
!thenExpression.isNull();
}
/**
* Determines whether the conditional expression of the query was parsed.
*
* @return true
the conditional expression was parsed; false
if nothing
* was parsed
*/
public boolean hasWhenExpression() {
return whenExpression != null &&
!whenExpression.isNull();
}
@Override
protected boolean isParsingComplete(WordParser wordParser, String word, Expression expression) {
return word.equalsIgnoreCase(WHEN) ||
word.equalsIgnoreCase(THEN) ||
word.equalsIgnoreCase(ELSE) ||
word.equalsIgnoreCase(END) ||
super.isParsingComplete(wordParser, word, expression);
}
@Override
protected void parse(WordParser wordParser, boolean tolerant) {
// Parse 'WHEN'
whenIdentifier = wordParser.moveForward(WHEN);
hasSpaceAfterWhen = wordParser.skipLeadingWhitespace() > 0;
// Parse the expression
whenExpression = parse(wordParser, InternalWhenClauseBNF.ID, tolerant);
hasSpaceAfterWhenExpression = wordParser.skipLeadingWhitespace() > 0;
// Parse 'THEN'
if (!tolerant || wordParser.startsWithIdentifier(THEN)) {
thenIdentifier = wordParser.moveForward(THEN);
hasSpaceAfterThen = wordParser.skipLeadingWhitespace() > 0;
}
// Parse the then expression
thenExpression = parse(wordParser, ScalarExpressionBNF.ID, tolerant);
}
@Override
protected void toParsedText(StringBuilder writer, boolean actual) {
// 'WHEN'
writer.append(actual ? whenIdentifier : WHEN);
if (hasSpaceAfterWhen) {
writer.append(SPACE);
}
// Expression
if (whenExpression != null) {
whenExpression.toParsedText(writer, actual);
}
if (hasSpaceAfterWhenExpression) {
writer.append(SPACE);
}
// 'THEN'
if (thenIdentifier != null) {
writer.append(actual ? thenIdentifier : THEN);
}
if (hasSpaceAfterThen) {
writer.append(SPACE);
}
// Then expression
if (thenExpression != null) {
thenExpression.toParsedText(writer, actual);
}
}
}