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