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