KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > speedo > query > lib > QueryResultCommon


1 /**
2  * Speedo: an implementation of JDO compliant personality on top of JORM generic
3  * I/O sub-system.
4  * Copyright (C) 2001-2005 France Telecom R&D
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  *
21  *
22  * Authors: S.Chassande-Barrioz.
23  * Created on 10 f�vr. 2005
24  *
25  */

26 package org.objectweb.speedo.query.lib;
27
28 import java.lang.reflect.Constructor JavaDoc;
29
30 import javax.jdo.JDOUserException;
31 import javax.jdo.PersistenceManager;
32
33 import org.objectweb.jorm.naming.api.PName;
34 import org.objectweb.medor.api.MedorException;
35 import org.objectweb.medor.tuple.api.Tuple;
36 import org.objectweb.medor.tuple.api.TupleCollection;
37 import org.objectweb.perseus.persistence.api.ConnectionHolder;
38 import org.objectweb.perseus.persistence.api.PersistenceException;
39 import org.objectweb.perseus.persistence.api.WorkingSet;
40 import org.objectweb.speedo.api.SpeedoException;
41 import org.objectweb.speedo.workingset.api.Transaction;
42 import org.objectweb.util.monolog.api.BasicLevel;
43 import org.objectweb.util.monolog.api.Logger;
44
45 /**
46  * Is a common classes used for compute the query result. This implementation
47  * supports user class or persistent class as query result.
48  *
49  * @author S.Chassande-Barrioz
50  */

51 public class QueryResultCommon {
52     /**
53      * The inner medor TupleCollection
54      */

55     protected TupleCollection tc = null;
56
57     /**
58      * The underlying connection used to evalue the query. These connections
59      * will be closed when the result will be no more used.
60      */

61     protected Object JavaDoc[] conns = null;
62
63     /**
64      * The proxy manager representing the current execution context. The
65      * persistenceManager is used to fetch the real object from the identifier.
66      */

67     protected PersistenceManager pm = null;
68
69     protected Logger logger;
70     
71     protected boolean debug;
72
73     /**
74      * is the Class encapsulating the result of the query. A null value means
75      * the result of the query is primitive field or a persistent class.
76      */

77     private Class JavaDoc resultClass;
78
79     /**
80      * indicates if the result is directly the first selected field.
81      * Of course if there are several selected fields, this fies must be false
82      */

83     private boolean firstIsResult;
84     
85     /**
86      * is the table of field types which compose the query result.
87      */

88     private Class JavaDoc[] selectedFieldTypes;
89     
90     /**
91      * is the constructor method to use for filling user class. This field is
92      * null when not result class has been defined.
93      */

94     private Constructor JavaDoc cons;
95     
96     /**
97      * index of the first element in the tuple collection
98      * This design supports data prefetching.
99      * 0: indicates that the indexes must be computed each time
100      * 1: is the first element
101      */

102     private int firstElementIdx;
103
104     /**
105      * Builds a QueryResultList.
106      * @param _tc the tuple collection representing the query result
107      * @param _pm is the peristence manager linked to the query
108      * @param _conns is the connection to the underlying support to close in
109      * same time than the query.
110      * @param _resultClazz is the class encapsulated the result
111      */

112     public QueryResultCommon(TupleCollection _tc,
113             PersistenceManager _pm,
114             Object JavaDoc[] _conns,
115             Class JavaDoc _resultClazz,
116             Class JavaDoc[] _selectedFieldTypes,
117             boolean staticFirstElementIndex,
118             Logger _logger)
119             throws MedorException, SpeedoException {
120         this.tc = _tc;
121         this.pm = _pm;
122         this.conns = _conns;
123         this.resultClass = _resultClazz;
124         this.selectedFieldTypes = _selectedFieldTypes;
125         this.logger = _logger;
126         this.firstElementIdx = 0;
127
128         debug = logger != null && logger.isLoggable(BasicLevel.DEBUG);
129         if (pm == null || pm.isClosed() || ((Transaction) pm.currentTransaction()).getStatus()
130                 == WorkingSet.CTX_CLOSED) {
131             throw new JDOUserException(
132                     "Impossible to use a query result without opened persistence manager");
133         }
134         firstIsResult = selectedFieldTypes.length == 1 //one projected field
135
&& (resultClass == null // no result class
136
|| resultClass == selectedFieldTypes[0] // result class is the projected field type
137
);
138
139         if (staticFirstElementIndex) {
140             //compute once time the first element index
141
this.firstElementIdx = getFirstElementIndex();
142             if (debug) {
143                 logger.log(BasicLevel.DEBUG, "index of the pname: " + firstElementIdx);
144             }
145         } //else dynamic pname index computed each time.
146

147         if (resultClass != null) {
148             try {
149                 cons = resultClass.getConstructor(selectedFieldTypes);
150             } catch (Exception JavaDoc e) {
151                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
152                 sb.append("No consutructor '");
153                 sb.append(resultClass.getName());
154                 sb.append("(");
155                 String JavaDoc sep = "";
156                 for (int i = 0; i < selectedFieldTypes.length; i++) {
157                     Class JavaDoc c = selectedFieldTypes[i];
158                     sb.append(sep);
159                     sep = ", ";
160                     sb.append(c == null ? "null" : selectedFieldTypes[i].getName());
161                 }
162                 sb.append(")' found. This constructor is required in a query result. Be carefull to not use non static inner class.");
163                 throw new JDOUserException(sb.toString(), e);
164             }
165         }
166     }
167
168     /**
169      * Close the connection to the data store. The query result will be no
170      * more usable after.
171      */

172     public void close() {
173         pm = null;
174         if (tc != null) {
175             try {
176                 tc.close();
177             } catch (MedorException e) {
178                 logger.log(BasicLevel.WARN, "Error during the connection closing: ", e);
179             }
180             tc = null;
181         }
182         if (conns != null) {
183             for(int i=0; i<conns.length; i++) {
184                 closeConnection(conns[i]);
185             }
186         }
187         conns = null;
188     }
189
190     public static void closeConnection(Object JavaDoc conn) {
191         if (conn instanceof ConnectionHolder) {
192             try {
193                 ((ConnectionHolder) conn).releaseCHConnection();
194             } catch (PersistenceException e) {
195             }
196         }
197     }
198     
199     /**
200      * Retrieves the PName index from the TupleStructure.
201      * @return
202      * @throws MedorException
203      */

204     private int getFirstElementIndex() throws MedorException {
205         if (firstElementIdx == 0) {
206             return tc.getMetaData().getSize() - selectedFieldTypes.length + 1;
207         } else {
208             return firstElementIdx;
209         }
210     }
211     
212     /**
213      * Fetch the persistent instance corresponding to an identifier
214      * @param pn is the persistent object identifier
215      * @return a persistent instance if it has been found, otherwise a null
216      * value.
217      */

218     protected Object JavaDoc pname2Object(PName pn) {
219         if (pn != null && !pn.isNull()) {
220             try {
221                 return pm.getObjectById(pn, false);
222             } catch (JDOUserException e) {
223                 if (debug) {
224                     logger.log(BasicLevel.DEBUG,
225                     "Ignore a deleted object, oid=" + pn, e);
226                 }
227             // Do nothing, the persistent object does not exist
228
// ==> ignore it and go to the next
229
} catch (Exception JavaDoc e) {
230                 logger.log(BasicLevel.WARN, "Unexpected exception", e);
231             }
232         }
233         return null;
234     }
235     
236     /**
237      * When the array #selectedFieldTypes contains a single element, the result
238      * of the query can or cannot be encapsulated into a user class. When this
239      * array contains several
240      * element and the #resultClass field is not definied, the
241      * @param tuple contains the result
242      * @return the query result
243      */

244     protected Object JavaDoc getValue(Tuple tuple) throws MedorException {
245         if (firstIsResult) {
246             //return directly the first element
247
Object JavaDoc o = tuple.getObject(getFirstElementIndex());
248             if (o instanceof PName) {
249                 //the element is a PName, then fetch the persistent object
250
// from the identifier
251
return pname2Object((PName) o);
252             } else {
253                 return o;
254             }
255         } else {
256             //Result is encapsulated into a user class or there are several
257
// selected fields
258

259             //fetch all values into an array
260
Object JavaDoc[] values = new Object JavaDoc[selectedFieldTypes.length];
261             for (int i = 0; i < values.length; i++) {
262                 values[i] = tuple.getObject(getFirstElementIndex() + i);
263                 if (values[i] instanceof PName) {
264                     //the element is a PName, then fetch the persistent object
265
// from the identifier
266
values[i] = pname2Object((PName) values[i]);
267                 }
268             }
269             if (resultClass == null) {
270                 //no user class specified but there are several selected fields
271
//then return an Object[] containing the values.
272
return values;
273             }
274             try {
275                 //instanciate the user class with values
276
return cons.newInstance(values);
277             } catch (Exception JavaDoc e) {
278                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
279                 sb.append("Class '");
280                 sb.append(resultClass.getName());
281                 sb.append("' used as query result is compatible with the following result: [");
282                 String JavaDoc sep = "";
283                 for (int i = 0; i < selectedFieldTypes.length; i++) {
284                     sb.append(sep);
285                     sep = ", ";
286                     sb.append(values[i]);
287                 }
288                 sb.append("]");
289                 throw new JDOUserException(sb.toString());
290             }
291         }
292     }
293 }
294
Popular Tags