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