View Javadoc

1   /***
2    * Copyright (c) 2003 held jointly by the individual authors.
3    * 
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    * 
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12   * for more details.
13   * 
14   * You should have received a copy of the GNU Lesser General Public License
15   * along with this library; if not, write to the Free Software Foundation, Inc.,
16   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17   *  > http://www.gnu.org/copyleft/lesser.html >
18   * http://www.opensource.org/licenses/lgpl-license.php
19   */
20  package net.mlw.vlh.adapter.hibernate3.util;
21  
22  import java.math.BigDecimal;
23  import java.math.BigInteger;
24  import java.sql.Blob;
25  import java.sql.Clob;
26  import java.util.Calendar;
27  import java.util.Date;
28  import java.util.Locale;
29  import java.util.TimeZone;
30  
31  import net.mlw.vlh.adapter.util.ObjectValidator;
32  
33  import org.hibernate.HibernateException;
34  import org.hibernate.ScrollableResults;
35  import org.hibernate.type.Type;
36  
37  /***
38   * The ScrollableResultsDecorator class enable or disable putting objects into a
39   * final ResultsSet, thus into a final valueList. To check validity it uses
40   * ObjectValidator's interface. This implementation ensures that the validation
41   * method is invoked only once per object.
42   * 
43   * @todo Implement setRowNumber
44   * @author Andrej Zachar
45   * @version $Revision: 1.1 $ $Date: 2005/10/20 16:45:24 $
46   */
47  public class ScrollableResultsDecorator implements ScrollableResults
48  {
49  
50     private static final int INITIAL_CAPACITY = 100;
51  
52     private ScrollableResults _scrollableResults;
53  
54     private ObjectValidator _validator;
55  
56     private int _currentRow = -1;
57  
58     private int[] _index;
59  
60     private int _size;
61  
62     private boolean _isComplete;
63  
64     /***
65      * Default contructor of decorator;
66      */
67     public ScrollableResultsDecorator(ScrollableResults scrollableResults, ObjectValidator validator)
68     {
69        super();
70        setValidator(validator);
71        setScrollableResults(scrollableResults); // the method calls reset() as well
72     }
73  
74     /***
75      * @see org.hibernate.ScrollableResults#beforeFirst()
76      */
77     public void beforeFirst() throws HibernateException
78     {
79        if (_scrollableResults.getRowNumber() >= 0)
80        {
81           _scrollableResults.beforeFirst();
82        }
83        _currentRow = -1;
84     }
85  
86     /***
87      * @see org.hibernate.ScrollableResults#first()
88      */
89     public boolean first() throws HibernateException
90     {
91        return move(0);
92     }
93  
94     /***
95      * @see org.hibernate.ScrollableResults#isFirst()
96      */
97     public boolean isFirst() throws HibernateException
98     {
99        return (_currentRow == 0);
100    }
101 
102    /***
103     * @see org.hibernate.ScrollableResults#afterLast()
104     */
105    public void afterLast() throws HibernateException
106    {
107       if (_isComplete)
108       {
109          // the end has been already reached
110          _scrollableResults.afterLast();
111          _currentRow = _size;
112       }
113       else
114       {
115          lastKnown();
116          while (nextValid())
117             ;
118       }
119    }
120 
121    /***
122     * @see org.hibernate.ScrollableResults#last()
123     */
124    public boolean last() throws HibernateException
125    {
126       if (_isComplete)
127       {
128          // the end has been already reached
129          return move(_size - 1);
130       }
131       else
132       {
133          afterLast();
134          return previous();
135       }
136    }
137 
138    /***
139     * @see org.hibernate.ScrollableResults#isLast()
140     */
141    public boolean isLast() throws HibernateException
142    {
143       if (_isComplete)
144       {
145          return ((_currentRow + 1) == _size);
146       }
147       else
148       {
149          boolean result = next();
150          previous();
151          return result;
152       }
153    }
154 
155    /***
156     * @see org.hibernate.ScrollableResults#next()
157     */
158    public boolean next() throws HibernateException
159    {
160       return move(_currentRow + 1);
161    }
162 
163    /***
164     * @see org.hibernate.ScrollableResults#previous()
165     */
166    public boolean previous() throws HibernateException
167    {
168       return move(_currentRow - 1);
169    }
170 
171    /***
172     * @see org.hibernate.ScrollableResults#scroll(int)
173     */
174    public boolean scroll(int i) throws HibernateException
175    {
176       if (i == 0)
177       {
178          return _scrollableResults.scroll(0);
179       }
180 
181       return move(_currentRow + i);
182    }
183 
184    /***
185     * @see org.hibernate.ScrollableResults#setRowNumber(int)
186     */
187    public boolean setRowNumber(int row) throws HibernateException
188    {
189       if (row >= 0)
190       {
191          return move(row);
192       }
193       else
194       {
195          if (!_isComplete)
196          {
197             // ensure the end has been already reached
198             afterLast();
199          }
200          return move(_size + row);
201       }
202    }
203 
204    private boolean move(int row) throws HibernateException
205    {
206       if (row >= 0)
207       {
208          if (row < _size)
209          {
210             _currentRow = row;
211             int rowNumber = _index[_currentRow];
212             if (rowNumber != _scrollableResults.getRowNumber())
213             {
214                return _scrollableResults.setRowNumber(rowNumber);
215             }
216             else
217             {
218                return true;
219             }
220          }
221          else
222          {
223             if (_isComplete)
224             {
225                afterLast();
226                return false;
227             }
228             else
229             {
230                lastKnown();
231                boolean result = true;
232                while (result && (_currentRow < row))
233                {
234                   result = nextValid();
235                }
236                return result;
237             }
238          }
239       }
240       else
241       {
242          beforeFirst();
243          return false;
244       }
245    }
246 
247    private void lastKnown() throws HibernateException
248    {
249       if (_size > 0)
250       {
251          _currentRow = _size - 1;
252          int rowNumber = _index[_currentRow];
253          if (rowNumber != _scrollableResults.getRowNumber())
254          {
255             _scrollableResults.setRowNumber(_index[_currentRow]);
256          }
257       }
258       else
259       {
260          beforeFirst();
261       }
262    }
263 
264    private boolean nextValid() throws HibernateException
265    {
266       boolean result;
267 
268       do
269       {
270          result = _scrollableResults.next();
271       }
272       while (result && !_validator.isAcceptable(_scrollableResults.get(0)));
273 
274       _currentRow++;
275 
276       if (result)
277       {
278          _size = _currentRow + 1;
279          ensureCapacity(_size);
280          _index[_currentRow] = _scrollableResults.getRowNumber();
281       }
282       else
283       {
284          _isComplete = true;
285       }
286 
287       return result;
288    }
289 
290    private void ensureCapacity(int minCapacity)
291    {
292       int oldCapacity = _index.length;
293       if (minCapacity > oldCapacity)
294       {
295          int[] oldData = _index;
296          int newCapacity = (oldCapacity * 3) / 2 + 1;
297          if (newCapacity < minCapacity)
298          {
299             newCapacity = minCapacity;
300          }
301          _index = new int[newCapacity];
302          System.arraycopy(oldData, 0, _index, 0, oldCapacity);
303       }
304    }
305 
306    /***
307     * @see org.hibernate.ScrollableResults#getRowNumber()
308     */
309    public int getRowNumber() throws HibernateException
310    {
311       return _currentRow;
312    }
313 
314    /* ###### delegated methods ###### */
315 
316    /***
317     * @see org.hibernate.ScrollableResults#get()
318     */
319    public Object[] get() throws HibernateException
320    {
321       return _scrollableResults.get();
322    }
323 
324    /***
325     * @see org.hibernate.ScrollableResults#get(int)
326     */
327    public Object get(int arg0) throws HibernateException
328    {
329       return _scrollableResults.get(arg0);
330    }
331 
332    /***
333     * @see org.hibernate.ScrollableResults#close()
334     */
335    public void close() throws HibernateException
336    {
337       _scrollableResults.close();
338    }
339 
340    /***
341     * @see org.hibernate.ScrollableResults#getBigDecimal(int)
342     */
343    public BigDecimal getBigDecimal(int arg0) throws HibernateException
344    {
345       return _scrollableResults.getBigDecimal(arg0);
346    }
347 
348    /***
349     * @see org.hibernate.ScrollableResults#getBigInteger(int)
350     */
351    public BigInteger getBigInteger(int arg0) throws HibernateException
352    {
353       return _scrollableResults.getBigInteger(arg0);
354    }
355 
356    /***
357     * @see org.hibernate.ScrollableResults#getBinary(int)
358     */
359    public byte[] getBinary(int arg0) throws HibernateException
360    {
361       return _scrollableResults.getBinary(arg0);
362    }
363 
364    /***
365     * @see org.hibernate.ScrollableResults#getBlob(int)
366     */
367    public Blob getBlob(int arg0) throws HibernateException
368    {
369       return _scrollableResults.getBlob(arg0);
370    }
371 
372    /***
373     * @see org.hibernate.ScrollableResults#getBoolean(int)
374     */
375    public Boolean getBoolean(int arg0) throws HibernateException
376    {
377       return _scrollableResults.getBoolean(arg0);
378    }
379 
380    /***
381     * @see org.hibernate.ScrollableResults#getByte(int)
382     */
383    public Byte getByte(int arg0) throws HibernateException
384    {
385       return _scrollableResults.getByte(arg0);
386    }
387 
388    /***
389     * @see org.hibernate.ScrollableResults#getCalendar(int)
390     */
391    public Calendar getCalendar(int arg0) throws HibernateException
392    {
393       return _scrollableResults.getCalendar(arg0);
394    }
395 
396    /***
397     * @see org.hibernate.ScrollableResults#getClob(int)
398     */
399    public Clob getClob(int arg0) throws HibernateException
400    {
401       return _scrollableResults.getClob(arg0);
402    }
403 
404    /***
405     * @see org.hibernate.ScrollableResults#getDate(int)
406     */
407    public Date getDate(int arg0) throws HibernateException
408    {
409       return _scrollableResults.getDate(arg0);
410    }
411 
412    /***
413     * @see org.hibernate.ScrollableResults#getDouble(int)
414     */
415    public Double getDouble(int arg0) throws HibernateException
416    {
417       return _scrollableResults.getDouble(arg0);
418    }
419 
420    /***
421     * @see org.hibernate.ScrollableResults#getFloat(int)
422     */
423    public Float getFloat(int arg0) throws HibernateException
424    {
425       return _scrollableResults.getFloat(arg0);
426    }
427 
428    /***
429     * @see org.hibernate.ScrollableResults#getCharacter(int)
430     */
431    public Character getCharacter(int arg0) throws HibernateException
432    {
433       return _scrollableResults.getCharacter(arg0);
434    }
435 
436    /***
437     * @see org.hibernate.ScrollableResults#getInteger(int)
438     */
439    public Integer getInteger(int arg0) throws HibernateException
440    {
441       return _scrollableResults.getInteger(arg0);
442    }
443 
444    /***
445     * @see org.hibernate.ScrollableResults#getLocale(int)
446     */
447    public Locale getLocale(int arg0) throws HibernateException
448    {
449       return _scrollableResults.getLocale(arg0);
450    }
451 
452    /***
453     * @see org.hibernate.ScrollableResults#getLong(int)
454     */
455    public Long getLong(int arg0) throws HibernateException
456    {
457       return _scrollableResults.getLong(arg0);
458    }
459 
460    /***
461     * @see org.hibernate.ScrollableResults#getShort(int)
462     */
463    public Short getShort(int arg0) throws HibernateException
464    {
465       return _scrollableResults.getShort(arg0);
466    }
467 
468    /***
469     * @see org.hibernate.ScrollableResults#getString(int)
470     */
471    public String getString(int arg0) throws HibernateException
472    {
473       return _scrollableResults.getString(arg0);
474    }
475 
476    /***
477     * @see org.hibernate.ScrollableResults#getText(int)
478     */
479    public String getText(int arg0) throws HibernateException
480    {
481       return _scrollableResults.getString(arg0);
482    }
483 
484    /***
485     * @see org.hibernate.ScrollableResults#getTimeZone(int)
486     */
487    public TimeZone getTimeZone(int arg0) throws HibernateException
488    {
489       return _scrollableResults.getTimeZone(arg0);
490    }
491 
492    /***
493     * @see org.hibernate.ScrollableResults#getType(int)
494     */
495    public Type getType(int arg0)
496    {
497       return _scrollableResults.getType(arg0);
498    }
499 
500    /* ###### getters / setters ###### */
501 
502    public void setScrollableResults(ScrollableResults scrollableResults)
503    {
504       _scrollableResults = scrollableResults;
505       reset();
506    }
507 
508    public void setValidator(ObjectValidator validator)
509    {
510       _validator = validator;
511    }
512 
513    private void reset()
514    {
515       _index = new int[INITIAL_CAPACITY];
516       _currentRow = -1;
517       _size = 0;
518       _isComplete = false;
519    }
520 }