KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > entity > util > EntityListIterator


1 /*
2  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
19  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
20  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */

22
23 package org.ofbiz.entity.util;
24
25
26 import java.sql.ResultSet JavaDoc;
27 import java.sql.SQLException JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.ListIterator JavaDoc;
30
31 import javolution.util.FastList;
32
33 import org.ofbiz.base.util.Debug;
34 import org.ofbiz.base.util.GeneralRuntimeException;
35 import org.ofbiz.entity.GenericDelegator;
36 import org.ofbiz.entity.GenericEntityException;
37 import org.ofbiz.entity.GenericResultSetClosedException;
38 import org.ofbiz.entity.GenericValue;
39 import org.ofbiz.entity.jdbc.SQLProcessor;
40 import org.ofbiz.entity.jdbc.SqlJdbcUtil;
41 import org.ofbiz.entity.model.ModelEntity;
42 import org.ofbiz.entity.model.ModelField;
43 import org.ofbiz.entity.model.ModelFieldTypeReader;
44
45
46 /**
47  * Generic Entity Cursor List Iterator for Handling Cursored DB Results
48  *
49  *@author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
50  *@version $Rev: 6562 $
51  *@since 2.0
52  */

53 public class EntityListIterator implements ListIterator JavaDoc {
54
55     /** Module Name Used for debugging */
56     public static final String JavaDoc module = EntityListIterator.class.getName();
57     
58     protected SQLProcessor sqlp;
59     protected ResultSet JavaDoc resultSet;
60     protected ModelEntity modelEntity;
61     protected List JavaDoc selectFields;
62     protected ModelFieldTypeReader modelFieldTypeReader;
63     protected boolean closed = false;
64     protected boolean haveMadeValue = false;
65     protected GenericDelegator delegator = null;
66
67     private boolean haveShowHasNextWarning = false;
68     
69     public EntityListIterator(SQLProcessor sqlp, ModelEntity modelEntity, List JavaDoc selectFields, ModelFieldTypeReader modelFieldTypeReader) {
70         this.sqlp = sqlp;
71         this.resultSet = sqlp.getResultSet();
72         this.modelEntity = modelEntity;
73         this.selectFields = selectFields;
74         this.modelFieldTypeReader = modelFieldTypeReader;
75     }
76
77     public void setDelegator(GenericDelegator delegator) {
78         this.delegator = delegator;
79     }
80
81     /** Sets the cursor position to just after the last result so that previous() will return the last result */
82     public void afterLast() throws GenericEntityException {
83         try {
84             resultSet.afterLast();
85         } catch (SQLException JavaDoc e) {
86             if (!closed) {
87                 this.close();
88                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
89             }
90             throw new GenericEntityException("Error setting the cursor to afterLast", e);
91         }
92     }
93
94     /** Sets the cursor position to just before the first result so that next() will return the first result */
95     public void beforeFirst() throws GenericEntityException {
96         try {
97             resultSet.beforeFirst();
98         } catch (SQLException JavaDoc e) {
99             if (!closed) {
100                 this.close();
101                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
102             }
103             throw new GenericEntityException("Error setting the cursor to beforeFirst", e);
104         }
105     }
106
107     /** Sets the cursor position to last result; if result set is empty returns false */
108     public boolean last() throws GenericEntityException {
109         try {
110             return resultSet.last();
111         } catch (SQLException JavaDoc e) {
112             if (!closed) {
113                 this.close();
114                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
115             }
116             throw new GenericEntityException("Error setting the cursor to last", e);
117         }
118     }
119
120     /** Sets the cursor position to last result; if result set is empty returns false */
121     public boolean first() throws GenericEntityException {
122         try {
123             return resultSet.first();
124         } catch (SQLException JavaDoc e) {
125             if (!closed) {
126                 this.close();
127                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
128             }
129             throw new GenericEntityException("Error setting the cursor to first", e);
130         }
131     }
132
133     public void close() throws GenericEntityException {
134         if (closed) {
135             //maybe not the best way: throw new GenericResultSetClosedException("This EntityListIterator has been closed, this operation cannot be performed");
136
Debug.logWarning("This EntityListIterator for Entity [" + modelEntity==null?"":modelEntity.getEntityName() + "] has already been closed, not closing again.", module);
137         } else {
138             sqlp.close();
139             closed = true;
140         }
141     }
142
143     /** NOTE: Calling this method does return the current value, but so does calling next() or previous(), so calling one of those AND this method will cause the value to be created twice */
144     public GenericValue currentGenericValue() throws GenericEntityException {
145         if (closed) throw new GenericResultSetClosedException("This EntityListIterator has been closed, this operation cannot be performed");
146
147         GenericValue value = GenericValue.create(modelEntity);
148
149         for (int j = 0; j < selectFields.size(); j++) {
150             ModelField curField = (ModelField) selectFields.get(j);
151
152             SqlJdbcUtil.getValue(resultSet, j + 1, curField, value, modelFieldTypeReader);
153         }
154
155         value.setDelegator(this.delegator);
156         value.synchronizedWithDatasource();
157         this.haveMadeValue = true;
158         if (delegator != null) {
159             delegator.decryptFields(value);
160         }
161         return value;
162     }
163
164     public int currentIndex() throws GenericEntityException {
165         if (closed) throw new GenericResultSetClosedException("This EntityListIterator has been closed, this operation cannot be performed");
166
167         try {
168             return resultSet.getRow();
169         } catch (SQLException JavaDoc e) {
170             if (!closed) {
171                 this.close();
172                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
173             }
174             throw new GenericEntityException("Error getting the current index", e);
175         }
176     }
177
178     /** performs the same function as the ResultSet.absolute method;
179      * if rowNum is positive, goes to that position relative to the beginning of the list;
180      * if rowNum is negative, goes to that position relative to the end of the list;
181      * a rowNum of 1 is the same as first(); a rowNum of -1 is the same as last()
182      */

183     public boolean absolute(int rowNum) throws GenericEntityException {
184         if (closed) throw new GenericResultSetClosedException("This EntityListIterator has been closed, this operation cannot be performed");
185
186         try {
187             return resultSet.absolute(rowNum);
188         } catch (SQLException JavaDoc e) {
189             if (!closed) {
190                 this.close();
191                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
192             }
193             throw new GenericEntityException("Error setting the absolute index to " + rowNum, e);
194         }
195     }
196
197     /** performs the same function as the ResultSet.relative method;
198      * if rows is positive, goes forward relative to the current position;
199      * if rows is negative, goes backward relative to the current position;
200      */

201     public boolean relative(int rows) throws GenericEntityException {
202         if (closed) throw new GenericResultSetClosedException("This EntityListIterator has been closed, this operation cannot be performed");
203
204         try {
205             return resultSet.relative(rows);
206         } catch (SQLException JavaDoc e) {
207             if (!closed) {
208                 this.close();
209                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
210             }
211             throw new GenericEntityException("Error going to the relative index " + rows, e);
212         }
213     }
214
215     /**
216      * PLEASE NOTE: Because of the nature of the JDBC ResultSet interface this method can be very inefficient; it is much better to just use next() until it returns null
217      * For example, you could use the following to iterate through the results in an EntityListIterator:
218      *
219      * GenericValue nextValue = null;
220      * while ((nextValue = (GenericValue) this.next()) != null) { ... }
221      *
222      */

223     public boolean hasNext() {
224         if (!haveShowHasNextWarning) {
225             // DEJ20050207 To further discourage use of this, and to find existing use, always log a big warning showing where it is used:
226
Exception JavaDoc whereAreWe = new Exception JavaDoc();
227             Debug.logWarning(whereAreWe, "WARNING: For performance reasons do not use the EntityListIterator.hasNext() method, just call next() until it returns null; see JavaDoc comments in the EntityListIterator class for details and an example", module);
228             
229             haveShowHasNextWarning = true;
230         }
231         
232         try {
233             if (resultSet.isLast() || resultSet.isAfterLast()) {
234                 return false;
235             } else {
236                 // do a quick game to see if the resultSet is empty:
237
// if we are not in the first or beforeFirst positions and we haven't made any values yet, the result set is empty so return false
238
if (!haveMadeValue && !resultSet.isBeforeFirst() && !resultSet.isFirst()) {
239                     return false;
240                 } else {
241                     return true;
242                 }
243             }
244         } catch (SQLException JavaDoc e) {
245             if (!closed) {
246                 try {
247                     this.close();
248                 } catch (GenericEntityException e1) {
249                     Debug.logError(e1, "Error auto-closing EntityListIterator on error, so info below for more info on original error; close error: " + e1.toString(), module);
250                 }
251                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
252             }
253             throw new GeneralRuntimeException("Error while checking to see if this is the last result", e);
254         }
255     }
256
257     /** PLEASE NOTE: Because of the nature of the JDBC ResultSet interface this method can be very inefficient; it is much better to just use previous() until it returns null */
258     public boolean hasPrevious() {
259         try {
260             if (resultSet.isFirst() || resultSet.isBeforeFirst()) {
261                 return false;
262             } else {
263                 // do a quick game to see if the resultSet is empty:
264
// if we are not in the last or afterLast positions and we haven't made any values yet, the result set is empty so return false
265
if (!haveMadeValue && !resultSet.isAfterLast() && !resultSet.isLast()) {
266                     return false;
267                 } else {
268                     return true;
269                 }
270             }
271         } catch (SQLException JavaDoc e) {
272             if (!closed) {
273                 try {
274                     this.close();
275                 } catch (GenericEntityException e1) {
276                     Debug.logError(e1, "Error auto-closing EntityListIterator on error, so info below for more info on original error; close error: " + e1.toString(), module);
277                 }
278                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
279             }
280             throw new GeneralRuntimeException("Error while checking to see if this is the first result", e);
281         }
282     }
283
284     /** Moves the cursor to the next position and returns the GenericValue object for that position; if there is no next, returns null
285      * For example, you could use the following to iterate through the results in an EntityListIterator:
286      *
287      * GenericValue nextValue = null;
288      * while ((nextValue = (GenericValue) this.next()) != null) { ... }
289      *
290      */

291     public Object JavaDoc next() {
292         try {
293             if (resultSet.next()) {
294                 return currentGenericValue();
295             } else {
296                 return null;
297             }
298         } catch (SQLException JavaDoc e) {
299             if (!closed) {
300                 try {
301                     this.close();
302                 } catch (GenericEntityException e1) {
303                     Debug.logError(e1, "Error auto-closing EntityListIterator on error, so info below for more info on original error; close error: " + e1.toString(), module);
304                 }
305                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
306             }
307             throw new GeneralRuntimeException("Error getting the next result", e);
308         } catch (GenericEntityException e) {
309             if (!closed) {
310                 try {
311                     this.close();
312                 } catch (GenericEntityException e1) {
313                     Debug.logError(e1, "Error auto-closing EntityListIterator on error, so info below for more info on original error; close error: " + e1.toString(), module);
314                 }
315                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
316             }
317             throw new GeneralRuntimeException("Error creating GenericValue", e);
318         }
319     }
320
321     /** Returns the index of the next result, but does not guarantee that there will be a next result */
322     public int nextIndex() {
323         try {
324             return currentIndex() + 1;
325         } catch (GenericEntityException e) {
326             if (!closed) {
327                 try {
328                     this.close();
329                 } catch (GenericEntityException e1) {
330                     Debug.logError(e1, "Error auto-closing EntityListIterator on error, so info below for more info on original error; close error: " + e1.toString(), module);
331                 }
332                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
333             }
334             throw new GeneralRuntimeException(e.getNonNestedMessage(), e.getNested());
335         }
336     }
337
338     /** Moves the cursor to the previous position and returns the GenericValue object for that position; if there is no previous, returns null */
339     public Object JavaDoc previous() {
340         try {
341             if (resultSet.previous()) {
342                 return currentGenericValue();
343             } else {
344                 return null;
345             }
346         } catch (SQLException JavaDoc e) {
347             if (!closed) {
348                 try {
349                     this.close();
350                 } catch (GenericEntityException e1) {
351                     Debug.logError(e1, "Error auto-closing EntityListIterator on error, so info below for more info on original error; close error: " + e1.toString(), module);
352                 }
353                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
354             }
355             throw new GeneralRuntimeException("Error getting the previous result", e);
356         } catch (GenericEntityException e) {
357             if (!closed) {
358                 try {
359                     this.close();
360                 } catch (GenericEntityException e1) {
361                     Debug.logError(e1, "Error auto-closing EntityListIterator on error, so info below for more info on original error; close error: " + e1.toString(), module);
362                 }
363                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
364             }
365             throw new GeneralRuntimeException("Error creating GenericValue", e);
366         }
367     }
368
369     /** Returns the index of the previous result, but does not guarantee that there will be a previous result */
370     public int previousIndex() {
371         try {
372             return currentIndex() - 1;
373         } catch (GenericEntityException e) {
374             if (!closed) {
375                 try {
376                     this.close();
377                 } catch (GenericEntityException e1) {
378                     Debug.logError(e1, "Error auto-closing EntityListIterator on error, so info below for more info on original error; close error: " + e1.toString(), module);
379                 }
380                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
381             }
382             throw new GeneralRuntimeException("Error getting the current index", e);
383         }
384     }
385
386     public void setFetchSize(int rows) throws GenericEntityException {
387         try {
388             resultSet.setFetchSize(rows);
389         } catch (SQLException JavaDoc e) {
390             if (!closed) {
391                 this.close();
392                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
393             }
394             throw new GenericEntityException("Error getting the next result", e);
395         }
396     }
397
398     public List JavaDoc getCompleteList() throws GenericEntityException {
399         try {
400             // if the resultSet has been moved forward at all, move back to the beginning
401
if (haveMadeValue && !resultSet.isBeforeFirst()) {
402                 // do a quick check to see if the ResultSet is empty
403
resultSet.beforeFirst();
404             }
405             List JavaDoc list = FastList.newInstance();
406             Object JavaDoc nextValue = null;
407
408             while ((nextValue = this.next()) != null) {
409                 list.add(nextValue);
410             }
411             return list;
412         } catch (SQLException JavaDoc e) {
413             if (!closed) {
414                 this.close();
415                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
416             }
417             throw new GeneralRuntimeException("Error getting results", e);
418         } catch (GeneralRuntimeException e) {
419             if (!closed) {
420                 this.close();
421                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
422             }
423             throw new GenericEntityException(e.getNonNestedMessage(), e.getNested());
424         }
425     }
426
427     /** Gets a partial list of results starting at start and containing at most number elements.
428      * Start is a one based value, ie 1 is the first element.
429      */

430     public List JavaDoc getPartialList(int start, int number) throws GenericEntityException {
431         try {
432             if (number == 0) return FastList.newInstance();
433             List JavaDoc list = FastList.newInstance();
434             
435             // just in case the caller missed the 1 based thingy
436
if (start == 0) start = 1;
437
438             // if starting on result 1 just call next() to avoid scrollable issues in some databases
439
if (start == 1) {
440                 if (!resultSet.next()) {
441                     return list;
442                 }
443             } else {
444                 // if can't reposition to desired index, throw exception
445
if (!resultSet.absolute(start)) {
446                     // maybe better to just return an empty list here...
447
return list;
448                     //throw new GenericEntityException("Could not move to the start position of " + start + ", there are probably not that many results for this find.");
449
}
450             }
451
452             // get the first as the current one
453
list.add(this.currentGenericValue());
454
455             Object JavaDoc nextValue = null;
456             // init numRetreived to one since we have already grabbed the initial one
457
int numRetreived = 1;
458
459             //number > numRetreived comparison goes first to avoid the unwanted call to next
460
while (number > numRetreived && (nextValue = this.next()) != null) {
461                 list.add(nextValue);
462                 numRetreived++;
463             }
464             return list;
465         } catch (SQLException JavaDoc e) {
466             if (!closed) {
467                 this.close();
468                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
469             }
470             throw new GeneralRuntimeException("Error getting results", e);
471         } catch (GeneralRuntimeException e) {
472             if (!closed) {
473                 this.close();
474                 Debug.logWarning("Warning: auto-closed EntityListIterator because of exception: " + e.toString(), module);
475             }
476             throw new GenericEntityException(e.getNonNestedMessage(), e.getNested());
477         }
478     }
479
480     public void add(Object JavaDoc obj) {
481         throw new GeneralRuntimeException("CursorListIterator currently only supports read-only access");
482     }
483
484     public void remove() {
485         throw new GeneralRuntimeException("CursorListIterator currently only supports read-only access");
486     }
487
488     public void set(Object JavaDoc obj) {
489         throw new GeneralRuntimeException("CursorListIterator currently only supports read-only access");
490     }
491
492     protected void finalize() throws Throwable JavaDoc {
493         try {
494             if (!closed) {
495                 this.close();
496                 Debug.logError("\n====================================================================\n EntityListIterator Not Closed for Entity [" + (modelEntity==null ? "" : modelEntity.getEntityName()) + "], caught in Finalize\n ====================================================================\n", module);
497             }
498         } catch (Exception JavaDoc e) {
499             Debug.logError(e, "Error closing the SQLProcessor in finalize EntityListIterator", module);
500         }
501         super.finalize();
502     }
503 }
504
Popular Tags