001    // Copyright 2006 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry5.internal.util;
016    
017    import java.util.Iterator;
018    
019    /**
020     * Represents a sequence of integer values, either ascending or descending. The sequence is always inclusive (of the
021     * finish value).
022     */
023    public final class IntegerRange implements Iterable<Integer>
024    {
025        private final int start;
026    
027        private final int finish;
028    
029        private class RangeIterator implements Iterator<Integer>
030        {
031            private final int increment;
032    
033            private int value = start;
034    
035            private boolean hasNext = true;
036    
037            RangeIterator()
038            {
039                increment = start < finish ? +1 : -1;
040            }
041    
042            public boolean hasNext()
043            {
044                return hasNext;
045            }
046    
047            public Integer next()
048            {
049                if (!hasNext) throw new IllegalStateException();
050    
051                int result = value;
052    
053                hasNext = value != finish;
054    
055                value += increment;
056    
057                return result;
058            }
059    
060            public void remove()
061            {
062                throw new UnsupportedOperationException();
063            }
064    
065        }
066    
067        public IntegerRange(final int start, final int finish)
068        {
069            this.start = start;
070            this.finish = finish;
071        }
072    
073        public int getFinish()
074        {
075            return finish;
076        }
077    
078        public int getStart()
079        {
080            return start;
081        }
082    
083        @Override
084        public String toString()
085        {
086            return String.format("%d..%d", start, finish);
087        }
088    
089        /**
090         * The main puprose of a range object is to produce an Iterator. Since IntegerRange is iterable, it is useful with
091         * the Tapestry Loop component, but also with the Java for loop!
092         */
093        public Iterator<Integer> iterator()
094        {
095            return new RangeIterator();
096        }
097    
098        @Override
099        public int hashCode()
100        {
101            final int PRIME = 31;
102    
103            int result = PRIME + finish;
104    
105            result = PRIME * result + start;
106    
107            return result;
108        }
109    
110        /**
111         * Returns true if the other object is an IntegerRange with the same start and finish values.
112         */
113        @Override
114        public boolean equals(Object obj)
115        {
116            if (this == obj) return true;
117            if (obj == null) return false;
118            if (getClass() != obj.getClass()) return false;
119            final IntegerRange other = (IntegerRange) obj;
120            if (finish != other.finish) return false;
121    
122            return start == other.start;
123        }
124    
125    }