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