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

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

There is a newer version: 4.0.2
Show newest version
/*
 * Copyright (c) 2012, 2018 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 java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.jpa.jpql.parser.AbstractEclipseLinkExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.AbstractPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionExpression;
import org.eclipse.persistence.jpa.jpql.parser.CollectionValuedPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.ConstructorExpression;
import org.eclipse.persistence.jpa.jpql.parser.JPQLExpression;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.SelectClause;
import org.eclipse.persistence.jpa.jpql.parser.SelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.StateFieldPathExpression;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.DatabaseQuery;

/**
 * This object scans a {@link DatabaseQuery} and checks if it's a constructor query. If it is one,
 * then the fully qualified class name and the persistent fields will be available.
 *
 * @version 2.5
 * @since 2.5
 * @author Pascal Filion
 */
public final class ConstructorQueryMappings {

    /**
     * The fully qualified class name defined in the constructor expression if one is defined,
     * otherwise null.
     */
    private String className;

    /**
     * The list of {@link DatabaseMapping} representing the parameter arguments if the JPQL query
     * does contain a constructor expression.
     */
    private List mappings;

    /**
     * The {@link DatabaseQuery} for which its JPQL query was scanned to check if it's constructor
     * query and if so, to gather the information.
     */
    private DatabaseQuery query;

    /**
     * Creates a new ConstructorQueryMappings.
     *
     * @param query The {@link DatabaseQuery} for which its JPQL query was scanned to check if it's
     * constructor query and if so, to gather the information.
     */
    ConstructorQueryMappings(DatabaseQuery query) {
        super();
        this.query = query;
        this.mappings = new LinkedList();
    }

    /**
     * Returns the class name used to define the constructor expression.
     *
     * @return Either the fully qualified class name used in the constructor expression or
     * null if the query is not a constructor query
     */
    public String getClassName() {
        return className;
    }

    /**
     * Returns the {@link DatabaseQuery} for which its JPQL query was scanned to check if it's
     * constructor query and if so, to gather the information.
     *
     * @return The {@link DatabaseQuery} that was scanned
     */
    public DatabaseQuery getQuery() {
        return query;
    }

    /**
     * Determines whether the JPQL query is a constructor query, i.e. the select expression is a
     * constructor expression.
     * 

* Example: SELECT new test.example.Employee(e.name, e.id) FROM Employee e * * @return true if the SELECT clause has a single select item * and it's a constructor expression; false otherwise */ public boolean isConstructorQuery() { return className != null; } /** * Returns a non-null {@link Iterable} over the ordered list of {@link DatabaseMapping} * objects that represents the parameter arguments defined in the constructor expression. * * @return The list contains the persistent fields that were passed to the constructor */ public Iterable mappings() { if (mappings.isEmpty()) { return Collections.emptyList(); } return new LinkedList(mappings); } /** * Populates this object by scanning the JPQL query using the given JPQL grammar. * * @param jpqlGrammar The {@link JPQLGrammar} how the JPQL query is parsed */ void populate(JPQLGrammar jpqlGrammar) { JPQLQueryContext queryContext = new JPQLQueryContext(query, jpqlGrammar); ConstructorVisitor visitor = new ConstructorVisitor(queryContext); queryContext.getJPQLExpression().accept(visitor); } /** * This visitor visits the constructor items and adds the attribute type mapped to the name. *

* Example:
* e.name -> "name" : String
* e.address.zipcode -> "zipcode" : int */ private class ConstructorItemVisitor extends AbstractEclipseLinkExpressionVisitor { private final JPQLQueryContext queryContext; ConstructorItemVisitor(JPQLQueryContext queryContext) { super(); this.queryContext = queryContext; } /** * {@inheritDoc} */ @Override public void visit(CollectionExpression expression) { expression.acceptChildren(this); } /** * {@inheritDoc} */ @Override public void visit(CollectionValuedPathExpression expression) { visitPathExpression(expression); } /** * {@inheritDoc} */ @Override public void visit(StateFieldPathExpression expression) { visitPathExpression(expression); } private void visitPathExpression(AbstractPathExpression expression) { DatabaseMapping mapping = queryContext.resolveMapping(expression); if (mapping != null) { mappings.add(mapping); } } } /** * Visits the JPQL query and gather the information contained in the constructor expressions. */ private class ConstructorVisitor extends AbstractEclipseLinkExpressionVisitor { private final JPQLQueryContext queryContext; ConstructorVisitor(JPQLQueryContext queryContext) { super(); this.queryContext = queryContext; } private DynamicClassLoader classLoader() { return (DynamicClassLoader) queryContext.getSession().getProperty(PersistenceUnitProperties.CLASSLOADER); } /** * {@inheritDoc} */ @Override public void visit(ConstructorExpression expression) { ConstructorQueryMappings.this.className = expression.getClassName(); // Visit the constructor items and retrieve the persistent fields ConstructorItemVisitor visitor = new ConstructorItemVisitor(queryContext); expression.getConstructorItems().accept(visitor); } /** * {@inheritDoc} */ @Override public void visit(JPQLExpression expression) { expression.getQueryStatement().accept(this); } /** * {@inheritDoc} */ @Override public void visit(SelectClause expression) { expression.getSelectExpression().accept(this); } /** * {@inheritDoc} */ @Override public void visit(SelectStatement expression) { expression.getSelectClause().accept(this); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy