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.internal.bind;
18
19 import java.io.IOException;
20 import java.lang.reflect.Array;
21 import java.lang.reflect.GenericArrayType;
22 import java.lang.reflect.Type;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import com.google.gson.Gson;
27 import com.google.gson.TypeAdapter;
28 import com.google.gson.TypeAdapterFactory;
29 import com.google.gson.internal.$Gson$Types;
30 import com.google.gson.reflect.TypeToken;
31 import com.google.gson.stream.JsonReader;
32 import com.google.gson.stream.JsonToken;
33 import com.google.gson.stream.JsonWriter;
34
35 /**
36  * Adapt an array of objects.
37  */

38 public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {
39   public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
40     @SuppressWarnings({"unchecked""rawtypes"})
41     @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
42       Type type = typeToken.getType();
43       if (!(type instanceof GenericArrayType || type instanceof Class && ((Class<?>) type).isArray())) {
44         return null;
45       }
46
47       Type componentType = $Gson$Types.getArrayComponentType(type);
48       TypeAdapter<?> componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType));
49       return new ArrayTypeAdapter(
50               gson, componentTypeAdapter, $Gson$Types.getRawType(componentType));
51     }
52   };
53
54   private final Class<E> componentType;
55   private final TypeAdapter<E> componentTypeAdapter;
56
57   public ArrayTypeAdapter(Gson context, TypeAdapter<E> componentTypeAdapter, Class<E> componentType) {
58     this.componentTypeAdapter =
59       new TypeAdapterRuntimeTypeWrapper<E>(context, componentTypeAdapter, componentType);
60     this.componentType = componentType;
61   }
62
63   @Override public Object read(JsonReader in) throws IOException {
64     if (in.peek() == JsonToken.NULL) {
65       in.nextNull();
66       return null;
67     }
68
69     List<E> list = new ArrayList<E>();
70     in.beginArray();
71     while (in.hasNext()) {
72       E instance = componentTypeAdapter.read(in);
73       list.add(instance);
74     }
75     in.endArray();
76
77     int size = list.size();
78     Object array = Array.newInstance(componentType, size);
79     for (int i = 0; i < size; i++) {
80       Array.set(array, i, list.get(i));
81     }
82     return array;
83   }
84
85   @SuppressWarnings("unchecked")
86   @Override public void write(JsonWriter out, Object array) throws IOException {
87     if (array == null) {
88       out.nullValue();
89       return;
90     }
91
92     out.beginArray();
93     for (int i = 0, length = Array.getLength(array); i < length; i++) {
94       E value = (E) Array.get(array, i);
95       componentTypeAdapter.write(out, value);
96     }
97     out.endArray();
98   }
99 }
100