Newer
Older

Karsch Lukas
committed
package mi.hdm.filesystem;

Karsch Lukas
committed
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

Karsch Lukas
committed
import mi.hdm.TastyPages;

Karsch Lukas
committed
import mi.hdm.mealPlan.MealPlan;
import mi.hdm.recipes.*;
import mi.hdm.shoppingList.ShoppingList;
import mi.hdm.typeAdapters.CategoryManagerTypeAdapter;
import mi.hdm.typeAdapters.MealPlanTypeAdapter;

Karsch Lukas
committed
import mi.hdm.typeAdapters.RecipeTypeAdapter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Karsch Lukas
committed

Karsch Lukas
committed
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
committed
import java.util.stream.Stream;
/**
* Containing methods to serialize and deserialize parts of the app content for saving to / loading from the filesystem
*/

Karsch Lukas
committed
public class FileManager {

Karsch Lukas
committed
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) {

Karsch Lukas
committed
}

Karsch Lukas
committed
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());

Karsch Lukas
committed
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());

Karsch Lukas
committed
}
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();
}
Path toMealPlanJson = Path.of(userPath + "/mealplan.json");
if (Files.exists(toMealPlanJson) && Files.isRegularFile(toMealPlanJson)) {
mealPlan = deserializeMealPlan(toMealPlanJson, recipeManager);
} else {
mealPlan = new MealPlan(recipeManager);
}

Karsch Lukas
committed
return null;
}

Karsch Lukas
committed
}

Karsch Lukas
committed
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 IOException {

Karsch Lukas
committed
Path recipePath = Path.of(path);
List<Path> recipePaths;

Karsch Lukas
committed
try (Stream<Path> stream = Files.list(recipePath)) { //TODO: catch clause
recipePaths = stream.toList();
}

Karsch Lukas
committed
.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
committed
}
})
.filter(Objects::nonNull)
.map(json -> JSONtoRecipe(json, ingredientManager))

Karsch Lukas
committed
.toList();
return new RecipeManager(recipes);
}
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
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);

Karsch Lukas
committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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, IngredientManager ingredientManager) {
Gson gson = new GsonBuilder().registerTypeAdapter(Recipe.class, new RecipeTypeAdapter(ingredientManager)).create();
return gson.fromJson(json, Recipe.class);

Karsch Lukas
committed
}
private static String getAbsolutePathFromResourceFolder() throws URISyntaxException {
URL resourceUrl = FileManager.class.getResource(FileManager.PATH_TO_DEFAULT_INGREDIENTS);

Karsch Lukas
committed
assert resourceUrl != null;
Path path = Paths.get(resourceUrl.toURI());
return path.toFile().getAbsolutePath();