Open Source Repository

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


org/hibernate/hql/ast/tree/MethodNode.java
// $Id: MethodNode.java 7460 2005-07-12 20:27:29Z steveebersole $
package org.hibernate.hql.ast.tree;

import java.util.Arrays;

import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.hql.CollectionProperties;
import org.hibernate.hql.antlr.SqlTokenTypes;
import org.hibernate.hql.ast.util.ASTUtil;
import org.hibernate.hql.ast.util.ColumnHelper;
import org.hibernate.persister.collection.CollectionPropertyNames;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.type.Type;

import antlr.SemanticException;
import antlr.collections.AST;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Represents a method call.
 *
 @author josh Aug 16, 2004 7:59:42 AM
 */
public class MethodNode extends AbstractSelectExpression implements SelectExpression {

  private static final Log log = LogFactory.getLogMethodNode.class );

  private String methodName;
  private FromElement fromElement;
  private String[] selectColumns;
  private SQLFunction function;
  private boolean inSelect;

  public void resolve(boolean inSelectthrows SemanticException {
    // Get the function name node.
    AST name = getFirstChild();
    initializeMethodNodename, inSelect );
    AST exprList = name.getNextSibling();
    // If the expression list has exactly one expression, and the type of the expression is a collection
    // then this might be a collection function, such as index(c) or size(c).
    if ASTUtil.hasExactlyOneChildexprList && isCollectionPropertyMethod() ) {
      collectionPropertyexprList.getFirstChild(), name );
    }
    else {
      dialectFunctionexprList );
    }
  }

  public SQLFunction getSQLFunction() {
    return function;
  }

  private void dialectFunction(AST exprList) {
    function = getSessionFactoryHelper().findSQLFunctionmethodName );
    if function != null ) {
      AST firstChild = exprList != null ? exprList.getFirstChild() null;
      Type functionReturnType = getSessionFactoryHelper()
          .findFunctionReturnTypemethodName, firstChild );
      setDataTypefunctionReturnType );
    }
    //TODO:
    /*else {
      methodName = (String) getWalker().getTokenReplacements().get( methodName );
    }*/
  }

  public boolean isCollectionPropertyMethod() {
    return CollectionProperties.isAnyCollectionPropertymethodName );
  }

  public void initializeMethodNode(AST name, boolean inSelect) {
    name.setTypeSqlTokenTypes.METHOD_NAME );
    String text = name.getText();
    methodName = text.toLowerCase();  // Use the lower case function name.
    this.inSelect = inSelect;      // Remember whether we're in a SELECT clause or not.
  }

  private String getMethodName() {
    return methodName;
  }

  private void collectionProperty(AST path, AST namethrows SemanticException {
    if path == null ) {
      throw new SemanticException"Collection function " + name.getText() " has no path!" );
    }

    SqlNode expr = SqlNode path;
    Type type = expr.getDataType();
    if log.isDebugEnabled() ) {
      log.debug"collectionProperty() :  name=" + name + " type=" + type );
    }

    resolveCollectionPropertyexpr );
  }

  public boolean isScalar() throws SemanticException {
    // Method expressions in a SELECT should always be considered scalar.
    return true;
  }

  public void resolveCollectionProperty(AST exprthrows SemanticException {
    String propertyName = CollectionProperties.getNormalizedPropertyNamegetMethodName() );
    if expr instanceof FromReferenceNode ) {
      FromReferenceNode collectionNode = FromReferenceNode expr;
      // If this is 'elements' then create a new FROM element.
      if CollectionPropertyNames.COLLECTION_ELEMENTS.equalspropertyName ) ) {
        handleElementscollectionNode, propertyName );
      }
      else {
        // Not elements(x)
        fromElement = collectionNode.getFromElement();
        setDataTypefromElement.getPropertyTypepropertyName, propertyName ) );
        selectColumns = fromElement.toColumnsfromElement.getTableAlias(), propertyName, inSelect );
      }
      if collectionNode instanceof DotNode ) {
        prepareAnyImplicitJoins( ( DotNode collectionNode );
      }
      if !inSelect ) {
        fromElement.setText"" );
        fromElement.setUseWhereFragmentfalse );
      }
      prepareSelectColumnsselectColumns );
      setTextselectColumns[0] );
      setTypeSqlTokenTypes.SQL_TOKEN );
    }
    else {
      throw new SemanticException
          "Unexpected expression " + expr + 
          " found for collection function " + propertyName 
        );
    }
  }

  private void prepareAnyImplicitJoins(DotNode dotNodethrows SemanticException {
    if dotNode.getLhs() instanceof DotNode ) {
      DotNode lhs = DotNode dotNode.getLhs();
      FromElement lhsOrigin = lhs.getFromElement();
      if lhsOrigin != null && "".equalslhsOrigin.getText() ) ) {
        String lhsOriginText = lhsOrigin.getQueryable().getTableName() +
                " " + lhsOrigin.getTableAlias();
        lhsOrigin.setTextlhsOriginText );
      }
      prepareAnyImplicitJoinslhs );
    }
  }

  private void handleElements(FromReferenceNode collectionNode, String propertyName) {
    FromElement collectionFromElement = collectionNode.getFromElement();
    QueryableCollection queryableCollection = collectionFromElement.getQueryableCollection();

    String path = collectionNode.getPath() "[]." + propertyName;
    log.debug"Creating elements for " + path );

    fromElement = collectionFromElement;
    if !collectionFromElement.isCollectionOfValuesOrComponents() ) {
      getWalker().addQuerySpacesqueryableCollection.getElementPersister().getQuerySpaces() );
    }

    setDataTypequeryableCollection.getElementType() );
    selectColumns = collectionFromElement.toColumnsfromElement.getTableAlias(), propertyName, inSelect );
  }

  public void setScalarColumnText(int ithrows SemanticException {
    if selectColumns == null ) {   // Dialect function
      ColumnHelper.generateSingleScalarColumnthis, i );
    }
    else {  // Collection 'property function'
      ColumnHelper.generateScalarColumnsthis, selectColumns, i );
    }
  }

  protected void prepareSelectColumns(String[] columns) {
    return;
  }

  public FromElement getFromElement() {
    return fromElement;
  }

  public String getDisplayText() {
    return "{" +
        "method=" + getMethodName() +
        ",selectColumns=" selectColumns == null 
            null : Arrays.asListselectColumns ) ) +
        ",fromElement=" + fromElement.getTableAlias() +
        "}";
  }
}