Skip to content
Snippets Groups Projects
FileManager.java 6.18 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;
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;
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);

    private final static Gson gson = new Gson();
    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);
            IngredientManager deserializedIngredientManager = deserializeIngredientManager(getAbsolutePathFromResourceFolder(PATH_TO_DEFAULT_INGREDIENTS));
            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 {
                ingredientManager = deserializeIngredientManager(getAbsolutePathFromResourceFolder(PATH_TO_DEFAULT_INGREDIENTS));
            }

            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();
            }
            return null;
        }
    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);
    }

    private static RecipeManager deserializeRecipeManager(String path, IngredientManager ingredientManager) throws Exception {
        Path recipePath = Path.of(path);
        List<Path> recipePaths;
        try (Stream<Path> stream = Files.list(recipePath)) { //TODO: catch clause
            recipePaths = stream.toList();
        }

        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);
                        return "";
                    }
                })
                .map(FileManager::JSONtoRecipe)
                .toList();
        return new RecipeManager(recipes);
    }

    private static CategoryManager deserializeCategoryManager() {
    private static MealPlan deserializeMealPlan() {
        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()
        );
    }

    private static Recipe JSONtoRecipe(String json) {
        //when loading a recipe, is it important that its ingredients are the same objects as in the ingredient manager?
        gson.fromJson(json, Recipe.class);
        return null;
    private static String getAbsolutePathFromResourceFolder(String resource) throws URISyntaxException {
        URL resourceUrl = FileManager.class.getResource(resource);
        assert resourceUrl != null;
        Path path = Paths.get(resourceUrl.toURI());
        return path.toFile().getAbsolutePath();