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

org.eclipse.persistence.jpa.jpql.tools.model.query.AbstractSelectStatementStateObject Maven / Gradle / Ivy

There is a newer version: 4.0.3
Show newest version
/*******************************************************************************
 * 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); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy