KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > accesslayer > ChainingIterator


1 package org.apache.ojb.broker.accesslayer;
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.util.ArrayList JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21
22 import org.apache.ojb.broker.PersistenceBrokerException;
23
24 /**
25  * @author matthew.baird (mattbaird@yahoo.com)
26  *
27  * The ChainingIterator is an extent aware Iterator.
28  *
29  * How the ChainingIterator works:
30  * The ChainedIterator holds a collection of RsIterators for each queried
31  * Interface-based extent.
32  *
33  * The RsIterator is able to load objects that are non-interface extents,
34  * mapped to the same table.
35  *
36  * The ChainingIterator cannot return sorted results as the iterator is a
37  * collection of query results across different tables.
38  *
39  * @version $Id: ChainingIterator.java,v 1.13.2.2 2005/12/21 22:22:58 tomdz Exp $
40  */

41 public class ChainingIterator implements OJBIterator
42 {
43     private List JavaDoc m_rsIterators = new ArrayList JavaDoc();
44     private OJBIterator m_activeIterator = null;
45
46     /**
47      * The following are used to maintain an index of where
48      * the cursor is in the array of rsiterators. We do this
49      * because we can't find the position through the interface,
50      * and we need the position in order to support the relative(x)
51      * calls
52      */

53     private int m_activeIteratorIndex = 0;
54     private int m_fullSize = -1;
55     private int m_currentCursorPosition = 0;
56     /** if true do not fire PBLifeCycleEvent. */
57     private boolean disableLifeCycleEvents = false;
58
59     /**
60      * Constructor for ChainingIterator.
61      */

62     public ChainingIterator()
63     {
64         super();
65     }
66
67     /**
68      * Constructor for ChainingIterator.
69      */

70     public ChainingIterator(List JavaDoc iterators)
71     {
72         Iterator JavaDoc checkIterator = iterators.iterator();
73         OJBIterator temp;
74
75         /**
76          * validate that all items in List are iterators and
77          * they are not empty.
78          */

79         while (checkIterator.hasNext())
80         {
81             temp = (OJBIterator) checkIterator.next();
82             addIterator(temp);
83         }
84     }
85
86     /**
87      * use this method to construct the ChainingIterator
88      * iterator by iterator.
89      */

90     public void addIterator(OJBIterator iterator)
91     {
92         /**
93          * only add iterators that are not null and non-empty.
94          */

95         if (iterator != null)
96         {
97             if (iterator.hasNext())
98             {
99                 setNextIterator();
100                 m_rsIterators.add(iterator);
101             }
102         }
103     }
104
105     /**
106      * Calculates the size of all the iterators. Caches it for fast
107      * lookups in the future. iterators shouldn't change size after the
108      * queries have been executed so caching is safe (assumption, should check).
109      * @return the combined size of all the iterators for all extents.
110      */

111     public int size() throws PersistenceBrokerException
112     {
113         if (m_fullSize == -1)
114         {
115             int size = 0;
116             Iterator JavaDoc it = m_rsIterators.iterator();
117             while (it.hasNext())
118             {
119                 size += ((OJBIterator) it.next()).size();
120             }
121             m_fullSize = size;
122         }
123         return m_fullSize;
124     }
125
126     /* (non-Javadoc)
127      * @see org.apache.ojb.broker.accesslayer.OJBIterator#fullSize()
128      */

129     public int fullSize() throws PersistenceBrokerException
130     {
131         return size();
132     }
133
134     /**
135      * the absolute and relative calls are the trickiest parts. We have to
136      * move across cursor boundaries potentially.
137      *
138      * a + row value indexes from beginning of resultset
139      * a - row value indexes from the end of th resulset.
140      *
141      * Calling absolute(1) is the same as calling first().
142      * Calling absolute(-1) is the same as calling last().
143      */

144     public boolean absolute(int row) throws PersistenceBrokerException
145     {
146         // 1. handle the special cases first.
147
if (row == 0)
148         {
149             return true;
150         }
151
152         if (row == 1)
153         {
154             m_activeIteratorIndex = 0;
155             m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
156             m_activeIterator.absolute(1);
157             return true;
158         }
159         if (row == -1)
160         {
161             m_activeIteratorIndex = m_rsIterators.size();
162             m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
163             m_activeIterator.absolute(-1);
164             return true;
165         }
166
167         // now do the real work.
168
boolean movedToAbsolute = false;
169         boolean retval = false;
170         setNextIterator();
171
172         // row is positive, so index from beginning.
173
if (row > 0)
174         {
175             int sizeCount = 0;
176             Iterator JavaDoc it = m_rsIterators.iterator();
177             OJBIterator temp = null;
178             while (it.hasNext() && !movedToAbsolute)
179             {
180                 temp = (OJBIterator) it.next();
181                 if (temp.size() < row)
182                 {
183                     sizeCount += temp.size();
184                 }
185                 else
186                 {
187                     // move to the offset - sizecount
188
m_currentCursorPosition = row - sizeCount;
189                     retval = temp.absolute(m_currentCursorPosition);
190                     movedToAbsolute = true;
191                 }
192             }
193
194         }
195
196         // row is negative, so index from end
197
else if (row < 0)
198         {
199             int sizeCount = 0;
200             OJBIterator temp = null;
201             for (int i = m_rsIterators.size(); ((i >= 0) && !movedToAbsolute); i--)
202             {
203                 temp = (OJBIterator) m_rsIterators.get(i);
204                 if (temp.size() < row)
205                 {
206                     sizeCount += temp.size();
207                 }
208                 else
209                 {
210                     // move to the offset - sizecount
211
m_currentCursorPosition = row + sizeCount;
212                     retval = temp.absolute(m_currentCursorPosition);
213                     movedToAbsolute = true;
214                 }
215             }
216         }
217
218         return retval;
219     }
220
221     /**
222      * Moves the cursor a relative number of rows.
223      * Movement can go in forward (positive) or reverse (negative).
224      *
225      * Calling relative does not "wrap" meaning if you move before first or
226      * after last you get positioned at the first or last row.
227      *
228      * Calling relative(0) does not change the cursor position.
229      *
230      * Note: Calling the method relative(1) is different from calling
231      * the method next() because is makes sense to call next() when
232      * there is no current row, for example, when the cursor is
233      * positioned before the first row or after the last row of
234      * the result set.
235      */

236     public boolean relative(int row) throws PersistenceBrokerException
237     {
238         if (row == 0)
239         {
240             return true;
241         }
242
243         boolean movedToRelative = false;
244         boolean retval = false;
245         setNextIterator();
246
247         if (row > 0)
248         {
249             // special case checking for the iterator we're currently in
250
// (since it isn't positioned on the boundary potentially)
251
if (row > (m_activeIterator.size() - m_currentCursorPosition))
252             {
253                 // the relative position lies over the border of the
254
// current iterator.
255

256                 // starting position counter should be set to whatever we have left in
257
// active iterator.
258
int positionCounter = m_activeIterator.size() - m_currentCursorPosition;
259                 for (int i = m_activeIteratorIndex + 1; ((i < m_rsIterators.size()) && !movedToRelative); i++)
260                 {
261                     m_activeIteratorIndex = i;
262                     m_currentCursorPosition = 0;
263                     m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
264                     if (!((row - positionCounter) > m_activeIterator.size()))
265                     {
266                         // the relative position requested is within this iterator.
267
m_currentCursorPosition = row - positionCounter;
268                         retval = m_activeIterator.relative(m_currentCursorPosition);
269                         movedToRelative = true;
270                     }
271                 }
272             }
273             else
274             {
275                 // the relative position lays within the current iterator.
276
retval = m_activeIterator.relative(row);
277                 movedToRelative = true;
278             }
279         }
280
281         return retval;
282     }
283
284     /**
285      * delegate to each contained OJBIterator and release
286      * its resources.
287      */

288     public void releaseDbResources()
289     {
290         Iterator JavaDoc it = m_rsIterators.iterator();
291         while (it.hasNext())
292         {
293             ((OJBIterator) it.next()).releaseDbResources();
294         }
295     }
296
297     /**
298      * check the list of iterators to see if we have a next element.
299      * @return true if one of the contained iterators past the current
300      * position has a next.
301      */

302     public boolean hasNext()
303     {
304         setNextIterator();
305         if (m_activeIterator == null)
306         {
307             return false;
308         }
309         else
310         {
311             return m_activeIterator.hasNext();
312         }
313     }
314
315     /**
316      * first checks to make sure we aren't at the end of the list of
317      * iterators, positions the cursor appropriately, then retrieves
318      * next object in active iterator.
319      * @return the next object in the iterator.
320      */

321     public Object JavaDoc next()
322     {
323         setNextIterator();
324         m_currentCursorPosition++;
325         return m_activeIterator.next();
326     }
327
328     public void remove()
329     {
330         setNextIterator();
331         m_activeIterator.remove();
332     }
333
334     /**
335      * Convenience routine to move to the next iterator if needed.
336      * @return true if the iterator is changed, false if no changes.
337      */

338     private boolean setNextIterator()
339     {
340         boolean retval = false;
341         // first, check if the activeIterator is null, and set it.
342
if (m_activeIterator == null)
343         {
344             if (m_rsIterators.size() > 0)
345             {
346                 m_activeIteratorIndex = 0;
347                 m_currentCursorPosition = 0;
348                 m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
349             }
350         }
351         else if (!m_activeIterator.hasNext())
352         {
353             if (m_rsIterators.size() > (m_activeIteratorIndex + 1))
354             {
355                 // we still have iterators in the collection, move to the
356
// next one, increment the counter, and set the active
357
// iterator.
358
m_activeIteratorIndex++;
359                 m_currentCursorPosition = 0;
360                 m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
361                 retval = true;
362             }
363         }
364
365         return retval;
366     }
367
368     /**
369      * Answer true if an Iterator for a Table is already available
370      * @param aTable
371      * @return
372      */

373     public boolean containsIteratorForTable(String JavaDoc aTable)
374     {
375         boolean result = false;
376
377         if (m_rsIterators != null)
378         {
379             for (int i = 0; i < m_rsIterators.size(); i++)
380             {
381                 OJBIterator it = (OJBIterator) m_rsIterators.get(i);
382                 if (it instanceof RsIterator)
383                 {
384                     if (((RsIterator) it).getClassDescriptor().getFullTableName().equals(aTable))
385                     {
386                         result = true;
387                         break;
388                     }
389                 }
390                 else if (it instanceof ChainingIterator)
391                 {
392                     result = ((ChainingIterator) it).containsIteratorForTable(aTable);
393                 }
394             }
395         }
396
397         return result;
398     }
399
400     /**
401      * @see org.apache.ojb.broker.accesslayer.OJBIterator#disableLifeCycleEvents()
402      */

403     public void disableLifeCycleEvents()
404     {
405         Iterator JavaDoc iterators = m_rsIterators.iterator();
406         while (iterators.hasNext())
407         {
408             OJBIterator iter = (OJBIterator) iterators.next();
409             iter.disableLifeCycleEvents();
410         }
411     }
412
413 }
414
Popular Tags