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: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 2012, 2023 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.internal.jpa.jpql;

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;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * 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 ClassDescriptor 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); } } } @Override public void visit(DeleteClause expression) { resolver = new DeclarationResolver(queryContext, null); collectDescriptors(expression, resolver); } @Override public void visit(FromClause expression) { resolver = new DeclarationResolver(queryContext, null); collectDescriptors(expression, resolver); } @Override public void visit(SimpleSelectStatement expression) { resolver = new DeclarationResolver(queryContext, resolver); collectDescriptors(expression, resolver); resolver = resolver.getParent(); } @Override public void visit(UpdateClause expression) { resolver = new DeclarationResolver(queryContext, null); collectDescriptors(expression, resolver); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy