All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.jpa.jpql.parser.HierarchicalQueryClause Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 2012, 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.Collection;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.WordParser;

/**
 * If a table contains hierarchical data, then rows can be selected in a hierarchical order using
 * the hierarchical query clause.
 * 

* START WITH specifies the root row(s) of the hierarchy. *

* CONNECT BY specifies the relationship between parent rows and child rows of * the hierarchy. * *

BNF: hierarchical_query_clause ::= [start_with_clause] connectby_clause [order_siblings_by_clause]

* * @see StartWithClause * @see ConnectByClause * @see OrderSiblingsByClause * * @version 2.5 * @since 2.5 * @author Pascal Filion */ public final class HierarchicalQueryClause extends AbstractExpression { /** * The {@link Expression} that represents the CONNECT BY clause. */ private AbstractExpression connectByClause; /** * Determines whether a whitespace was parsed after the CONNECT BY clause. */ private boolean hasSpaceAfterConnectByClause; /** * Determines whether a whitespace was parsed after the START WITH clause. */ private boolean hasSpaceAfterStartWithClause; /** * The {@link Expression} that represents the ORDER SIBLINGS BY clause. */ private AbstractExpression orderSiblingsByClause; /** * The {@link Expression} that represents the START WITH clause. */ private AbstractExpression startWithClause; /** * Creates a new HierarchicalQueryClause. * * @param parent The parent of this expression */ public HierarchicalQueryClause(AbstractExpression parent) { super(parent); } /** * {@inheritDoc} */ public void accept(ExpressionVisitor visitor) { acceptUnknownVisitor(visitor); } /** * {@inheritDoc} */ public void acceptChildren(ExpressionVisitor visitor) { getStartWithClause().accept(visitor); getConnectByClause().accept(visitor); getOrderSiblingsByClause().accept(visitor); } /** * {@inheritDoc} */ @Override protected void addChildrenTo(Collection children) { super.addChildrenTo(children); children.add(getStartWithClause()); children.add(getConnectByClause()); children.add(getOrderSiblingsByClause()); } /** * {@inheritDoc} */ @Override protected void addOrderedChildrenTo(List children) { // START WITH clause if (startWithClause != null) { children.add(startWithClause); } if (hasSpaceAfterStartWithClause) { children.add(buildStringExpression(SPACE)); } // CONNECT BY clause if (connectByClause != null) { children.add(connectByClause); } if (hasSpaceAfterConnectByClause) { children.add(buildStringExpression(SPACE)); } // ORDER SIBLINGS BY clause if (orderSiblingsByClause != null) { children.add(orderSiblingsByClause); } } /** * {@inheritDoc} */ @Override public JPQLQueryBNF findQueryBNF(Expression expression) { if ((startWithClause != null) && startWithClause.isAncestor(expression)) { return getQueryBNF(StartWithClauseBNF.ID); } if ((connectByClause != null) && connectByClause.isAncestor(expression)) { return getQueryBNF(ConnectByClauseBNF.ID); } if ((orderSiblingsByClause != null) && orderSiblingsByClause.isAncestor(expression)) { return getQueryBNF(OrderSiblingsByClauseBNF.ID); } return super.findQueryBNF(expression); } /** * Returns the {@link Expression} representing the CONNECT BY clause. * * @return The expression representing the CONNECT BY clause */ public Expression getConnectByClause() { if (connectByClause == null) { connectByClause = buildNullExpression(); } return connectByClause; } /** * Returns the {@link Expression} representing the ORDER SIBLINGS BY clause. * * @return The expression representing the ORDER SIBLINGS BY clause */ public Expression getOrderSiblingsByClause() { if (orderSiblingsByClause == null) { orderSiblingsByClause = buildNullExpression(); } return orderSiblingsByClause; } /** * {@inheritDoc} */ public JPQLQueryBNF getQueryBNF() { return getQueryBNF(HierarchicalQueryClauseBNF.ID); } /** * Returns the {@link Expression} representing the START WITH clause. * * @return The expression representing the START WITH clause */ public Expression getStartWithClause() { if (startWithClause == null) { startWithClause = buildNullExpression(); } return startWithClause; } /** * Determines whether the CONNECT BY clause is defined. * * @return true if the query that got parsed had the CONNECT BY clause */ public boolean hasConnectByClause() { return connectByClause != null && !connectByClause.isNull(); } /** * Determines whether the ORDER SIBLINGS BY clause is defined. * * @return true if the query that got parsed had the ORDER SIBLINGS BY clause */ public boolean hasOrderSiblingsByClause() { return orderSiblingsByClause != null && !orderSiblingsByClause.isNull(); } /** * Determines whether a whitespace was found after the CONNECT BY clause. In * some cases, the space is owned by a child of the hierarchical query clause. * * @return true if there was a whitespace after the CONNECT BY * clause and owned by this expression; false otherwise */ public boolean hasSpaceAfterConnectByClause() { return hasSpaceAfterConnectByClause; } /** * Determines whether a whitespace was found after the START WITH clause. In * some cases, the space is owned by a child of the hierarchical query clause. * * @return true if there was a whitespace after the START WITH * clause and owned by this expression; false otherwise */ public boolean hasSpaceAfterStartWithClause() { return hasSpaceAfterStartWithClause; } /** * Determines whether the START WITH clause is defined. * * @return true if the query that got parsed had the START WITH clause */ public boolean hasStartWithClause() { return startWithClause != null && !startWithClause.isNull(); } /** * {@inheritDoc} */ @Override protected void parse(WordParser wordParser, boolean tolerant) { int count = 0; // START WITH clause if (wordParser.startsWithIdentifier(START_WITH)) { startWithClause = new StartWithClause(this); startWithClause.parse(wordParser, tolerant); count = wordParser.skipLeadingWhitespace(); hasSpaceAfterStartWithClause = (count > 0); } // CONNECT BY clause if (wordParser.startsWithIdentifier(CONNECT_BY)) { connectByClause = new ConnectByClause(this); connectByClause.parse(wordParser, tolerant); count = wordParser.skipLeadingWhitespace(); hasSpaceAfterConnectByClause = (count > 0); } // ORDER SIBLINGS BY clause if (wordParser.startsWithIdentifier(ORDER_SIBLINGS_BY)) { orderSiblingsByClause = new OrderSiblingsByClause(this); orderSiblingsByClause.parse(wordParser, tolerant); } // Let's the parent statement own the whitespace if (hasSpaceAfterStartWithClause && connectByClause == null && orderSiblingsByClause == null) { hasSpaceAfterStartWithClause = false; wordParser.moveBackward(count); } else if (hasSpaceAfterConnectByClause && orderSiblingsByClause == null) { hasSpaceAfterConnectByClause = false; wordParser.moveBackward(count); } } /** * {@inheritDoc} */ @Override protected void toParsedText(StringBuilder writer, boolean actual) { // START WITH clause if (startWithClause != null) { startWithClause.toParsedText(writer, actual); if (hasSpaceAfterStartWithClause) { writer.append(SPACE); } } // CONNECT BY clause if (connectByClause != null) { connectByClause.toParsedText(writer, actual); if (hasSpaceAfterConnectByClause) { writer.append(SPACE); } } // ORDER SIBLINGS BY clause if (orderSiblingsByClause != null) { orderSiblingsByClause.toParsedText(writer, actual); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy