org.eclipse.persistence.jpa.jpql.tools.model.query.CollectionMemberDeclarationStateObject 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 180e602
/*******************************************************************************
* Copyright (c) 2011, 2014 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 v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation
*
******************************************************************************/
package org.eclipse.persistence.jpa.jpql.tools.model.query;
import java.io.IOException;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.persistence.jpa.jpql.parser.CollectionMemberDeclaration;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedType;
import org.eclipse.persistence.jpa.jpql.tools.utility.iterable.SingleElementListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.*;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.*;
/**
* An identification variable declared by a collection_member_declaration
ranges over
* values of a collection obtained by navigation using a path expression. Such a path expression
* represents a navigation involving the association-fields of an entity abstract schema type.
* Because a path expression can be based on another path expression, the navigation can use the
* association-fields of related entities. An identification variable of a collection member
* declaration is declared using a special operator, the reserved identifier IN
.
* The argument to the IN
operator is a collection-valued path expression. The
* path expression evaluates to a collection type specified as a result of navigation to a
* collection-valued association-field of an entity abstract schema type. The syntax for declaring a
* collection member identification variable is as follows:
*
* BNF: collection_member_declaration ::= IN(collection_valued_path_expression) [AS] identification_variable
* or
* BNF: derived_collection_member_declaration ::= IN superquery_identification_variable.{single_valued_object_field.}*collection_valued_field
*
* @see FromClauseStateObject
* @see CollectionMemberDeclaration
*
* @version 2.5
* @since 2.4
* @author Pascal Filion
*/
@SuppressWarnings({"nls", "unused"}) // unused used for the import statement: see bug 330740
public class CollectionMemberDeclarationStateObject extends AbstractStateObject
implements VariableDeclarationStateObject {
/**
* Flag used to determine if the AS
identifier is used or not.
*/
private boolean as;
/**
* The model object representing the collection-valued association-field of an entity abstract
* schema type.
*/
private CollectionValuedPathExpressionStateObject collectionValuedPath;
/**
* Determines whether this collection member declaration is used as a deriving collection-valued
* path expression.
*/
private boolean derived;
/**
* The model object representing an identification variable evaluating to a collection-valued
* association-field of an entity abstract schema type.
*/
private IdentificationVariableStateObject identificationVariable;
/**
* Notifies the visibility of the AS
identifier has changed.
*/
public static final String AS_PROPERTY = "as";
/**
* Creates a new CollectionMemberDeclarationStateObject
.
*
* @param parent The parent of this state object, which cannot be null
* @exception NullPointerException The given parent cannot be null
*/
public CollectionMemberDeclarationStateObject(AbstractFromClauseStateObject parent) {
super(parent);
}
/**
* Creates a new CollectionMemberDeclarationStateObject
.
*
* @param parent The parent of this state object, which cannot be null
* @param paths The segments that represent the collection-valued path
* @param as Determine whether the AS
identifier is used or not
* @param identificationVariable The identification variable declaring the collection-valued path
* @exception NullPointerException The given parent cannot be null
*/
public CollectionMemberDeclarationStateObject(AbstractFromClauseStateObject parent,
ListIterator paths,
boolean as,
String identificationVariable) {
super(parent);
this.as = as;
getCollectionValuedPath().setPaths(paths);
setIdentificationVariable(identificationVariable);
}
/**
* Creates a new CollectionMemberDeclarationStateObject
.
*
* @param parent The parent of this state object, which cannot be null
* @param paths The segments that represent the collection-valued path
* @param identificationVariable The identification variable declaring the collection-valued path
* @exception NullPointerException The given parent cannot be null
*/
public CollectionMemberDeclarationStateObject(AbstractFromClauseStateObject parent,
ListIterator paths,
String identificationVariable) {
this(parent, paths, false, identificationVariable);
}
/**
* Creates a new CollectionMemberDeclarationStateObject
.
*
* @param parent The parent of this state object, which cannot be null
* @param collectionValuedPath The derived collection-valued path expression
* @exception NullPointerException The given parent cannot be null
*/
public CollectionMemberDeclarationStateObject(SimpleFromClauseStateObject parent,
String collectionValuedPath) {
super(parent);
this.derived = true;
setPath(collectionValuedPath);
}
/**
* {@inheritDoc}
*/
public void accept(StateObjectVisitor visitor) {
visitor.visit(this);
}
/**
* Makes sure the AS
identifier is specified.
*
* @return This object
*/
public CollectionMemberDeclarationStateObject addAs() {
if (!as) {
setAs(true);
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
protected void addChildren(List children) {
super.addChildren(children);
children.add(collectionValuedPath);
children.add(identificationVariable);
}
/**
* Returns the model object representing the collection-valued association-field
* of an entity abstract schema type.
*
* @return The collection-valued association-field of an entity abstract
* schema type
*/
public CollectionValuedPathExpressionStateObject getCollectionValuedPath() {
return collectionValuedPath;
}
/**
* {@inheritDoc}
*/
@Override
public CollectionMemberDeclaration getExpression() {
return (CollectionMemberDeclaration) super.getExpression();
}
/**
* Returns the model object representing an identification variable
* evaluating to a collection-valued association-field of an entity abstract
* schema type.
*
* @return The identification variable portion of this declaration
*/
public IdentificationVariableStateObject getIdentificationVariable() {
return identificationVariable;
}
/**
* {@inheritDoc}
*/
public IManagedType getManagedType(StateObject stateObject) {
if (identificationVariable.isEquivalent(stateObject)) {
return collectionValuedPath.getManagedType();
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public AbstractFromClauseStateObject getParent() {
return (AbstractFromClauseStateObject) super.getParent();
}
/**
* Determines whether the AS
identifier is used or not.
*
* @return true
if the AS
identifier is part
* of the expression; false
otherwise
*/
public boolean hasAs() {
return as;
}
/**
* Determines whether an identification variable was defined.
*
* @return true
if an identification variable is defined; false
otherwise
*/
public boolean hasIdentificationVariable() {
return identificationVariable.hasText();
}
/**
* {@inheritDoc}
*/
public ListIterable identificationVariables() {
return new SingleElementListIterable(identificationVariable);
}
/**
* {@inheritDoc}
*/
@Override
protected void initialize() {
super.initialize();
collectionValuedPath = new CollectionValuedPathExpressionStateObject(this);
identificationVariable = new IdentificationVariableStateObject(this);
}
/**
* Determines whether this collection member declaration is used as a derived collection-valued
* path expression.
*
* @return true
if this collection member declaration is used as this form:
* "IN collection_valued_path_expression
" in a subquery; false
* if it's used as this form: IN(collection_valued_path_expression)
* [AS] identification_variable
" in a top-level or subquery queries
*/
public boolean isDerived() {
return derived;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEquivalent(StateObject stateObject) {
if (super.isEquivalent(stateObject)) {
CollectionMemberDeclarationStateObject declaration = (CollectionMemberDeclarationStateObject) stateObject;
return as == declaration.as &&
derived == declaration.derived &&
identificationVariable.isEquivalent(declaration.identificationVariable) &&
collectionValuedPath .isEquivalent(declaration.collectionValuedPath);
}
return false;
}
/**
* Makes sure the AS
identifier is not specified.
*/
public void removeAs() {
if (as) {
setAs(false);
}
}
/**
* Sets whether the AS
identifier is used or not.
*
* @param as true
if the AS
identifier is part of the expression;
* false
otherwise
*/
public void setAs(boolean as) {
boolean oldAs = this.as;
this.as = as;
firePropertyChanged(AS_PROPERTY, oldAs, as);
}
/**
* Sets whether this collection member declaration is used as a derived collection-valued path
* expression.
*
* @param derived true
if this collection member declaration is used as this form:
* "IN collection_valued_path_expression
" in a subquery; false
* if it's used as this form: IN(collection_valued_path_expression)
* [AS] identification_variable
" in a top-level or subquery queries
*/
public void setDerived(boolean derived) {
this.derived = derived;
}
/**
* Keeps a reference of the {@link CollectionMemberDeclaration parsed object} object, which
* should only be done when this object is instantiated during the conversion of a parsed JPQL
* query into {@link StateObject StateObjects}.
*
* @param expression The {@link CollectionMemberDeclaration parsed object} representing an IN
* expression
*/
public void setExpression(CollectionMemberDeclaration expression) {
super.setExpression(expression);
}
/**
* Sets the new identification variable that will range over the collection-valued path.
*
* @param identificationVariable The new identification variable
*/
public void setIdentificationVariable(String identificationVariable) {
this.identificationVariable.setText(identificationVariable);
}
/**
* Changes the path expression with the list of segments, the identification variable will also
* be updated with the first segment.
*
* @param path The new path expression
*/
public void setPath(String path) {
collectionValuedPath.setPath(path);
}
/**
* Changes the path expression with the list of segments, the identification variable will also
* be updated with the first segment.
*
* @param paths The new path expression
*/
public void setPaths(List paths) {
collectionValuedPath.setPaths(paths);
}
/**
* Changes the path expression with the list of segments, the identification variable will also
* be updated with the first segment.
*
* @param paths The new path expression
*/
public void setPaths(ListIterator paths) {
collectionValuedPath.setPaths(paths);
}
/**
* Changes the path expression with the list of segments, the identification variable will also
* be updated with the first segment.
*
* @param paths The new path expression
*/
public void setPaths(String... paths) {
collectionValuedPath.setPaths(paths);
}
/**
* Toggles the usage of the AS
identifier.
*/
public void toggleAs() {
setAs(!as);
}
/**
* {@inheritDoc}
*/
@Override
protected void toTextInternal(Appendable writer) throws IOException {
writer.append(IN);
if (!derived) {
writer.append(LEFT_PARENTHESIS);
}
else {
writer.append(SPACE);
}
collectionValuedPath.toString(writer);
if (!derived) {
writer.append(RIGHT_PARENTHESIS);
}
if (!derived) {
writer.append(SPACE);
if (as) {
writer.append(AS);
writer.append(SPACE);
}
identificationVariable.toString(writer);
}
}
}