KickJava   Java API By Example, From Geeks To Geeks.

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


1 // $Id: IdentNode.java,v 1.1 2005/07/12 20:27:16 steveebersole Exp $
2
package org.hibernate.hql.ast.tree;
3
4 import java.util.List JavaDoc;
5
6 import org.hibernate.dialect.function.SQLFunction;
7 import org.hibernate.hql.antlr.SqlTokenTypes;
8 import org.hibernate.hql.ast.util.ColumnHelper;
9 import org.hibernate.persister.collection.QueryableCollection;
10 import org.hibernate.persister.entity.Queryable;
11 import org.hibernate.sql.JoinFragment;
12 import org.hibernate.type.CollectionType;
13 import org.hibernate.type.Type;
14 import org.hibernate.util.StringHelper;
15
16 import antlr.SemanticException;
17 import antlr.collections.AST;
18
19 /**
20  * Represents an identifier all by itself, which may be a function name,
21  * a class alias, or a form of naked property-ref depending on the
22  * context.
23  *
24  * @author josh Aug 16, 2004 7:20:55 AM
25  */

26 public class IdentNode extends FromReferenceNode implements SelectExpression {
27
28     private static final int UNKNOWN = 0;
29     private static final int PROPERTY_REF = 1;
30     private static final int COMPONENT_REF = 2;
31
32     private boolean nakedPropertyRef = false;
33     private boolean root;
34     
35     public void setRoot() {
36         root = true;
37     }
38
39     public void resolveIndex(AST parent) throws SemanticException {
40         // An ident node can represent an index expression if the ident
41
// represents a naked property ref
42
// *Note: this makes the assumption (which is currently the case
43
// in the hql-sql grammar) that the ident is first resolved
44
// itself (addrExpr -> resolve()). The other option, if that
45
// changes, is to call resolve from here; but it is
46
// currently un-needed overhead.
47
if ( !( isResolved() && nakedPropertyRef ) ) {
48             throw new UnsupportedOperationException JavaDoc();
49         }
50
51         String JavaDoc propertyName = getOriginalText();
52         if ( !getDataType().isCollectionType() ) {
53             throw new SemanticException( "Collection expected; [" + propertyName + "] does not refer to a collection property" );
54         }
55
56         // TODO : most of below was taken verbatim from DotNode; should either delegate this logic or super-type it
57
CollectionType type = ( CollectionType ) getDataType();
58         String JavaDoc role = type.getRole();
59         QueryableCollection queryableCollection = getSessionFactoryHelper().requireQueryableCollection( role );
60
61         String JavaDoc alias = null; // DotNode uses null here...
62
String JavaDoc columnTableAlias = getFromElement().getTableAlias();
63         int joinType = JoinFragment.INNER_JOIN;
64         boolean fetch = false;
65
66         FromElementFactory factory = new FromElementFactory(
67                 getWalker().getCurrentFromClause(),
68                 getFromElement(),
69                 propertyName,
70                 alias,
71                 getFromElement().toColumns( columnTableAlias, propertyName, false ),
72                 true
73         );
74         FromElement elem = factory.createCollection( queryableCollection, role, joinType, fetch, true );
75         setFromElement( elem );
76         getWalker().addQuerySpaces( queryableCollection.getCollectionSpaces() ); // Always add the collection's query spaces.
77
}
78
79     public void resolve(boolean generateJoin, boolean implicitJoin, String JavaDoc classAlias, AST parent) {
80         if ( !isResolved() ) {
81             if ( getWalker().getCurrentFromClause().isFromElementAlias( getText() ) ) {
82                 if ( resolveAsAlias() ) {
83                     setResolved();
84                     // We represent a from-clause alias
85
}
86             }
87             else if ( parent != null && parent.getType() == SqlTokenTypes.DOT ) {
88                 DotNode dot = ( DotNode ) parent;
89                 if ( parent.getFirstChild() == this ) {
90                     if ( resolveAsNakedComponentPropertyRefLHS( dot ) ) {
91                         // we are the LHS of the DOT representing a naked comp-prop-ref
92
setResolved();
93                     }
94                 }
95                 else {
96                     if ( resolveAsNakedComponentPropertyRefRHS( dot ) ) {
97                         // we are the RHS of the DOT representing a naked comp-prop-ref
98
setResolved();
99                     }
100                 }
101             }
102             else {
103                 int result = resolveAsNakedPropertyRef();
104                 if ( result == PROPERTY_REF ) {
105                     // we represent a naked (simple) prop-ref
106
setResolved();
107                 }
108                 else if ( result == COMPONENT_REF ) {
109                     // EARLY EXIT!!! return so the resolve call explicitly coming from DotNode can
110
// resolve this...
111
return;
112                 }
113             }
114
115             // if we are still not resolved, we might represent a constant.
116
// needed to add this here because the allowance of
117
// naked-prop-refs in the grammar collides with the
118
// definition of literals/constants ("nondeterminism").
119
// TODO: cleanup the grammar so that "processConstants" is always just handled from here
120
if ( !isResolved() ) {
121                 // Avoid recursion from LiteralProcessor...
122
if ( !getWalker().getCurrentFromClause().isFromElementAlias( getText() ) ) {
123                     try {
124                         getWalker().getLiteralProcessor().processConstant( this );
125                     }
126                     catch( Throwable JavaDoc ignore ) {
127                         // just ignore it for now, it'll get resolved later...
128
}
129                 }
130             }
131         }
132     }
133
134     private boolean resolveAsAlias() {
135         // This is not actually a constant, but a reference to FROM element.
136
FromElement element = getWalker().getCurrentFromClause().getFromElement( getText() );
137         if ( element != null ) {
138             setFromElement( element );
139             setText( element.getIdentityColumn() );
140             setType( SqlTokenTypes.ALIAS_REF );
141             return true;
142         }
143         return false;
144     }
145
146     private int resolveAsNakedPropertyRef() {
147         FromElement fromElement = locateSingleFromElement();
148         if ( fromElement == null ) {
149             return UNKNOWN;
150         }
151         Queryable persister = fromElement.getQueryable();
152         if ( persister == null ) {
153             return UNKNOWN;
154         }
155
156         String JavaDoc property = getText();
157         Type propertyType = null;
158         try {
159             propertyType = fromElement.getPropertyType( getText(), property );
160         }
161         catch( Throwable JavaDoc t ) {
162             // assume this ident's text does *not* refer to a property on the given persister
163
return UNKNOWN;
164         }
165
166         if ( propertyType.isComponentType() && !root ) {
167             return COMPONENT_REF;
168         }
169
170         setFromElement( fromElement );
171
172         if ( persister != null ) {
173             String JavaDoc[] columns = getWalker().isSelectStatement()
174                     ? persister.toColumns( fromElement.getTableAlias(), property )
175                     : persister.toColumns( property );
176             String JavaDoc text = StringHelper.join( ", ", columns );
177             setText( columns.length==1 ? text : "(" + text + ")" );
178             setType( SqlTokenTypes.SQL_TOKEN );
179         }
180
181         // these pieces are needed for usage in select clause
182
super.setDataType( propertyType );
183         nakedPropertyRef = true;
184
185         return PROPERTY_REF;
186     }
187
188     private boolean resolveAsNakedComponentPropertyRefLHS(DotNode parent) {
189         FromElement fromElement = locateSingleFromElement();
190         if ( fromElement == null ) {
191             return false;
192         }
193
194         String JavaDoc propertyPath = getText() + "." + getNextSibling().getText();
195         Type propertyType = null; // used to inject the dot node
196
try {
197             // check to see if our "propPath" actually
198
// represents a property on the persister
199
propertyType = fromElement.getPropertyType( getText(), propertyPath );
200         }
201         catch( Throwable JavaDoc t ) {
202             // assume we do *not* refer to a property on the given persister
203
return false;
204         }
205
206         setFromElement( fromElement );
207         parent.setPropertyPath( propertyPath );
208         parent.setDataType( propertyType );
209
210         return true;
211     }
212
213     private boolean resolveAsNakedComponentPropertyRefRHS(DotNode parent) {
214         FromElement fromElement = locateSingleFromElement();
215         if ( fromElement == null ) {
216             return false;
217         }
218
219         Type propertyType = null;
220         String JavaDoc propertyPath = parent.getLhs().getText() + "." + getText();
221         try {
222             // check to see if our "propPath" actually
223
// represents a property on the persister
224
propertyType = fromElement.getPropertyType( getText(), propertyPath );
225         }
226         catch( Throwable JavaDoc t ) {
227             // assume we do *not* refer to a property on the given persister
228
return false;
229         }
230
231         setFromElement( fromElement );
232
233         // this piece is needed for usage in select clause
234
super.setDataType( propertyType );
235         nakedPropertyRef = true;
236
237         return true;
238     }
239
240     private FromElement locateSingleFromElement() {
241         List JavaDoc fromElements = getWalker().getCurrentFromClause().getFromElements();
242         if ( fromElements == null || fromElements.size() != 1 ) {
243             // TODO : should this be an error?
244
return null;
245         }
246         FromElement element = ( FromElement ) fromElements.get(0);
247         if ( element.getClassAlias() != null ) {
248             // naked property-refs cannot be used with an aliased from element
249
return null;
250         }
251         return element;
252     }
253     
254     public Type getDataType() {
255         Type type = super.getDataType();
256         if (type!=null) return type;
257         FromElement fe = getFromElement();
258         if (fe!=null) return fe.getDataType();
259         SQLFunction sf = getWalker().getSessionFactoryHelper().findSQLFunction( getText() );
260         return sf==null ? null : sf.getReturnType(null, null);
261     }
262
263     public void setScalarColumnText(int i) throws SemanticException {
264         if ( nakedPropertyRef ) {
265             // do *not* over-write the column text, as that has already been
266
// "rendered" during resolve
267
ColumnHelper.generateSingleScalarColumn( this, i );
268         }
269         else {
270             FromElement fe = getFromElement();
271             if (fe!=null) {
272                 setText( fe.renderScalarIdentifierSelect( i ) );
273             }
274             else {
275                 ColumnHelper.generateSingleScalarColumn( this, i );
276             }
277         }
278     }
279
280     public String JavaDoc getDisplayText() {
281         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
282
283         if ( getType() == SqlTokenTypes.ALIAS_REF ) {
284             buf.append( "{alias=" ).append( getOriginalText() );
285             if ( getFromElement() == null ) {
286                 buf.append( ", no from element" );
287             }
288             else {
289                 buf.append( ", className=" ).append( getFromElement().getClassName() );
290                 buf.append( ", tableAlias=" ).append( getFromElement().getTableAlias() );
291             }
292             buf.append( "}" );
293         }
294         else {
295             buf.append( "{originalText=" + getOriginalText() ).append( "}" );
296         }
297         return buf.toString();
298     }
299
300 }
301
Popular Tags