package com.dataart.android.devicehive.network; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.http.HttpEntity; import org.apache.http.entity.StringEntity; import android.content.Context; import android.os.Bundle; import android.util.Log; import com.dataart.android.devicehive.DeviceHive; import com.dataart.android.devicehive.ObjectWrapper; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; /** * Base command for JSON-related commands. * */ public abstract class JsonNetworkCommand extends NetworkCommand { private final static Gson gson; static { GsonBuilder builder = new GsonBuilder(); builder.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY); builder.registerTypeAdapter(ObjectWrapper.class, new ObjectWrapperAdapter()); gson = builder.create(); } private static class ObjectWrapperAdapter implements JsonDeserializer<ObjectWrapper<Serializable>>, JsonSerializer<ObjectWrapper<Serializable>> { public JsonElement serialize(ObjectWrapper<Serializable> src, Type typeOfSrc, JsonSerializationContext context) { return context.serialize(src.getObject()); } @Override public ObjectWrapper<Serializable> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return new ObjectWrapper<Serializable>( (Serializable) parseElement(json)); } private Object parseElement(JsonElement jsonElement) { if (jsonElement.isJsonPrimitive()) { return parsePrimitive(jsonElement.getAsJsonPrimitive()); } else if (jsonElement.isJsonArray()) { return parseArray(jsonElement.getAsJsonArray()); } else { return parseObject(jsonElement.getAsJsonObject()); } } private Object parsePrimitive(JsonPrimitive primitive) { if (primitive.isBoolean()) { return primitive.getAsBoolean(); } else if (primitive.isNumber()) { return primitive.getAsDouble(); } else { return primitive.getAsString(); } } private ArrayList<Object> parseArray(JsonArray jsonArray) { final int size = jsonArray.size(); ArrayList<Object> result = new ArrayList<Object>(size); for (int i = 0; i < size; i++) { result.add(parseElement(jsonArray.get(i))); } return result; } private Object parseObject(JsonObject jsonObject) { HashMap<String, Object> result = new HashMap<String, Object>(); final Set<Entry<String, JsonElement>> entrySet = jsonObject .entrySet(); for (Entry<String, JsonElement> property : entrySet) { result.put(property.getKey(), parseElement(property.getValue())); } return result; } } @Override protected Map<String, String> getHeaders() { final Map<String, String> headers = new HashMap<String, String>(); headers.put("Content-Type", "application/json; charset=utf-8"); return headers; } @Override protected HttpEntity getRequestEntity() { String data = toJson(gson); HttpEntity entity = null; try { entity = new StringEntity(data, "utf-8"); } catch (UnsupportedEncodingException e) { Log.e(DeviceHive.TAG, "Failed to create entity", e); } return entity; } protected abstract String toJson(final Gson gson); protected abstract int fromJson(final String response, final Gson gson, final Bundle resultData); @Override protected int handleResponse(final String response, final Bundle resultData, final Context context) { return fromJson(response, gson, resultData); } protected static String encodedString(String stringToEncode) { String encodedString = null; try { encodedString = URLEncoder.encode(stringToEncode, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("String to encode is illegal"); } return encodedString; } }