View Javadoc

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