1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.functor.range;
18
19 import java.util.Iterator;
20
21 import org.apache.commons.functor.BinaryFunction;
22 import org.apache.commons.lang3.Validate;
23
24 /**
25 * A range of longs.
26 *
27 * @since 1.0
28 * @version $Revision: 1385335 $ $Date: 2012-09-16 15:08:31 -0300 (Sun, 16 Sep 2012) $
29 */
30 public final class LongRange extends NumericRange<Long> {
31 // attributes
32 //---------------------------------------------------------------
33
34 /**
35 * Calculate default step.
36 */
37 public static final BinaryFunction<Long, Long, Long> DEFAULT_STEP = new BinaryFunction<Long, Long, Long>() {
38
39 public Long evaluate(Long left, Long right) {
40 return left > right ? -1L : 1L;
41 }
42 };
43
44 // constructors
45 // ---------------------------------------------------------------
46 /**
47 * Create a new LongRange.
48 *
49 * @param from start
50 * @param to end
51 */
52 public LongRange(Number from, Number to) {
53 this(from.longValue(), to.longValue());
54 }
55
56 /**
57 * Create a new LongRange.
58 *
59 * @param from start
60 * @param to end
61 * @param step increment
62 */
63 public LongRange(Number from, Number to, Number step) {
64 this(from.longValue(), to.longValue(), step.longValue());
65 }
66
67 /**
68 * Create a new LongRange.
69 *
70 * @param from start
71 * @param to end
72 */
73 public LongRange(long from, long to) {
74 this(from, to, DEFAULT_STEP.evaluate(from, to).longValue());
75 }
76
77 /**
78 * Create a new LongRange.
79 *
80 * @param from start
81 * @param to end
82 * @param step increment
83 */
84 public LongRange(long from, long to, long step) {
85 this(from, DEFAULT_LEFT_BOUND_TYPE, to, DEFAULT_RIGHT_BOUND_TYPE, step);
86 }
87
88 /**
89 * Create a new LongRange.
90 *
91 * @param from start
92 * @param to end
93 * @throws NullPointerException if either {@link Endpoint} is {@code null}
94 */
95 public LongRange(Endpoint<Long> from, Endpoint<Long> to) {
96 this(from, to, DEFAULT_STEP.evaluate(from.getValue(), to.getValue()));
97 }
98
99 /**
100 * Create a new LongRange.
101 *
102 * @param from start
103 * @param to end
104 * @param step increment
105 * @throws NullPointerException if either {@link Endpoint} is {@code null}
106 */
107 public LongRange(Endpoint<Long> from, Endpoint<Long> to, int step) {
108 this(from, to, (long) step);
109 }
110
111 /**
112 * Create a new LongRange.
113 *
114 * @param from start
115 * @param leftBoundType type of left bound
116 * @param to end
117 * @param rightBoundType type of right bound
118 * @throws NullPointerException if either {@link BoundType} is {@code null}
119 */
120 public LongRange(long from, BoundType leftBoundType, long to, BoundType rightBoundType) {
121 this(from, leftBoundType, to, rightBoundType, DEFAULT_STEP.evaluate(from, to));
122 }
123
124 /**
125 * Create a new LongRange.
126 *
127 * @param from start
128 * @param to end
129 * @param step increment
130 * @throws NullPointerException if either {@link Endpoint} is {@code null}
131 */
132 public LongRange(Endpoint<Long> from, Endpoint<Long> to, long step) {
133 super(from, to, Long.valueOf(step), new BinaryFunction<Long, Long, Long>() {
134
135 public Long evaluate(Long left, Long right) {
136 return Long.valueOf(left.longValue() + right.longValue());
137 }
138 });
139
140 final long f = from.getValue();
141 final long t = to.getValue();
142
143 Validate.isTrue(f == t || Long.signum(step) == Long.signum(t - f),
144 "Will never reach '%s' from '%s' using step %s", t, f, step);
145 }
146
147 /**
148 * Create a new LongRange.
149 *
150 * @param from start
151 * @param leftBoundType type of left bound
152 * @param to end
153 * @param rightBoundType type of right bound
154 * @param step increment
155 * @throws NullPointerException if either {@link BoundType} is {@code null}
156 */
157 public LongRange(long from, BoundType leftBoundType, long to,
158 BoundType rightBoundType, long step) {
159 this(new Endpoint<Long>(from, leftBoundType), new Endpoint<Long>(to, rightBoundType), step);
160 }
161
162 // iterable
163 // ---------------------------------------------------------------
164
165 /**
166 * {@inheritDoc}
167 */
168 protected Iterator<Long> createIterator() {
169 return new Iterator<Long>() {
170 private long currentValue;
171
172 {
173 currentValue = leftEndpoint.getValue();
174
175 if (leftEndpoint.getBoundType() == BoundType.OPEN) {
176 this.currentValue += step;
177 }
178 }
179
180 public void remove() {
181 throw new UnsupportedOperationException();
182 }
183
184 public Long next() {
185 final long step = getStep();
186 final long r = currentValue;
187 currentValue += step;
188 return Long.valueOf(r);
189 }
190
191 public boolean hasNext() {
192 final int cmp = Long.valueOf(currentValue).compareTo(rightEndpoint.getValue());
193
194 if (cmp == 0) {
195 return rightEndpoint.getBoundType() == BoundType.CLOSED;
196 }
197 if (step > 0L) {
198 return cmp < 0;
199 }
200 return cmp > 0;
201 }
202 };
203 }
204
205 }