org.eclipse.persistence.jpa.jpql.parser.ConnectByClause 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.Collection;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.WordParser;
/**
* The CONNECT BY clause allows selecting rows in a hierarchical order using the hierarchical
* query clause. CONNECT BY specifies the relationship between parent rows and child rows of
* the hierarchy.
*
* BNF: connectby_clause ::= CONNECT BY { single_valued_object_path_expression | collection_valued_path_expression }
*
* @version 2.5
* @since 2.5
* @author Pascal Filion
*/
public final class ConnectByClause extends AbstractExpression {
/**
* The actual identifier found in the string representation of the JPQL query.
*/
private String actualIdentifier;
/**
* The conditional expression.
*/
private AbstractExpression expression;
/**
* Determines whether a whitespace was parsed after CONNECT BY.
*/
private boolean hasSpaceAfterConnectBy;
/**
* Creates a new ConnectByClause
.
*
* @param parent The parent of this expression
*/
public ConnectByClause(AbstractExpression parent) {
super(parent, CONNECT_BY);
}
@Override
public void accept(ExpressionVisitor visitor) {
acceptUnknownVisitor(visitor);
}
@Override
public void acceptChildren(ExpressionVisitor visitor) {
getExpression().accept(visitor);
}
@Override
protected void addChildrenTo(Collection children) {
children.add(getExpression());
}
@Override
protected void addOrderedChildrenTo(List children) {
// 'CONNECT BY'
children.add(buildStringExpression(CONNECT_BY));
if (hasSpaceAfterConnectBy) {
children.add(buildStringExpression(SPACE));
}
// Relationship expression
if (expression != null) {
children.add(expression);
}
}
@Override
public JPQLQueryBNF findQueryBNF(Expression expression) {
if ((this.expression != null) && this.expression.isAncestor(expression)) {
return getQueryBNF(CollectionValuedPathExpressionBNF.ID);
}
return super.findQueryBNF(expression);
}
/**
* Returns the actual CONNECT BY identifier found in the string representation of the JPQL
* query, which has the actual case that was used.
*
* @return The CONNECT BY identifier that was actually parsed, or an empty string if it
* was not parsed
*/
public String getActualIdentifier() {
return actualIdentifier;
}
/**
* Returns the {@link Expression} representing the relationship expression.
*
* @return The expression representing the relationship expression
*/
public Expression getExpression() {
if (expression == null) {
expression = buildNullExpression();
}
return expression;
}
@Override
public JPQLQueryBNF getQueryBNF() {
return getQueryBNF(ConnectByClauseBNF.ID);
}
/**
* Determines whether the relationship expression was parsed.
*
* @return true
if the relationship expression was parsed; false
if it
* was not parsed
*/
public boolean hasExpression() {
return expression != null &&
!expression.isNull();
}
/**
* Determines whether a whitespace was found after CONNECT BY.
*
* @return true
if there was a whitespace after CONNECT BY;
* false
otherwise
*/
public boolean hasSpaceAfterConnectBy() {
return hasSpaceAfterConnectBy;
}
@Override
protected void parse(WordParser wordParser, boolean tolerant) {
// 'CONNECT BY'
actualIdentifier = wordParser.moveForward(CONNECT_BY);
hasSpaceAfterConnectBy = wordParser.skipLeadingWhitespace() > 0;
// Relationship expression
expression = parse(wordParser, InternalConnectByClauseBNF.ID, tolerant);
}
@Override
protected void toParsedText(StringBuilder writer, boolean actual) {
// 'CONNECT BY'
writer.append(actual ? getActualIdentifier() : getText());
if (hasSpaceAfterConnectBy) {
writer.append(SPACE);
}
// Relationship expression
if (expression != null) {
expression.toParsedText(writer, actual);
}
}
}