org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractSelectStatementStateObject 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 org.eclipse.persistence.jpa.jpql.parser.AbstractSelectStatement;
import org.eclipse.persistence.jpa.jpql.tools.spi.IEntity;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.*;
/**
* This state object represents the select statement, which has at least a SELECT
* clause and a FROM
clause.
*
* @see SelectStatementStateObject
* @see FromClauseStateObject
* @see GroupByClauseStateObject
* @see HavingClauseStateObject
* @see SelectClauseStateObject
* @see WhereClauseStateObject
*
* @see AbstractSelectStatement
*
* @version 2.5
* @since 2.4
* @author Pascal Filion
*/
@SuppressWarnings("nls")
public abstract class AbstractSelectStatementStateObject extends AbstractStateObject {
/**
* The state object representing the FROM
clause.
*/
private AbstractFromClauseStateObject fromClause;
/**
* The state object representing the GROUP BY
clause.
*/
private GroupByClauseStateObject groupByClause;
/**
* The state object representing the HAVING
clause.
*/
private HavingClauseStateObject havingClause;
/**
* The state object representing the SELECT
clause.
*/
private AbstractSelectClauseStateObject selectClause;
/**
* The state object representing the WHERE
clause.
*/
private WhereClauseStateObject whereClause;
/**
* Notify the state object representing the GROUP BY
clause has changed.
*/
public static String GROUP_BY_CLAUSE_PROPERTY = "groupByClause";
/**
* Notify the state object representing the HAVING
clause has changed.
*/
public static String HAVING_CLAUSE_PROPERTY = "havingClause";
/**
* Notify the state object representing the WHERE
clause has changed.
*/
public static String WHERE_CLAUSE_PROPERTY = "whereClause";
/**
* Creates a new AbstractSelectStatementStateObject
.
*
* @param parent The parent of this state object, which cannot be null
* @exception NullPointerException The given parent cannot be null
*/
protected AbstractSelectStatementStateObject(StateObject parent) {
super(parent);
}
/**
* {@inheritDoc}
*/
@Override
protected void addChildren(List children) {
super.addChildren(children);
children.add(selectClause);
children.add(fromClause);
if (whereClause != null) {
children.add(whereClause);
}
if (groupByClause != null) {
children.add(groupByClause);
}
if (havingClause != null) {
children.add(havingClause);
}
}
/**
* Adds a new collection declaration to the FROM
clause.
*
* @return The {@link CollectionMemberDeclarationStateObject} representing the collection
* declaration
*/
public CollectionMemberDeclarationStateObject addCollectionDeclaration() {
return getFromClause().addCollectionDeclaration();
}
/**
* Adds a new collection declaration to the FROM
clause.
*
* @param collectionValuedPath The collection-valued path expression
* @param identificationVariable The variable defining the collection-valued path expression
* @return The {@link CollectionMemberDeclarationStateObject} representing the collection
* declaration
*/
public CollectionMemberDeclarationStateObject addCollectionDeclaration(String collectionValuedPath,
String identificationVariable) {
return getFromClause().addCollectionDeclaration(collectionValuedPath, identificationVariable);
}
/**
* Adds the GROUP BY
clause. The clause is not added if it's already present.
*
* @return The {@link GroupByClauseStateObject}
*/
public GroupByClauseStateObject addGroupByClause() {
if (!hasGroupByClause()) {
setGroupByClause(new GroupByClauseStateObject(this));
}
return groupByClause;
}
/**
* Adds the GROUP BY
clause and parses the given JPQL fragment. The clause is
* not added if it's already present.
*
* @param jpqlFragment The fragment of the JPQL to parse that represents the group by items, the
* fragment cannot start with GROUP BY
* @return The {@link GroupByClauseStateObject}
*/
public GroupByClauseStateObject addGroupByClause(String jpqlFragment) {
GroupByClauseStateObject stateObject = addGroupByClause();
stateObject.parse(jpqlFragment);
return stateObject;
}
/**
* Adds the HAVING
clause. The clause is not added if it's already present.
*
* @return The {@link GroupByClauseStateObject}
*/
public HavingClauseStateObject addHavingClause() {
if (!hasHavingClause()) {
setHavingClause(new HavingClauseStateObject(this));
}
return havingClause;
}
/**
* Adds the HAVING
clause and parses the given JPQL fragment. The clause is
* not added if it's already present.
*
* @param jpqlFragment The fragment of the JPQL to parse that represents the conditional expression,
* the fragment cannot start with HAVING
* @return The {@link HavingClauseStateObject}
*/
public HavingClauseStateObject addHavingClause(String jpqlFragment) {
HavingClauseStateObject stateObject = addHavingClause();
stateObject.parse(jpqlFragment);
return stateObject;
}
/**
* Adds a new range variable declaration to the FROM
clause.
*
* @return The {@link StateObject} representing the new range variable declaration
*/
public IdentificationVariableDeclarationStateObject addRangeDeclaration() {
return getFromClause().addRangeDeclaration();
}
/**
* Adds to this select statement a new range variable declaration.
*
* @param entity The external form of the entity to add to the declaration list
* @param identificationVariable The unique identifier identifying the given {@link IEntity}
* @return The {@link StateObject} representing the new range variable declaration
*/
public IdentificationVariableDeclarationStateObject addRangeDeclaration(IEntity entity,
String identificationVariable) {
return getFromClause().addRangeDeclaration(entity, identificationVariable);
}
/**
* Adds to this select statement a new range variable declaration.
*
* @param entityName The name of the entity
* @param identificationVariable The unique identifier identifying the entity
* @return The {@link StateObject} representing the range variable declaration
*/
public IdentificationVariableDeclarationStateObject addRangeDeclaration(String entityName,
String identificationVariable) {
return getFromClause().addRangeDeclaration(entityName, identificationVariable);
}
/**
* Adds the WHERE
clause. The clause is not added if it's already present.
*
* @return The {@link GroupByClauseStateObject}
*/
public WhereClauseStateObject addWhereClause() {
if (!hasWhereClause()) {
setWhereClause(new WhereClauseStateObject(this));
}
return whereClause;
}
/**
* Adds the WHERE
clause and parses the given JPQL fragment. The clause is
* not added if it's already present.
*
* @param jpqlFragment The fragment of the JPQL to parse that represents the conditional expression,
* the fragment cannot start with WHERE
* @return The {@link WhereClauseStateObject}
*/
public WhereClauseStateObject addWhereClause(String jpqlFragment) {
WhereClauseStateObject stateObject = addWhereClause();
stateObject.parse(jpqlFragment);
return stateObject;
}
/**
* Creates the state object representing the FROM
clause.
*
* @return A concrete instance of {@link AbstractFromClauseStateObject}
*/
protected abstract AbstractFromClauseStateObject buildFromClause();
/**
* Creates the state object representing the SELECT
clause.
*
* @return A concrete instance of {@link AbstractSelectClauseStateObject}
*/
protected abstract AbstractSelectClauseStateObject buildSelectClause();
/**
* Returns the list of {@link VariableDeclarationStateObject} defining the variable declarations,
* which are mapping an entity to a variable or a collection-valued member to a variable.
*
* Example:
*
* Employee e
* IN (e.employees) AS emps
*
*
* @return The list of {@link VariableDeclarationStateObject}
*/
public ListIterable declarations() {
return fromClause.items();
}
/**
* {@inheritDoc}
*/
@Override
public IdentificationVariableStateObject findIdentificationVariable(String identificationVariable) {
return fromClause.findIdentificationVariable(identificationVariable);
}
/**
* {@inheritDoc}
*/
@Override
public DeclarationStateObject getDeclaration() {
return fromClause;
}
/**
* {@inheritDoc}
*/
@Override
public AbstractSelectStatement getExpression() {
return (AbstractSelectStatement) super.getExpression();
}
/**
* Returns the state object representing the FROM
clause.
*
* @return The state object representing the FROM
clause, which is never
* null
*/
public AbstractFromClauseStateObject getFromClause() {
return fromClause;
}
/**
* Returns the state object representing the GROUP BY
clause.
*
* @return Either the actual state object representing the GROUP BY
clause or
* null
if it's not present
*/
public GroupByClauseStateObject getGroupByClause() {
return groupByClause;
}
/**
* Returns the state object representing the HAVING
clause.
*
* @return Either the actual state object representing the HAVING
clause or
* null
if it's not present
*/
public HavingClauseStateObject getHavingClause() {
return havingClause;
}
/**
* Returns the state object representing the SELECT
clause.
*
* @return Either the actual state object representing the SELECT
clause,
* which is never null
*/
public AbstractSelectClauseStateObject getSelectClause() {
return selectClause;
}
/**
* Returns the state object representing the WHERE
clause.
*
* @return Either the actual state object representing the WHERE
clause or
* the null
state object since null
is never returned
*/
public WhereClauseStateObject getWhereClause() {
return whereClause;
}
/**
* Returns the state object representing the GROUP BY
clause.
*
* @return Either the actual state object representing the GROUP BY
clause or
* null
if it's not present
*/
public boolean hasGroupByClause() {
return groupByClause != null;
}
/**
* Returns the state object representing the HAVING
clause.
*
* @return Either the actual state object representing the HAVING
clause or
* null
if it's not present
*/
public boolean hasHavingClause() {
return havingClause != null;
}
/**
* Returns the state object representing the WHERE
clause.
*
* @return Either the actual state object representing the WHERE
clause or
* null
if it's not present
*/
public boolean hasWhereClause() {
return whereClause != null;
}
/**
* Returns the {@link IdentificationVariableStateObject IdentificationVariableStateObjects}
* holding onto the identification variables, which are the variables defined in the
* FROM
clause.
*
* Example:
*
* Employee e
; e is returned
* IN (e.employees) AS emps
; emps is returned
* Manager m JOIN m.employees emps
; m and emps are returned
*
*
* @return The list of {@link IdentificationVariableStateObject IdentificationVariableStateObjects}
*/
public Iterable identificationVariables() {
return fromClause.identificationVariables();
}
/**
* {@inheritDoc}
*/
@Override
protected void initialize() {
super.initialize();
selectClause = buildSelectClause();
fromClause = buildFromClause();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEquivalent(StateObject stateObject) {
if (super.isEquivalent(stateObject)) {
AbstractSelectStatementStateObject select = (AbstractSelectStatementStateObject) stateObject;
return areEquivalent(selectClause, select.selectClause) &&
areEquivalent(fromClause, select.fromClause) &&
areEquivalent(fromClause, select.fromClause) &&
areEquivalent(whereClause, select.whereClause) &&
areEquivalent(groupByClause, select.groupByClause) &&
areEquivalent(havingClause, select.havingClause);
}
return false;
}
/**
* Parses the given JPQL fragment and create the select item. For the top-level query, the
* fragment can contain several select items but for a subquery, it can represent only one.
*
* @param jpqlFragment The portion of the query representing one or several select items
*/
public void parseSelect(String jpqlFragment) {
getSelectClause().parse(jpqlFragment);
}
/**
* Removes the GROUP BY
clause.
*/
public void removeGroupByClause() {
setGroupByClause(null);
}
/**
* Removes the HAVING
clause.
*/
public void removeHavingClause() {
setHavingClause(null);
}
/**
* Removes the WHERE
clause.
*/
public void removeWhereClause() {
setWhereClause(null);
}
private void setGroupByClause(GroupByClauseStateObject groupByClause) {
GroupByClauseStateObject oldGroupByClause = this.groupByClause;
this.groupByClause = groupByClause;
firePropertyChanged(GROUP_BY_CLAUSE_PROPERTY, oldGroupByClause, groupByClause);
}
private void setHavingClause(HavingClauseStateObject havingClause) {
HavingClauseStateObject oldHavingClause = this.havingClause;
this.havingClause = havingClause;
firePropertyChanged(HAVING_CLAUSE_PROPERTY, oldHavingClause, havingClause);
}
private void setWhereClause(WhereClauseStateObject whereClause) {
WhereClauseStateObject oldWhereClause = this.whereClause;
this.whereClause = whereClause;
firePropertyChanged(WHERE_CLAUSE_PROPERTY, oldWhereClause, whereClause);
}
/**
* Either adds or removes the state object representing the GROUP BY
clause.
*/
public void toggleGroupByClause() {
if (hasGroupByClause()) {
removeGroupByClause();
}
else {
addGroupByClause();
}
}
/**
* Either adds or removes the state object representing the HAVING
clause.
*/
public void toggleHavingClause() {
if (hasHavingClause()) {
removeHavingClause();
}
else {
addHavingClause();
}
}
/**
* Either adds or removes the state object representing the WHERE
clause.
*/
public void toggleWhereClause() {
if (hasWhereClause()) {
removeWhereClause();
}
else {
addWhereClause();
}
}
/**
* {@inheritDoc}
*/
@Override
protected void toTextInternal(Appendable writer) throws IOException {
selectClause.toString(writer);
writer.append(SPACE);
fromClause.toString(writer);
if (whereClause != null) {
writer.append(SPACE);
whereClause.toString(writer);
}
if (groupByClause != null) {
writer.append(SPACE);
groupByClause.toString(writer);
}
if (havingClause != null) {
writer.append(SPACE);
havingClause.toString(writer);
}
}
}