KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > spi > persistence > support > sqlstore > query > jqlc > JQLC


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * JQLC.java
26  *
27  * Created on March 8, 2000
28  */

29
30 package com.sun.jdo.spi.persistence.support.sqlstore.query.jqlc;
31
32 import java.io.Reader JavaDoc;
33 import java.io.StringReader JavaDoc;
34 import java.util.*;
35
36 import persistence.antlr.TokenBuffer;
37 import persistence.antlr.ANTLRException;
38
39 import com.sun.jdo.api.persistence.support.JDOQueryException;
40 import com.sun.jdo.api.persistence.support.JDOUnsupportedOptionException;
41 import com.sun.jdo.api.persistence.support.JDOFatalInternalException;
42 import com.sun.jdo.spi.persistence.utility.I18NHelper;
43 import com.sun.jdo.spi.persistence.utility.StringHelper;
44 import com.sun.jdo.spi.persistence.support.sqlstore.PersistenceManager;
45 import com.sun.jdo.spi.persistence.support.sqlstore.RetrieveDesc;
46 import com.sun.jdo.spi.persistence.support.sqlstore.ExtentCollection;
47 import com.sun.jdo.spi.persistence.utility.logging.Logger;
48
49 import com.sun.jdo.spi.persistence.support.sqlstore.query.util.type.TypeTable;
50
51 /**
52  *
53  * @author Michael Bouschen
54  * @version 0.1
55  *
56  * Note: this class allows to override its fields even after all the processing
57  * is done via the corresponding setXXX methods. This is not expected behavior.
58  * A better solution would be to change all setters to be private and have use
59  * a constructor to populate all the values. The constructor will call private
60  * setters to process the arguments.
61  */

62 public class JQLC
63 {
64     /** */
65     protected TypeTable typetab;
66
67     /** */
68     protected ErrorMsg errorMsg;
69     
70     /** */
71     protected Class JavaDoc candidateClass;
72     
73     /** */
74     protected JQLAST filterAST = null;
75     
76     /** */
77     protected JQLAST importsAST = null;
78     
79     /** */
80     protected JQLAST varsAST = null;
81     
82     /** */
83     protected JQLAST paramsAST = null;
84     
85     /** */
86     protected JQLAST orderingAST = null;
87
88     /** */
89     protected JQLAST resultAST = null;
90
91     /** */
92     protected JQLAST queryAST = null;
93     
94     /** */
95     private boolean prefetchEnabled;
96     
97     /**
98      * RD cache, key is a string build from actual param values
99      * (see ParameterTable.getKeyForRetrieveDescCache).
100      * It's ok to use WeakHashMap from java.util, because the key is a string
101      * which is not referenced by the RD.
102      */

103     protected Map retrieveDescCache = new HashMap();
104
105     /** I18N support */
106     protected final static ResourceBundle messages =
107         I18NHelper.loadBundle(JQLC.class);
108
109     /** The logger */
110     private static Logger logger = LogHelperQueryCompilerJDO.getLogger();
111
112     /**
113      *
114      */

115     public JQLC()
116     {
117         this.errorMsg = new ErrorMsg();
118     }
119     
120     /**
121      *
122      */

123     public void setClass(Class JavaDoc candidateClass)
124     {
125         // check valid candidate class definition
126
if (candidateClass == null)
127         {
128             JDOQueryException ex = new JDOQueryException(I18NHelper.getMessage(
129                 messages, "jqlc.jqlc.generic.nocandidateclass")); //NOI18N
130
logger.throwing("jqlc.JQLC", "setClass", ex); //NOI18N
131
throw ex;
132         }
133         this.candidateClass = candidateClass;
134     }
135
136     /**
137      *
138      */

139     public void declareImports(String JavaDoc imports)
140     {
141         if (imports == null)
142         {
143             importsAST = null;
144             return;
145         }
146
147         try
148         {
149             JQLParser parser = createStringParser(imports);
150             parser.parseImports();
151             importsAST = (JQLAST)parser.getAST();
152         }
153         catch (ANTLRException ex)
154         {
155             JQLParser.handleANTLRException(ex, errorMsg);
156         }
157     }
158     
159     /**
160      *
161      */

162     public void declareParameters(String JavaDoc parameters)
163     {
164         if (parameters == null)
165         {
166             paramsAST = null;
167             return;
168         }
169         
170         try
171         {
172             JQLParser parser = createStringParser(parameters);
173             parser.parseParameters();
174             paramsAST = (JQLAST)parser.getAST();
175         }
176         catch (ANTLRException ex)
177         {
178             JQLParser.handleANTLRException(ex, errorMsg);
179         }
180     }
181     
182     /**
183      *
184      */

185     public void declareVariables(String JavaDoc variables)
186     {
187         if (variables == null)
188         {
189             varsAST = null;
190             return;
191         }
192         
193         try
194         {
195             JQLParser parser = createStringParser(variables);
196             parser.parseVariables();
197             varsAST = (JQLAST)parser.getAST();
198         }
199         catch (ANTLRException ex)
200         {
201             JQLParser.handleANTLRException(ex, errorMsg);
202         }
203     }
204     
205     /**
206      *
207      */

208     public void setOrdering(String JavaDoc ordering)
209     {
210         if (ordering == null)
211         {
212             orderingAST = null;
213             return;
214         }
215         
216         try
217         {
218             JQLParser parser = createStringParser(ordering);
219             parser.parseOrdering();
220             orderingAST = (JQLAST)parser.getAST();
221         }
222         catch (ANTLRException ex)
223         {
224             JQLParser.handleANTLRException(ex, errorMsg);
225         }
226     }
227     
228     /**
229      *
230      */

231     public void setResult(String JavaDoc result)
232     {
233         if (result == null)
234         {
235             resultAST = null;
236             return;
237         }
238         
239         try
240         {
241             JQLParser parser = createStringParser(result);
242             parser.parseResult();
243             resultAST = (JQLAST)parser.getAST();
244         }
245         catch (ANTLRException ex)
246         {
247             JQLParser.handleANTLRException(ex, errorMsg);
248         }
249     }
250     
251     /**
252      *
253      */

254     public void setFilter(String JavaDoc filter)
255     {
256         if (StringHelper.isEmpty(filter))
257         {
258             // If there is no filter specified use "true" as filter.
259
// This is the case if
260
// - setFilter is not called at all (filter == null)
261
// - the filter is empty or contians whitespecace only.
262
// Internally the filter has to be specified,
263
// otherwise semantic analysis has problems with empty AST.
264
filter = "true"; //NOI18N
265
}
266         
267         try
268         {
269             JQLParser parser = createStringParser(filter);
270             parser.parseFilter();
271             filterAST = (JQLAST)parser.getAST();
272         }
273         catch (ANTLRException ex)
274         {
275             JQLParser.handleANTLRException(ex, errorMsg);
276         }
277      }
278     
279     /**
280      *
281      */

282     public void setPrefetchEnabled(boolean prefetchEnabled)
283     {
284         this.prefetchEnabled = prefetchEnabled;
285     }
286
287     /**
288      *
289      */

290     public void semanticCheck(ParameterTable paramtab)
291     {
292         boolean finer = logger.isLoggable(Logger.FINER);
293         boolean finest = logger.isLoggable(Logger.FINEST);
294         this.typetab = TypeTable.getInstance(candidateClass.getClassLoader());
295         paramtab.init();
296         Semantic semantic = new Semantic();
297         semantic.init(typetab, paramtab, errorMsg);
298         semantic.setASTFactory(JQLAST.Factory.getInstance());
299         
300         // create complete tree representation
301
JQLAST classAST = semantic.checkCandidateClass(candidateClass);
302         queryAST = semantic.createQueryAST(classAST, importsAST, paramsAST, varsAST,
303                                            orderingAST, resultAST, filterAST);
304         
305         if (finest) logger.finest("LOG_JQLCDumpTree", queryAST.getTreeRepr("(AST)")); //NOI18N
306

307         // start semantic check
308
try
309         {
310             if (finer) logger.finer("LOG_JQLCStartPass", "semantic analysis"); //NOI18N
311
semantic.query(queryAST);
312             queryAST = (JQLAST)semantic.getAST();
313             if (finest) logger.finest("LOG_JQLCDumpTree", queryAST.getTreeRepr("(typed AST)")); //NOI18N
314
}
315         catch (ANTLRException ex)
316         {
317             errorMsg.fatal("JQLC.semanticCheck unexpected exception", ex); //NOI18N
318
}
319     }
320
321     /**
322      *
323      */

324     public RetrieveDesc codeGen(PersistenceManager pm, ParameterTable paramtab)
325     {
326         boolean finer = logger.isLoggable(Logger.FINER);
327         boolean finest = logger.isLoggable(Logger.FINEST);
328         RetrieveDesc rd = null;
329         
330         // check if a RetrieveDescriptor for the actual parameter constellation
331
// is already available in the cache
332
String JavaDoc key = paramtab.getKeyForRetrieveDescCache();
333
334         synchronized(retrieveDescCache)
335         {
336             if (key != null)
337                 rd = (RetrieveDesc)retrieveDescCache.get(key);
338             
339             if (rd == null) {
340                 Optimizer optimizer = new Optimizer();
341                 optimizer.init(typetab, paramtab, errorMsg);
342                 optimizer.setASTFactory(JQLAST.Factory.getInstance());
343                 
344                 CodeGeneration codeGen = new CodeGeneration();
345                 codeGen.init(pm, typetab, paramtab, errorMsg, prefetchEnabled);
346                 codeGen.setASTFactory(JQLAST.Factory.getInstance());
347                 
348                 try
349                 {
350                     JQLAST ast = queryAST;
351                     
352                     // The optimizer should treat query parameters as constant values,
353
// so I cannot call the optimzer before the query parameter values
354
// are known. That's why optimization is part of codeGen which is
355
// called by Query.execute and not called by Query.compile.
356
if (finer) logger.finer("LOG_JQLCStartPass", "optimizer"); //NOI18N
357
optimizer.query(ast);
358                     // Do not store the optimizer result in the instance variable queryAST,
359
// it cannot be reused by the next execution of this query. The next execute
360
// might have different query parameter values, so the optimized AST is different.
361
ast = (JQLAST)optimizer.getAST();
362                     if (finest) logger.finest("LOG_JQLCDumpTree", ast.getTreeRepr("(optimized AST)")); //NOI18N
363

364                     if (finer) logger.finer("LOG_JQLCStartPass", "code generation"); //NOI18N
365
codeGen.query(ast);
366                     rd = codeGen.getRetrieveDesc();
367                     // add the current RetrieveDescriptor to the cache,
368
// if the key is not null
369
if (key != null)
370                         retrieveDescCache.put(key, rd);
371                 }
372                 catch (ANTLRException ex)
373                 {
374                     errorMsg.fatal("JQLC.codeGen unexpected exception", ex); //NOI18N
375
}
376             }
377             else {
378                 if (finer) logger.finest("LOG_JQLCReuseRetrieveDesc"); //NOI18N
379
}
380         }
381         
382         return rd;
383     }
384
385     /**
386      *
387      */

388     public void checkCandidates(Class JavaDoc candidateClass, Collection candidateCollection)
389     {
390         if (candidateClass == null)
391             throw new JDOQueryException(
392                 I18NHelper.getMessage(messages, "jqlc.jqlc.generic.nocandidateclass")); //NOI18N
393
if (!(candidateCollection instanceof ExtentCollection))
394             throw new JDOUnsupportedOptionException(
395                 I18NHelper.getMessage(messages, "jqlc.jqlc.checkcandidates.memorycollection")); //NOI18N
396

397         Class JavaDoc candidatePCClass = ((ExtentCollection)candidateCollection).getPersistenceCapableClass();
398         if (candidatePCClass == null)
399             throw new JDOFatalInternalException(
400                 I18NHelper.getMessage(messages, "jqlc.jqlc.checkcandidates.nullpc")); //NOI18N
401

402         if (!candidateClass.getName().equals(candidatePCClass.getName()))
403             throw new JDOQueryException(
404                 I18NHelper.getMessage(messages, "jqlc.jqlc.checkcandidates.mismatch", candidateClass.getName())); //NOI18N
405
}
406
407     /** */
408     private JQLParser createStringParser(String JavaDoc text)
409     {
410         return createStringParser(text, errorMsg);
411     }
412
413     /**
414      * Returns a JQLParser instance parsing the specified text.
415      */

416     public static JQLParser createStringParser(String JavaDoc text, ErrorMsg errorMsg)
417     {
418         Reader JavaDoc in = new StringReader JavaDoc(text);
419         JQLLexer lexer = new JQLLexer(in);
420         lexer.init(errorMsg);
421         TokenBuffer buffer = new TokenBuffer(lexer);
422         JQLParser parser = new JQLParser(buffer);
423         parser.init(errorMsg);
424         parser.setASTFactory(JQLAST.Factory.getInstance());
425         return parser;
426     }
427     
428 }
429
Popular Tags