001    /*
002     * Licensed under the Apache License, Version 2.0 (the "License");
003     * you may not use this file except in compliance with the License.
004     * You may obtain a copy of the License at
005     *
006     *      http://www.apache.org/licenses/LICENSE-2.0
007     *
008     * Unless required by applicable law or agreed to in writing, software
009     * distributed under the License is distributed on an "AS IS" BASIS,
010     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011     * See the License for the specific language governing permissions and
012     * limitations under the License.
013     */
014    
015    package org.apache.commons.functor.generator.util;
016    
017    import org.apache.commons.functor.UnaryProcedure;
018    import org.apache.commons.functor.generator.BaseGenerator;
019    
020    
021    /**
022     * A generator for the range <i>from</i> (inclusive) to <i>to</i> (exclusive).
023     *
024     * @since 1.0
025     * @version $Revision: 1156804 $ $Date: 2011-08-11 22:14:47 +0200 (Thu, 11 Aug 2011) $
026     * @author Jason Horman (jason@jhorman.org)
027     * @author Rodney Waldhoff
028     */
029    public final class IntegerRange extends BaseGenerator<Integer> {
030        // attributes
031        //---------------------------------------------------------------
032    
033        private final int from;
034        private final int to;
035        private final int step;
036    
037        // constructors
038        //---------------------------------------------------------------
039        /**
040         * Create a new IntegerRange.
041         * @param from start
042         * @param to end
043         */
044        public IntegerRange(Number from, Number to) {
045            this(from.intValue(), to.intValue());
046        }
047    
048        /**
049         * Create a new IntegerRange.
050         * @param from start
051         * @param to end
052         * @param step increment
053         */
054        public IntegerRange(Number from, Number to, Number step) {
055            this(from.intValue(), to.intValue(), step.intValue());
056        }
057    
058        /**
059         * Create a new IntegerRange.
060         * @param from start
061         * @param to end
062         */
063        public IntegerRange(int from, int to) {
064            this(from, to, defaultStep(from, to));
065        }
066    
067        /**
068         * Create a new IntegerRange.
069         * @param from start
070         * @param to end
071         * @param step increment
072         */
073        public IntegerRange(int from, int to, int step) {
074            if (from != to && signOf(step) != signOf(to - from)) {
075                throw new IllegalArgumentException("Will never reach " + to + " from " + from + " using step " + step);
076            }
077            this.from = from;
078            this.to = to;
079            this.step = step;
080        }
081    
082        // methods
083        //---------------------------------------------------------------
084        /**
085         * {@inheritDoc}
086         */
087        public void run(UnaryProcedure<? super Integer> proc) {
088            if (signOf(step) == -1) {
089                for (int i = from; i > to; i += step) {
090                    proc.run(i);
091                }
092            } else {
093                for (int i = from; i < to; i += step) {
094                    proc.run(i);
095                }
096            }
097        }
098    
099        /**
100         * {@inheritDoc}
101         */
102        public String toString() {
103            return "IntegerRange<" + from + "," + to + "," + step + ">";
104        }
105    
106        /**
107         * {@inheritDoc}
108         */
109        public boolean equals(Object obj) {
110            if (obj == this) {
111                return true;
112            }
113            if (!(obj instanceof IntegerRange)) {
114                return false;
115            }
116            IntegerRange that = (IntegerRange) obj;
117            return this.from == that.from && this.to == that.to && this.step == that.step;
118        }
119    
120        /**
121         * {@inheritDoc}
122         */
123        public int hashCode() {
124            int hash = "IntegerRange".hashCode();
125            hash <<= 2;
126            hash ^= from;
127            hash <<= 2;
128            hash ^= to;
129            hash <<= 2;
130            hash ^= step;
131            return hash;
132        }
133    
134        // private methods
135        //---------------------------------------------------------------
136        /**
137         * Get <code>value/|value|</code> (0 when value == 0).
138         * @param value to test
139         * @return int
140         */
141        private static int signOf(int value) {
142            return value < 0 ? -1 : value > 0 ? 1 : 0;
143        }
144    
145        /**
146         * Calculate default step to get from <code>from</code> to <code>to</code>.
147         * @param from start
148         * @param to end
149         * @return int
150         */
151        private static int defaultStep(int from, int to) {
152            return from > to ? -1 : 1;
153        }
154    
155    }