diff --git a/src/main/java/ch/zhaw/gartenverwaltung/io/JsonTaskDatabase.java b/src/main/java/ch/zhaw/gartenverwaltung/io/JsonTaskDatabase.java index caf02d1..a460f2f 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/io/JsonTaskDatabase.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/io/JsonTaskDatabase.java @@ -1,67 +1,112 @@ package ch.zhaw.gartenverwaltung.io; -import ch.zhaw.gartenverwaltung.types.HardinessZone; import ch.zhaw.gartenverwaltung.types.Task; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; -import com.fasterxml.jackson.datatype.jsr310.deser.YearMonthDeserializer; import java.io.File; import java.io.IOException; import java.net.URL; import java.time.LocalDate; -import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +/** + * Implements the {@link TaskDatabase} interface for loading and writing {@link Task} objects + * from and to a JSON file. + * The reads are cached to minimize file-io operations. + */ public class JsonTaskDatabase implements TaskDatabase{ + IdProvider idProvider; private final URL dataSource = getClass().getResource("taskdb.json"); private Map taskMap = Collections.emptyMap(); + /** + * Creating constant objects required to deserialize the {@link LocalDate} classes + */ private final static JavaTimeModule timeModule = new JavaTimeModule(); static { - DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yy-MM"); - YearMonthDeserializer dateDeserializer = new YearMonthDeserializer(dateFormat); - timeModule.addDeserializer(YearMonth.class, dateDeserializer); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + LocalDateDeserializer dateDeserializer = new LocalDateDeserializer(dateFormat); + timeModule.addDeserializer(LocalDate.class, dateDeserializer); } + /** + * If no data is currently loaded, data is loaded from {@link #dataSource}. + * In any case, the values of {@link #taskMap} are returned. + * + * @see TaskDatabase#getTaskList(LocalDate, LocalDate) + */ @Override public List getTaskList(LocalDate start, LocalDate end) throws IOException{ - if(taskMap.isEmpty()) { loadTaskListFromFile(); } return taskMap.values().stream().filter(task -> task.isInTimePeriode(start, end)).toList(); } + /** + * If no data is currently loaded, data is loaded from {@link #dataSource}. + * If the {@link Task} has an id than the task is added to the {@link #taskMap} + * otherwise the id is generated with the {@link IdProvider} before adding + * it to the {@link #taskMap}. In any case, the {@link #taskMap} is written + * to the {@link #dataSource}. + * + * @see TaskDatabase#saveTask(Task) + */ @Override public void saveTask(Task task) throws IOException { - ObjectMapper mapper = new ObjectMapper(); - if(dataSource != null) { - mapper.writeValue(new File(dataSource.getFile()), task); + if(taskMap.isEmpty()) { + loadTaskListFromFile(); } + if(task.getId() == 0) { + task.withId(idProvider.incrementAndGet()); + } + writeTaskListToFile(); } + /** + * If no data is currently loaded, data is loaded from {@link #dataSource}. + * If the {@link Task}s id is found in the {@link #taskMap}, the Task is removed + * from the {@link #taskMap}. Then the Task are written to the {@link #dataSource}. + * + * @see TaskDatabase#removeTask(Task) + */ @Override public void removeTask(Task task) throws IOException { - if(!taskMap.isEmpty() && taskMap.containsKey(task.getId())){ + if(taskMap.isEmpty()) { + loadTaskListFromFile(); + } + if(taskMap.containsKey(task.getId())){ taskMap.remove(task.getId()); + writeTaskListToFile(); } } + /** + * Writes cached data to the {@link #dataSource}. + * + * @throws IOException If the database cannot be accessed + */ private void writeTaskListToFile() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(timeModule); - mapper.writeValue(new File(dataSource.getFile()), taskMap); + if(dataSource != null) { + mapper.writeValue(new File(dataSource.getFile()), taskMap); + } } - + /** + * Loads the database from {@link #dataSource} and updates the cached data. + * + * @throws IOException If the database cannot be accessed + */ private void loadTaskListFromFile() throws IOException { if (dataSource != null) { ObjectMapper mapper = new ObjectMapper(); @@ -74,26 +119,6 @@ public class JsonTaskDatabase implements TaskDatabase{ .collect(HashMap::new, (res, task) -> res.put(task.getId(), task), (existing, replacement) -> {}); - System.out.println(taskMap); - } - } - - //Test main method - public static void main(String[] args) { - LocalDate date = LocalDate.now(); - LocalDate yesterday = LocalDate.now(); - yesterday = yesterday.minusDays(1); - Task testTask = new Task("water", "apply water", date); - JsonTaskDatabase jsonTaskDatabase = new JsonTaskDatabase(); - JsonPlantDatabase jsonPlantDatabase = new JsonPlantDatabase(); - - try { - //test load file - jsonPlantDatabase.getPlantList(HardinessZone.ZONE_8A); - jsonTaskDatabase.loadTaskListFromFile(); - - } catch (Exception e){ - System.out.println("Task load failed!: " + e.getMessage()); } } } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/io/TaskDatabase.java b/src/main/java/ch/zhaw/gartenverwaltung/io/TaskDatabase.java index e9c52a8..19ad778 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/io/TaskDatabase.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/io/TaskDatabase.java @@ -1,5 +1,7 @@ package ch.zhaw.gartenverwaltung.io; +import ch.zhaw.gartenverwaltung.types.HardinessZone; +import ch.zhaw.gartenverwaltung.types.Plant; import ch.zhaw.gartenverwaltung.types.Task; import java.io.IOException; @@ -7,8 +9,34 @@ import java.time.LocalDate; import java.util.Date; import java.util.List; +/** + * A database of {@link Task}s. + * The interface specifies the minimal required operations. + */ public interface TaskDatabase { + /** + * Yields a list of all {@link Task}s in the database with the start and end date of a period of time. + * + * @param start The start date of the wanted time period + * @param end The end date of the wanted time period + * @return A list of {@link Task}s planned in the specified time period + * @throws IOException If the database cannot be accessed + */ List getTaskList(LocalDate start, LocalDate end) throws IOException; + + /** + * Saves the {@link Task} in the Cache. + * + * @param task The {@link Task} which is wanted to be saved in the TaskList + * @throws IOException If the database cannot be accessed + */ void saveTask(Task task) throws IOException; + + /** + * Removes the {@link Task}from the Cache. + * + * @param task The {@link Task} which has to be removed from the {@link Task} list. + * @throws IOException If the database cannot be accessed + */ void removeTask(Task task) throws IOException; } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/types/Task.java b/src/main/java/ch/zhaw/gartenverwaltung/types/Task.java index 64d1331..3b26745 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/types/Task.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/types/Task.java @@ -16,6 +16,16 @@ public class Task { private Integer interval; private LocalDate endDate; + /** + * default constructor + * (used by Json deserializer) + */ + public Task(){ + name= ""; + description= ""; + startDate = LocalDate.now(); + } + public Task(String name, String description, LocalDate startDate) { this.name = name; this.description = description; diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/io/taskdb.json b/src/main/resources/ch/zhaw/gartenverwaltung/io/taskdb.json index 1597ab0..da201c9 100644 --- a/src/main/resources/ch/zhaw/gartenverwaltung/io/taskdb.json +++ b/src/main/resources/ch/zhaw/gartenverwaltung/io/taskdb.json @@ -2,49 +2,49 @@ { "id" : 1, "name" : "sow plant", - "description": "Plant the seeds/ crops in de bed.", - "startDate" : "22-05", - "endDate" : "22-05", + "description": "Plant the seeds, crops in de bed.", + "startDate" : "2022-05-01", + "endDate" : "2022-05-01", "interval" : 0 }, { "id" : 2, "name" : "water plant", "description": "water the plant, so that the soil is wet around the plant.", - "startDate" : "22-05", - "endDate" : "22-09", + "startDate" : "2022-05-01", + "endDate" : "2022-09-01", "interval" : 2 }, { "id" : 3, "name" : "fertilize plant", - "description": "The fertilizer has to be mixed with water. Then fertilize the plant's soil with the mixture", - "startDate" : "22-06", - "endDate" : "22-08", + "description": "The fertilizer has to be mixed with water. Then fertilize the plants soil with the mixture", + "startDate" : "2022-06-01", + "endDate" : "2022-08-01", "interval" : 28 }, { "id" : 4, "name" : "covering plant", "description": "Take a big enough coverage for the plants. Cover the whole plant with a bit space between the plant and the coverage", - "startDate" : "22-07", - "endDate" : "22-07", + "startDate" : "2022-07-01", + "endDate" : "2022-07-01", "interval" : 0 }, { "id" : 5, "name" : "look after plant", "description": "Look for pest or illness at the leaves of the plant. Check the soil around the plant, if the roots are enough covered with soil", - "startDate" : "22-05", - "endDate" : "22-09", + "startDate" : "2022-05-01", + "endDate" : "2022-09-01", "interval" : 5 }, { "id" : 6, "name" : "harvest plant", "description": "Pull the ripe vegetables out from the soil. Clean them with clear, fresh water. ", - "startDate" : "22-09", - "endDate" : "22-09", + "startDate" : "2022-09-01", + "endDate" : "2022-09-01", "interval" : 0 } ] \ No newline at end of file