View Javadoc
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.jexl3.internal;
18  
19  import java.lang.reflect.Array;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.NoSuchElementException;
23  
24  /**
25   * A range of integers.
26   */
27  public abstract class IntegerRange implements Collection<Integer> {
28      /** The lower boundary. */
29      protected final int min;
30      /** The upper boundary. */
31      protected final int max;
32  
33      /**
34       * Creates a range, ascending or descending depending on boundaries order.
35       * @param from the lower inclusive boundary
36       * @param to   the higher inclusive boundary
37       * @return a range
38       */
39      public static IntegerRange create(final int from, final int to) {
40          if (from <= to) {
41              return new IntegerRange.Ascending(from, to);
42          }
43          return new IntegerRange.Descending(to, from);
44      }
45      /**
46       * Creates a new range.
47       * @param from the lower inclusive boundary
48       * @param to  the higher inclusive boundary
49       */
50      public IntegerRange(final int from, final int to) {
51          min = from;
52          max = to;
53      }
54  
55      /**
56       * Gets the interval minimum value.
57       * @return the low boundary
58       */
59      public int getMin() {
60          return min;
61      }
62  
63      /**
64       * Gets the interval maximum value.
65       * @return the high boundary
66       */
67      public int getMax() {
68          return max;
69      }
70  
71  
72      @Override
73      public int hashCode() {
74          int hash = getClass().hashCode();
75          //CSOFF: MagicNumber
76          hash = 13 * hash + this.min;
77          hash = 13 * hash + this.max;
78          //CSON: MagicNumber
79          return hash;
80      }
81  
82      @Override
83      public boolean equals(final Object obj) {
84          if (obj == null) {
85              return false;
86          }
87          if (getClass() != obj.getClass()) {
88              return false;
89          }
90          final IntegerRange other = (IntegerRange) obj;
91          if (this.min != other.min) {
92              return false;
93          }
94          if (this.max != other.max) {
95              return false;
96          }
97          return true;
98      }
99  
100     @Override
101     public abstract Iterator<Integer> iterator();
102 
103     @Override
104     public int size() {
105         return max - min + 1;
106     }
107 
108     @Override
109     public boolean isEmpty() {
110         return false;
111     }
112 
113     @Override
114     public boolean contains(final Object o) {
115         if (o instanceof Number) {
116             final long v = ((Number) o).intValue();
117             return min <= v && v <= max;
118         }
119         return false;
120     }
121 
122     @Override
123     public Object[] toArray() {
124         final int size = size();
125         final Object[] array = new Object[size];
126         for(int a = 0; a < size; ++a) {
127             array[a] = min + a;
128         }
129         return array;
130     }
131 
132     @Override
133     @SuppressWarnings("unchecked")
134     public <T> T[] toArray(final T[] array) {
135         final Class<?> ct = array.getClass().getComponentType();
136         final int length = size();
137         T[] copy = array;
138         if (ct.isAssignableFrom(Integer.class)) {
139             if (array.length < length) {
140                 copy = (T[]) Array.newInstance(ct, length);
141             }
142             for (int a = 0; a < length; ++a) {
143                 Array.set(copy, a, min + a);
144             }
145             if (length < copy.length) {
146                 copy[length] = null;
147             }
148             return copy;
149         }
150         throw new UnsupportedOperationException();
151     }
152 
153     @Override
154     public boolean containsAll(final Collection<?> c) {
155         for(final Object cc : c) {
156             if (!contains(cc)) {
157                 return false;
158             }
159         }
160         return true;
161     }
162 
163     @Override
164     public boolean add(final Integer e) {
165         throw new UnsupportedOperationException();
166     }
167 
168     @Override
169     public boolean remove(final Object o) {
170         throw new UnsupportedOperationException();
171     }
172 
173     @Override
174     public boolean addAll(final Collection<? extends Integer> c) {
175         throw new UnsupportedOperationException();
176     }
177 
178     @Override
179     public boolean removeAll(final Collection<?> c) {
180         throw new UnsupportedOperationException();
181     }
182 
183     @Override
184     public boolean retainAll(final Collection<?> c) {
185         throw new UnsupportedOperationException();
186     }
187 
188     @Override
189     public void clear() {
190         throw new UnsupportedOperationException();
191     }
192 
193     /**
194      * Ascending integer range.
195      */
196     public static class Ascending extends IntegerRange {
197         /**
198          * Constructor.
199          * @param from lower boundary
200          * @param to upper boundary
201          */
202         protected Ascending(final int from, final int to) {
203             super(from, to);
204         }
205 
206         @Override
207         public Iterator<Integer> iterator() {
208             return new AscIntegerIterator(min, max);
209         }
210     }
211 
212     /**
213      * Descending integer range.
214      */
215     public static class Descending extends IntegerRange {
216         /**
217          * Constructor.
218          * @param from upper boundary
219          * @param to lower boundary
220          */
221         protected Descending(final int from, final int to) {
222             super(from, to);
223         }
224 
225         @Override
226         public Iterator<Integer> iterator() {
227             return new DescIntegerIterator(min, max);
228         }
229     }
230 }
231 
232 /**
233  * An ascending iterator on an integer range.
234  */
235 class AscIntegerIterator implements Iterator<Integer> {
236     /** The lower boundary. */
237     private final int min;
238     /** The upper boundary. */
239     private final int max;
240     /** The current value. */
241     private int cursor;
242     /**
243      * Creates a iterator on the range.
244      * @param l low boundary
245      * @param h high boundary
246      */
247     public AscIntegerIterator(final int l, final int h) {
248         min = l;
249         max = h;
250         cursor = min;
251     }
252 
253     @Override
254     public boolean hasNext() {
255         return cursor <= max;
256     }
257 
258     @Override
259     public Integer next() {
260         if (cursor <= max) {
261             return cursor++;
262         }
263         throw new NoSuchElementException();
264     }
265 
266     @Override
267     public void remove() {
268         throw new UnsupportedOperationException("Not supported.");
269     }
270 }
271 
272 /**
273  * A descending iterator on an integer range.
274  */
275 class DescIntegerIterator implements Iterator<Integer> {
276     /** The lower boundary. */
277     private final int min;
278     /** The upper boundary. */
279     private final int max;
280     /** The current value. */
281     private int cursor;
282     /**
283      * Creates a iterator on the range.
284      * @param l low boundary
285      * @param h high boundary
286      */
287     public DescIntegerIterator(final int l, final int h) {
288         min = l;
289         max = h;
290         cursor = max;
291     }
292 
293     @Override
294     public boolean hasNext() {
295         return cursor >= min;
296     }
297 
298     @Override
299     public Integer next() {
300         if (cursor >= min) {
301             return cursor--;
302         }
303         throw new NoSuchElementException();
304     }
305 
306     @Override
307     public void remove() {
308         throw new UnsupportedOperationException("Not supported.");
309     }
310 }