Skip to content
Snippets Groups Projects
FileManager.java 7.66 KiB
Newer Older
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import mi.hdm.mealPlan.MealPlan;
import mi.hdm.recipes.*;
import mi.hdm.shoppingList.ShoppingList;
Karsch Lukas's avatar
Karsch Lukas committed
import mi.hdm.typeAdapters.CategoryManagerTypeAdapter;
import mi.hdm.typeAdapters.MealPlanTypeAdapter;
import mi.hdm.typeAdapters.RecipeTypeAdapter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
Karsch Lukas's avatar
Karsch Lukas committed
import java.util.Objects;
import java.util.stream.Stream;

/**
 * Containing methods to serialize and deserialize parts of the app content for saving to / loading from the filesystem
 */
    private final static String PATH_TO_DEFAULT_INGREDIENTS = "/data/nutrition.csv";
    private final static String PATH_TO_USER_DATA = System.getProperty("user.home") + "\\AppData\\Roaming\\TastyPages";

    private final static Logger log = LogManager.getLogger(FileManager.class);

    public static void serializeToFile(TastyPages app) {
    public static TastyPages deserializeFromFile() throws Exception { //TODO: if this fails, log.fatal and System.exit
        log.info("Trying to read {}", PATH_TO_USER_DATA);
        Path userPath = Path.of(PATH_TO_USER_DATA);
        if (userPath.toFile().mkdirs()) { //If .mkdirs() returns true, that means the folder has not existed before -> in this case, only load default ingredients!
            log.info("TastyPages folder has been created at {}", userPath);
Karsch Lukas's avatar
Karsch Lukas committed
            IngredientManager deserializedIngredientManager = deserializeIngredientManager(getAbsolutePathFromResourceFolder());
            return new TastyPages(deserializedIngredientManager);
        } else { //otherwise, read user data
            log.info("Found TastyPages folder at {}, loading user data from there.", userPath);
            IngredientManager ingredientManager;
            RecipeManager recipeManager;
            CategoryManager categoryManager;
            MealPlan mealPlan;
            ShoppingList shoppingList;

            if (Files.exists(Path.of(userPath + "ingredients.csv"))) {
                ingredientManager = deserializeIngredientManager(PATH_TO_USER_DATA);
            } else {
Karsch Lukas's avatar
Karsch Lukas committed
                ingredientManager = deserializeIngredientManager(getAbsolutePathFromResourceFolder());
            }

            Path recipeFolder = Path.of(userPath + "/recipes");
            if (Files.exists(recipeFolder) && Files.isDirectory(recipeFolder)) {
                recipeManager = deserializeRecipeManager(PATH_TO_USER_DATA + "/recipes", ingredientManager);
            } else {
                recipeFolder.toFile().mkdir();
                recipeManager = new RecipeManager();
            }

            Path toCategoryJson = Path.of(userPath + "/categories.json");
            if (Files.exists(toCategoryJson) && Files.isRegularFile(toCategoryJson)) {
                categoryManager = deserializeCategoryManager(toCategoryJson);
            } else {
                categoryManager = new CategoryManager();
            }

Karsch Lukas's avatar
Karsch Lukas committed
            Path toMealPlanJson = Path.of(userPath + "/mealplan.json");
            if (Files.exists(toMealPlanJson) && Files.isRegularFile(toMealPlanJson)) {
                mealPlan = deserializeMealPlan(toMealPlanJson, recipeManager);
            } else {
                mealPlan = new MealPlan(recipeManager);
            }

    private static IngredientManager deserializeIngredientManager(String path) throws IOException {
        CSVParser parser = new CSVParser();
        List<Ingredient> ingredients = parser.getIngredientsFromCSV(
                path,
                ',',
                "name", "calories", "carbohydrate", "fat", "protein", "fiber", "sodium"
        );
        return new IngredientManager(ingredients);
    }

Karsch Lukas's avatar
Karsch Lukas committed
    private static RecipeManager deserializeRecipeManager(String path, IngredientManager ingredientManager) throws IOException {
        Path recipePath = Path.of(path);
        List<Path> recipePaths;
Karsch Lukas's avatar
Karsch Lukas committed
        log.info("Reading recipes from '{}'", path);
        try (Stream<Path> stream = Files.list(recipePath)) { //TODO: catch clause
            recipePaths = stream.toList();
        }

Karsch Lukas's avatar
Karsch Lukas committed
        List<Recipe> recipes = recipePaths
                .stream()
                .map(p -> {
                    try {
                        return Files.readString(p);
                    } catch (IOException e) {
                        e.printStackTrace();
                        log.error("Could not read file contents for {}. Check file permissions and content", p);
Karsch Lukas's avatar
Karsch Lukas committed
                        return null;
Karsch Lukas's avatar
Karsch Lukas committed
                .filter(Objects::nonNull)
                .map(json -> JSONtoRecipe(json, ingredientManager))
Karsch Lukas's avatar
Karsch Lukas committed
    private static CategoryManager deserializeCategoryManager(Path path) throws IOException {
        log.info("Reading categories from {}", path);
        Gson gson = new GsonBuilder().registerTypeAdapter(CategoryManager.class, new CategoryManagerTypeAdapter()).create();
        String fileContent = Files.readString(path);
        return gson.fromJson(fileContent, CategoryManager.class);
Karsch Lukas's avatar
Karsch Lukas committed
    private static MealPlan deserializeMealPlan(Path filepath, RecipeManager recipeManager) throws IOException {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(MealPlan.class, new MealPlanTypeAdapter(recipeManager))
                .create();
        String fileContent = Files.readString(filepath);
        MealPlan mealPlan = gson.fromJson(fileContent, MealPlan.class);
        return null;
    }

    private static ShoppingList deserializeShoppingList() {
        return null;
    }

    private static String recipeToJSON(Recipe recipe, IngredientManager ingredientManager) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(Recipe.class, new RecipeTypeAdapter(ingredientManager))
                .create();
        return gson.toJson(recipe);
    }

    /**
     * Used to convert an ingredient into a CSV String seperated by comma
     *
     * @return a comma seperated String containing the name of the ingredient as well as the contents of its nutrition table
     */
    private static String ingredientToCSV(Ingredient ingredient) {
        //"name", "calories", "carbohydrate", "fat", "protein", "fiber", "sodium"
        Map<Nutrition, BigDecimal> map = ingredient.getNutritionTable().getTable();
        return String.format(
                "%s, %f, %f, %f, %f, %f, %f%n",
                ingredient.getName(),
                map.get(Nutrition.CALORIES).doubleValue(),
                map.get(Nutrition.CARBS).doubleValue(),
                map.get(Nutrition.FAT).doubleValue(),
                map.get(Nutrition.PROTEINS).doubleValue(),
                map.get(Nutrition.FIBERS).doubleValue(),
                map.get(Nutrition.SALT).doubleValue()
        );
    }

Karsch Lukas's avatar
Karsch Lukas committed
    private static Recipe JSONtoRecipe(String json, IngredientManager ingredientManager) {
        Gson gson = new GsonBuilder().registerTypeAdapter(Recipe.class, new RecipeTypeAdapter(ingredientManager)).create();
        return gson.fromJson(json, Recipe.class);
Karsch Lukas's avatar
Karsch Lukas committed
    private static String getAbsolutePathFromResourceFolder() throws URISyntaxException {
        URL resourceUrl = FileManager.class.getResource(FileManager.PATH_TO_DEFAULT_INGREDIENTS);
        assert resourceUrl != null;
        Path path = Paths.get(resourceUrl.toURI());
        return path.toFile().getAbsolutePath();