BUG-4661: Introduce Decimal64, Empty, Uint{8,16,32,64}
[yangtools.git] / yang / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / Uint32.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 com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.cache.CacheBuilder;
14 import com.google.common.cache.CacheLoader;
15 import com.google.common.cache.LoadingCache;
16 import com.google.common.primitives.UnsignedInteger;
17 import org.opendaylight.yangtools.concepts.Immutable;
18
19 /**
20  * Dedicated type for YANG's 'type uint32' type.
21  *
22  * @author Robert Varga
23  */
24 @Beta
25 public final class Uint32 extends Number implements Comparable<Uint32>, Immutable {
26     private static final long serialVersionUID = 1L;
27     private static final long MIN_VALUE = 0;
28     private static final long MAX_VALUE = 0xffffffffL;
29
30     /**
31      * Cache of first 256 values.
32      */
33     private static final Uint32[] CACHE = new Uint32[Uint8.MAX_VALUE];
34     /**
35      * Commonly encountered values.
36      */
37     private static final Uint32[] COMMON = {
38         new Uint32(Short.MAX_VALUE),
39         new Uint32(32768),
40         new Uint32(65535),
41         new Uint32(65536),
42         new Uint32(Integer.MAX_VALUE),
43     };
44
45     /**
46      * Tunable weak LRU cache for other values. By default it holds {@value #DEFAULT_LRU_SIZE} entries. This can be
47      * changed via {@value #LRU_SIZE_PROPERTY} system property.
48      */
49     private static final int DEFAULT_LRU_SIZE = 1024;
50     private static final String LRU_SIZE_PROPERTY = "org.opendaylight.yangtools.yang.common.Uint32.LRU.size";
51     private static final int MAX_LRU_SIZE = 0xffffff;
52     private static final int LRU_SIZE;
53
54     static {
55         final int p = Integer.getInteger(LRU_SIZE_PROPERTY, DEFAULT_LRU_SIZE);
56         LRU_SIZE = p >= 0 ? Math.min(p, MAX_LRU_SIZE) : DEFAULT_LRU_SIZE;
57     }
58
59     private static final LoadingCache<Integer, Uint32> LRU = CacheBuilder.newBuilder().weakValues()
60         .maximumSize(LRU_SIZE).build(new CacheLoader<Integer, Uint32>() {
61                 @Override
62                 public Uint32 load(final Integer key) {
63                     return new Uint32(key);
64                 }
65             });
66
67     private final int value;
68
69     private Uint32(final int value) {
70         this.value = value;
71     }
72
73     private static Uint32 instanceFor(final int value) {
74         final long longSlot = Integer.toUnsignedLong(value);
75         if (longSlot >= CACHE.length) {
76             for (Uint32 c : COMMON) {
77                 if (c.value == value) {
78                     return c;
79                 }
80             }
81
82             return LRU.getUnchecked(value);
83         }
84
85         final int slot = (int)longSlot;
86         Uint32 ret = CACHE[slot];
87         if (ret == null) {
88             synchronized (CACHE) {
89                 ret = CACHE[slot];
90                 if (ret == null) {
91                     ret = new Uint32(value);
92                     CACHE[slot] = ret;
93                 }
94             }
95         }
96
97         return ret;
98     }
99
100     public static Uint32 fromIntBits(final int bits) {
101         return instanceFor(bits);
102     }
103
104     public static Uint32 fromUnsignedInteger(final UnsignedInteger uint) {
105         return instanceFor(uint.intValue());
106     }
107
108     public static Uint32 valueOf(final byte byteVal) {
109         checkArgument(byteVal >= MIN_VALUE, "Negative values are not allowed");
110         return instanceFor(byteVal);
111     }
112
113     public static Uint32 valueOf(final short shortVal) {
114         checkArgument(shortVal >= MIN_VALUE, "Negative values are not allowed");
115         return instanceFor(shortVal);
116     }
117
118     public static Uint32 valueOf(final int intVal) {
119         checkArgument(intVal >= MIN_VALUE, "Value %s is outside of allowed range", intVal);
120         return instanceFor(intVal);
121     }
122
123     public static Uint32 valueOf(final long longVal) {
124         checkArgument(longVal >= MIN_VALUE && longVal <= MAX_VALUE, "Value %s is outside of allowed range", longVal);
125         return instanceFor((int)longVal);
126     }
127
128     public static Uint32 valueOf(final Uint8 uint) {
129         return instanceFor(uint.shortValue());
130     }
131
132     public static Uint32 valueOf(final Uint16 uint) {
133         return instanceFor(uint.intValue());
134     }
135
136     public static Uint32 valueOf(final String string) {
137         return valueOf(string, 10);
138     }
139
140     public static Uint32 valueOf(final String string, final int radix) {
141         return instanceFor(Integer.parseUnsignedInt(string, radix));
142     }
143
144     @Override
145     public int intValue() {
146         return value;
147     }
148
149     @Override
150     public long longValue() {
151         return Integer.toUnsignedLong(value);
152     }
153
154     @Override
155     public float floatValue() {
156         return longValue();
157     }
158
159     @Override
160     public double doubleValue() {
161         return longValue();
162     }
163
164     public UnsignedInteger toUnsignedInteger() {
165         return UnsignedInteger.fromIntBits(value);
166     }
167
168     @Override
169     @SuppressWarnings("checkstyle:parameterName")
170     public int compareTo(final Uint32 o) {
171         return Integer.compareUnsigned(value, o.value);
172     }
173
174     @Override
175     public int hashCode() {
176         return Integer.hashCode(value);
177     }
178
179     @Override
180     public boolean equals(final Object obj) {
181         if (this == obj) {
182             return true;
183         }
184
185         return obj instanceof Uint32 && value == ((Uint32)obj).value;
186     }
187
188     @Override
189     public String toString() {
190         return Integer.toUnsignedString(value);
191     }
192
193     private Object readResolve() {
194         return instanceFor(value);
195     }
196 }