package com.breeze.util;
import java.io.IOException;
import java.util.IdentityHashMap;
import java.util.Map;
// import com.google.gson.*;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
/**
* Creates $id property for each object serialized to JSON object,
* and $ref when the same object is visited again, thus handling circular references.
* Also adds $type to include the class of each object.
* @author IdeaBlade
*/
public class BreezeTypeAdapterFactory implements TypeAdapterFactory {
private Map<Object, String> _entityMap;
private long _nextId;
public BreezeTypeAdapterFactory() {
_entityMap = new IdentityHashMap<Object, String>();
_nextId = 1;
}
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class rawType = type.getRawType();
// eliminate enums
if (rawType.isEnum()) return null;
String name = rawType.getCanonicalName();
// eliminate all simple types
if ((name.indexOf('.') == -1) || name.startsWith("java.")) {
return null;
}
final TypeAdapter<T> delegateAdapter = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
// elementAdapter.write(out, delegateAdapter.toJsonTree(value));
out.nullValue();
return;
}
JsonElement tree;
JsonObject jo;
String ref =_entityMap.get(value);
if (ref == null) {
String id = Long.toString(_nextId++);
_entityMap.put(value, id);
tree = delegateAdapter.toJsonTree(value);
jo = tree.getAsJsonObject();
jo.add("$type", new JsonPrimitive(value.getClass().getName()));
jo.add("$id", new JsonPrimitive(id));
} else {
jo = new JsonObject();
jo.addProperty("$ref", ref);
tree = (JsonElement) jo;
}
elementAdapter.write(out, tree);
}
@Override
public T read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
tree = afterRead(tree);
return delegateAdapter.fromJsonTree(tree);
}
};
}
/**
* Override this to muck with {@code deserialized} before it parsed into
* the application type.
*/
protected JsonElement afterRead(JsonElement deserialized) {
return deserialized;
}
}