app/src/main/java/com/futsch1/medtimer/database/JSONBackup.java
package com.futsch1.medtimer.database;
import android.util.Log;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.Expose;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.List;
public abstract class JSONBackup<T> {
private final Class<T> contentClass;
protected JSONBackup(Class<T> contentClass) {
this.contentClass = contentClass;
}
public String createBackupAsString(int databaseVersion, List<T> list) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
return gson.toJson(createBackup(databaseVersion, list));
}
public JsonElement createBackup(int databaseVersion, List<T> list) {
JSONBackup.DatabaseContentWithVersion<T> content = new JSONBackup.DatabaseContentWithVersion<>(databaseVersion, list);
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
return gson.toJsonTree(content);
}
public @Nullable List<T> parseBackup(String jsonFile) {
// In a first step, parse with the version set to 0
Gson gson = registerTypeAdapters(new GsonBuilder()).setVersion(0.0).create();
try {
Type type = TypeToken.getParameterized(DatabaseContentWithVersion.class, contentClass).getType();
DatabaseContentWithVersion<T> content = gson.fromJson(jsonFile, type);
gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setVersion(content.version).create();
content = gson.fromJson(jsonFile, type);
return checkBackup(content.list);
} catch (JsonParseException e) {
Log.e("JSONBackup", e.getMessage() != null ? e.getMessage() : "");
return null;
}
}
protected abstract GsonBuilder registerTypeAdapters(GsonBuilder builder);
private @Nullable List<T> checkBackup(List<T> list) {
if (list != null) {
for (T item : list) {
if (isInvalid(item)) return null;
}
}
return list;
}
protected abstract boolean isInvalid(T item);
public abstract void applyBackup(List<T> list, MedicineRepository medicineRepository);
protected record DatabaseContentWithVersion<T>(@Expose int version,
@Expose List<T> list) {
}
protected static class FullDeserialize<T> implements JsonDeserializer<T> {
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
T pojo = new Gson().fromJson(je, type);
Field[] fields = pojo.getClass().getDeclaredFields();
for (Field f : fields) {
try {
if (f.get(pojo) == null) {
throw new JsonParseException("Missing field in JSON: " + f.getName());
}
} catch (IllegalArgumentException | IllegalAccessException ex) {
Log.e("JSONBackup", "Internal error");
}
}
return pojo;
}
}
}