Package org.eclipse.persistence.jpa.jpql

Source Code of org.eclipse.persistence.jpa.jpql.FromSubqueryResolver$VirtualMappingBuilder

/*******************************************************************************
* 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.jpa.jpql;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.persistence.jpa.jpql.parser.AbstractEclipseLinkExpressionVisitor;
import org.eclipse.persistence.jpa.jpql.parser.CollectionExpression;
import org.eclipse.persistence.jpa.jpql.parser.Expression;
import org.eclipse.persistence.jpa.jpql.parser.ResultVariable;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectClause;
import org.eclipse.persistence.jpa.jpql.parser.SimpleSelectStatement;
import org.eclipse.persistence.jpa.jpql.parser.StateFieldPathExpression;
import org.eclipse.persistence.jpa.jpql.spi.IManagedType;
import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeProvider;
import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeVisitor;
import org.eclipse.persistence.jpa.jpql.spi.IMapping;
import org.eclipse.persistence.jpa.jpql.spi.IMappingType;
import org.eclipse.persistence.jpa.jpql.spi.IType;
import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
import org.eclipse.persistence.jpa.jpql.util.iterator.CloneIterator;
import org.eclipse.persistence.jpa.jpql.util.iterator.IterableIterator;

import static org.eclipse.persistence.jpa.jpql.LiteralType.*;

/**
* This {@link Resolver} wraps a subquery that is used as the "root" object in a query's declaration.
* <p>
* Example:
* <p>
* <pre><code> SELECT e.firstName
* FROM Employee e, (SELECT count(e2), e2.firstName FROM Employee e2) e3
* WHERE e.firstName = e3.firstName</code></pre>
*
* @version 2.4
* @since 2.4
* @author Pascal Filion
*/
public class FromSubqueryResolver extends Resolver {

  /**
   * The virtual {@link IManagedType} representing the subquery.
   */
  private IManagedType managedType;

  /**
   * The {@link JPQLQueryContext} is used to query information about the application metadata and
   * cached information.
   */
  private JPQLQueryContext queryContext;

  /**
   * The subquery being defined as a "root" object.
   */
  private SimpleSelectStatement subquery;

  /**
   * Creates a new <code>FromSubqueryResolver</code>.
   *
   * @param parent The parent of this resolver, which is never <code>null</code>
   * @param queryContext The context used to query information about the application metadata and
   * cached information
   * @param subquery
   * @exception NullPointerException If the parent is <code>null</code>
   */
  public FromSubqueryResolver(Resolver parent,
                              JPQLQueryContext queryContext,
                              SimpleSelectStatement subquery) {

    super(parent);
    this.subquery     = subquery;
    this.queryContext = queryContext;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void accept(ResolverVisitor visitor) {
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected IType buildType() {
    return getManagedType().getType();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected ITypeDeclaration buildTypeDeclaration() {
    return getType().getTypeDeclaration();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public IManagedType getManagedType() {
    if (managedType == null) {
      managedType = new VirtualManagedType();
    }
    return managedType;
  }

  /**
   * This {@link IManagedType} represents a virtual managed type where its content will be derived
   * from the subquery.
   */
  protected class VirtualManagedType implements IManagedType {

    /**
     * The virtual {@link IMapping mappings} representing what is selected.
     */
    private Map<String, IMapping> mappings;

    /**
     * {@inheritDoc}
     */
    public void accept(IManagedTypeVisitor visitor) {
    }

    /**
     * {@inheritDoc}
     */
    public int compareTo(IManagedType managedType) {
      return getType().getName().compareTo(managedType.getType().getName());
    }

    /**
     * {@inheritDoc}
     */
    public IMapping getMappingNamed(String name) {
      initializeMappings();
      return mappings.get(name);
    }

    /**
     * {@inheritDoc}
     */
    public IManagedTypeProvider getProvider() {
      return FromSubqueryResolver.this.getProvider();
    }

    /**
     * {@inheritDoc}
     */
    public IType getType() {
      return getProvider().getTypeRepository().getType(IType.UNRESOLVABLE_TYPE);
    }

    private void initializeMappings() {

      if (mappings == null) {
        mappings = new HashMap<String, IMapping>();

        // Create virtual mappings that wraps the select items
        VirtualMappingBuilder builder = new VirtualMappingBuilder();
        builder.parent   = this;
        builder.mappings = mappings;

        subquery.accept(builder);
      }
    }

    /**
     * {@inheritDoc}
     */
    public IterableIterator<IMapping> mappings() {
      initializeMappings();
      return new CloneIterator<IMapping>(mappings.values());
    }
  }

  /**
   * This virtual {@link IMapping} wraps one of the select items.
   */
  protected class VirtualMapping implements IMapping {

    private String name;
    private IManagedType parent;
    private Resolver resolver;

    protected VirtualMapping(IManagedType parent, String name, Resolver resolver) {
      super();
      this.name     = name;
      this.parent   = parent;
      this.resolver = resolver;
    }

    /**
     * {@inheritDoc}
     */
    public int compareTo(IMapping mapping) {
      return getName().compareTo(mapping.getName());
    }

    /**
     * {@inheritDoc}
     */
    public int getMappingType() {
      IMapping mapping = resolver.getMapping();
      return (mapping != null) ? mapping.getMappingType() : IMappingType.TRANSIENT;
    }

    /**
     * {@inheritDoc}
     */
    public String getName() {
      return name;
    }

    /**
     * {@inheritDoc}
     */
    public IManagedType getParent() {
      return parent;
    }

    /**
     * {@inheritDoc}
     */
    public IType getType() {
      return resolver.getType();
    }

    /**
     * {@inheritDoc}
     */
    public ITypeDeclaration getTypeDeclaration() {
      return resolver.getTypeDeclaration();
    }

    /**
     * {@inheritDoc}
     */
    public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
      // TODO: Can we do this???
      return getType().hasAnnotation(annotationType);
    }

    /**
     * {@inheritDoc}
     */
    public boolean isCollection() {
      IMapping mapping = resolver.getMapping();
      return (mapping != null) ? mapping.isCollection() : false;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isProperty() {
      IMapping mapping = resolver.getMapping();
      return (mapping != null) ? mapping.isProperty() : false;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isRelationship() {
      IMapping mapping = resolver.getMapping();
      return (mapping != null) ? mapping.isRelationship() : false;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isTransient() {
      IMapping mapping = resolver.getMapping();
      return (mapping != null) ? mapping.isTransient() : false;
    }
  }

  /**
   * This visitor will traverse the <code><b>SELECT</b></code> clause and create virtual mappings
   * for the state field path expressions and any expression aliased with a result variable.
   */
  protected class VirtualMappingBuilder extends AbstractEclipseLinkExpressionVisitor {

    /**
     * The virtual {@link IMapping} that wraps a select item mapped with the result variable if
     * one was defined otherwise the name will be generated based on the type of select item.
     */
    private Map<String, IMapping> mappings;

    /**
     * The virtual {@link IManagedType}.
     */
    protected IManagedType parent;

    protected IMapping buildMapping(String name, Resolver resolver) {
      return new VirtualMapping(parent, name, resolver);
    }

    protected String literal(Expression expression, LiteralType literalType) {
      return queryContext.literal(expression, literalType);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visit(CollectionExpression expression) {
      expression.acceptChildren(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visit(ResultVariable expression) {

      String name = literal(expression, RESULT_VARIABLE);

      if (ExpressionTools.stringIsNotEmpty(name)) {
        Resolver resolver = queryContext.getResolver(expression.getSelectExpression());
        mappings.put(name, buildMapping(name, resolver));
      }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visit(SimpleSelectClause expression) {
      expression.getSelectExpression().accept(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visit(SimpleSelectStatement expression) {
      expression.getSelectClause().accept(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visit(StateFieldPathExpression expression) {

      if (!expression.startsWithDot()) {
        String name = literal(expression, PATH_EXPRESSION_LAST_PATH);

        if (ExpressionTools.stringIsNotEmpty(name)) {
          Resolver resolver = queryContext.getResolver(expression);
          mappings.put(name, buildMapping(name, resolver));
        }
      }
    }
  }
}
TOP

Related Classes of org.eclipse.persistence.jpa.jpql.FromSubqueryResolver$VirtualMappingBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.