// Path: common/src/main/java/com/vexsoftware/votifier/platform/LoggingAdapter.java
// public interface LoggingAdapter {
//     void error(String s);
//     void error(String s, Object... o);
//     void error(String s, Throwable e, Object... o);
// 
//     void warn(String s);
//     void warn(String s, Object... o);
// 
//     void info(String s);
//     void info(String s, Object... o);
// }
// 
// Path: common/src/main/java/com/vexsoftware/votifier/platform/VotifierPlugin.java
// public interface VotifierPlugin extends VoteHandler {
//     AttributeKey<VotifierPlugin> KEY = AttributeKey.valueOf("votifier_plugin");
// 
//     Map<String, Key> getTokens();
// 
//     KeyPair getProtocolV1Key();
// 
//     LoggingAdapter getPluginLogger();
// 
//     VotifierScheduler getScheduler();
// 
//     default boolean isDebug() {
//         return false;
//     }
// }
// 
// Path: common/src/main/java/com/vexsoftware/votifier/platform/scheduler/ScheduledVotifierTask.java
// public interface ScheduledVotifierTask {
//     void cancel();
// }
// 
// Path: common/src/main/java/com/vexsoftware/votifier/util/GsonInst.java
// public class GsonInst {
// 
//     public static final Gson gson = new GsonBuilder().create();
// 
// }


import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.vexsoftware.votifier.platform.LoggingAdapter;
import com.vexsoftware.votifier.platform.VotifierPlugin;
import com.vexsoftware.votifier.platform.scheduler.ScheduledVotifierTask;
import com.vexsoftware.votifier.util.GsonInst;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.util.*;
import java.util.concurrent.TimeUnit;
            save();
        }
    }

    private Collection<VoteWithRecordedTimestamp> readVotes(JsonArray voteArray) {
        Collection<VoteWithRecordedTimestamp> votes = new HashSet<>(voteArray.size());
        for (int i = 0; i < voteArray.size(); i++) {
            JsonObject voteObject = voteArray.get(i).getAsJsonObject();
            VoteWithRecordedTimestamp v = new VoteWithRecordedTimestamp(voteObject);
            if (hasTimedOut(v))
                l.warn("Purging out of date vote.", v);
            else
                votes.add(v);
        }
        return votes;
    }

    public void save() throws IOException {
        JsonObject votesObject = new JsonObject();

        cacheLock.lock();
        try {
            votesObject.addProperty("version", 2);
            votesObject.add("players", serializeMap(playerVoteCache));
            votesObject.add("servers", serializeMap(voteCache));
        } finally {
            cacheLock.unlock();
        }

        try (BufferedWriter writer = Files.newBufferedWriter(cacheFile.toPath(), StandardCharsets.UTF_8)) {
// Path: common/src/main/java/com/vexsoftware/votifier/platform/LoggingAdapter.java
// public interface LoggingAdapter {
//     void error(String s);
//     void error(String s, Object... o);
//     void error(String s, Throwable e, Object... o);
// 
//     void warn(String s);
//     void warn(String s, Object... o);
// 
//     void info(String s);
//     void info(String s, Object... o);
// }
// 
// Path: common/src/main/java/com/vexsoftware/votifier/platform/VotifierPlugin.java
// public interface VotifierPlugin extends VoteHandler {
//     AttributeKey<VotifierPlugin> KEY = AttributeKey.valueOf("votifier_plugin");
// 
//     Map<String, Key> getTokens();
// 
//     KeyPair getProtocolV1Key();
// 
//     LoggingAdapter getPluginLogger();
// 
//     VotifierScheduler getScheduler();
// 
//     default boolean isDebug() {
//         return false;
//     }
// }
// 
// Path: common/src/main/java/com/vexsoftware/votifier/platform/scheduler/ScheduledVotifierTask.java
// public interface ScheduledVotifierTask {
//     void cancel();
// }
// 
// Path: common/src/main/java/com/vexsoftware/votifier/util/GsonInst.java
// public class GsonInst {
// 
//     public static final Gson gson = new GsonBuilder().create();
// 
// }


// Path: common/src/main/java/com/vexsoftware/votifier/support/forwarding/cache/FileVoteCache.java
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.vexsoftware.votifier.platform.LoggingAdapter;
import com.vexsoftware.votifier.platform.VotifierPlugin;
import com.vexsoftware.votifier.platform.scheduler.ScheduledVotifierTask;
import com.vexsoftware.votifier.util.GsonInst;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.util.*;
import java.util.concurrent.TimeUnit;

            save();
        }
    }

    private Collection<VoteWithRecordedTimestamp> readVotes(JsonArray voteArray) {
        Collection<VoteWithRecordedTimestamp> votes = new HashSet<>(voteArray.size());
        for (int i = 0; i < voteArray.size(); i++) {
            JsonObject voteObject = voteArray.get(i).getAsJsonObject();
            VoteWithRecordedTimestamp v = new VoteWithRecordedTimestamp(voteObject);
            if (hasTimedOut(v))
                l.warn("Purging out of date vote.", v);
            else
                votes.add(v);
        }
        return votes;
    }

    public void save() throws IOException {
        JsonObject votesObject = new JsonObject();

        cacheLock.lock();
        try {
            votesObject.addProperty("version", 2);
            votesObject.add("players", serializeMap(playerVoteCache));
            votesObject.add("servers", serializeMap(voteCache));
        } finally {
            cacheLock.unlock();
        }

        try (BufferedWriter writer = Files.newBufferedWriter(cacheFile.toPath(), StandardCharsets.UTF_8)) {
            GsonInst.gson.toJson(votesObject, writer);