| /* |
| * Copyright (c) 2011, 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.internal.jpa.jpql; |
| |
| import java.util.Collections; |
| import java.util.List; |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.jpa.jpql.ExpressionTools; |
| import org.eclipse.persistence.jpa.jpql.JPQLQueryDeclaration; |
| import org.eclipse.persistence.jpa.jpql.parser.AbstractExpression; |
| import org.eclipse.persistence.jpa.jpql.parser.Expression; |
| import org.eclipse.persistence.jpa.jpql.parser.IdentificationVariable; |
| import org.eclipse.persistence.jpa.jpql.parser.Join; |
| import org.eclipse.persistence.mappings.DatabaseMapping; |
| |
| /** |
| * A <code>Declaration</code> is the corresponding representation of a single declaration defined in |
| * the <code><b>FROM</b></code> clause of a query. |
| * |
| * @version 2.5 |
| * @since 2.4 |
| * @author Pascal Filion |
| */ |
| abstract class Declaration implements JPQLQueryDeclaration { |
| |
| /** |
| * TODO. |
| */ |
| Expression baseExpression; |
| |
| /** |
| * The declaration expression, which is either an |
| * {@link org.eclipse.persistence.jpa.jpql.parser.IdentificationVariableDeclaration IdentificationVariableDeclaration} |
| * or a {@link org.eclipse.persistence.jpa.jpql.parser.CollectionMemberDeclaration CollectionMemberDeclaration} |
| * when part of a <b>FROM</b> clause, otherwise it's either the |
| * {@link org.eclipse.persistence.jpa.jpql.parser.DeleteClause DeleteClause} or the |
| * {@link org.eclipse.persistence.jpa.jpql.parser.UpdateClause UpdateClause}. |
| */ |
| Expression declarationExpression; |
| |
| /** |
| * The cached {@link ClassDescriptor} that represents this {@link Declaration}'s "root" path. |
| */ |
| private ClassDescriptor descriptor; |
| |
| /** |
| * The {@link IdentificationVariable} used to declare a "root" object. |
| */ |
| IdentificationVariable identificationVariable; |
| |
| /** |
| * The cached {@link DatabaseMapping} if this {@link Declaration}'s "root" path points to a |
| * mapping, otherwise it will be <code>null</code>. |
| */ |
| private DatabaseMapping mapping; |
| |
| /** |
| * The {@link JPQLQueryContext} is used to query information about the application metadata and |
| * cached information. |
| */ |
| final JPQLQueryContext queryContext; |
| |
| /** |
| * The {@link org.eclipse.persistence.expressions.Expression Expression} representing the |
| * information of this {@link Declaration}. |
| */ |
| private org.eclipse.persistence.expressions.Expression queryExpression; |
| |
| /** |
| * The "root" object for objects which may not be reachable by navigation, it is either the |
| * abstract schema name (entity name), a derived path expression (which is only defined in a |
| * subquery) or <code>null</code> if this {@link Declaration} is a collection member declaration. |
| */ |
| String rootPath; |
| |
| /** |
| * Creates a new <code>Declaration</code>. |
| * |
| * @param queryContext The context used to query information about the application metadata and |
| * cached information |
| */ |
| Declaration(JPQLQueryContext queryContext) { |
| super(); |
| this.queryContext = queryContext; |
| } |
| |
| /** |
| * Creates the Expression {@link Expression} for this {@link Declaration}. |
| * |
| * @return A new {@link org.eclipse.persistence.expressions.Expression Expression} |
| */ |
| abstract org.eclipse.persistence.expressions.Expression buildQueryExpression(); |
| |
| @Override |
| public Expression getBaseExpression() { |
| return baseExpression; |
| } |
| |
| @Override |
| public Expression getDeclarationExpression() { |
| return declarationExpression; |
| } |
| |
| /** |
| * Returns the {@link ClassDescriptor} that represents this {@link Declaration}'s "root" path. |
| * |
| * @return The descriptor of the "root" path |
| */ |
| final ClassDescriptor getDescriptor() { |
| if (descriptor == null) { |
| descriptor = resolveDescriptor(); |
| } |
| return descriptor; |
| } |
| |
| @Override |
| public List<Join> getJoins() { |
| return Collections.emptyList(); |
| } |
| |
| /** |
| * Returns the {@link DatabaseMapping} that this {@link Declaration} represents, which may be |
| * <code>null</code> in the case it does not represent one. |
| * |
| * @return Either the {@link DatabaseMapping} of the "root" path, or <code>null</code> if the |
| * "root" path is not a mapping |
| */ |
| final DatabaseMapping getMapping() { |
| if (mapping == null) { |
| mapping = resolveMapping(); |
| } |
| return mapping; |
| } |
| |
| /** |
| * Returns the Expression {@link Expression} for this {@link Declaration}. |
| * |
| * @return The {@link org.eclipse.persistence.expressions.Expression Expression} representing the |
| * information of this {@link Declaration} |
| */ |
| final org.eclipse.persistence.expressions.Expression getQueryExpression() { |
| |
| if (queryExpression == null) { |
| |
| // First create the Expression |
| queryExpression = buildQueryExpression(); |
| |
| // Cache the base expression with its identification variable as well |
| queryContext.addQueryExpressionImp(getVariableName(), queryExpression); |
| } |
| |
| return queryExpression; |
| } |
| |
| @Override |
| public final String getVariableName() { |
| if (identificationVariable == null) { |
| return ExpressionTools.EMPTY_STRING; |
| } |
| return identificationVariable.getVariableName(); |
| } |
| |
| @Override |
| public boolean hasJoins() { |
| return false; |
| } |
| |
| /** |
| * Resolves this {@link Declaration} and returns the associated {@link ClassDescriptor}. For a |
| * {@link org.eclipse.persistence.jpa.jpql.parser.RangeVariableDeclaration}, this will return the actual descriptor for the entity. For |
| * a mapping, this will return the reference descriptor. |
| * |
| * @return The descriptor associated with this declaration |
| */ |
| abstract ClassDescriptor resolveDescriptor(); |
| |
| /** |
| * Resolves this {@link Declaration} and returns the associated {@link DatabaseMapping} if this |
| * represents a path expression. In the case of a {@link org.eclipse.persistence.jpa.jpql.parser.RangeVariableDeclaration}, this will |
| * return <code>null</code>. |
| * |
| * @return The mapping associated with this declaration |
| */ |
| abstract DatabaseMapping resolveMapping(); |
| |
| @Override |
| public String toString() { |
| |
| if (declarationExpression != null) { |
| return declarationExpression.toParsedText(); |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| sb.append(rootPath); |
| |
| if (identificationVariable != null) { |
| sb.append(AbstractExpression.SPACE); |
| sb.append(identificationVariable.getText()); |
| } |
| |
| return sb.toString(); |
| } |
| } |