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