a05c1fe0e3078f0d41746fe3908d70d6954832cf
[unical.git] / gson / com / google / gson / TreeTypeAdapter.java
1 /*
2 * Copyright (C) 2011 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 com.google.gson.internal.$Gson$Preconditions;
20 import com.google.gson.internal.Streams;
21 import com.google.gson.reflect.TypeToken;
22 import com.google.gson.stream.JsonReader;
23 import com.google.gson.stream.JsonWriter;
24 import java.io.IOException;
25
26 /**
27 * Adapts a Gson 1.x tree-style adapter as a streaming TypeAdapter. Since the
28 * tree adapter may be serialization-only or deserialization-only, this class
29 * has a facility to lookup a delegate type adapter on demand.
30 */
31 final class TreeTypeAdapter<T> extends TypeAdapter<T> {
32 private final JsonSerializer<T> serializer;
33 private final JsonDeserializer<T> deserializer;
34 private final Gson gson;
35 private final TypeToken<T> typeToken;
36 private final TypeAdapterFactory skipPast;
37
38 /** The delegate is lazily created because it may not be needed, and creating it may fail. */
39 private TypeAdapter<T> delegate;
40
41 private TreeTypeAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
42 Gson gson, TypeToken<T> typeToken, TypeAdapterFactory skipPast) {
43 this.serializer = serializer;
44 this.deserializer = deserializer;
45 this.gson = gson;
46 this.typeToken = typeToken;
47 this.skipPast = skipPast;
48 }
49
50 @Override public T read(JsonReader in) throws IOException {
51 if (deserializer == null) {
52 return delegate().read(in);
53 }
54 JsonElement value = Streams.parse(in);
55 if (value.isJsonNull()) {
56 return null;
57 }
58 return deserializer.deserialize(value, typeToken.getType(), gson.deserializationContext);
59 }
60
61 @Override public void write(JsonWriter out, T value) throws IOException {
62 if (serializer == null) {
63 delegate().write(out, value);
64 return;
65 }
66 if (value == null) {
67 out.nullValue();
68 return;
69 }
70 JsonElement tree = serializer.serialize(value, typeToken.getType(), gson.serializationContext);
71 Streams.write(tree, out);
72 }
73
74 private TypeAdapter<T> delegate() {
75 TypeAdapter<T> d = delegate;
76 return d != null
77 ? d
78 : (delegate = gson.getDelegateAdapter(skipPast, typeToken));
79 }
80
81 /**
82 * Returns a new factory that will match each type against {@code exactType}.
83 */
84 public static TypeAdapterFactory newFactory(TypeToken<?> exactType, Object typeAdapter) {
85 return new SingleTypeFactory(typeAdapter, exactType, false, null);
86 }
87
88 /**
89 * Returns a new factory that will match each type and its raw type against
90 * {@code exactType}.
91 */
92 public static TypeAdapterFactory newFactoryWithMatchRawType(
93 TypeToken<?> exactType, Object typeAdapter) {
94 // only bother matching raw types if exact type is a raw type
95 boolean matchRawType = exactType.getType() == exactType.getRawType();
96 return new SingleTypeFactory(typeAdapter, exactType, matchRawType, null);
97 }
98
99 /**
100 * Returns a new factory that will match each type's raw type for assignability
101 * to {@code hierarchyType}.
102 */
103 public static TypeAdapterFactory newTypeHierarchyFactory(
104 Class<?> hierarchyType, Object typeAdapter) {
105 return new SingleTypeFactory(typeAdapter, null, false, hierarchyType);
106 }
107
108 private static class SingleTypeFactory implements TypeAdapterFactory {
109 private final TypeToken<?> exactType;
110 private final boolean matchRawType;
111 private final Class<?> hierarchyType;
112 private final JsonSerializer<?> serializer;
113 private final JsonDeserializer<?> deserializer;
114
115 private SingleTypeFactory(Object typeAdapter, TypeToken<?> exactType, boolean matchRawType,
116 Class<?> hierarchyType) {
117 serializer = typeAdapter instanceof JsonSerializer
118 ? (JsonSerializer<?>) typeAdapter
119 : null;
120 deserializer = typeAdapter instanceof JsonDeserializer
121 ? (JsonDeserializer<?>) typeAdapter
122 : null;
123 $Gson$Preconditions.checkArgument(serializer != null || deserializer != null);
124 this.exactType = exactType;
125 this.matchRawType = matchRawType;
126 this.hierarchyType = hierarchyType;
127 }
128
129 @SuppressWarnings("unchecked") // guarded by typeToken.equals() call
130 public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
131 boolean matches = exactType != null
132 ? exactType.equals(type) || matchRawType && exactType.getType() == type.getRawType()
133 : hierarchyType.isAssignableFrom(type.getRawType());
134 return matches
135 ? new TreeTypeAdapter<T>((JsonSerializer<T>) serializer,
136 (JsonDeserializer<T>) deserializer, gson, type, this)
137 : null;
138 }
139 }
140 }
This page took 0.023174 seconds and 3 git commands to generate.