KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > hql > classic > SelectParser


1 //$Id: SelectParser.java,v 1.2 2005/02/13 11:50:03 oneovthafew Exp $
2
package org.hibernate.hql.classic;
3
4 import org.hibernate.Hibernate;
5 import org.hibernate.QueryException;
6 import org.hibernate.dialect.function.SQLFunction;
7 import org.hibernate.hql.QuerySplitter;
8 import org.hibernate.type.Type;
9 import org.hibernate.util.ReflectHelper;
10
11 import java.util.HashSet JavaDoc;
12 import java.util.LinkedList JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Set JavaDoc;
15
16 /**
17  * Parsers the select clause of a Hibernate query.
18  *
19  * @author Gavin King, David Channon
20  */

21 public class SelectParser implements Parser {
22
23     //TODO: arithmetic expressions, multiple new Foo(...)
24

25     private static final Set JavaDoc COUNT_MODIFIERS = new HashSet JavaDoc();
26
27     static {
28         COUNT_MODIFIERS.add( "distinct" );
29         COUNT_MODIFIERS.add( "all" );
30         COUNT_MODIFIERS.add( "*" );
31     }
32
33     private LinkedList JavaDoc aggregateFuncTokenList = new LinkedList JavaDoc();
34
35     private boolean ready;
36     private boolean aggregate;
37     private boolean first;
38     private boolean afterNew;
39     private boolean insideNew;
40     private boolean aggregateAddSelectScalar;
41     private Class JavaDoc holderClass;
42
43     private final SelectPathExpressionParser pathExpressionParser;
44     private final PathExpressionParser aggregatePathExpressionParser;
45
46     {
47         pathExpressionParser = new SelectPathExpressionParser();
48         aggregatePathExpressionParser = new PathExpressionParser();
49         //TODO: would be nice to use false, but issues with MS SQL
50
pathExpressionParser.setUseThetaStyleJoin( true );
51         aggregatePathExpressionParser.setUseThetaStyleJoin( true );
52     }
53
54     public void token(String JavaDoc token, QueryTranslatorImpl q) throws QueryException {
55
56         String JavaDoc lctoken = token.toLowerCase();
57
58         if ( first ) {
59             first = false;
60             if ( "distinct".equals( lctoken ) ) {
61                 q.setDistinct( true );
62                 return;
63             }
64             else if ( "all".equals( lctoken ) ) {
65                 q.setDistinct( false );
66                 return;
67             }
68         }
69
70         if ( afterNew ) {
71             afterNew = false;
72             try {
73                 holderClass = ReflectHelper.classForName( QuerySplitter.getImportedClass( token, q.getFactory() ) );
74             }
75             catch ( ClassNotFoundException JavaDoc cnfe ) {
76                 throw new QueryException( cnfe );
77             }
78             if ( holderClass == null ) throw new QueryException( "class not found: " + token );
79             q.setHolderClass( holderClass );
80             insideNew = true;
81         }
82         else if ( token.equals( "," ) ) {
83             if ( !aggregate && ready ) throw new QueryException( "alias or expression expected in SELECT" );
84             q.appendScalarSelectToken( ", " );
85             ready = true;
86         }
87         else if ( "new".equals( lctoken ) ) {
88             afterNew = true;
89             ready = false;
90         }
91         else if ( "(".equals( token ) ) {
92             if ( insideNew && !aggregate && !ready ) {
93                 //opening paren in new Foo ( ... )
94
ready = true;
95             }
96             else if ( aggregate ) {
97                 q.appendScalarSelectToken( token );
98             }
99             else {
100                 throw new QueryException( "aggregate function expected before ( in SELECT" );
101             }
102             ready = true;
103         }
104         else if ( ")".equals( token ) ) {
105             if ( insideNew && !aggregate && !ready ) {
106                 //if we are inside a new Result(), but not inside a nested function
107
insideNew = false;
108             }
109             else if ( aggregate && ready ) {
110                 q.appendScalarSelectToken( token );
111                 aggregateFuncTokenList.removeLast();
112                 if ( aggregateFuncTokenList.size() < 1 ) {
113                     aggregate = false;
114                     ready = false;
115                 }
116             }
117             else {
118                 throw new QueryException( "( expected before ) in select" );
119             }
120         }
121         else if ( COUNT_MODIFIERS.contains( lctoken ) ) {
122             if ( !ready || !aggregate ) throw new QueryException( token + " only allowed inside aggregate function in SELECT" );
123             q.appendScalarSelectToken( token );
124             if ( "*".equals( token ) ) q.addSelectScalar( Hibernate.INTEGER ); //special case
125
}
126         else if ( getFunction( lctoken, q ) != null && token.equals( q.unalias( token ) ) ) {
127             // the name of an SQL function
128
if ( !ready ) throw new QueryException( ", expected before aggregate function in SELECT: " + token );
129             aggregate = true;
130             aggregateAddSelectScalar = true;
131             aggregateFuncTokenList.add( lctoken );
132             ready = false;
133             q.appendScalarSelectToken( token );
134             if ( !aggregateHasArgs( lctoken, q ) ) {
135                 q.addSelectScalar( aggregateType( aggregateFuncTokenList, null, q ) );
136                 if ( !aggregateFuncNoArgsHasParenthesis( lctoken, q ) ) {
137                     aggregateFuncTokenList.removeLast();
138                     if ( aggregateFuncTokenList.size() < 1 ) {
139                         aggregate = false;
140                         ready = false;
141                     }
142                     else {
143                         ready = true;
144                     }
145                 }
146             }
147         }
148         else if ( aggregate ) {
149             boolean constantToken = false;
150             if ( !ready ) throw new QueryException( "( expected after aggregate function in SELECT" );
151             try {
152                 ParserHelper.parse( aggregatePathExpressionParser, q.unalias( token ), ParserHelper.PATH_SEPARATORS, q );
153             }
154             catch ( QueryException qex ) {
155                 constantToken = true;
156             }
157
158             if ( constantToken ) {
159                 q.appendScalarSelectToken( token );
160             }
161             else {
162                 if ( aggregatePathExpressionParser.isCollectionValued() ) {
163                     q.addCollection( aggregatePathExpressionParser.getCollectionName(),
164                             aggregatePathExpressionParser.getCollectionRole() );
165                 }
166                 q.appendScalarSelectToken( aggregatePathExpressionParser.getWhereColumn() );
167                 if ( aggregateAddSelectScalar ) {
168                     q.addSelectScalar( aggregateType( aggregateFuncTokenList, aggregatePathExpressionParser.getWhereColumnType(), q ) );
169                     aggregateAddSelectScalar = false;
170                 }
171                 aggregatePathExpressionParser.addAssociation( q );
172             }
173         }
174         else {
175             if ( !ready ) throw new QueryException( ", expected in SELECT" );
176             ParserHelper.parse( pathExpressionParser, q.unalias( token ), ParserHelper.PATH_SEPARATORS, q );
177             if ( pathExpressionParser.isCollectionValued() ) {
178                 q.addCollection( pathExpressionParser.getCollectionName(),
179                         pathExpressionParser.getCollectionRole() );
180             }
181             else if ( pathExpressionParser.getWhereColumnType().isEntityType() ) {
182                 q.addSelectClass( pathExpressionParser.getSelectName() );
183             }
184             q.appendScalarSelectTokens( pathExpressionParser.getWhereColumns() );
185             q.addSelectScalar( pathExpressionParser.getWhereColumnType() );
186             pathExpressionParser.addAssociation( q );
187
188             ready = false;
189         }
190     }
191
192     public boolean aggregateHasArgs(String JavaDoc funcToken, QueryTranslatorImpl q) {
193         return getFunction( funcToken, q ).hasArguments();
194     }
195
196     public boolean aggregateFuncNoArgsHasParenthesis(String JavaDoc funcToken, QueryTranslatorImpl q) {
197         return getFunction( funcToken, q ).hasParenthesesIfNoArguments();
198     }
199
200     public Type aggregateType(List JavaDoc funcTokenList, Type type, QueryTranslatorImpl q) throws QueryException {
201         Type retType = type;
202         Type argType;
203         for ( int i = funcTokenList.size() - 1; i >= 0; i-- ) {
204             argType = retType;
205             String JavaDoc funcToken = ( String JavaDoc ) funcTokenList.get( i );
206             retType = getFunction( funcToken, q ).getReturnType( argType, q.getFactory() );
207         }
208         return retType;
209     }
210
211     private SQLFunction getFunction(String JavaDoc name, QueryTranslatorImpl q) {
212         return ( SQLFunction ) q.getFactory().getDialect().getFunctions().get( name );
213     }
214
215     public void start(QueryTranslatorImpl q) {
216         ready = true;
217         first = true;
218         aggregate = false;
219         afterNew = false;
220         insideNew = false;
221         holderClass = null;
222         aggregateFuncTokenList.clear();
223     }
224
225     public void end(QueryTranslatorImpl q) {
226     }
227
228 }
229
Popular Tags