Finish second-to-last commit
[unical.git] / gson / com / google / gson / JsonPrimitive.java
1 /*
2 * Copyright (C) 2008 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.google.gson;
18
19 import java.math.BigDecimal;
20 import java.math.BigInteger;
21
22 import com.google.gson.internal.$Gson$Preconditions;
23 import com.google.gson.internal.LazilyParsedNumber;
24
25 /**
26 * A class representing a Json primitive value. A primitive value
27 * is either a String, a Java primitive, or a Java primitive
28 * wrapper type.
29 *
30 * @author Inderjeet Singh
31 * @author Joel Leitch
32 */
33 public final class JsonPrimitive extends JsonElement {
34
35 private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,
36 float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
37 Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };
38
39 private Object value;
40
41 /**
42 * Create a primitive containing a boolean value.
43 *
44 * @param bool the value to create the primitive with.
45 */
46 public JsonPrimitive(Boolean bool) {
47 setValue(bool);
48 }
49
50 /**
51 * Create a primitive containing a {@link Number}.
52 *
53 * @param number the value to create the primitive with.
54 */
55 public JsonPrimitive(Number number) {
56 setValue(number);
57 }
58
59 /**
60 * Create a primitive containing a String value.
61 *
62 * @param string the value to create the primitive with.
63 */
64 public JsonPrimitive(String string) {
65 setValue(string);
66 }
67
68 /**
69 * Create a primitive containing a character. The character is turned into a one character String
70 * since Json only supports String.
71 *
72 * @param c the value to create the primitive with.
73 */
74 public JsonPrimitive(Character c) {
75 setValue(c);
76 }
77
78 /**
79 * Create a primitive using the specified Object. It must be an instance of {@link Number}, a
80 * Java primitive type, or a String.
81 *
82 * @param primitive the value to create the primitive with.
83 */
84 JsonPrimitive(Object primitive) {
85 setValue(primitive);
86 }
87
88 @Override
89 JsonPrimitive deepCopy() {
90 return this;
91 }
92
93 void setValue(Object primitive) {
94 if (primitive instanceof Character) {
95 // convert characters to strings since in JSON, characters are represented as a single
96 // character string
97 char c = ((Character) primitive).charValue();
98 this.value = String.valueOf(c);
99 } else {
100 $Gson$Preconditions.checkArgument(primitive instanceof Number
101 || isPrimitiveOrString(primitive));
102 this.value = primitive;
103 }
104 }
105
106 /**
107 * Check whether this primitive contains a boolean value.
108 *
109 * @return true if this primitive contains a boolean value, false otherwise.
110 */
111 public boolean isBoolean() {
112 return value instanceof Boolean;
113 }
114
115 /**
116 * convenience method to get this element as a {@link Boolean}.
117 *
118 * @return get this element as a {@link Boolean}.
119 */
120 @Override
121 Boolean getAsBooleanWrapper() {
122 return (Boolean) value;
123 }
124
125 /**
126 * convenience method to get this element as a boolean value.
127 *
128 * @return get this element as a primitive boolean value.
129 */
130 @Override
131 public boolean getAsBoolean() {
132 if (isBoolean()) {
133 return getAsBooleanWrapper().booleanValue();
134 } else {
135 // Check to see if the value as a String is "true" in any case.
136 return Boolean.parseBoolean(getAsString());
137 }
138 }
139
140 /**
141 * Check whether this primitive contains a Number.
142 *
143 * @return true if this primitive contains a Number, false otherwise.
144 */
145 public boolean isNumber() {
146 return value instanceof Number;
147 }
148
149 /**
150 * convenience method to get this element as a Number.
151 *
152 * @return get this element as a Number.
153 * @throws NumberFormatException if the value contained is not a valid Number.
154 */
155 @Override
156 public Number getAsNumber() {
157 return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value;
158 }
159
160 /**
161 * Check whether this primitive contains a String value.
162 *
163 * @return true if this primitive contains a String value, false otherwise.
164 */
165 public boolean isString() {
166 return value instanceof String;
167 }
168
169 /**
170 * convenience method to get this element as a String.
171 *
172 * @return get this element as a String.
173 */
174 @Override
175 public String getAsString() {
176 if (isNumber()) {
177 return getAsNumber().toString();
178 } else if (isBoolean()) {
179 return getAsBooleanWrapper().toString();
180 } else {
181 return (String) value;
182 }
183 }
184
185 /**
186 * convenience method to get this element as a primitive double.
187 *
188 * @return get this element as a primitive double.
189 * @throws NumberFormatException if the value contained is not a valid double.
190 */
191 @Override
192 public double getAsDouble() {
193 return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString());
194 }
195
196 /**
197 * convenience method to get this element as a {@link BigDecimal}.
198 *
199 * @return get this element as a {@link BigDecimal}.
200 * @throws NumberFormatException if the value contained is not a valid {@link BigDecimal}.
201 */
202 @Override
203 public BigDecimal getAsBigDecimal() {
204 return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString());
205 }
206
207 /**
208 * convenience method to get this element as a {@link BigInteger}.
209 *
210 * @return get this element as a {@link BigInteger}.
211 * @throws NumberFormatException if the value contained is not a valid {@link BigInteger}.
212 */
213 @Override
214 public BigInteger getAsBigInteger() {
215 return value instanceof BigInteger ?
216 (BigInteger) value : new BigInteger(value.toString());
217 }
218
219 /**
220 * convenience method to get this element as a float.
221 *
222 * @return get this element as a float.
223 * @throws NumberFormatException if the value contained is not a valid float.
224 */
225 @Override
226 public float getAsFloat() {
227 return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString());
228 }
229
230 /**
231 * convenience method to get this element as a primitive long.
232 *
233 * @return get this element as a primitive long.
234 * @throws NumberFormatException if the value contained is not a valid long.
235 */
236 @Override
237 public long getAsLong() {
238 return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString());
239 }
240
241 /**
242 * convenience method to get this element as a primitive short.
243 *
244 * @return get this element as a primitive short.
245 * @throws NumberFormatException if the value contained is not a valid short value.
246 */
247 @Override
248 public short getAsShort() {
249 return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString());
250 }
251
252 /**
253 * convenience method to get this element as a primitive integer.
254 *
255 * @return get this element as a primitive integer.
256 * @throws NumberFormatException if the value contained is not a valid integer.
257 */
258 @Override
259 public int getAsInt() {
260 return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString());
261 }
262
263 @Override
264 public byte getAsByte() {
265 return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString());
266 }
267
268 @Override
269 public char getAsCharacter() {
270 return getAsString().charAt(0);
271 }
272
273 private static boolean isPrimitiveOrString(Object target) {
274 if (target instanceof String) {
275 return true;
276 }
277
278 Class<?> classOfPrimitive = target.getClass();
279 for (Class<?> standardPrimitive : PRIMITIVE_TYPES) {
280 if (standardPrimitive.isAssignableFrom(classOfPrimitive)) {
281 return true;
282 }
283 }
284 return false;
285 }
286
287 @Override
288 public int hashCode() {
289 if (value == null) {
290 return 31;
291 }
292 // Using recommended hashing algorithm from Effective Java for longs and doubles
293 if (isIntegral(this)) {
294 long value = getAsNumber().longValue();
295 return (int) (value ^ (value >>> 32));
296 }
297 if (value instanceof Number) {
298 long value = Double.doubleToLongBits(getAsNumber().doubleValue());
299 return (int) (value ^ (value >>> 32));
300 }
301 return value.hashCode();
302 }
303
304 @Override
305 public boolean equals(Object obj) {
306 if (this == obj) {
307 return true;
308 }
309 if (obj == null || getClass() != obj.getClass()) {
310 return false;
311 }
312 JsonPrimitive other = (JsonPrimitive)obj;
313 if (value == null) {
314 return other.value == null;
315 }
316 if (isIntegral(this) && isIntegral(other)) {
317 return getAsNumber().longValue() == other.getAsNumber().longValue();
318 }
319 if (value instanceof Number && other.value instanceof Number) {
320 double a = getAsNumber().doubleValue();
321 // Java standard types other than double return true for two NaN. So, need
322 // special handling for double.
323 double b = other.getAsNumber().doubleValue();
324 return a == b || (Double.isNaN(a) && Double.isNaN(b));
325 }
326 return value.equals(other.value);
327 }
328
329 /**
330 * Returns true if the specified number is an integral type
331 * (Long, Integer, Short, Byte, BigInteger)
332 */
333 private static boolean isIntegral(JsonPrimitive primitive) {
334 if (primitive.value instanceof Number) {
335 Number number = (Number) primitive.value;
336 return number instanceof BigInteger || number instanceof Long || number instanceof Integer
337 || number instanceof Short || number instanceof Byte;
338 }
339 return false;
340 }
341 }
This page took 0.033427 seconds and 4 git commands to generate.