Package org.hibernate.hql.ast.tree

Source Code of org.hibernate.hql.ast.tree.FromElement

// $Id: FromElement.java 10852 2006-11-21 17:39:14Z steve.ebersole@jboss.com $
package org.hibernate.hql.ast.tree;

import java.util.LinkedList;
import java.util.List;

import org.hibernate.QueryException;
import org.hibernate.engine.JoinSequence;
import org.hibernate.hql.QueryTranslator;
import org.hibernate.hql.CollectionProperties;
import org.hibernate.hql.antlr.SqlTokenTypes;
import org.hibernate.hql.ast.util.ASTUtil;
import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.util.StringHelper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Represents a single mapped class mentioned in an HQL FROM clause.  Each
* class reference will have the following symbols:
* <ul>
* <li>A class name - This is the name of the Java class that is mapped by Hibernate.</li>
* <li>[optional] an HQL alias for the mapped class.</li>
* <li>A table name - The name of the table that is mapped to the Java class.</li>
* <li>A table alias - The alias for the table that will be used in the resulting SQL.</li>
* </ul>
* <br>
* User: josh<br>
* Date: Dec 6, 2003<br>
* Time: 10:28:17 AM<br>
*/
public class FromElement extends HqlSqlWalkerNode implements DisplayableNode {
  private static final Logger log = LoggerFactory.getLogger( FromElement.class );

  private String className;
  private String classAlias;
  private String tableAlias;
  private String collectionTableAlias;
  private FromClause fromClause;
  private boolean includeSubclasses = true;
  private boolean collectionJoin = false;
  private FromElement origin;
  private String[] columns;
  private String role;
  private boolean fetch;
  private boolean isAllPropertyFetch;
  private boolean filter = false;
  private int sequence = -1;
  private boolean useFromFragment = false;
  private boolean initialized = false;
  private FromElementType elementType;
  private boolean useWhereFragment = true;
  private List destinations = new LinkedList();
  private boolean manyToMany = false;
  private String withClauseFragment = null;
  private String withClauseJoinAlias;
  private boolean dereferencedBySuperclassProperty;
  private boolean dereferencedBySubclassProperty;

  public FromElement() {
  }

  public String getCollectionSuffix() {
    return elementType.getCollectionSuffix();
  }

  public void setCollectionSuffix(String suffix) {
    elementType.setCollectionSuffix(suffix);
  }

  public void initializeCollection(FromClause fromClause, String classAlias, String tableAlias) {
    doInitialize( fromClause, tableAlias, null, classAlias, null, null );
    initialized = true;
  }

  public void initializeEntity(
          FromClause fromClause,
          String className,
          EntityPersister persister,
          EntityType type,
          String classAlias,
          String tableAlias) {
    doInitialize( fromClause, tableAlias, className, classAlias, persister, type );
    this.sequence = fromClause.nextFromElementCounter();
    initialized = true;
  }

  private void doInitialize(FromClause fromClause, String tableAlias, String className, String classAlias,
                EntityPersister persister, EntityType type) {
    if ( initialized ) {
      throw new IllegalStateException( "Already initialized!!" );
    }
    this.fromClause = fromClause;
    this.tableAlias = tableAlias;
    this.className = className;
    this.classAlias = classAlias;
    this.elementType = new FromElementType( this, persister, type );
    // Register the FromElement with the FROM clause, now that we have the names and aliases.
    fromClause.registerFromElement( this );
    if ( log.isDebugEnabled() ) {
      log.debug( fromClause + " :  " + className + " ("
          + ( classAlias == null ? "no alias" : classAlias ) + ") -> " + tableAlias );
    }
  }

  public EntityPersister getEntityPersister() {
    return elementType.getEntityPersister();
  }

  public Type getDataType() {
    return elementType.getDataType();
  }

  public Type getSelectType() {
    return elementType.getSelectType();
  }

  public Queryable getQueryable() {
    return elementType.getQueryable();
  }

  public String getClassName() {
    return className;
  }

  public String getClassAlias() {
    return classAlias;
    //return classAlias == null ? className : classAlias;
  }

  private String getTableName() {
    Queryable queryable = getQueryable();
    return ( queryable != null ) ? queryable.getTableName() : "{none}";
  }

  public String getTableAlias() {
    return tableAlias;
  }

  /**
   * Render the identifier select, but in a 'scalar' context (i.e. generate the column alias).
   *
   * @param i the sequence of the returned type
   * @return the identifier select with the column alias.
   */
  String renderScalarIdentifierSelect(int i) {
    return elementType.renderScalarIdentifierSelect( i );
  }

  void checkInitialized() {
    if ( !initialized ) {
      throw new IllegalStateException( "FromElement has not been initialized!" );
    }
  }

  /**
   * Returns the identifier select SQL fragment.
   *
   * @param size The total number of returned types.
   * @param k    The sequence of the current returned type.
   * @return the identifier select SQL fragment.
   */
  String renderIdentifierSelect(int size, int k) {
    return elementType.renderIdentifierSelect( size, k );
  }

  /**
   * Returns the property select SQL fragment.
   *
   * @param size The total number of returned types.
   * @param k    The sequence of the current returned type.
   * @return the property select SQL fragment.
   */
  String renderPropertySelect(int size, int k) {
    return elementType.renderPropertySelect( size, k, isAllPropertyFetch );
  }

  String renderCollectionSelectFragment(int size, int k) {
    return elementType.renderCollectionSelectFragment( size, k );
  }

  String renderValueCollectionSelectFragment(int size, int k) {
    return elementType.renderValueCollectionSelectFragment( size, k );
  }

  public FromClause getFromClause() {
    return fromClause;
  }

  /**
   * Returns true if this FromElement was implied by a path, or false if this FROM element is explicitly declared in
   * the FROM clause.
   *
   * @return true if this FromElement was implied by a path, or false if this FROM element is explicitly declared
   */
  public boolean isImplied() {
    return false// This is an explicit FROM element.
  }

  /**
   * Returns additional display text for the AST node.
   *
   * @return String - The additional display text.
   */
  public String getDisplayText() {
    StringBuffer buf = new StringBuffer();
    buf.append( "FromElement{" );
    appendDisplayText( buf );
    buf.append( "}" );
    return buf.toString();
  }

  protected void appendDisplayText(StringBuffer buf) {
    buf.append( isImplied() ? (
        isImpliedInFromClause() ? "implied in FROM clause" : "implied" )
        : "explicit" );
    buf.append( "," ).append( isCollectionJoin() ? "collection join" : "not a collection join" );
    buf.append( "," ).append( fetch ? "fetch join" : "not a fetch join" );
    buf.append( "," ).append( isAllPropertyFetch ? "fetch all properties" : "fetch non-lazy properties" );
    buf.append( ",classAlias=" ).append( getClassAlias() );
    buf.append( ",role=" ).append( role );
    buf.append( ",tableName=" ).append( getTableName() );
    buf.append( ",tableAlias=" ).append( getTableAlias() );
    FromElement origin = getRealOrigin();
    buf.append( ",origin=" ).append( origin == null ? "null" : origin.getText() );
    buf.append( ",colums={" );
    if ( columns != null ) {
      for ( int i = 0; i < columns.length; i++ ) {
        buf.append( columns[i] );
        if ( i < columns.length ) {
          buf.append( " " );
        }
      }
    }
    buf.append( ",className=" ).append( className );
    buf.append( "}" );
  }

  public int hashCode() {
    return super.hashCode();
  }

  public boolean equals(Object obj) {
    return super.equals( obj );
  }


  public void setJoinSequence(JoinSequence joinSequence) {
    elementType.setJoinSequence( joinSequence );
  }

  public JoinSequence getJoinSequence() {
    return elementType.getJoinSequence();
  }

  public void setIncludeSubclasses(boolean includeSubclasses) {
    if ( isDereferencedBySuperclassOrSubclassProperty() ) {
      if ( !includeSubclasses && log.isTraceEnabled() ) {
        log.trace( "attempt to disable subclass-inclusions", new Exception( "stack-trace source" ) );
      }
    }
    this.includeSubclasses = includeSubclasses;
  }

  public boolean isIncludeSubclasses() {
    return includeSubclasses;
  }

  public boolean isDereferencedBySuperclassOrSubclassProperty() {
    return dereferencedBySubclassProperty || dereferencedBySuperclassProperty;
  }

  public String getIdentityColumn() {
    checkInitialized();
    String table = getTableAlias();
    if ( table == null ) {
      throw new IllegalStateException( "No table alias for node " + this );
    }
    String[] cols;
    String propertyName;
    if ( getEntityPersister() != null && getEntityPersister().getEntityMetamodel() != null
        && getEntityPersister().getEntityMetamodel().hasNonIdentifierPropertyNamedId() ) {
      propertyName = getEntityPersister().getIdentifierPropertyName();
    }
    else {
      propertyName = EntityPersister.ENTITY_ID;
    }
    if ( getWalker().getStatementType() == HqlSqlWalker.SELECT ) {
      cols = getPropertyMapping( propertyName ).toColumns( table, propertyName );
    }
    else {
      cols = getPropertyMapping( propertyName ).toColumns( propertyName );
    }
    String result = StringHelper.join( ", ", cols );
    return  cols.length == 1 ? result : "(" + result + ")";
  }

  public void setCollectionJoin(boolean collectionJoin) {
    this.collectionJoin = collectionJoin;
  }

  public boolean isCollectionJoin() {
    return collectionJoin;
  }

  public void setRole(String role) {
    this.role = role;
  }

  public void setQueryableCollection(QueryableCollection queryableCollection) {
    elementType.setQueryableCollection( queryableCollection );
  }

  public QueryableCollection getQueryableCollection() {
    return elementType.getQueryableCollection();
  }

  public void setColumns(String[] columns) {
    this.columns = columns;
  }

  public void setOrigin(FromElement origin, boolean manyToMany) {
    this.origin = origin;
    this.manyToMany = manyToMany;
    origin.addDestination( this );
    if ( origin.getFromClause() == this.getFromClause() ) {
      // TODO: Figure out a better way to get the FROM elements in a proper tree structure.
      // If this is not the destination of a many-to-many, add it as a child of the origin.
      if ( manyToMany ) {
        ASTUtil.appendSibling( origin, this );
      }
      else {
        if ( !getWalker().isInFrom() && !getWalker().isInSelect() ) {
          getFromClause().addChild( this );
        }
        else {
          origin.addChild( this );
        }
      }
    }
    else if ( !getWalker().isInFrom() ) {
      // HHH-276 : implied joins in a subselect where clause - The destination needs to be added
      // to the destination's from clause.
      getFromClause().addChild( this )// Not sure if this is will fix everything, but it works.
    }
    else {
      // Otherwise, the destination node was implied by the FROM clause and the FROM clause processor
      // will automatically add it in the right place.
    }
  }

  public boolean isManyToMany() {
    return manyToMany;
  }

  private void addDestination(FromElement fromElement) {
    destinations.add( fromElement );
  }

  public List getDestinations() {
    return destinations;
  }

  public FromElement getOrigin() {
    return origin;
  }

  public FromElement getRealOrigin() {
    if ( origin == null ) {
      return null;
    }
    if ( origin.getText() == null || "".equals( origin.getText() ) ) {
      return origin.getRealOrigin();
    }
    return origin;
  }

  public Type getPropertyType(String propertyName, String propertyPath) {
    return elementType.getPropertyType( propertyName, propertyPath );
  }

  public String[] toColumns(String tableAlias, String path, boolean inSelect) {
    return elementType.toColumns( tableAlias, path, inSelect );
  }

  public String[] toColumns(String tableAlias, String path, boolean inSelect, boolean forceAlias) {
    return elementType.toColumns( tableAlias, path, inSelect, forceAlias );
  }

  public PropertyMapping getPropertyMapping(String propertyName) {
    return elementType.getPropertyMapping( propertyName );
  }

  public void setFetch(boolean fetch) {
    this.fetch = fetch;
    // Fetch can't be used with scroll() or iterate().
    if ( fetch && getWalker().isShallowQuery() ) {
      throw new QueryException( QueryTranslator.ERROR_CANNOT_FETCH_WITH_ITERATE );
    }
  }

  public boolean isFetch() {
    return fetch;
  }

  public int getSequence() {
    return sequence;
  }

  public void setFilter(boolean b) {
    filter = b;
  }

  public boolean isFilter() {
    return filter;
  }

  public boolean useFromFragment() {
    checkInitialized();
    // If it's not implied or it is implied and it's a many to many join where the target wasn't found.
    return !isImplied() || this.useFromFragment;
  }

  public void setUseFromFragment(boolean useFromFragment) {
    this.useFromFragment = useFromFragment;
  }

  public boolean useWhereFragment() {
    return useWhereFragment;
  }

  public void setUseWhereFragment(boolean b) {
    useWhereFragment = b;
  }


  public void setCollectionTableAlias(String collectionTableAlias) {
    this.collectionTableAlias = collectionTableAlias;
  }

  public String getCollectionTableAlias() {
    return collectionTableAlias;
  }

  public boolean isCollectionOfValuesOrComponents() {
    return elementType.isCollectionOfValuesOrComponents();
  }

  public boolean isEntity() {
    return elementType.isEntity();
  }

  public void setImpliedInFromClause(boolean flag) {
    throw new UnsupportedOperationException( "Explicit FROM elements can't be implied in the FROM clause!" );
  }

  public boolean isImpliedInFromClause() {
    return false// Since this is an explicit FROM element, it can't be implied in the FROM clause.
  }

  public void setInProjectionList(boolean inProjectionList) {
    // Do nothing, eplicit from elements are *always* in the projection list.
  }

  public boolean inProjectionList() {
    return !isImplied() && isFromOrJoinFragment();
  }

  public boolean isFromOrJoinFragment() {
    return getType() == SqlTokenTypes.FROM_FRAGMENT || getType() == SqlTokenTypes.JOIN_FRAGMENT;
  }

  public boolean isAllPropertyFetch() {
    return isAllPropertyFetch;
  }

  public void setAllPropertyFetch(boolean fetch) {
    isAllPropertyFetch = fetch;
  }

  public String getWithClauseFragment() {
    return withClauseFragment;
  }

  public String getWithClauseJoinAlias() {
    return withClauseJoinAlias;
  }

  public void setWithClauseFragment(String withClauseJoinAlias, String withClauseFragment) {
    this.withClauseJoinAlias = withClauseJoinAlias;
    this.withClauseFragment = withClauseFragment;
  }

  public boolean hasCacheablePersister() {
    if ( getQueryableCollection() != null ) {
      return getQueryableCollection().hasCache();
    }
    else {
      return getQueryable().hasCache();
    }
  }

  public void handlePropertyBeingDereferenced(Type propertySource, String propertyName) {
    if ( getQueryableCollection() != null && CollectionProperties.isCollectionProperty( propertyName ) ) {
      // propertyName refers to something like collection.size...
      return;
    }
    if ( propertySource.isComponentType() ) {
      // property name is a sub-path of a component...
      return;
    }

    Queryable persister = getQueryable();
    if ( persister != null ) {
      try {
        Queryable.Declarer propertyDeclarer = persister.getSubclassPropertyDeclarer( propertyName );
        if ( log.isTraceEnabled() ) {
          log.trace( "handling property dereference [" + persister.getEntityName() + " (" + getClassAlias() + ") -> " + propertyName + " (" + propertyDeclarer + ")]" );
        }
        if ( propertyDeclarer == Queryable.Declarer.SUBCLASS ) {
          dereferencedBySubclassProperty = true;
          includeSubclasses = true;
        }
        else if ( propertyDeclarer == Queryable.Declarer.SUPERCLASS ) {
          dereferencedBySuperclassProperty = true;
        }
      }
      catch( QueryException ignore ) {
        // ignore it; the incoming property could not be found so we
        // cannot be sure what to do here.  At the very least, the
        // safest is to simply not apply any dereference toggling...

      }
    }
  }

  public boolean isDereferencedBySuperclassProperty() {
    return dereferencedBySuperclassProperty;
  }

  public boolean isDereferencedBySubclassProperty() {
    return dereferencedBySubclassProperty;
  }
}
TOP

Related Classes of org.hibernate.hql.ast.tree.FromElement

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.