001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.util;
020
021import lucee.runtime.PageContext;
022import lucee.runtime.exp.PageException;
023import lucee.runtime.op.Operator;
024import lucee.runtime.type.KeyImpl;
025import lucee.runtime.type.Query;
026
027/**
028 * A Number Iterator Implementation to iterate from to
029 */
030public final class NumberIterator {
031        
032        private int _from;
033        private int _to;
034        private int _current;
035        private int recordcount;
036        
037        //private static int count=0;
038        
039        /**
040         * constructor of the number iterator
041         * @param from iterate from
042         * @param to iterate to
043         * @param recordcount 
044         */
045        private NumberIterator(int from, int to, int recordcount) {
046            //lucee.print.ln(count++);
047        init(from,to,recordcount);
048        }
049        private NumberIterator init(int from, int to, int recordcount) {
050            this._from=from;
051                this._current=from;
052                this._to=to; 
053                this.recordcount=recordcount;
054                return this;
055        }
056                
057        /**
058         * @return returns if there is a next value
059         */
060        public boolean hasNext() {
061                return _current<_to;
062        }
063        public boolean hasNext(boolean useRecordcount) {
064                return _current<(useRecordcount?recordcount:_to);
065        }
066        
067        /**
068         * @return increment and return new value
069         */
070        public int next() {
071            return ++_current;
072        }
073        
074        /**
075         * @return returns if there is a previous value
076         */
077        public boolean hasPrevious() {
078                return _current>_from;
079        }
080        
081        /**
082         * @return decrement and return new value
083         */
084        public int previous() {
085                return --_current;
086        }
087        
088        /**
089         * @return returns smallest possible value
090         */
091        public int from() {
092                return _from;
093        }
094        
095        /**
096         * @return returns greatest value
097         */
098        public int to() {
099                return _to;
100        }
101        
102        /**
103         * @return set value to first and return
104         */
105        public int first() {
106                return _current=_from;
107        }
108        
109        /**
110         * @return set value to last and return thid value
111         */
112        public int last() {
113                return _current=_to;
114        }
115        /**
116         * @return returns current value
117         */
118        public int current() {
119                return _current;
120        }
121        
122        /**
123         * sets the current position
124         * @param current
125         */
126        public void setCurrent(int current) {
127                _current=current;
128        }
129
130        /**
131         * @return is after last
132         */
133        public boolean isAfterLast() {
134                return _current>_to;
135        }       
136        /**
137         * @return is pointer on a valid position
138         */
139        public boolean isValid() {
140                return _current>=_from && _current<=_to;
141        }       
142        
143        public boolean isValid(int current) {
144                _current=current;
145                return _current>=_from && _current<=_to;
146        }       
147        
148        
149        
150        
151        private static NumberIterator[] iterators=new NumberIterator[]{
152                    new NumberIterator(1,1,1),
153                    new NumberIterator(1,1,1),
154                    new NumberIterator(1,1,1),
155                    new NumberIterator(1,1,1),
156                    new NumberIterator(1,1,1),
157                    new NumberIterator(1,1,1),
158                    new NumberIterator(1,1,1),
159                    new NumberIterator(1,1,1),
160                    new NumberIterator(1,1,1),
161                    new NumberIterator(1,1,1)
162        };
163        private static int pointer=0;
164        
165        /**
166         * load a iterator
167         * @param from
168         * @param to iterate to
169         * @return NumberIterator
170         */
171        private static NumberIterator _load(int from, int to) {
172                return _load(from, to, to);
173        }
174        private static NumberIterator _load(int from, int to, int recordcount) {
175                if(pointer>=iterators.length) return new NumberIterator(from,to,recordcount);
176            return iterators[pointer++].init(from,to,recordcount);
177        }
178        
179        /**
180         * create a Number Iterator with value from and to
181         * @param from
182         * @param to
183         * @return NumberIterator
184         */
185        public static synchronized NumberIterator load(double from, double to) {
186                return _load((int)from,(int)to,(int)to);
187        }
188        public static synchronized NumberIterator load(int from, int to) {
189                return _load(from,to,to);
190        }
191        
192        /**
193         * create a Number Iterator with value from and to
194         * @param from
195         * @param to
196         * @param max
197         * @return NumberIterator
198         */
199        public static synchronized NumberIterator load(double from, double to, double max) {
200            return loadMax((int)from, (int)to, (int)max);
201        }
202        
203        public static synchronized NumberIterator loadMax(int from, int to, int max) {
204            return _load(from,((from+max-1<to)?from+max-1:to),to);
205        }
206        
207        public static synchronized NumberIterator loadEnd(int from, int to, int end) {
208            return _load(from,((end<to)?end:to),to);
209        }
210        
211        /**
212         * @param ni
213         * @param query
214         * @param groupName
215         * @param caseSensitive
216         * @return number iterator for group
217         * @throws PageException
218         */
219        public static synchronized NumberIterator load(PageContext pc, NumberIterator ni, Query query, String groupName, boolean caseSensitive) throws PageException {
220                int startIndex=query.getCurrentrow(pc.getId()); 
221                
222        Object startValue=query.get(KeyImpl.init(groupName)); 
223        while(ni.hasNext(true)) { 
224            if(!Operator.equals(startValue,query.getAt(groupName,ni.next()),caseSensitive)) { 
225
226                        ni.previous();
227                        return _load(startIndex,ni.current());
228            } 
229        } 
230        return _load(startIndex,ni.current());
231    } 
232        
233        /**
234         * @param ni Iterator to release
235         */
236        public static synchronized void release(NumberIterator ni) {
237            if(pointer>0) {
238                iterators[--pointer]=ni;
239            }
240        }
241        
242        
243        
244        
245        
246        
247        
248}