1/* 2 * Copyright (C) 2012 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 17package com.google.caliper.json; 18 19import com.google.common.collect.ImmutableSet; 20import com.google.common.collect.Maps; 21import com.google.gson.Gson; 22import com.google.gson.TypeAdapter; 23import com.google.gson.TypeAdapterFactory; 24import com.google.gson.reflect.TypeToken; 25import com.google.gson.stream.JsonReader; 26import com.google.gson.stream.JsonWriter; 27 28import java.io.IOException; 29import java.lang.reflect.ParameterizedType; 30import java.lang.reflect.Type; 31import java.util.Map; 32import java.util.SortedMap; 33import java.util.TreeMap; 34 35/** 36 * Serializes and deserializes {@link SortedMap} instances using a {@link TreeMap} with natural 37 * ordering as an intermediary. 38 */ 39final class NaturallySortedMapTypeAdapterFactory implements TypeAdapterFactory { 40 @SuppressWarnings("rawtypes") 41 private static final ImmutableSet<Class<? extends SortedMap>> CLASSES = 42 ImmutableSet.of(SortedMap.class, TreeMap.class); 43 44 @SuppressWarnings("unchecked") 45 @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { 46 Type type = typeToken.getType(); 47 if (!CLASSES.contains(typeToken.getRawType()) 48 || !(type instanceof ParameterizedType)) { 49 return null; 50 } 51 52 com.google.common.reflect.TypeToken<SortedMap<?, ?>> betterToken = 53 (com.google.common.reflect.TypeToken<SortedMap<?, ?>>) 54 com.google.common.reflect.TypeToken.of(typeToken.getType()); 55 final TypeAdapter<Map<?, ?>> mapAdapter = 56 (TypeAdapter<Map<?, ?>>) gson.getAdapter( 57 TypeToken.get(betterToken.getSupertype(Map.class).getType())); 58 return new TypeAdapter<T>() { 59 @Override public void write(JsonWriter out, T value) throws IOException { 60 TreeMap<?, ?> treeMap = Maps.newTreeMap((SortedMap<?, ?>) value); 61 mapAdapter.write(out, treeMap); 62 } 63 64 @SuppressWarnings("rawtypes") 65 @Override public T read(JsonReader in) throws IOException { 66 TreeMap treeMap = Maps.newTreeMap(); 67 treeMap.putAll(mapAdapter.read(in)); 68 return (T) treeMap; 69 } 70 }; 71 } 72} 73