1 package org.hibernate.hql.ast.tree; 3 4 import java.util.Arrays ; 5 6 import org.hibernate.dialect.function.SQLFunction; 7 import org.hibernate.hql.CollectionProperties; 8 import org.hibernate.hql.antlr.SqlTokenTypes; 9 import org.hibernate.hql.ast.util.ASTUtil; 10 import org.hibernate.hql.ast.util.ColumnHelper; 11 import org.hibernate.persister.collection.CollectionPropertyNames; 12 import org.hibernate.persister.collection.QueryableCollection; 13 import org.hibernate.type.Type; 14 15 import antlr.SemanticException; 16 import antlr.collections.AST; 17 18 import org.apache.commons.logging.Log; 19 import org.apache.commons.logging.LogFactory; 20 21 26 public class MethodNode extends AbstractSelectExpression implements SelectExpression { 27 28 private static final Log log = LogFactory.getLog( MethodNode.class ); 29 30 private String methodName; 31 private FromElement fromElement; 32 private String [] selectColumns; 33 private SQLFunction function; 34 private boolean inSelect; 35 36 public void resolve(boolean inSelect) throws SemanticException { 37 AST name = getFirstChild(); 39 initializeMethodNode( name, inSelect ); 40 AST exprList = name.getNextSibling(); 41 if ( ASTUtil.hasExactlyOneChild( exprList ) && isCollectionPropertyMethod() ) { 44 collectionProperty( exprList.getFirstChild(), name ); 45 } 46 else { 47 dialectFunction( exprList ); 48 } 49 } 50 51 public SQLFunction getSQLFunction() { 52 return function; 53 } 54 55 private void dialectFunction(AST exprList) { 56 function = getSessionFactoryHelper().findSQLFunction( methodName ); 57 if ( function != null ) { 58 AST firstChild = exprList != null ? exprList.getFirstChild() : null; 59 Type functionReturnType = getSessionFactoryHelper() 60 .findFunctionReturnType( methodName, firstChild ); 61 setDataType( functionReturnType ); 62 } 63 67 } 68 69 public boolean isCollectionPropertyMethod() { 70 return CollectionProperties.isAnyCollectionProperty( methodName ); 71 } 72 73 public void initializeMethodNode(AST name, boolean inSelect) { 74 name.setType( SqlTokenTypes.METHOD_NAME ); 75 String text = name.getText(); 76 methodName = text.toLowerCase(); this.inSelect = inSelect; } 79 80 private String getMethodName() { 81 return methodName; 82 } 83 84 private void collectionProperty(AST path, AST name) throws SemanticException { 85 if ( path == null ) { 86 throw new SemanticException( "Collection function " + name.getText() + " has no path!" ); 87 } 88 89 SqlNode expr = ( SqlNode ) path; 90 Type type = expr.getDataType(); 91 if ( log.isDebugEnabled() ) { 92 log.debug( "collectionProperty() : name=" + name + " type=" + type ); 93 } 94 95 resolveCollectionProperty( expr ); 96 } 97 98 public boolean isScalar() throws SemanticException { 99 return true; 101 } 102 103 public void resolveCollectionProperty(AST expr) throws SemanticException { 104 String propertyName = CollectionProperties.getNormalizedPropertyName( getMethodName() ); 105 if ( expr instanceof FromReferenceNode ) { 106 FromReferenceNode collectionNode = ( FromReferenceNode ) expr; 107 if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( propertyName ) ) { 109 handleElements( collectionNode, propertyName ); 110 } 111 else { 112 fromElement = collectionNode.getFromElement(); 114 setDataType( fromElement.getPropertyType( propertyName, propertyName ) ); 115 selectColumns = fromElement.toColumns( fromElement.getTableAlias(), propertyName, inSelect ); 116 } 117 if ( collectionNode instanceof DotNode ) { 118 prepareAnyImplicitJoins( ( DotNode ) collectionNode ); 119 } 120 if ( !inSelect ) { 121 fromElement.setText( "" ); 122 fromElement.setUseWhereFragment( false ); 123 } 124 prepareSelectColumns( selectColumns ); 125 setText( selectColumns[0] ); 126 setType( SqlTokenTypes.SQL_TOKEN ); 127 } 128 else { 129 throw new SemanticException( 130 "Unexpected expression " + expr + 131 " found for collection function " + propertyName 132 ); 133 } 134 } 135 136 private void prepareAnyImplicitJoins(DotNode dotNode) throws SemanticException { 137 if ( dotNode.getLhs() instanceof DotNode ) { 138 DotNode lhs = ( DotNode ) dotNode.getLhs(); 139 FromElement lhsOrigin = lhs.getFromElement(); 140 if ( lhsOrigin != null && "".equals( lhsOrigin.getText() ) ) { 141 String lhsOriginText = lhsOrigin.getQueryable().getTableName() + 142 " " + lhsOrigin.getTableAlias(); 143 lhsOrigin.setText( lhsOriginText ); 144 } 145 prepareAnyImplicitJoins( lhs ); 146 } 147 } 148 149 private void handleElements(FromReferenceNode collectionNode, String propertyName) { 150 FromElement collectionFromElement = collectionNode.getFromElement(); 151 QueryableCollection queryableCollection = collectionFromElement.getQueryableCollection(); 152 153 String path = collectionNode.getPath() + "[]." + propertyName; 154 log.debug( "Creating elements for " + path ); 155 156 fromElement = collectionFromElement; 157 if ( !collectionFromElement.isCollectionOfValuesOrComponents() ) { 158 getWalker().addQuerySpaces( queryableCollection.getElementPersister().getQuerySpaces() ); 159 } 160 161 setDataType( queryableCollection.getElementType() ); 162 selectColumns = collectionFromElement.toColumns( fromElement.getTableAlias(), propertyName, inSelect ); 163 } 164 165 public void setScalarColumnText(int i) throws SemanticException { 166 if ( selectColumns == null ) { ColumnHelper.generateSingleScalarColumn( this, i ); 168 } 169 else { ColumnHelper.generateScalarColumns( this, selectColumns, i ); 171 } 172 } 173 174 protected void prepareSelectColumns(String [] columns) { 175 return; 176 } 177 178 public FromElement getFromElement() { 179 return fromElement; 180 } 181 182 public String getDisplayText() { 183 return "{" + 184 "method=" + getMethodName() + 185 ",selectColumns=" + ( selectColumns == null ? 186 null : Arrays.asList( selectColumns ) ) + 187 ",fromElement=" + fromElement.getTableAlias() + 188 "}"; 189 } 190 } 191 | Popular Tags |