001    package org.apache.ojb.broker.accesslayer;
002    
003    /* Copyright 2003-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import org.apache.ojb.broker.PersistenceBrokerException;
019    import org.apache.ojb.broker.query.Query;
020    
021    /**
022     * PagingIterator is wrapper around an OJBIterator to support startAt endAt
023     * positions. The PagingIterator returns rows <b>including</b> startAt 
024     * and <b>including</b> endAt.
025     * 
026     * startAt = 1, endAt = 11 returns rows 1 to 11 if available
027     * if endAt == Query.NO_END_AT_INDEX endAt is set to the last available row
028     * 
029     * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
030     * @version $Id: PagingIterator.java,v 1.1 2007-08-24 22:17:30 ewestfal Exp $
031     */
032    public class PagingIterator implements OJBIterator
033    {
034        private final OJBIterator m_iterator;
035        private int m_startAt;
036        private int m_endAt;
037        private int m_rowLimit;
038        private int m_fullSize;
039        private int m_currentCursorPosition; // position of the wrapped iterator
040    
041        /**
042         * Constructor 
043         * @param anIterator wrapped Iterator
044         * @param startAt (first row is 1)
045         * @param endAt (Query.NO_END_AT_INDEX stands for all available rows) 
046         */
047        public PagingIterator(OJBIterator anIterator, int startAt, int endAt)
048        {
049            super();
050    
051            if (endAt != Query.NO_START_AT_INDEX && startAt > endAt)
052            {
053                throw new PersistenceBrokerException("startAt must be less than endAt.");
054            }
055    
056            m_iterator = anIterator;
057            m_fullSize = m_iterator.size();
058    
059            if (startAt == Query.NO_START_AT_INDEX)
060            {
061                m_startAt = 1;
062            }
063            else
064            {
065                m_startAt = startAt;
066            }
067    
068            if (endAt == Query.NO_END_AT_INDEX)
069            {
070                m_endAt = m_fullSize;
071            }
072            else
073            {
074                m_endAt = Math.min(endAt, m_fullSize);
075            }
076            
077            m_rowLimit = Math.max(0, m_endAt - m_startAt + 1);
078            m_currentCursorPosition = m_startAt - 1;
079    
080            m_iterator.absolute(m_currentCursorPosition);
081        }
082    
083        /**
084             * @see org.apache.ojb.broker.accesslayer.OJBIterator#size()
085             */
086        public int size() throws PersistenceBrokerException
087        {
088            if (m_fullSize < m_rowLimit)
089            {
090                return m_fullSize;
091            }
092            else
093            {
094                return m_rowLimit;
095            }
096        }
097    
098        /**
099         * @see org.apache.ojb.broker.accesslayer.OJBIterator#fullSize()
100         */
101        public int fullSize() throws PersistenceBrokerException
102        {
103            return m_fullSize;
104        }
105        
106        /**
107             * @see org.apache.ojb.broker.accesslayer.OJBIterator#absolute(int)
108             */
109        public boolean absolute(int row) throws PersistenceBrokerException
110        {
111            int newPosition = (m_startAt - 1) + row;
112            
113            if (newPosition < m_startAt)
114            {
115                newPosition = Math.max(m_endAt + row, m_startAt - 1);
116            }
117            
118            if (newPosition > m_endAt)
119            {
120                newPosition = m_endAt;
121            }
122            
123            m_currentCursorPosition = newPosition;
124            return m_iterator.absolute(newPosition);
125        }
126    
127        /**
128             * @see org.apache.ojb.broker.accesslayer.OJBIterator#relative(int)
129             */
130        public boolean relative(int row) throws PersistenceBrokerException
131        {
132            return absolute(m_currentCursorPosition - (m_startAt - 1) + row);
133        }
134    
135        /**
136             * @see org.apache.ojb.broker.accesslayer.OJBIterator#releaseDbResources()
137             */
138        public void releaseDbResources()
139        {
140            m_iterator.releaseDbResources();
141        }
142    
143        /**
144             * remove is not supported
145             */
146        public void remove()
147        {
148            throw new UnsupportedOperationException("remove not supported by PagingIterator");
149        }
150    
151        /**
152             * @see java.util.Iterator#hasNext()
153             */
154        public boolean hasNext()
155        {
156            if (m_currentCursorPosition < m_endAt)
157            {
158                return true;
159            }
160            else
161            {
162                releaseDbResources();
163                return false;
164            }
165    
166        }
167    
168        /**
169             * @see java.util.Iterator#next()
170             */
171        public Object next()
172        {
173            m_currentCursorPosition++;
174            return m_iterator.next();
175        }
176    
177        /**
178         * @see org.apache.ojb.broker.accesslayer.OJBIterator#disableLifeCycleEvents()
179         */
180        public void disableLifeCycleEvents()
181        {
182            m_iterator.disableLifeCycleEvents();       
183        }
184    }