package by.istin.android.xcore.gson; import android.content.ContentValues; 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.annotations.SerializedName; import java.lang.reflect.Type; import java.util.List; import by.istin.android.xcore.annotations.JsonEntityConverter; import by.istin.android.xcore.annotations.JsonSubJSONObject; import by.istin.android.xcore.annotations.dbBoolean; import by.istin.android.xcore.annotations.dbByte; import by.istin.android.xcore.annotations.dbDouble; import by.istin.android.xcore.annotations.dbEntities; import by.istin.android.xcore.annotations.dbEntity; import by.istin.android.xcore.annotations.dbInteger; import by.istin.android.xcore.annotations.dbLong; import by.istin.android.xcore.annotations.dbString; import by.istin.android.xcore.utils.ReflectUtils; public abstract class AbstractValuesAdapter<T> implements JsonDeserializer<T> { public static final int UNKNOWN_POSITION = -1; private final Class<?> mContentValuesEntityClazz; private List<ReflectUtils.XField> mEntityKeys; private JsonEntityConverter mJsonEntityConverterAnnotation; public Class<?> getContentValuesEntityClazz() { return mContentValuesEntityClazz; } public AbstractValuesAdapter(Class<?> contentValuesEntityClazz) { this.mContentValuesEntityClazz = contentValuesEntityClazz; this.mJsonEntityConverterAnnotation = mContentValuesEntityClazz.getAnnotation(JsonEntityConverter.class); } @Override public T deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { return deserializeContentValues(null, UNKNOWN_POSITION, jsonElement, type, jsonDeserializationContext); } public T deserializeContentValues(T parent, int position, JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { if (mEntityKeys == null) { mEntityKeys = ReflectUtils.getEntityKeys(mContentValuesEntityClazz); } ContentValues contentValues = new ContentValues(); if (mEntityKeys == null) { return proceed(parent, position, contentValues); } if (isCustomConverter(contentValues, parent, jsonElement, type, jsonDeserializationContext)) { return proceed(parent, position, contentValues); } if (jsonElement.isJsonPrimitive()) { return null; } if (jsonElement.isJsonArray()) { return null; } JsonObject jsonObject = (JsonObject) jsonElement; for (ReflectUtils.XField field : mEntityKeys) { JsonElement jsonValue = null; String fieldValue = ReflectUtils.getStaticStringValue(field); String serializedName = fieldValue; if (ReflectUtils.isAnnotationPresent(field, SerializedName.class)) { SerializedName serializedAnnotation = ReflectUtils.getAnnotation(field, SerializedName.class); if (serializedAnnotation != null) { serializedName = serializedAnnotation.value(); } } String separator = null; boolean isFirstObjectForJsonArray = false; if (ReflectUtils.isAnnotationPresent(field, JsonSubJSONObject.class)) { JsonSubJSONObject jsonSubJSONObject = ReflectUtils.getAnnotation(field, JsonSubJSONObject.class); if (jsonSubJSONObject != null) { separator = jsonSubJSONObject.separator(); isFirstObjectForJsonArray = jsonSubJSONObject.isFirstObjectForJsonArray(); } } if (separator != null && serializedName.contains(separator)) { String[] values = serializedName.split(separator); JsonObject tempElement = jsonObject; for (int i = 0; i < values.length; i++) { if (i == values.length - 1) { jsonValue = tempElement.get(values[i]); } else { JsonElement element = tempElement.get(values[i]); if (element == null) { break; } if (element.isJsonObject()) { tempElement = (JsonObject) element; } else { if (isFirstObjectForJsonArray && element.isJsonArray()) { JsonArray jsonArray = (JsonArray) element; if (jsonArray.size() > 0) { tempElement = (JsonObject) jsonArray.get(0); } else { break; } } else { break; } } } } } else { jsonValue = jsonObject.get(serializedName); } if (jsonValue == null) { continue; } if (jsonValue.isJsonPrimitive()) { putPrimitiveValue(contentValues, field, jsonValue, fieldValue); } else if (ReflectUtils.isAnnotationPresent(field, dbEntity.class)) { dbEntity entity = ReflectUtils.getAnnotation(field, dbEntity.class); Class<?> clazz = entity.clazz(); JsonObject subEntityJsonObject = jsonValue.getAsJsonObject(); proceedSubEntity(type, jsonDeserializationContext, contentValues, field, fieldValue, clazz, subEntityJsonObject); } else if (ReflectUtils.isAnnotationPresent(field, dbEntities.class)) { if (jsonValue.isJsonArray()) { JsonArray jsonArray = jsonValue.getAsJsonArray(); proceedSubEntities(type, jsonDeserializationContext, contentValues, field, fieldValue, jsonArray); } else { dbEntities entity = ReflectUtils.getAnnotation(field, dbEntities.class); Class<?> clazz = entity.clazz(); JsonObject subEntityJsonObject = jsonValue.getAsJsonObject(); proceedSubEntity(type, jsonDeserializationContext, contentValues, field, fieldValue, clazz, subEntityJsonObject); } } } return proceed(parent, position, contentValues); } private boolean isCustomConverter(ContentValues contentValues, T parent, JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { if (mJsonEntityConverterAnnotation == null) { return false; } Class<? extends IGsonEntityConverter> primitiveConverter = mJsonEntityConverterAnnotation.converter(); IGsonEntityConverter primitiveConverterInstance = ReflectUtils.getInstanceInterface(primitiveConverter, IGsonEntityConverter.class); primitiveConverterInstance.convert(contentValues, parent, jsonElement, type, jsonDeserializationContext); return true; } protected void putPrimitiveValue(ContentValues contentValues, ReflectUtils.XField field, JsonElement jsonValue, String fieldValue) { if (ReflectUtils.isAnnotationPresent(field, dbLong.class)) { contentValues.put(fieldValue, jsonValue.getAsLong()); } else if (ReflectUtils.isAnnotationPresent(field, dbString.class)) { contentValues.put(fieldValue, jsonValue.getAsString()); } else if (ReflectUtils.isAnnotationPresent(field, dbBoolean.class)) { contentValues.put(fieldValue, jsonValue.getAsBoolean()); } else if (ReflectUtils.isAnnotationPresent(field, dbByte.class)) { contentValues.put(fieldValue, jsonValue.getAsByte()); } else if (ReflectUtils.isAnnotationPresent(field, dbDouble.class)) { contentValues.put(fieldValue, jsonValue.getAsDouble()); } else if (ReflectUtils.isAnnotationPresent(field, dbInteger.class)) { contentValues.put(fieldValue, jsonValue.getAsInt()); } } protected abstract void proceedSubEntities(Type type, JsonDeserializationContext jsonDeserializationContext, ContentValues contentValues, ReflectUtils.XField field, String fieldValue, JsonArray jsonArray); protected abstract void proceedSubEntity(Type type, JsonDeserializationContext jsonDeserializationContext, ContentValues contentValues, ReflectUtils.XField field, String fieldValue, Class<?> clazz, JsonObject subEntityJsonObject); protected abstract T proceed(T parent, int position, ContentValues contentValues); }