2 * Copyright (C) 2011 Google Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com
.google
.gson
;
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
;
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.
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
;
38 /** The delegate is lazily created because it may not be needed, and creating it may fail. */
39 private TypeAdapter
<T
> delegate
;
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
;
46 this.typeToken
= typeToken
;
47 this.skipPast
= skipPast
;
50 @Override public T
read(JsonReader in
) throws IOException
{
51 if (deserializer
== null) {
52 return delegate().read(in
);
54 JsonElement value
= Streams
.parse(in
);
55 if (value
.isJsonNull()) {
58 return deserializer
.deserialize(value
, typeToken
.getType(), gson
.deserializationContext
);
61 @Override public void write(JsonWriter out
, T value
) throws IOException
{
62 if (serializer
== null) {
63 delegate().write(out
, value
);
70 JsonElement tree
= serializer
.serialize(value
, typeToken
.getType(), gson
.serializationContext
);
71 Streams
.write(tree
, out
);
74 private TypeAdapter
<T
> delegate() {
75 TypeAdapter
<T
> d
= delegate
;
78 : (delegate
= gson
.getDelegateAdapter(skipPast
, typeToken
));
82 * Returns a new factory that will match each type against {@code exactType}.
84 public static TypeAdapterFactory
newFactory(TypeToken
<?
> exactType
, Object typeAdapter
) {
85 return new SingleTypeFactory(typeAdapter
, exactType
, false, null);
89 * Returns a new factory that will match each type and its raw type against
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);
100 * Returns a new factory that will match each type's raw type for assignability
101 * to {@code hierarchyType}.
103 public static TypeAdapterFactory
newTypeHierarchyFactory(
104 Class
<?
> hierarchyType
, Object typeAdapter
) {
105 return new SingleTypeFactory(typeAdapter
, null, false, hierarchyType
);
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
;
115 private SingleTypeFactory(Object typeAdapter
, TypeToken
<?
> exactType
, boolean matchRawType
,
116 Class
<?
> hierarchyType
) {
117 serializer
= typeAdapter
instanceof JsonSerializer
118 ?
(JsonSerializer
<?
>) typeAdapter
120 deserializer
= typeAdapter
instanceof JsonDeserializer
121 ?
(JsonDeserializer
<?
>) typeAdapter
123 $Gson$Preconditions
.checkArgument(serializer
!= null || deserializer
!= null);
124 this.exactType
= exactType
;
125 this.matchRawType
= matchRawType
;
126 this.hierarchyType
= hierarchyType
;
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());
135 ?
new TreeTypeAdapter
<T
>((JsonSerializer
<T
>) serializer
,
136 (JsonDeserializer
<T
>) deserializer
, gson
, type
, this)