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