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 integers. 026 * 027 * @since 1.0 028 * @version $Revision: 1385335 $ $Date: 2012-09-16 15:08:31 -0300 (Sun, 16 Sep 2012) $ 029 */ 030public class IntegerRange extends NumericRange<Integer> { 031 032 // attributes 033 // --------------------------------------------------------------- 034 035 /** 036 * Calculate default step. 037 */ 038 public static final BinaryFunction<Integer, Integer, Integer> DEFAULT_STEP = 039 new BinaryFunction<Integer, Integer, Integer>() { 040 041 public Integer evaluate(Integer left, Integer right) { 042 return left > right ? -1 : 1; 043 } 044 }; 045 046 // constructors 047 // --------------------------------------------------------------- 048 /** 049 * Create a new IntegerRange. 050 * 051 * @param from 052 * start 053 * @param to 054 * end 055 */ 056 public IntegerRange(Number from, Number to) { 057 this(from.intValue(), to.intValue()); 058 } 059 060 /** 061 * Create a new IntegerRange. 062 * 063 * @param from 064 * start 065 * @param to 066 * end 067 * @param step 068 * increment 069 */ 070 public IntegerRange(Number from, Number to, Number step) { 071 this(from.intValue(), to.intValue(), step.intValue()); 072 } 073 074 /** 075 * Create a new IntegerRange. 076 * 077 * @param from 078 * start 079 * @param to 080 * end 081 */ 082 public IntegerRange(int from, int to) { 083 this(from, to, DEFAULT_STEP.evaluate(from, to).intValue()); 084 } 085 086 /** 087 * Create a new IntegerRange. 088 * 089 * @param from 090 * start 091 * @param to 092 * end 093 * @param step 094 * increment 095 */ 096 public IntegerRange(int from, int to, int step) { 097 this(from, DEFAULT_LEFT_BOUND_TYPE, to, DEFAULT_RIGHT_BOUND_TYPE, step); 098 } 099 100 /** 101 * Create a new IntegerRange. 102 * 103 * @param from 104 * start 105 * @param to 106 * end 107 * @throws NullPointerException 108 * if either {@link Endpoint} is {@code null} 109 */ 110 public IntegerRange(Endpoint<Integer> from, Endpoint<Integer> to) { 111 this(from, to, DEFAULT_STEP.evaluate(from.getValue(), to.getValue())); 112 } 113 114 /** 115 * Create a new IntegerRange. 116 * 117 * @param from 118 * start 119 * @param leftBoundType 120 * type of left bound 121 * @param to 122 * end 123 * @param rightBoundType 124 * type of right bound 125 * @throws NullPointerException 126 * if either {@link BoundType} is {@code null} 127 */ 128 public IntegerRange(int from, BoundType leftBoundType, int to, BoundType rightBoundType) { 129 this(from, leftBoundType, to, rightBoundType, DEFAULT_STEP.evaluate(from, to)); 130 } 131 132 /** 133 * Create a new IntegerRange. 134 * 135 * @param from 136 * start 137 * @param to 138 * end 139 * @param step 140 * increment 141 * @throws NullPointerException 142 * if either {@link Endpoint} is {@code null} 143 */ 144 public IntegerRange(Endpoint<Integer> from, Endpoint<Integer> to, int step) { 145 super(from, to, Integer.valueOf(step), new BinaryFunction<Integer, Integer, Integer>() { 146 147 public Integer evaluate(Integer left, Integer right) { 148 return Integer.valueOf(left.intValue() + right.intValue()); 149 } 150 }); 151 152 final int f = from.getValue(); 153 final int t = to.getValue(); 154 155 Validate.isTrue(f == t || Integer.signum(step) == Integer.signum(t - f), 156 "Will never reach '%s' from '%s' using step %s", t, f, step); 157 } 158 159 /** 160 * Create a new IntegerRange. 161 * 162 * @param from 163 * start 164 * @param leftBoundType 165 * type of left bound 166 * @param to 167 * end 168 * @param rightBoundType 169 * type of right bound 170 * @param step 171 * increment 172 * @throws NullPointerException 173 * if either {@link BoundType} is {@code null} 174 */ 175 public IntegerRange(int from, BoundType leftBoundType, int to, BoundType rightBoundType, int step) { 176 this(new Endpoint<Integer>(from, leftBoundType), new Endpoint<Integer>(to, rightBoundType), step); 177 } 178 179 /** 180 * {@inheritDoc} 181 */ 182 protected Iterator<Integer> createIterator() { 183 return new Iterator<Integer>() { 184 private int currentValue; 185 186 { 187 currentValue = leftEndpoint.getValue(); 188 189 if (leftEndpoint.getBoundType() == BoundType.OPEN) { 190 this.currentValue += step; 191 } 192 } 193 194 public void remove() { 195 throw new UnsupportedOperationException(); 196 } 197 198 public Integer next() { 199 final int step = getStep(); 200 final int r = currentValue; 201 currentValue += step; 202 return Integer.valueOf(r); 203 } 204 205 public boolean hasNext() { 206 final int cmp = Integer.valueOf(currentValue).compareTo(rightEndpoint.getValue()); 207 208 if (cmp == 0) { 209 return rightEndpoint.getBoundType() == BoundType.CLOSED; 210 } 211 if (step > 0) { 212 return cmp < 0; 213 } 214 return cmp > 0; 215 } 216 }; 217 } 218 219}