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
015package org.apache.tapestry5.commons.util;
016
017import 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 */
023public 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}