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     * A generator for the range <i>from</i> (inclusive) to <i>to</i> (exclusive).
022     *
023     * @since 1.0
024     * @version $Revision: 1156805 $ $Date: 2011-08-11 22:15:35 +0200 (Thu, 11 Aug 2011) $
025     * @author Jason Horman (jason@jhorman.org)
026     * @author Rodney Waldhoff
027     */
028    public final class LongRange extends BaseGenerator<Long> {
029        // attributes
030        //---------------------------------------------------------------
031    
032        private final long from;
033        private final long to;
034        private final long step;
035    
036        // constructors
037        //---------------------------------------------------------------
038        /**
039         * Create a new LongRange.
040         * @param from start
041         * @param to end
042         */
043        public LongRange(Number from, Number to) {
044            this(from.longValue(), to.longValue());
045        }
046    
047        /**
048         * Create a new LongRange.
049         * @param from start
050         * @param to end
051         * @param step increment
052         */
053        public LongRange(Number from, Number to, Number step) {
054            this(from.longValue(), to.longValue(), step.longValue());
055        }
056    
057        /**
058         * Create a new LongRange.
059         * @param from start
060         * @param to end
061         */
062        public LongRange(long from, long to) {
063            this(from, to, defaultStep(from, to));
064        }
065    
066        /**
067         * Create a new LongRange.
068         * @param from start
069         * @param to end
070         * @param step increment
071         */
072        public LongRange(long from, long to, long step) {
073            if (from != to && signOf(step) != signOf(to - from)) {
074                throw new IllegalArgumentException("Will never reach " + to + " from " + from + " using step " + step);
075            }
076            this.from = from;
077            this.to = to;
078            this.step = step;
079        }
080    
081        // methods
082        //---------------------------------------------------------------
083        /**
084         * {@inheritDoc}
085         */
086        public void run(UnaryProcedure<? super Long> proc) {
087            if (signOf(step) == -1L) {
088                for (long i = from; i > to; i += step) {
089                    proc.run(i);
090                }
091            } else {
092                for (long i = from; i < to; i += step) {
093                    proc.run(i);
094                }
095            }
096        }
097    
098        /**
099         * {@inheritDoc}
100         */
101        public String toString() {
102            return "LongRange<" + from + "," + to + "," + step + ">";
103        }
104    
105        /**
106         * {@inheritDoc}
107         */
108        public boolean equals(Object obj) {
109            if (obj == this) {
110                return true;
111            }
112            if (!(obj instanceof LongRange)) {
113                return false;
114            }
115            LongRange that = (LongRange) obj;
116            return this.from == that.from && this.to == that.to && this.step == that.step;
117        }
118    
119        /**
120         * {@inheritDoc}
121         */
122        public int hashCode() {
123            int hash = "LongRange".hashCode();
124            hash <<= 2;
125            hash ^= from;
126            hash <<= 2;
127            hash ^= to;
128            hash <<= 2;
129            hash ^= step;
130            return hash;
131        }
132    
133        // private methods
134        //---------------------------------------------------------------
135        /**
136         * Get <code>value/|value|</code> (0L when value == 0L).
137         * @param value to test
138         * @return long
139         */
140        private static long signOf(long value) {
141            return value < 0L ? -1L : value > 0L ? 1L : 0L;
142        }
143    
144        /**
145         * Calculate default step to get from <code>from</code> to <code>to</code>.
146         * @param from start
147         * @param to end
148         * @return long
149         */
150        private static long defaultStep(long from, long to) {
151            return from > to ? -1L : 1L;
152        }
153    
154    }