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