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