package com.asteria.utility; import java.io.FileWriter; import com.google.common.base.Preconditions; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; /** * A utility class used for constructing and writing {@code JSON} files. * <p> * <p> * And an example of usage: * * <pre> * JsonSaver json = new JsonSaver(); * * for (Player player : players) { * json.current().addProperty("name", player.getUsername()); * json.current().addProperty("value1", 1); * json.current().addProperty("value2", true); * json.split(); * } * * json.publish("./data/some_player_database.json"); * </pre> * * @author lare96 <http://github.org/lare96> */ public final class JsonSaver { /** * A gson builder, allows us to turn {@code Object}s into {@code JSON} * format and vice-versa. */ private final Gson serializer = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); /** * An array that will hold all of our sub-tables. */ private final JsonArray array = new JsonArray(); /** * The flag that determines if only one table can exist. */ private final boolean singletonTable; /** * A writer that acts as a sub-table, instantiated after each * {@code split()}. */ private JsonObject currentWriter = new JsonObject(); /** * Creates a new {@link JsonSaver}. * * @param singletonTable * determines if only one table can exist. */ public JsonSaver(boolean singletonTable) { this.singletonTable = singletonTable; } /** * Creates a new {@link JsonSaver} that can have an infinite amount of * tables. */ public JsonSaver() { this(false); } /** * <strong>Invocation of this function is expensive and should be cached or * avoided whenever possible.</strong> This function will call * {@code split()} if the {@code currentWriter} has unsplit elements added * to it. * <p> * <p> * This function returns the contents of this class in pretty printed * {@code JSON} format. */ @Override public String toString() { if (singletonTable) return serializer.toJson(currentWriter); if (currentWriter.entrySet().size() > 0) split(); return serializer.toJson(array); } /** * Adds the data within {@code currentWriter} to the internal * {@link JsonArray} then instantiates a new writer, effectively splitting * the data up into tables. If this instance is a {@code singletonTable}, * throws an {@link IllegalStateException}. * * @throws IllegalStateException * if this instance is only allowed one internal table. */ public void split() { Preconditions.checkState(!singletonTable, "JsonSaver instance is a singleton table!"); array.add(currentWriter); currentWriter = new JsonObject(); } /*** * Gets the current {@link JsonObject} that is writing data. * * @return the current writer. */ public JsonObject current() { return currentWriter; } /** * Gets the internal gson that allows for serialization. * * @return the internal gson. */ public Gson serializer() { return serializer; } /** * Publishes the contents of this {@link JsonSaver} to the file at * {@code path}. * * @param path * the path to publish the contents. */ public void publish(String path) { try (FileWriter fw = new FileWriter(path)) { fw.write(toString()); } catch (Exception e) { e.printStackTrace(); } } }