org.eclipse.persistence.jpa.jpql.parser.CollectionMemberExpression 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, 2020 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.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.WordParser;
/**
* This expression tests whether the designated value is a member of the collection specified by the
* collection-valued path expression. If the collection-valued path expression designates an empty
* collection, the value of the MEMBER OF expression is FALSE and the value of the
* NOT MEMBER OF expression is TRUE. Otherwise, if the value of the collection-valued
* path expression or single-valued association-field path expression in the collection member
* expression is NULL or unknown, the value of the collection member expression is unknown.
*
* BNF: collection_member_expression ::= entity_or_value_expression [NOT] MEMBER [OF] collection_valued_path_expression
*
* @version 2.5
* @since 2.3
* @author Pascal Filion
*/
public final class CollectionMemberExpression extends AbstractExpression {
/**
* The {@link Expression} representing the collection-valued path expression.
*/
private AbstractExpression collectionValuedPathExpression;
/**
* The {@link Expression} representing the entity expression.
*/
private AbstractExpression entityExpression;
/**
* Determines whether a whitespace was parsed after MEMBER.
*/
private boolean hasSpaceAfterMember;
/**
* Determines whether a whitespace was parsed after OF.
*/
private boolean hasSpaceAfterOf;
/**
* The actual MEMBER identifier found in the string representation of the JPQL query.
*/
private String memberIdentifier;
/**
* The actual NOT identifier found in the string representation of the JPQL query.
*/
private String notIdentifier;
/**
* The actual OF identifier found in the string representation of the JPQL query.
*/
private String ofIdentifier;
/**
* Creates a new CollectionMemberExpression
.
*
* @param parent The parent of this expression
* @param expression The entity expression that was parsed before parsing this one
*/
public CollectionMemberExpression(AbstractExpression parent, AbstractExpression expression) {
super(parent);
if (expression != null) {
this.entityExpression = expression;
this.entityExpression.setParent(this);
}
}
@Override
public void accept(ExpressionVisitor visitor) {
visitor.visit(this);
}
@Override
public void acceptChildren(ExpressionVisitor visitor) {
getEntityExpression().accept(visitor);
getCollectionValuedPathExpression().accept(visitor);
}
@Override
protected void addChildrenTo(Collection children) {
children.add(getEntityExpression());
children.add(getCollectionValuedPathExpression());
}
@Override
protected void addOrderedChildrenTo(List children) {
// Entity expression
if (entityExpression != null) {
children.add(entityExpression);
}
// 'NOT'
if (notIdentifier != null) {
if (hasEntityExpression()) {
children.add(buildStringExpression(SPACE));
}
children.add(buildStringExpression(NOT));
}
if ((notIdentifier != null) || hasEntityExpression()) {
children.add(buildStringExpression(SPACE));
}
// 'MEMBER'
children.add(buildStringExpression(MEMBER));
if (hasSpaceAfterMember) {
children.add(buildStringExpression(SPACE));
}
// 'OF'
if (ofIdentifier != null) {
children.add(buildStringExpression(OF));
}
if (hasSpaceAfterOf) {
children.add(buildStringExpression(SPACE));
}
// Collection-valued path expression
if (collectionValuedPathExpression != null) {
children.add(collectionValuedPathExpression);
}
}
@Override
public JPQLQueryBNF findQueryBNF(Expression expression) {
if ((entityExpression != null) && entityExpression.isAncestor(expression)) {
return getQueryBNF(EntityExpressionBNF.ID);
}
if ((collectionValuedPathExpression != null) && collectionValuedPathExpression.isAncestor(expression)) {
return getQueryBNF(CollectionValuedPathExpressionBNF.ID);
}
return super.findQueryBNF(expression);
}
/**
* Returns the actual MEMBER identifier found in the string representation of the JPQL
* query, which has the actual case that was used.
*
* @return The MEMBER identifier that was actually parsed
*/
public String getActualMemberIdentifier() {
return memberIdentifier;
}
/**
* Returns the actual NOT identifier found in the string representation of the JPQL query,
* which has the actual case that was used.
*
* @return The NOT identifier that was actually parsed, or an empty string if it was not
* parsed
*/
public String getActualNotIdentifier() {
return (notIdentifier != null) ? notIdentifier : ExpressionTools.EMPTY_STRING;
}
/**
* Returns the actual OF identifier found in the string representation of the JPQL query,
* which has the actual case that was used.
*
* @return The OF identifier that was actually parsed, or an empty string if it was not
* parsed
*/
public String getActualOfIdentifier() {
return (ofIdentifier != null) ? ofIdentifier : ExpressionTools.EMPTY_STRING;
}
/**
* Returns the {@link Expression} representing the collection-valued path expression.
*
* @return The expression that was parsed representing the collection valued path expression
*/
public Expression getCollectionValuedPathExpression() {
if (collectionValuedPathExpression == null) {
collectionValuedPathExpression = buildNullExpression();
}
return collectionValuedPathExpression;
}
/**
* Returns the {@link Expression} representing the entity expression.
*
* @return The expression that was parsed representing the entity expression
*/
public Expression getEntityExpression() {
if (entityExpression == null) {
entityExpression = buildNullExpression();
}
return entityExpression;
}
/**
* Returns the identifier for this expression that may include NOT and OF if it was parsed.
*
* @return Either MEMBER, NOT MEMBER, NOT MEMBER OF or MEMBER OF
*/
public String getIdentifier() {
if ((notIdentifier != null) && (ofIdentifier != null)) {
return NOT_MEMBER_OF;
}
if (notIdentifier != null) {
return NOT_MEMBER;
}
if (ofIdentifier != null) {
return MEMBER_OF;
}
return MEMBER;
}
@Override
public JPQLQueryBNF getQueryBNF() {
return getQueryBNF(CollectionMemberExpressionBNF.ID);
}
/**
* Determines whether the collection-valued path expression was parsed.
*
* @return true
if the collection-valued path expression was parsed;
* false
otherwise
*/
public boolean hasCollectionValuedPathExpression() {
return collectionValuedPathExpression != null &&
!collectionValuedPathExpression.isNull();
}
/**
* Determines whether the entity expression was parsed.
*
* @return true
if the entity expression was parsed; false
otherwise
*/
public boolean hasEntityExpression() {
return entityExpression != null &&
!entityExpression.isNull();
}
/**
* Determines whether the identifier NOT was parsed.
*
* @return true
if the identifier NOT was parsed; false
otherwise
*/
public boolean hasNot() {
return notIdentifier != null;
}
/**
* Determines whether the identifier OF was parsed.
*
* @return true
if the identifier OF was parsed; false
otherwise
*/
public boolean hasOf() {
return ofIdentifier != null;
}
/**
* Determines whether a whitespace was found after MEMBER.
*
* @return true
if there was a whitespace after MEMBER; false
otherwise
*/
public boolean hasSpaceAfterMember() {
return hasSpaceAfterMember;
}
/**
* Determines whether a whitespace was found after OF.
*
* @return true
if there was a whitespace after OF; false
otherwise
*/
public boolean hasSpaceAfterOf() {
return hasSpaceAfterOf;
}
@Override
protected void parse(WordParser wordParser, boolean tolerant) {
// Parse 'NOT'
if (wordParser.startsWithIgnoreCase('N')) {
notIdentifier = wordParser.moveForward(NOT);
wordParser.skipLeadingWhitespace();
}
// Parse 'MEMBER'
memberIdentifier = wordParser.moveForward(MEMBER);
hasSpaceAfterMember = wordParser.skipLeadingWhitespace() > 0;
// Parse 'OF'
if (wordParser.startsWithIdentifier(OF)) {
ofIdentifier = wordParser.moveForward(OF);
hasSpaceAfterOf = wordParser.skipLeadingWhitespace() > 0;
}
// Parse the collection-valued path expression
collectionValuedPathExpression = parse(
wordParser,
CollectionValuedPathExpressionBNF.ID,
tolerant
);
}
@Override
protected void toParsedText(StringBuilder writer, boolean actual) {
// Entity expression
if (entityExpression != null) {
entityExpression.toParsedText(writer, actual);
}
// 'NOT'
if (notIdentifier != null) {
if (hasEntityExpression()) {
writer.append(SPACE);
}
writer.append(actual ? notIdentifier : NOT);
}
if ((notIdentifier != null) || hasEntityExpression()) {
writer.append(SPACE);
}
// 'MEMBER'
writer.append(actual ? memberIdentifier : MEMBER);
if (hasSpaceAfterMember) {
writer.append(SPACE);
}
// 'OF'
if (ofIdentifier != null) {
writer.append(actual ? ofIdentifier : OF);
}
if (hasSpaceAfterOf) {
writer.append(SPACE);
}
// Collection-valued path expression
if (collectionValuedPathExpression != null) {
collectionValuedPathExpression.toParsedText(writer, actual);
}
}
}