Use pattern matching on instanceof in yang-common
[yangtools.git] / common / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / Uint16.java
1 /*
2  * Copyright (c) 2015 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.common;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.collect.Interner;
14 import com.google.common.collect.Interners;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.eclipse.jdt.annotation.NonNullByDefault;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.yangtools.concepts.Either;
19
20 /**
21  * Dedicated type for YANG's 'type uint16' type.
22  *
23  * @author Robert Varga
24  */
25 @Beta
26 @NonNullByDefault
27 public class Uint16 extends Number implements CanonicalValue<Uint16> {
28     public static final class Support extends AbstractCanonicalValueSupport<Uint16> {
29         public Support() {
30             super(Uint16.class);
31         }
32
33         @Override
34         public Either<Uint16, CanonicalValueViolation> fromString(final String str) {
35             try {
36                 return Either.ofFirst(Uint16.valueOf(str));
37             } catch (IllegalArgumentException e) {
38                 return CanonicalValueViolation.variantOf(e);
39             }
40         }
41     }
42
43     private static final CanonicalValueSupport<Uint16> SUPPORT = new Support();
44     private static final long serialVersionUID = 1L;
45     private static final int MAX_VALUE_INT = 65535;
46     private static final String MAX_VALUE_STR = "65535";
47
48     private static final String CACHE_SIZE_PROPERTY = "org.opendaylight.yangtools.yang.common.Uint16.cache.size";
49     private static final int DEFAULT_CACHE_SIZE = 256;
50
51     /**
52      * Tunable cache for values. By default it holds {@value #DEFAULT_CACHE_SIZE} entries. This can be
53      * changed via {@value #CACHE_SIZE_PROPERTY} system property.
54      */
55     private static final int CACHE_SIZE;
56
57     static {
58         final int p = Integer.getInteger(CACHE_SIZE_PROPERTY, DEFAULT_CACHE_SIZE);
59         CACHE_SIZE = p >= 0 ? Math.min(p, MAX_VALUE_INT + 1) : DEFAULT_CACHE_SIZE;
60     }
61
62     private static final @NonNull Uint16[] CACHE;
63
64     static {
65         final Uint16[] c = new Uint16[CACHE_SIZE];
66         for (int i = 0; i < c.length; ++i) {
67             c[i] = new Uint16((short) i);
68         }
69         CACHE = c;
70     }
71
72     private static final Interner<Uint16> INTERNER = Interners.newWeakInterner();
73
74     /**
75      * Value of {@code 0}.
76      */
77     public static final Uint16 ZERO = valueOf(0).intern();
78     /**
79      * Value of {@code 1}.
80      */
81     public static final Uint16 ONE = valueOf(1).intern();
82     /**
83      * Value of {@code 2}.
84      */
85     public static final Uint16 TWO = valueOf(2).intern();
86     /**
87      * Value of {@code 10}.
88      */
89     public static final Uint16 TEN = valueOf(10).intern();
90     /**
91      * Value of {@code 65535}.
92      */
93     public static final Uint16 MAX_VALUE = valueOf(MAX_VALUE_INT).intern();
94
95     private final short value;
96
97     private Uint16(final short value) {
98         this.value = value;
99     }
100
101     protected Uint16(final Uint16 other) {
102         this(other.value);
103     }
104
105     private static Uint16 instanceFor(final short value) {
106         final int slot = Short.toUnsignedInt(value);
107         return slot < CACHE.length ? CACHE[slot] : new Uint16(value);
108     }
109
110     /**
111      * Returns an {@code Uint16} corresponding to a given bit representation. The argument is interpreted as an
112      * unsigned 16-bit value.
113      *
114      * @param bits unsigned bit representation
115      * @return A Uint16 instance
116      */
117     public static Uint16 fromShortBits(final short bits) {
118         return instanceFor(bits);
119     }
120
121     /**
122      * Returns an {@code Uint16} corresponding to a given {@code byteVal}. The inverse operation is
123      * {@link #byteValue()}.
124      *
125      * @param byteVal byte value
126      * @return A Uint16 instance
127      * @throws IllegalArgumentException if byteVal is less than zero
128      */
129     public static Uint16 valueOf(final byte byteVal) {
130         UintConversions.checkNonNegative(byteVal, MAX_VALUE_STR);
131         return instanceFor(byteVal);
132     }
133
134     /**
135      * Returns an {@code Uint16} corresponding to a given {@code shortVal}. The inverse operation is
136      * {@link #shortValue()}.
137      *
138      * @param shortVal short value
139      * @return A Uint16 instance
140      * @throws IllegalArgumentException if shortVal is less than zero.
141      */
142     public static Uint16 valueOf(final short shortVal) {
143         UintConversions.checkNonNegative(shortVal, MAX_VALUE_STR);
144         return instanceFor(shortVal);
145     }
146
147     /**
148      * Returns an {@code Uint16} corresponding to a given {@code intVal}. The inverse operation is {@link #intValue()}.
149      *
150      * @param intVal int value
151      * @return A Uint16 instance
152      * @throws IllegalArgumentException if intVal is less than zero or greater than 65535.
153      */
154     public static Uint16 valueOf(final int intVal) {
155         UintConversions.checkRange(intVal, MAX_VALUE_INT);
156         return instanceFor((short)intVal);
157     }
158
159     /**
160      * Returns an {@code Uint16} corresponding to a given {@code longVal}. The inverse operation is
161      * {@link #longValue()}.
162      *
163      * @param longVal long value
164      * @return A Uint16 instance
165      * @throws IllegalArgumentException if intVal is less than zero or greater than 65535.
166      */
167     public static Uint16 valueOf(final long longVal) {
168         UintConversions.checkRange(longVal, MAX_VALUE_INT);
169         return instanceFor((short)longVal);
170     }
171
172     /**
173      * Returns an {@code Uint16} corresponding to a given {@code uint}.
174      *
175      * @param uint Uint8 value
176      * @return A Uint16 instance
177      * @throws NullPointerException if uint is null
178      */
179     public static Uint16 valueOf(final Uint8 uint) {
180         return instanceFor(uint.shortValue());
181     }
182
183     /**
184      * Returns an {@code Uint8} corresponding to a given {@code uint}.
185      *
186      * @param uint Uint32 value
187      * @return A Uint16 instance
188      * @throws NullPointerException if uint is null
189      * @throws IllegalArgumentException if uint is greater than 65535.
190      */
191     public static Uint16 valueOf(final Uint32 uint) {
192         return valueOf(uint.longValue());
193     }
194
195     /**
196      * Returns an {@code Uint8} corresponding to a given {@code uint}.
197      *
198      * @param uint Uint64 value
199      * @return A Uint16 instance
200      * @throws NullPointerException if uint is null
201      * @throws IllegalArgumentException if uint is greater than 65535.
202      */
203     public static Uint16 valueOf(final Uint64 uint) {
204         return valueOf(uint.longValue());
205     }
206
207     /**
208      * Returns an {@code Uint16} holding the value of the specified {@code String}, parsed as an unsigned {@code int}
209      * value.
210      *
211      * @param string String to parse
212      * @return A Uint16 instance
213      * @throws NullPointerException if string is null
214      * @throws IllegalArgumentException if the parsed value is less than zero or greater than 65535
215      * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int} value.
216      */
217     public static Uint16 valueOf(final String string) {
218         return valueOf(string, 10);
219     }
220
221     /**
222      * Returns an {@code Uint16} holding the value of the specified {@code String}, parsed as an unsigned {@code int}
223      * value.
224      *
225      * @param string String to parse
226      * @param radix Radix to use
227      * @return A Uint16 instance
228      * @throws NullPointerException if string is null
229      * @throws IllegalArgumentException if the parsed value is less than zero or greater than 65535
230      * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int} value, or if the
231      *                               {@code radix} is outside of allowed range.
232      */
233     public static Uint16 valueOf(final String string, final int radix) {
234         return valueOf(Integer.parseInt(requireNonNull(string), radix));
235     }
236
237     /**
238      * Returns an {@code Uint16} corresponding to a given {@code byteVal} if it is representable. If the value is
239      * negative {@link #ZERO} will be returned.
240      *
241      * @param byteVal byte value
242      * @return A Uint16 instance
243      */
244     public static Uint16 saturatedOf(final byte byteVal) {
245         return byteVal <= 0 ? Uint16.ZERO : instanceFor(byteVal);
246     }
247
248     /**
249      * Returns an {@code Uint16} corresponding to a given {@code shortVal} if it is representable. If the value is
250      * negative {@link #ZERO} will be returned.
251      *
252      * @param shortVal short value
253      * @return A Uint16 instance
254      */
255     public static Uint16 saturatedOf(final short shortVal) {
256         return shortVal <= 0 ? Uint16.ZERO : instanceFor(shortVal);
257     }
258
259     /**
260      * Returns an {@code Uint16} corresponding to a given {@code intVal} if it is representable. If the value is
261      * negative {@link #ZERO} will be returned. If the value is greater than 65535, {@link #MAX_VALUE} will be returned.
262      *
263      * @param intVal int value
264      * @return A Uint16 instance
265      */
266     public static Uint16 saturatedOf(final int intVal) {
267         if (intVal <= 0) {
268             return Uint16.ZERO;
269         }
270         if (intVal >= MAX_VALUE_INT) {
271             return Uint16.MAX_VALUE;
272         }
273         return instanceFor((short) intVal);
274     }
275
276     /**
277      * Returns an {@code Uint16} corresponding to a given {@code longVal} if it is representable. If the value is
278      * negative {@link #ZERO} will be returned. If the value is greater than 65535, {@link #MAX_VALUE} will be returned.
279      *
280      * @param longVal long value
281      * @return A Uint16 instance
282      */
283     public static Uint16 saturatedOf(final long longVal) {
284         if (longVal <= 0) {
285             return Uint16.ZERO;
286         }
287         if (longVal >= MAX_VALUE_INT) {
288             return Uint16.MAX_VALUE;
289         }
290         return instanceFor((short) longVal);
291     }
292
293     /**
294      * {@inheritDoc}
295      *
296      * <p>
297      * The inverse operation is {@link #fromShortBits(short)}. In case this value is greater than
298      * {@link Short#MAX_VALUE}, the returned value will be equal to {@code this - 2^16}.
299      */
300     @Override
301     public final short shortValue() {
302         return value;
303     }
304
305     @Override
306     public final int intValue() {
307         return Short.toUnsignedInt(value);
308     }
309
310     @Override
311     public final long longValue() {
312         return Short.toUnsignedLong(value);
313     }
314
315     @Override
316     public final float floatValue() {
317         return intValue();
318     }
319
320     @Override
321     public final double doubleValue() {
322         return intValue();
323     }
324
325     @Override
326     @SuppressWarnings("checkstyle:parameterName")
327     public final int compareTo(final Uint16 o) {
328         return Short.compareUnsigned(value, o.value);
329     }
330
331     @Override
332     public final String toCanonicalString() {
333         return Integer.toString(intValue());
334     }
335
336     @Override
337     public final CanonicalValueSupport<Uint16> support() {
338         return SUPPORT;
339     }
340
341     /**
342      * Return an interned (shared) instance equivalent to this object. This may return the same object.
343      *
344      * @return A shared instance.
345      */
346     public final Uint16 intern() {
347         return intValue() < CACHE_SIZE ? this : INTERNER.intern(this);
348     }
349
350     /**
351      * Convert this value to an {@code int}.
352      *
353      * @return An int
354      */
355     public final int toJava() {
356         return intValue();
357     }
358
359     /**
360      * Convert this value to a {@code Uint8}.
361      *
362      * @return A Uint8
363      * @throws IllegalArgumentException if this value is greater than 255.
364      */
365     public final Uint8 toUint8() {
366         return Uint8.valueOf(toJava());
367     }
368
369     /**
370      * Convert this value to a {@code Uint32}.
371      *
372      * @return A Uint32
373      */
374     public final Uint32 toUint32() {
375         return Uint32.fromIntBits(intValue());
376     }
377
378     /**
379      * Convert this value to a {@code Uint64}.
380      *
381      * @return A Uint64
382      */
383     public final Uint64 toUint64() {
384         return Uint64.fromLongBits(longValue());
385     }
386
387     public final Uint8 toSaturatedUint8() {
388         return Uint8.saturatedOf(toJava());
389     }
390
391     @Override
392     public final int hashCode() {
393         return Short.hashCode(value);
394     }
395
396     @Override
397     public final boolean equals(final @Nullable Object obj) {
398         return this == obj || obj instanceof Uint16 other && value == other.value;
399     }
400
401     /**
402      * A slightly faster version of {@link #equals(Object)}.
403      *
404      * @param obj Uint16 object
405      * @return  {@code true} if this object is the same as the obj argument; {@code false} otherwise.
406      */
407     public final boolean equals(final @Nullable Uint16 obj) {
408         return this == obj || obj != null && value == obj.value;
409     }
410
411     @Override
412     public final String toString() {
413         return toCanonicalString();
414     }
415
416     private Object readResolve() {
417         return instanceFor(value);
418     }
419 }