<commit_before>package org.openforis.ceo;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.net.URLDecoder;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.StreamSupport;
import spark.Request;
import spark.Response;

public class AJAX {

    private static String expandResourcePath(String filename) {
        return AJAX.class.getResource(filename).getFile();
    }

    private static JsonElement readJsonFile(String filename) {
        String jsonDataDir = expandResourcePath("/public/json/");
        try (FileReader fileReader = new FileReader(new File(jsonDataDir, filename))) {
            return (new JsonParser()).parse(fileReader);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void writeJsonFile(String filename, JsonElement data) {
        String jsonDataDir = expandResourcePath("/public/json/");
        try (FileWriter fileWriter = new FileWriter(new File(jsonDataDir, filename))) {
            fileWriter.write(data.toString());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static Collector<JsonElement, ?, JsonArray> intoJsonArray =
        Collector.of(JsonArray::new, JsonArray::add,
                     (left, right) -> { left.addAll(right); return left; });

    private static JsonArray mapJsonArray(JsonArray array, Function<JsonObject, JsonObject> mapper) {
        return StreamSupport.stream(array.spliterator(), false)
            .map(element -> element.getAsJsonObject())
            .map(mapper)
            .collect(intoJsonArray);
    }

    // Note: The JSON file must contain an array of objects.
    private static void updateJsonFile(String filename, Function<JsonObject, JsonObject> mapper) {
        JsonArray array = readJsonFile(filename).getAsJsonArray();
        JsonArray updatedArray = mapJsonArray(array, mapper);
        writeJsonFile(filename, updatedArray);
    }

    public static String getAllProjects(Request req, Response res) {
        return readJsonFile("project_list.json").toString();
    }

    public static String getProjectPlots(Request req, Response res) {
        String projectId = req.body();
        return readJsonFile("plot_data_" + projectId + ".json").toString();
    }

    public static String dumpProjectAggregateData(Request req, Response res) {
        // FIXME: Write downloads/ceo_<project_name>_<yyyy-mm-dd>.csv and return its filename
        // Fields: plot_id, center_lon, center_lat, radius_m, sample_points,
        //         user_assignments, value1_%, value2_%, ..., valueN_%
        String projectId = req.body();

        // Get sample values for this project
        JsonArray projects = readJsonFile("project_list.json").getAsJsonArray();

        String[] labels = StreamSupport.stream(projects.spliterator(), false)
            .map(project -> project.getAsJsonObject())
            .filter(project -> projectId.equals(project.get("id").getAsString()))
            .map(project -> {
                    JsonArray sampleValues = project.get("sample_values").getAsJsonArray();
                    return StreamSupport.stream(sampleValues.spliterator(), false)
                        .map(sampleValue -> sampleValue.getAsJsonObject())
                        .sorted(Comparator.comparing(sampleValue -> sampleValue.get("id").getAsInt()))
                        .map(sampleValue -> sampleValue.get("name").getAsString())
                        .toArray(String[]::new);
                })
            .findFirst()
            .get();

        System.out.println("Sample Values:");
        Arrays.stream(labels).forEach(System.out::println);

        return "downloads/ceo_mekong_river_region_2017-04-29.csv";
    }

    public static String archiveProject(Request req, Response res) {
        String projectId = req.body();

        updateJsonFile("project_list.json",
                       project -> {
                           if (projectId.equals(project.get("id").getAsString())) {
                               project.remove("archived");
                               project.addProperty("archived", true);
                               return project;
                           } else {
                               return project;
                           }
                       });

        return "";
    }

    public static String addUserSamples(Request req, Response res) {
        JsonObject jsonInputs = (new JsonParser()).parse(req.body()).getAsJsonObject();
        String projectId = jsonInputs.get("projectId").getAsString();
        String plotId = jsonInputs.get("plotId").getAsString();
        String userId = jsonInputs.get("userId").getAsString();
        JsonObject userSamples = jsonInputs.get("userSamples").getAsJsonObject();

        updateJsonFile("plot_data_" + projectId + ".json",
                       plot -> {
                           JsonObject plotAttributes = plot.get("plot").getAsJsonObject();
                           JsonArray samples = plot.get("samples").getAsJsonArray();
                           if (plotId.equals(plotAttributes.get("id").getAsString())) {
                               int currentAnalyses = plotAttributes.get("analyses").getAsInt();
                               plotAttributes.remove("analyses");
                               plotAttributes.addProperty("analyses", currentAnalyses + 1);
                               plotAttributes.remove("user");
                               plotAttributes.addProperty("user", userId);
                               plot.remove("plot");
                               plot.add("plot", plotAttributes);
                               JsonArray updatedSamples = mapJsonArray(samples,
                                                                       sample -> {
                                                                           String sampleId = sample.get("id").getAsString();
                                                                           sample.remove("value");
                                                                           sample.addProperty("value", userSamples.get(sampleId).getAsInt());
                                                                           return sample;
                                                                       });
                               plot.remove("samples");
                               plot.add("samples", updatedSamples);
                               return plot;
                           } else {
                               return plot;
                           }
                       });

        return "";
    }

    public static String flagPlot(Request req, Response res) {
        JsonObject jsonInputs = (new JsonParser()).parse(req.body()).getAsJsonObject();
        String projectId = jsonInputs.get("projectId").getAsString();
        String plotId = jsonInputs.get("plotId").getAsString();

        updateJsonFile("plot_data_" + projectId + ".json",
                       plot -> {
                           JsonObject plotAttributes = plot.get("plot").getAsJsonObject();
                           if (plotId.equals(plotAttributes.get("id").getAsString())) {
                               plotAttributes.remove("flagged");
                               plotAttributes.addProperty("flagged", true);
                               plot.remove("plot");
                               plot.add("plot", plotAttributes);
                               return plot;
                           } else {
                               return plot;
                           }
                       });

        return "";
    }

    public static String geodashId(Request req, Response res) {
        String geodashDataDir = expandResourcePath("/public/json/");

        try (FileReader projectFileReader = new FileReader(new File(geodashDataDir, "proj.json"))) {
            JsonParser parser = new JsonParser();
            JsonArray projects = parser.parse(projectFileReader).getAsJsonArray();

            Optional matchingProject = StreamSupport.stream(projects.spliterator(), false)
                .map(project -> project.getAsJsonObject())
                .filter(project -> req.params(":id").equals(project.get("projectID").getAsString()))
                .map(project -> {
                        try (FileReader dashboardFileReader = new FileReader(new File(geodashDataDir, "dash-" + project.get("dashboard").getAsString() + ".json"))) {
                            return parser.parse(dashboardFileReader).getAsJsonObject();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    })
                .findFirst();

            if (matchingProject.isPresent()) {
                if (req.queryParams("callback") != null) {
                    return req.queryParams("callback") + "(" + matchingProject.get().toString() + ")";<commit_msg>Reordered the String.equals() calls in AJAX.java for readability.<commit_after>package org.openforis.ceo;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.net.URLDecoder;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.StreamSupport;
import spark.Request;
import spark.Response;

public class AJAX {

    private static String expandResourcePath(String filename) {
        return AJAX.class.getResource(filename).getFile();
    }

    private static JsonElement readJsonFile(String filename) {
        String jsonDataDir = expandResourcePath("/public/json/");
        try (FileReader fileReader = new FileReader(new File(jsonDataDir, filename))) {
            return (new JsonParser()).parse(fileReader);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void writeJsonFile(String filename, JsonElement data) {
        String jsonDataDir = expandResourcePath("/public/json/");
        try (FileWriter fileWriter = new FileWriter(new File(jsonDataDir, filename))) {
            fileWriter.write(data.toString());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static Collector<JsonElement, ?, JsonArray> intoJsonArray =
        Collector.of(JsonArray::new, JsonArray::add,
                     (left, right) -> { left.addAll(right); return left; });

    private static JsonArray mapJsonArray(JsonArray array, Function<JsonObject, JsonObject> mapper) {
        return StreamSupport.stream(array.spliterator(), false)
            .map(element -> element.getAsJsonObject())
            .map(mapper)
            .collect(intoJsonArray);
    }

    // Note: The JSON file must contain an array of objects.
    private static void updateJsonFile(String filename, Function<JsonObject, JsonObject> mapper) {
        JsonArray array = readJsonFile(filename).getAsJsonArray();
        JsonArray updatedArray = mapJsonArray(array, mapper);
        writeJsonFile(filename, updatedArray);
    }

    public static String getAllProjects(Request req, Response res) {
        return readJsonFile("project_list.json").toString();
    }

    public static String getProjectPlots(Request req, Response res) {
        String projectId = req.body();
        return readJsonFile("plot_data_" + projectId + ".json").toString();
    }

    public static String dumpProjectAggregateData(Request req, Response res) {
        // FIXME: Write downloads/ceo_<project_name>_<yyyy-mm-dd>.csv and return its filename
        // Fields: plot_id, center_lon, center_lat, radius_m, sample_points,
        //         user_assignments, value1_%, value2_%, ..., valueN_%
        String projectId = req.body();

        // Get sample values for this project
        JsonArray projects = readJsonFile("project_list.json").getAsJsonArray();

        String[] labels = StreamSupport.stream(projects.spliterator(), false)
            .map(project -> project.getAsJsonObject())
            .filter(project -> project.get("id").getAsString().equals(projectId))
            .map(project -> {
                    JsonArray sampleValues = project.get("sample_values").getAsJsonArray();
                    return StreamSupport.stream(sampleValues.spliterator(), false)
                        .map(sampleValue -> sampleValue.getAsJsonObject())
                        .sorted(Comparator.comparing(sampleValue -> sampleValue.get("id").getAsInt()))
                        .map(sampleValue -> sampleValue.get("name").getAsString())
                        .toArray(String[]::new);
                })
            .findFirst()
            .get();

        System.out.println("Sample Values:");
        Arrays.stream(labels).forEach(System.out::println);

        return "downloads/ceo_mekong_river_region_2017-04-29.csv";
    }

    public static String archiveProject(Request req, Response res) {
        String projectId = req.body();

        updateJsonFile("project_list.json",
                       project -> {
                           if (project.get("id").getAsString().equals(projectId)) {
                               project.remove("archived");
                               project.addProperty("archived", true);
                               return project;
                           } else {
                               return project;
                           }
                       });

        return "";
    }

    public static String addUserSamples(Request req, Response res) {
        JsonObject jsonInputs = (new JsonParser()).parse(req.body()).getAsJsonObject();
        String projectId = jsonInputs.get("projectId").getAsString();
        String plotId = jsonInputs.get("plotId").getAsString();
        String userId = jsonInputs.get("userId").getAsString();
        JsonObject userSamples = jsonInputs.get("userSamples").getAsJsonObject();

        updateJsonFile("plot_data_" + projectId + ".json",
                       plot -> {
                           JsonObject plotAttributes = plot.get("plot").getAsJsonObject();
                           JsonArray samples = plot.get("samples").getAsJsonArray();
                           if (plotAttributes.get("id").getAsString().equals(plotId)) {
                               int currentAnalyses = plotAttributes.get("analyses").getAsInt();
                               plotAttributes.remove("analyses");
                               plotAttributes.addProperty("analyses", currentAnalyses + 1);
                               plotAttributes.remove("user");
                               plotAttributes.addProperty("user", userId);
                               plot.remove("plot");
                               plot.add("plot", plotAttributes);
                               JsonArray updatedSamples = mapJsonArray(samples,
                                                                       sample -> {
                                                                           String sampleId = sample.get("id").getAsString();
                                                                           sample.remove("value");
                                                                           sample.addProperty("value", userSamples.get(sampleId).getAsInt());
                                                                           return sample;
                                                                       });
                               plot.remove("samples");
                               plot.add("samples", updatedSamples);
                               return plot;
                           } else {
                               return plot;
                           }
                       });

        return "";
    }

    public static String flagPlot(Request req, Response res) {
        JsonObject jsonInputs = (new JsonParser()).parse(req.body()).getAsJsonObject();
        String projectId = jsonInputs.get("projectId").getAsString();
        String plotId = jsonInputs.get("plotId").getAsString();

        updateJsonFile("plot_data_" + projectId + ".json",
                       plot -> {
                           JsonObject plotAttributes = plot.get("plot").getAsJsonObject();
                           if (plotAttributes.get("id").getAsString().equals(plotId)) {
                               plotAttributes.remove("flagged");
                               plotAttributes.addProperty("flagged", true);
                               plot.remove("plot");
                               plot.add("plot", plotAttributes);
                               return plot;
                           } else {
                               return plot;
                           }
                       });

        return "";
    }

    public static String geodashId(Request req, Response res) {
        String geodashDataDir = expandResourcePath("/public/json/");

        try (FileReader projectFileReader = new FileReader(new File(geodashDataDir, "proj.json"))) {
            JsonParser parser = new JsonParser();
            JsonArray projects = parser.parse(projectFileReader).getAsJsonArray();

            Optional matchingProject = StreamSupport.stream(projects.spliterator(), false)
                .map(project -> project.getAsJsonObject())
                .filter(project -> project.get("projectID").getAsString().equals(req.params(":id")))
                .map(project -> {
                        try (FileReader dashboardFileReader = new FileReader(new File(geodashDataDir, "dash-" + project.get("dashboard").getAsString() + ".json"))) {
                            return parser.parse(dashboardFileReader).getAsJsonObject();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    })
                .findFirst();

            if (matchingProject.isPresent()) {
                if (req.queryParams("callback") != null) {
                    return req.queryParams("callback") + "(" + matchingProject.get().toString() + ")";
{'fraction_non_alphanumeric': 0.10858243932923654, 'fraction_numerical': 0.001145713988126237, 'mean_word_length': 1.7335231316725979, 'pattern_counts': {'":': 2, '<': 13, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 42, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7379673', 'n_tokens_mistral': 4562, 'n_tokens_neox': 4428, 'n_words': 885}