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

org.eclipse.persistence.internal.jpa.jpql.JPQLQueryHelper Maven / Gradle / Ivy

There is a newer version: 4.0.3
Show newest version
/*******************************************************************************
 * Copyright (c) 2012, 2013 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.internal.jpa.jpql;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.jpql.Assert;
import org.eclipse.persistence.jpa.jpql.parser.AbstractEclipseLinkTraverseChildrenVisitor;
import org.eclipse.persistence.jpa.jpql.parser.DefaultEclipseLinkJPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.DeleteClause;
import org.eclipse.persistence.jpa.jpql.parser.Expression;
import org.eclipse.persistence.jpa.jpql.parser.FromClause;
import org.eclipse.persistence.jpa.jpql.parser.JPQLExpression;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.UpdateClause;
import org.eclipse.persistence.queries.DatabaseQuery;

/**
 * This helper can perform various operations over a JPQL query.
 *
 * @version 2.5
 * @since 2.5
 * @author Pascal Filion
 */
public class JPQLQueryHelper {

	/**
	 * The grammar that defines how to parse a JPQL query.
	 */
	private JPQLGrammar jpqlGrammar;

	/**
	 * Creates a new JPQLQueryHelper which uses the latest JPQL grammar.
	 */
	public JPQLQueryHelper() {
		this(DefaultEclipseLinkJPQLGrammar.instance());
	}

	/**
	 * Creates a new JPQLQueryHelper.
	 *
	 * @param jpqlGrammar The {@link JPQLGrammar} that will determine how to parse JPQL queries
	 * @exception NullPointerException The {@link JPQLGrammar} cannot be null
	 */
	public JPQLQueryHelper(JPQLGrammar jpqlGrammar) {
		super();
		Assert.isNotNull(jpqlGrammar, "The JPQLGrammar cannot be null");
		this.jpqlGrammar = jpqlGrammar;
	}

	/**
	 * Retrieves the list of {@link ClassDescriptor descriptors} corresponding to the entities used
	 * throughout the given JPQL query.
	 *
	 * @param jpqlQuery The JPQL query used to gather the descriptors defined in the declaration clause
	 * @param session The {@link AbstractSession} is used to retrieve the descriptors
	 * @return The list of {@link ClassDescriptors descriptors} used in the JPQL query or an empty
	 * list if the JPQL query is invalid or incomplete
	 */
	public List getClassDescriptors(CharSequence jpqlQuery, AbstractSession session) {

		// Parse the JPQL query
		JPQLExpression jpqlExpression = new JPQLExpression(jpqlQuery, jpqlGrammar, true);

		// Create the context and cache the information
		JPQLQueryContext queryContext = new JPQLQueryContext(jpqlGrammar);
		queryContext.cache(session, null, jpqlExpression, jpqlQuery);

		// Visit the JPQL query and collect the descriptors defined in the declaration clauses
		DescriptorCollector collector = new DescriptorCollector(queryContext);
		jpqlExpression.accept(collector);

		return new ArrayList(collector.descriptors);
	}

	/**
	 * Retrieves the class names and the attribute names mapped to their types that are used in the
	 * constructor expressions defined in the SELECT clause.
	 * 

* For instance, from the following JPQL query: *

*

 SELECT new test.example.Employee(e.name, e.id),
	 *        new test.example.Address(a.zipcode)
	 * FROM Employee e, Address a
*

* The return object is *

 |- test.example.Employee
	 * |-   |- name : String
	 * |-   |- id : int
	 * |- test.example.Address
	 *      |- zipcode : int
* * @param session The {@link AbstractSession} is used to retrieve the mappings used in the * constructor items * @return The holder of the result */ public List getConstructorQueryMappings(AbstractSession session) { List allMappings = new LinkedList(); for (DatabaseQuery query : session.getJPAQueries()) { ConstructorQueryMappings mappings = getConstructorQueryMappings(session, query); allMappings.add(mappings); } return allMappings; } /** * Retrieves the class names and the attribute names mapped to their types that are used in the * constructor expressions defined in the SELECT clause. *

* For instance, from the following JPQL query: *

*

 SELECT new test.example.Address(a.streetName, a.zipcode)
	 * FROM Address a
*

* The return object is *

 test.example.Address
	 *    |- BasicMapping(streetName) : String
	 *    |- BasicMapping(zipcode) : int
* * @param session The {@link AbstractSession} is used to retrieve the mappings used in the * constructor items * @return The holder of the result */ public ConstructorQueryMappings getConstructorQueryMappings(AbstractSession session, DatabaseQuery query) { JPQLQueryContext queryContext = new JPQLQueryContext(query, jpqlGrammar); ConstructorQueryMappings mappings = new ConstructorQueryMappings(query); mappings.populate(jpqlGrammar); return mappings; } /** * Returns the JPQL grammar that will be used to define how to parse a JPQL query. * * @return The grammar that will determine how to parse a JPQL query */ public JPQLGrammar getGrammar() { return jpqlGrammar; } private static class DescriptorCollector extends AbstractEclipseLinkTraverseChildrenVisitor { private Set descriptors; private JPQLQueryContext queryContext; private DeclarationResolver resolver; /** * Creates a new DescriptorCollector. */ private DescriptorCollector(JPQLQueryContext queryContext) { super(); this.descriptors = new HashSet(); this.queryContext = queryContext; } private void collectDescriptors(Expression expression, DeclarationResolver resolver) { resolver.populate(expression); for (Declaration declaration : resolver.getDeclarations()) { ClassDescriptor descriptor = declaration.getDescriptor(); if (descriptor != null) { descriptors.add(descriptor); } } } /** * {@inheritDoc} */ @Override public void visit(DeleteClause expression) { resolver = new DeclarationResolver(queryContext, null); collectDescriptors(expression, resolver); } /** * {@inheritDoc} */ @Override public void visit(FromClause expression) { resolver = new DeclarationResolver(queryContext, null); collectDescriptors(expression, resolver); } /** * {@inheritDoc} */ @Override public void visit(SimpleSelectStatement expression) { resolver = new DeclarationResolver(queryContext, resolver); collectDescriptors(expression, resolver); resolver = resolver.getParent(); } /** * {@inheritDoc} */ @Override public void visit(UpdateClause expression) { resolver = new DeclarationResolver(queryContext, null); collectDescriptors(expression, resolver); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy