Open Source Repository

Home /hibernate/hibernate-3.2.4.ga | Repository Home


org/hibernate/loader/OuterJoinableAssociation.java
//$Id: OuterJoinableAssociation.java 6828 2005-05-19 07:28:59Z steveebersole $
package org.hibernate.loader;

import java.util.List;
import java.util.Map;

import org.hibernate.MappingException;
import org.hibernate.engine.JoinHelper;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;

public final class OuterJoinableAssociation {
  private final AssociationType joinableType;
  private final Joinable joinable;
  private final String lhsAlias; // belong to other persister
  private final String[] lhsColumns; // belong to other persister
  private final String rhsAlias;
  private final String[] rhsColumns;
  private final int joinType;
  private final String on;
  private final Map enabledFilters;

  public OuterJoinableAssociation(
    AssociationType joinableType,
    String lhsAlias,
    String[] lhsColumns,
    String rhsAlias,
    int joinType,
    SessionFactoryImplementor factory,
    Map enabledFilters)
  throws MappingException {
    this.joinableType = joinableType;
    this.lhsAlias = lhsAlias;
    this.lhsColumns = lhsColumns;
    this.rhsAlias = rhsAlias;
    this.joinType = joinType;
    this.joinable = joinableType.getAssociatedJoinable(factory);
    this.rhsColumns = JoinHelper.getRHSColumnNames(joinableType, factory);
    this.on = joinableType.getOnCondition(rhsAlias, factory, enabledFilters);
    this.enabledFilters = enabledFilters; // needed later for many-to-many/filter application
  }

  public int getJoinType() {
    return joinType;
  }

  public String getRHSAlias() {
    return rhsAlias;
  }

  private boolean isOneToOne() {
    if joinableType.isEntityType() )  {
      EntityType etype = (EntityTypejoinableType;
      return etype.isOneToOne() /*&& etype.isReferenceToPrimaryKey()*/;
    }
    else {
      return false;
    }
      
  }
  
  public AssociationType getJoinableType() {
    return joinableType;
  }
  
  public String getRHSUniqueKeyName() {
    return joinableType.getRHSUniqueKeyPropertyName();
  }

  public boolean isCollection() {
    return joinableType.isCollectionType();
  }

  public Joinable getJoinable() {
    return joinable;
  }

  public int getOwner(final List associations) {
    if isOneToOne() || isCollection() ) {
      return getPosition(lhsAlias, associations);
    }
    else {
      return -1;
    }
  }

  /**
   * Get the position of the join with the given alias in the
   * list of joins
   */
  private static int getPosition(String lhsAlias, List associations) {
    int result = 0;
    for int i=0; i<associations.size(); i++ ) {
      OuterJoinableAssociation oj = (OuterJoinableAssociationassociations.get(i);
      if oj.getJoinable().consumesEntityAlias() /*|| oj.getJoinable().consumesCollectionAlias() */ ) {
        if oj.rhsAlias.equals(lhsAlias) ) return result;
        result++;
      }
    }
    return -1;
  }

  public void addJoins(JoinFragment outerjointhrows MappingException {
    outerjoin.addJoin(
      joinable.getTableName(),
      rhsAlias,
      lhsColumns,
      rhsColumns,
      joinType,
      on
    );
    outerjoin.addJoins(
      joinable.fromJoinFragment(rhsAlias, false, true),
      joinable.whereJoinFragment(rhsAlias, false, true)
    );
  }

  public void validateJoin(String paththrows MappingException {
    if (
      rhsColumns==null || 
      lhsColumns==null ||
      lhsColumns.length!=rhsColumns.length ||
      lhsColumns.length==0
    ) {
      throw new MappingException("invalid join columns for association: " + path);
    }
  }

  public boolean isManyToManyWith(OuterJoinableAssociation other) {
    if joinable.isCollection() ) {
      QueryableCollection persister = QueryableCollection joinable;
      if persister.isManyToMany() ) {
        return persister.getElementType() == other.getJoinableType();
      }
    }
    return false;
  }

  public void addManyToManyJoin(JoinFragment outerjoin, QueryableCollection collectionthrows MappingException {
    String manyToManyFilter = collection.getManyToManyFilterFragmentrhsAlias, enabledFilters );
    String condition = "".equalsmanyToManyFilter )
        ? on
        "".equalson )
            ? manyToManyFilter
            : on + " and " + manyToManyFilter;
    outerjoin.addJoin(
            joinable.getTableName(),
            rhsAlias,
            lhsColumns,
            rhsColumns,
            joinType,
            condition
    );
    outerjoin.addJoins(
      joinable.fromJoinFragment(rhsAlias, false, true),
      joinable.whereJoinFragment(rhsAlias, false, true)
    );
  }
}