KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > hql > ast > tree > MethodNode


1 // $Id: MethodNode.java,v 1.1 2005/07/12 20:27:16 steveebersole Exp $
2
package org.hibernate.hql.ast.tree;
3
4 import java.util.Arrays JavaDoc;
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 /**
22  * Represents a method call.
23  *
24  * @author josh Aug 16, 2004 7:59:42 AM
25  */

26 public class MethodNode extends AbstractSelectExpression implements SelectExpression {
27
28     private static final Log log = LogFactory.getLog( MethodNode.class );
29
30     private String JavaDoc methodName;
31     private FromElement fromElement;
32     private String JavaDoc[] selectColumns;
33     private SQLFunction function;
34     private boolean inSelect;
35
36     public void resolve(boolean inSelect) throws SemanticException {
37         // Get the function name node.
38
AST name = getFirstChild();
39         initializeMethodNode( name, inSelect );
40         AST exprList = name.getNextSibling();
41         // If the expression list has exactly one expression, and the type of the expression is a collection
42
// then this might be a collection function, such as index(c) or size(c).
43
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         //TODO:
64
/*else {
65             methodName = (String) getWalker().getTokenReplacements().get( methodName );
66         }*/

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 JavaDoc text = name.getText();
76         methodName = text.toLowerCase(); // Use the lower case function name.
77
this.inSelect = inSelect; // Remember whether we're in a SELECT clause or not.
78
}
79
80     private String JavaDoc 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         // Method expressions in a SELECT should always be considered scalar.
100
return true;
101     }
102
103     public void resolveCollectionProperty(AST expr) throws SemanticException {
104         String JavaDoc propertyName = CollectionProperties.getNormalizedPropertyName( getMethodName() );
105         if ( expr instanceof FromReferenceNode ) {
106             FromReferenceNode collectionNode = ( FromReferenceNode ) expr;
107             // If this is 'elements' then create a new FROM element.
108
if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( propertyName ) ) {
109                 handleElements( collectionNode, propertyName );
110             }
111             else {
112                 // Not elements(x)
113
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 JavaDoc 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 JavaDoc propertyName) {
150         FromElement collectionFromElement = collectionNode.getFromElement();
151         QueryableCollection queryableCollection = collectionFromElement.getQueryableCollection();
152
153         String JavaDoc 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 ) { // Dialect function
167
ColumnHelper.generateSingleScalarColumn( this, i );
168         }
169         else { // Collection 'property function'
170
ColumnHelper.generateScalarColumns( this, selectColumns, i );
171         }
172     }
173
174     protected void prepareSelectColumns(String JavaDoc[] columns) {
175         return;
176     }
177
178     public FromElement getFromElement() {
179         return fromElement;
180     }
181
182     public String JavaDoc 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