KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > odmg > oql > OQLQueryImpl


1 package org.apache.ojb.odmg.oql;
2
3 /* Copyright 2002-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import java.io.StringReader JavaDoc;
19 import java.util.Enumeration JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.ListIterator JavaDoc;
22 import java.util.Vector JavaDoc;
23 import java.util.List JavaDoc;
24
25 import antlr.RecognitionException;
26 import antlr.TokenStreamException;
27 import org.apache.ojb.broker.ManageableCollection;
28 import org.apache.ojb.broker.PBKey;
29 import org.apache.ojb.broker.PersistenceBroker;
30 import org.apache.ojb.broker.PersistenceBrokerFactory;
31 import org.apache.ojb.broker.accesslayer.OJBIterator;
32 import org.apache.ojb.broker.query.BetweenCriteria;
33 import org.apache.ojb.broker.query.Criteria;
34 import org.apache.ojb.broker.query.Query;
35 import org.apache.ojb.broker.query.ReportQuery;
36 import org.apache.ojb.broker.query.SelectionCriteria;
37 import org.apache.ojb.broker.util.collections.ManageableArrayList;
38 import org.apache.ojb.broker.util.configuration.Configurable;
39 import org.apache.ojb.broker.util.configuration.Configuration;
40 import org.apache.ojb.broker.util.configuration.ConfigurationException;
41 import org.apache.ojb.broker.util.logging.Logger;
42 import org.apache.ojb.broker.util.logging.LoggerFactory;
43 import org.apache.ojb.odmg.ImplementationImpl;
44 import org.apache.ojb.odmg.OdmgConfiguration;
45 import org.apache.ojb.odmg.PBCapsule;
46 import org.apache.ojb.odmg.RuntimeObject;
47 import org.apache.ojb.odmg.TransactionImpl;
48 import org.odmg.QueryInvalidException;
49 import org.odmg.Transaction;
50
51 /**
52  * The OQL query interface implementation.
53  *
54  * @version $Id: OQLQueryImpl.java,v 1.18.2.5 2005/12/21 22:29:53 tomdz Exp $
55  */

56 public class OQLQueryImpl implements EnhancedOQLQuery, Configurable
57 {
58     private Logger log = LoggerFactory.getLogger(OQLQueryImpl.class);
59
60     /**
61      * holds the compiled query object
62      */

63     private Query query = null;
64     private ListIterator JavaDoc bindIterator = null;
65     private ImplementationImpl odmg;
66
67     public OQLQueryImpl(ImplementationImpl odmg)
68     {
69         this.odmg = odmg;
70     }
71
72     /**
73      * @deprecated
74      * @param pbKey
75      */

76     public OQLQueryImpl(PBKey pbKey)
77     {
78     }
79
80
81     /**
82      * returns the compiled query object
83      */

84     public Query getQuery()
85     {
86         return query;
87     }
88
89     /**
90      * returns the collection type to be used to contain oql query result sets
91      */

92     protected Class JavaDoc getCollectionClass()
93     {
94         return odmg.getOqlCollectionClass();
95     }
96
97     /**
98      * Bind a parameter to the query.
99      * A parameter is denoted in the query string passed to <code>create</code> by <i>$i</i>,
100      * where <i>i</i> is the rank of the parameter, beginning with 1.
101      * The parameters are set consecutively by calling this method <code>bind</code>.
102      * The <i>ith</i> variable is set by the <i>ith</i> call to the <code>bind</code> method.
103      * If any of the <i>$i</i> are not set by a call to <code>bind</code> at the point
104      * <code>execute</code> is called, <code>QueryParameterCountInvalidException</code> is thrown.
105      * The parameters must be objects, and the result is an <code>Object</code>.
106      * Objects must be used instead of primitive types (<code>Integer</code> instead
107      * of <code>int</code>) for passing the parameters.
108      * <p>
109      * If the parameter is of the wrong type,
110      * <code>QueryParameterTypeInvalidException</code> is thrown.
111      * After executing a query, the parameter list is reset.
112      * @param parameter A value to be substituted for a query parameter.
113      * @exception org.odmg.QueryParameterCountInvalidException The number of calls to
114      * <code>bind</code> has exceeded the number of parameters in the query.
115      * @exception org.odmg.QueryParameterTypeInvalidException The type of the parameter does
116      * not correspond with the type of the parameter in the query.
117      */

118     public void bind(Object JavaDoc parameter)
119             throws org.odmg.QueryParameterCountInvalidException, org.odmg.QueryParameterTypeInvalidException
120     {
121         try
122         {
123             SelectionCriteria crit = (SelectionCriteria) getBindIterator().next();
124             crit.bind(parameter);
125
126             // BRJ: bind is called twice for between
127
if (crit instanceof BetweenCriteria && !crit.isBound())
128             {
129                 getBindIterator().previous();
130             }
131         }
132         catch (Exception JavaDoc e)
133         {
134             throw new org.odmg.QueryParameterCountInvalidException(e.getMessage());
135         }
136     }
137
138     private Vector JavaDoc flatten(Criteria crit, Vector JavaDoc acc)
139     {
140         Enumeration JavaDoc e = crit.getElements();
141         while (e.hasMoreElements())
142         {
143             Object JavaDoc o = e.nextElement();
144             if (o instanceof Criteria)
145             {
146                 Criteria pc = (Criteria) o;
147                 flatten(pc, acc);
148             }
149             else
150             {
151                 SelectionCriteria c = (SelectionCriteria) o;
152                 // BRJ : only add bindable criteria
153
if (!c.isBound())
154                 {
155                     acc.add(c);
156                 }
157             }
158         }
159         return acc;
160     }
161
162     /**
163      * Create an OQL query from the string parameter.
164      * In order to execute a query, an <code>OQLQuery</code> object must be created
165      * by calling <code>Implementation.newOQLQuery</code>, then calling the
166      * <code>create</code> method with the query string.
167      * The <code>create</code> method might throw <code>QueryInvalidException</code>
168      * if the query could not be compiled properly. Some implementations may not want
169      * to compile the query before <code>execute</code> is called. In this case
170      * <code>QueryInvalidException</code> is thrown when <code>execute</code> is called.
171      * @param queryString An OQL query.
172      * @exception QueryInvalidException The query syntax is invalid.
173      */

174     public void create(String JavaDoc queryString) throws org.odmg.QueryInvalidException
175     {
176         create(queryString, Query.NO_START_AT_INDEX, Query.NO_END_AT_INDEX);
177     }
178
179     public void create(String JavaDoc queryString, int startAtIndex, int endAtIndex) throws QueryInvalidException
180     {
181         if (log.isDebugEnabled()) log.debug("create query for query-string: " + queryString);
182         /**
183          * Check preconditions.
184          * End Index cannot be set before start index.
185          * End Index cannot equal StartAtIndex
186          */

187         if ((endAtIndex != Query.NO_END_AT_INDEX) && (endAtIndex < startAtIndex))
188         {
189             throw new QueryInvalidException("endAtIndex must be greater than startAtIndex");
190         }
191         if (((endAtIndex != Query.NO_END_AT_INDEX) && (startAtIndex != Query.NO_START_AT_INDEX))
192                 && (endAtIndex == startAtIndex))
193         {
194             throw new QueryInvalidException("endAtIndex cannot be set equal to startAtIndex");
195         }
196
197         try
198         {
199 // Query query = QueryPool.getQuery(queryString);
200
// Use the OQL parser to transform a query string to a valid org.apache.ojb.broker.query object
201
Query _query;
202             StringReader JavaDoc reader = new StringReader JavaDoc(queryString);
203             OQLLexer lexer = new OQLLexer(reader);
204             OQLParser parser = new OQLParser(lexer);
205             _query = parser.buildQuery();
206             setBindIterator(flatten(_query.getCriteria(), new Vector JavaDoc()).listIterator());
207             _query.setStartAtIndex(startAtIndex);
208             _query.setEndAtIndex(endAtIndex);
209             setQuery(_query);
210         }
211         catch (RecognitionException e)
212         {
213             throw new QueryInvalidException(e.getMessage());
214         }
215         catch (TokenStreamException e)
216         {
217             throw new QueryInvalidException(e.getMessage());
218         }
219     }
220
221     /**
222      * Execute the query.
223      * After executing a query, the parameter list is reset.
224      * Some implementations may throw additional exceptions that are also derived
225      * from <code>ODMGException</code>.
226      * @return The object that represents the result of the query.
227      * The returned data, whatever its OQL type, is encapsulated into an object.
228      * For instance, when OQL returns an integer, the result is put into an
229      * <code>Integer</code> object. When OQL returns a collection (literal or object),
230      * the result is always a Java collection object of the same kind
231      * (for instance, a <code>DList</code>).
232      * @exception org.odmg.QueryException An exception has occurred while executing the query.
233      */

234     public Object JavaDoc execute() throws org.odmg.QueryException
235     {
236         if (log.isDebugEnabled()) log.debug("Start execute query");
237
238         //obtain current ODMG transaction
239
TransactionImpl tx = odmg.getTxManager().getTransaction();
240         // create PBCapsule
241
PBCapsule capsule = null;
242         ManageableCollection result = null;
243
244         try
245         {
246             capsule = new PBCapsule(odmg.getCurrentPBKey(), tx);
247             PersistenceBroker broker = capsule.getBroker();
248
249             // ask the broker to perfom the query.
250
// the concrete result type is configurable
251

252             if (!(query instanceof ReportQuery))
253             {
254                 result = broker.getCollectionByQuery(this.getCollectionClass(), query);
255                 performLockingIfRequired(tx, broker, result);
256             }
257             else
258             {
259                 Iterator JavaDoc iter = null;
260                 result = new ManageableArrayList();
261                 iter = broker.getReportQueryIteratorByQuery(query);
262                 try
263                 {
264                     while (iter.hasNext())
265                     {
266                         Object JavaDoc[] res = (Object JavaDoc[]) iter.next();
267
268                         if (res.length == 1)
269                         {
270                             if (res[0] != null) // skip null values
271
{
272                                 result.ojbAdd(res[0]);
273                             }
274                         }
275                         else
276                         {
277                             // skip null tuples
278
for (int i = 0; i < res.length; i++)
279                             {
280                                 if (res[i] != null)
281                                 {
282                                     result.ojbAdd(res);
283                                     break;
284                                 }
285                             }
286                         }
287                     }
288                 }
289                 finally
290                 {
291                     if (iter instanceof OJBIterator)
292                     {
293                         ((OJBIterator) iter).releaseDbResources();
294                     }
295                 }
296             }
297             // reset iterator to start of list so we can reuse this query
298
ListIterator JavaDoc it = getBindIterator();
299             while (it.hasPrevious())
300             {
301                 it.previous();
302             }
303         }
304         finally
305         {
306             if (capsule != null) capsule.destroy();
307         }
308         return result;
309     }
310
311
312     protected void performLockingIfRequired(
313             TransactionImpl tx,
314             PersistenceBroker broker,
315             ManageableCollection result)
316     {
317         // if tx is available and implicit locking is required,
318
// we do READ-lock all found objects
319
if ((tx != null) && tx.isImplicitLocking() && tx.isOpen())
320         {
321             // read-lock all resulting objects to the current transaction
322
Iterator JavaDoc iter = result.ojbIterator();
323             Object JavaDoc toBeLocked = null;
324             try
325             {
326                 List JavaDoc regList = tx.getRegistrationList();
327                 while (iter.hasNext())
328                 {
329                     toBeLocked = iter.next();
330                     RuntimeObject rt = new RuntimeObject(toBeLocked, tx, false);
331                     tx.lockAndRegister(rt, Transaction.READ, true, regList);
332                 }
333             }
334             finally
335             {
336                 tx.clearRegistrationList();
337             }
338         }
339     }
340
341
342     protected OdmgConfiguration getConfiguration()
343     {
344         OdmgConfiguration config = (OdmgConfiguration) PersistenceBrokerFactory.getConfigurator().getConfigurationFor(null);
345         return config;
346     }
347
348
349     /**
350      * Sets the query.
351      * @param query The query to set
352      */

353     private void setQuery(Query query)
354     {
355         this.query = query;
356     }
357
358     /**
359      * Gets the bindIterator.
360      * @return Returns a ListIterator
361      */

362     protected ListIterator JavaDoc getBindIterator()
363     {
364         return bindIterator;
365     }
366
367     /**
368      * Sets the bindIterator.
369      * @param bindIterator The bindIterator to set
370      */

371     private void setBindIterator(ListIterator JavaDoc bindIterator)
372     {
373         this.bindIterator = bindIterator;
374     }
375
376     /**
377      * @see Configurable#configure(Configuration)
378      */

379     public void configure(Configuration pConfig) throws ConfigurationException
380     {
381     }
382
383     public int fullSize()
384     {
385         return this.query.fullSize();
386     }
387 }
388
Popular Tags