001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.functor.range; 018 019import java.util.Iterator; 020 021import org.apache.commons.functor.BinaryFunction; 022import org.apache.commons.lang3.Validate; 023 024/** 025 * A range of longs. 026 * 027 * @since 1.0 028 * @version $Revision: 1385335 $ $Date: 2012-09-16 15:08:31 -0300 (Sun, 16 Sep 2012) $ 029 */ 030public final class LongRange extends NumericRange<Long> { 031 // attributes 032 //--------------------------------------------------------------- 033 034 /** 035 * Calculate default step. 036 */ 037 public static final BinaryFunction<Long, Long, Long> DEFAULT_STEP = new BinaryFunction<Long, Long, Long>() { 038 039 public Long evaluate(Long left, Long right) { 040 return left > right ? -1L : 1L; 041 } 042 }; 043 044 // constructors 045 // --------------------------------------------------------------- 046 /** 047 * Create a new LongRange. 048 * 049 * @param from start 050 * @param to end 051 */ 052 public LongRange(Number from, Number to) { 053 this(from.longValue(), to.longValue()); 054 } 055 056 /** 057 * Create a new LongRange. 058 * 059 * @param from start 060 * @param to end 061 * @param step increment 062 */ 063 public LongRange(Number from, Number to, Number step) { 064 this(from.longValue(), to.longValue(), step.longValue()); 065 } 066 067 /** 068 * Create a new LongRange. 069 * 070 * @param from start 071 * @param to end 072 */ 073 public LongRange(long from, long to) { 074 this(from, to, DEFAULT_STEP.evaluate(from, to).longValue()); 075 } 076 077 /** 078 * Create a new LongRange. 079 * 080 * @param from start 081 * @param to end 082 * @param step increment 083 */ 084 public LongRange(long from, long to, long step) { 085 this(from, DEFAULT_LEFT_BOUND_TYPE, to, DEFAULT_RIGHT_BOUND_TYPE, step); 086 } 087 088 /** 089 * Create a new LongRange. 090 * 091 * @param from start 092 * @param to end 093 * @throws NullPointerException if either {@link Endpoint} is {@code null} 094 */ 095 public LongRange(Endpoint<Long> from, Endpoint<Long> to) { 096 this(from, to, DEFAULT_STEP.evaluate(from.getValue(), to.getValue())); 097 } 098 099 /** 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}