001    package railo.runtime.util;
002    
003    import railo.runtime.PageContext;
004    import railo.runtime.exp.PageException;
005    import railo.runtime.op.Operator;
006    import railo.runtime.type.KeyImpl;
007    import railo.runtime.type.Query;
008    
009    /**
010     * A Number Iterator Implementation to iterate from to
011     */
012    public final class NumberIterator {
013            
014            private int _from;
015            private int _to;
016            private int _current;
017            private int recordcount;
018            
019            //private static int count=0;
020            
021            /**
022             * constructor of the number iterator
023             * @param from iterate from
024             * @param to iterate to
025             * @param recordcount 
026             */
027            private NumberIterator(int from, int to, int recordcount) {
028                //railo.print.ln(count++);
029            init(from,to,recordcount);
030            }
031            private NumberIterator init(int from, int to, int recordcount) {
032                this._from=from;
033                    this._current=from;
034                    this._to=to; 
035                    this.recordcount=recordcount;
036                    return this;
037            }
038                    
039            /**
040             * @return returns if there is a next value
041             */
042            public boolean hasNext() {
043                    return _current<_to;
044            }
045            public boolean hasNext(boolean useRecordcount) {
046                    return _current<(useRecordcount?recordcount:_to);
047            }
048            
049            /**
050             * @return increment and return new value
051             */
052            public int next() {
053                return ++_current;
054            }
055            
056            /**
057             * @return returns if there is a previous value
058             */
059            public boolean hasPrevious() {
060                    return _current>_from;
061            }
062            
063            /**
064             * @return decrement and return new value
065             */
066            public int previous() {
067                    return --_current;
068            }
069            
070            /**
071             * @return returns smallest possible value
072             */
073            public int from() {
074                    return _from;
075            }
076            
077            /**
078             * @return returns greatest value
079             */
080            public int to() {
081                    return _to;
082            }
083            
084            /**
085             * @return set value to first and return
086             */
087            public int first() {
088                    return _current=_from;
089            }
090            
091            /**
092             * @return set value to last and return thid value
093             */
094            public int last() {
095                    return _current=_to;
096            }
097            /**
098             * @return returns current value
099             */
100            public int current() {
101                    return _current;
102            }
103            
104            /**
105             * sets the current position
106             * @param current
107             */
108            public void setCurrent(int current) {
109                    _current=current;
110            }
111    
112            /**
113             * @return is after last
114             */
115            public boolean isAfterLast() {
116                    return _current>_to;
117            }       
118            /**
119             * @return is pointer on a valid position
120             */
121            public boolean isValid() {
122                    return _current>=_from && _current<=_to;
123            }       
124            
125            
126            
127            
128            private static NumberIterator[] iterators=new NumberIterator[]{
129                        new NumberIterator(1,1,1),
130                        new NumberIterator(1,1,1),
131                        new NumberIterator(1,1,1),
132                        new NumberIterator(1,1,1),
133                        new NumberIterator(1,1,1),
134                        new NumberIterator(1,1,1),
135                        new NumberIterator(1,1,1),
136                        new NumberIterator(1,1,1),
137                        new NumberIterator(1,1,1),
138                        new NumberIterator(1,1,1)
139            };
140            private static int pointer=0;
141            
142            /**
143             * load a iterator
144             * @param from
145             * @param to iterate to
146             * @return NumberIterator
147             */
148            private static NumberIterator _load(int from, int to) {
149                    return _load(from, to, to);
150            }
151            private static NumberIterator _load(int from, int to, int recordcount) {
152                    if(pointer>=iterators.length) return new NumberIterator(from,to,recordcount);
153                return iterators[pointer++].init(from,to,recordcount);
154            }
155            
156            /**
157             * create a Number Iterator with value from and to
158             * @param from
159             * @param to
160             * @return NumberIterator
161             */
162            public static synchronized NumberIterator load(double from, double to) {
163                    return _load((int)from,(int)to,(int)to);
164            }
165            
166            /**
167             * create a Number Iterator with value from and to
168             * @param from
169             * @param to
170             * @param max
171             * @return NumberIterator
172             */
173            public static synchronized NumberIterator load(double from, double to, double max) {
174                return _load((int)from,(int)((from+max-1<to)?from+max-1:to),(int)to);
175            }
176            
177            /**
178             * @param ni
179             * @param query
180             * @param groupName
181             * @param caseSensitive
182             * @return number iterator for group
183             * @throws PageException
184             */
185            public static synchronized NumberIterator load(PageContext pc, NumberIterator ni, Query query, String groupName, boolean caseSensitive) throws PageException {
186                    int startIndex=query.getCurrentrow(); 
187                    // FUTURE int startIndex=query.getCurrentrow(pc.getId()); 
188            
189            Object startValue=query.get(KeyImpl.init(groupName)); 
190            // FUTURE Object startValue=query.get(pc,KeyImpl.init(groupName)); 
191            while(ni.hasNext(true)) { 
192                if(!Operator.equals(startValue,query.getAt(groupName,ni.next()),caseSensitive)) { 
193                            ni.previous();
194                            return _load(startIndex,ni.current());
195                } 
196            } 
197            return _load(startIndex,ni.current());
198        } 
199            
200            /**
201             * @param ni Iterator to release
202             */
203            public static synchronized void release(NumberIterator ni) {
204                if(pointer>0) {
205                    iterators[--pointer]=ni;
206                }
207            }
208            
209            
210            
211            
212            
213            
214            
215    }