diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 80c333abc98..4d305f391e8 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -292,14 +292,14 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
| `* * *` | NUS student | search for a name in the contact | easily find the person’s contact |
| `* * *` | NUS student | add contacts into my address book easily | retrieve the saved contact |
| `* * *` | NUS student living on campus | save the contacts of my neighbors | contact them in case of any emergencies |
-| `* * *` | NUS student living on campus | save the addresses of my neighbours | locate them easily when necessary |
+| `* * *` | NUS student living on campus | save the addresses of my neighbours | locate them easily when necessary |
| `* * *` | NUS student in multiple CCAs | filter my contacts by tags to identify all people in a group | find the relevant contacts in a certain group quickly |
| `* * *` | student staying on campus | label multiple tags to my contacts | locate my friends taking the same module and staying in the same campus residence as me |
| `* * *` | user that is familiar with the keyboard | use the keyboard to type commands in the applications | access the features of the application |
| `* * *` | user with bad memory | save a short description of my contact | identify my contacts better |
| `* * *` | visual-reliant user | save a photo of the person into my contacts | quickly recognise and find them |
| `* * *` | non-tech-savvy user | use the help feature of the app | navigate about the app easily |
-| `* *` | NUS student | import the NUS calendar into the application | view all academic commitments more conveniently |
+| `* *` | NUS student | import the NUS calendar into the application | view all academic commitments more conveniently |
| `* *` | NUS Student | compare timetables/calendars with my peers easily | plan meetings more conveniently |
| `* *` | NUS student | allocate tasks and responsibilities within a project or CCA group | tasks can be done efficiently |
| `* *` | NUS Student in multiple CCAs | group my contacts | identify which group my contacts belong to |
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index ec47f0d8656..61ce3909631 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -6,10 +6,6 @@
UniMate is a desktop app for students to **manage contacts** and **manage schedules** optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, UniMate can get your contact management tasks done faster than traditional GUI apps.
-AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized for use via a Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps.
-
-
-
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java
index 3d6bd06d5af..b1ab27c450a 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/address/MainApp.java
@@ -21,9 +21,14 @@
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.UserPrefs;
+import seedu.address.model.calendar.Calendar;
+import seedu.address.model.calendar.ReadOnlyCalendar;
+import seedu.address.model.util.SampleCalendarUtil;
import seedu.address.model.util.SampleDataUtil;
import seedu.address.storage.AddressBookStorage;
+import seedu.address.storage.CalendarStorage;
import seedu.address.storage.JsonAddressBookStorage;
+import seedu.address.storage.JsonCalendarStorage;
import seedu.address.storage.JsonUserPrefsStorage;
import seedu.address.storage.Storage;
import seedu.address.storage.StorageManager;
@@ -58,7 +63,8 @@ public void init() throws Exception {
UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath());
UserPrefs userPrefs = initPrefs(userPrefsStorage);
AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath());
- storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ CalendarStorage calendarStorage = new JsonCalendarStorage(userPrefs.getCalendarFilePath());
+ storage = new StorageManager(addressBookStorage, calendarStorage, userPrefsStorage);
model = initModelManager(storage, userPrefs);
@@ -76,21 +82,37 @@ private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
logger.info("Using data file : " + storage.getAddressBookFilePath());
Optional addressBookOptional;
- ReadOnlyAddressBook initialData;
+ ReadOnlyAddressBook addressBookInitialData;
+ Optional calendarOptional;
+ ReadOnlyCalendar calendarInitialData;
+
try {
addressBookOptional = storage.readAddressBook();
if (!addressBookOptional.isPresent()) {
logger.info("Creating a new data file " + storage.getAddressBookFilePath()
+ " populated with a sample AddressBook.");
}
- initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
+ addressBookInitialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook);
+ } catch (DataLoadingException e) {
+ logger.warning("Data file at " + storage.getAddressBookFilePath() + " could not be loaded."
+ + " Will be starting with an empty AddressBook.");
+ addressBookInitialData = new AddressBook();
+ }
+
+ try {
+ calendarOptional = storage.readCalendar();
+ if (!calendarOptional.isPresent()) {
+ logger.info("Creating a new data file " + storage.getCalendarFilePath()
+ + " populated with a sample Calendar.");
+ }
+ calendarInitialData = calendarOptional.orElseGet(SampleCalendarUtil::getSampleCalendar);
} catch (DataLoadingException e) {
logger.warning("Data file at " + storage.getAddressBookFilePath() + " could not be loaded."
+ " Will be starting with an empty AddressBook.");
- initialData = new AddressBook();
+ calendarInitialData = new Calendar();
}
- return new ModelManager(initialData, userPrefs);
+ return new ModelManager(addressBookInitialData, calendarInitialData, userPrefs);
}
private void initLogging(Config config) {
diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java
index 670097ab93d..c7ec65cca22 100644
--- a/src/main/java/seedu/address/logic/LogicManager.java
+++ b/src/main/java/seedu/address/logic/LogicManager.java
@@ -52,6 +52,7 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
try {
storage.saveAddressBook(model.getAddressBook());
+ storage.saveCalendar(model.getCalendar());
} catch (AccessDeniedException e) {
throw new CommandException(String.format(FILE_OPS_PERMISSION_ERROR_FORMAT, e.getMessage()), e);
} catch (IOException ioe) {
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
index 2b684d7462d..5d9daa2c9f1 100644
--- a/src/main/java/seedu/address/model/Model.java
+++ b/src/main/java/seedu/address/model/Model.java
@@ -7,6 +7,7 @@
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
+import seedu.address.model.calendar.ReadOnlyCalendar;
import seedu.address.model.event.Event;
import seedu.address.model.event.exceptions.EventNotFoundException;
import seedu.address.model.person.Person;
@@ -56,6 +57,24 @@ public interface Model {
/** Returns the AddressBook */
ReadOnlyAddressBook getAddressBook();
+ /**
+ * Returns the user prefs' calendar file path.
+ */
+ Path getCalendarFilePath();
+
+ /**
+ * Sets the user prefs' calendar file path.
+ */
+ void setCalendarFilePath(Path calendarFilePath);
+
+ /**
+ * Replaces calendar data with the data in {@code calendar}.
+ */
+ void setCalendar(ReadOnlyCalendar calendar);
+
+ /** Returns the Calendar */
+ ReadOnlyCalendar getCalendar();
+
/**
* Returns true if a person with the same identity as {@code person} exists in the address book.
*/
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
index a86dda7f49c..51c669face0 100644
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ b/src/main/java/seedu/address/model/ModelManager.java
@@ -15,6 +15,7 @@
import seedu.address.commons.core.GuiSettings;
import seedu.address.commons.core.LogsCenter;
import seedu.address.model.calendar.Calendar;
+import seedu.address.model.calendar.ReadOnlyCalendar;
import seedu.address.model.event.Event;
import seedu.address.model.event.exceptions.EventNotFoundException;
import seedu.address.model.person.Person;
@@ -26,27 +27,26 @@ public class ModelManager implements Model {
private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
private final AddressBook addressBook;
+ private final Calendar calendar;
private final UserPrefs userPrefs;
private final FilteredList filteredPersons;
- private final Calendar calendar;
-
/**
- * Initializes a ModelManager with the given addressBook and userPrefs.
+ * Initializes a ModelManager with the given addressBook, calendar and userPrefs.
*/
- public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) {
+ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyCalendar calendar, ReadOnlyUserPrefs userPrefs) {
requireAllNonNull(addressBook, userPrefs);
logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs);
this.addressBook = new AddressBook(addressBook);
+ this.calendar = new Calendar(calendar);
this.userPrefs = new UserPrefs(userPrefs);
filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
- calendar = new Calendar();
}
public ModelManager() {
- this(new AddressBook(), new UserPrefs());
+ this(new AddressBook(), new Calendar(), new UserPrefs());
}
//=========== UserPrefs ==================================================================================
@@ -84,6 +84,16 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
userPrefs.setAddressBookFilePath(addressBookFilePath);
}
+ @Override
+ public Path getCalendarFilePath() {
+ return userPrefs.getCalendarFilePath();
+ }
+
+ @Override
+ public void setCalendarFilePath(Path calendarFilePath) {
+ requireNonNull(calendarFilePath);
+ userPrefs.setCalendarFilePath(calendarFilePath);
+ }
//=========== AddressBook ================================================================================
@@ -129,6 +139,17 @@ public void sortPersonList(Comparator personComparator) {
}
//=========== Calendar ===================================================================================
+
+ @Override
+ public void setCalendar(ReadOnlyCalendar calendar) {
+ this.calendar.resetData(calendar);
+ }
+
+ @Override
+ public ReadOnlyCalendar getCalendar() {
+ return calendar;
+ }
+
@Override
public boolean canAddEvent(Event event) {
return calendar.canAddEvent(event);
@@ -195,6 +216,7 @@ public boolean equals(Object other) {
ModelManager otherModelManager = (ModelManager) other;
return addressBook.equals(otherModelManager.addressBook)
+ && calendar.equals(otherModelManager.calendar)
&& userPrefs.equals(otherModelManager.userPrefs)
&& filteredPersons.equals(otherModelManager.filteredPersons);
}
diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java
index 6be655fb4c7..bcce5a4241d 100644
--- a/src/main/java/seedu/address/model/UserPrefs.java
+++ b/src/main/java/seedu/address/model/UserPrefs.java
@@ -15,6 +15,7 @@ public class UserPrefs implements ReadOnlyUserPrefs {
private GuiSettings guiSettings = new GuiSettings();
private Path addressBookFilePath = Paths.get("data" , "addressbook.json");
+ private Path calendarFilePath = Paths.get("data", "calendar.json");
/**
* Creates a {@code UserPrefs} with default values.
@@ -56,6 +57,15 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
this.addressBookFilePath = addressBookFilePath;
}
+ public Path getCalendarFilePath() {
+ return calendarFilePath;
+ }
+
+ public void setCalendarFilePath(Path calendarFilePath) {
+ requireNonNull(calendarFilePath);
+ this.calendarFilePath = calendarFilePath;
+ }
+
@Override
public boolean equals(Object other) {
if (other == this) {
diff --git a/src/main/java/seedu/address/model/calendar/Calendar.java b/src/main/java/seedu/address/model/calendar/Calendar.java
index 649daddbb15..aa984e1b846 100644
--- a/src/main/java/seedu/address/model/calendar/Calendar.java
+++ b/src/main/java/seedu/address/model/calendar/Calendar.java
@@ -3,15 +3,17 @@
import static java.util.Objects.requireNonNull;
import java.time.LocalDateTime;
+import java.util.List;
import java.util.Optional;
+import javafx.collections.ObservableList;
import seedu.address.model.event.AllDaysEventListManager;
import seedu.address.model.event.Event;
/**
* Represents a calendar that stores and manages events.
*/
-public class Calendar {
+public class Calendar implements ReadOnlyCalendar {
private final AllDaysEventListManager eventManager;
/**
@@ -21,6 +23,33 @@ public Calendar() {
this.eventManager = new AllDaysEventListManager();
}
+ /**
+ * Creates a Calendar using the Events in the {@code toBeCopied}
+ */
+ public Calendar(ReadOnlyCalendar toBeCopied) {
+ this();
+ resetData(toBeCopied);
+ }
+
+ //// overwrite operations
+
+ /**
+ * Replaces the contents of the Calendar with {@code events}.
+ * {@code events} must not contain duplicate events.
+ */
+ public void setEvents(List events) {
+ events.forEach(this::addEvent);
+ }
+
+ /**
+ * Resets the existing data of this {@code Calendar} with {@code newData}.
+ */
+ public void resetData(ReadOnlyCalendar newData) {
+ requireNonNull(newData);
+
+ setEvents(newData.getEventList());
+ }
+
/**
* Return the AllDaysEventListManager managing the events for this calendar.
*
@@ -107,6 +136,11 @@ public boolean hasEvents() {
return false;
}
+ @Override
+ public ObservableList getEventList() {
+ return eventManager.asUnmodifiableObservableList();
+ }
+
@Override
public boolean equals(Object other) {
if (this == other) {
diff --git a/src/main/java/seedu/address/model/ReadOnlyCalendar.java b/src/main/java/seedu/address/model/calendar/ReadOnlyCalendar.java
similarity index 89%
rename from src/main/java/seedu/address/model/ReadOnlyCalendar.java
rename to src/main/java/seedu/address/model/calendar/ReadOnlyCalendar.java
index 5ff8dc3593e..11ea85ef9e2 100644
--- a/src/main/java/seedu/address/model/ReadOnlyCalendar.java
+++ b/src/main/java/seedu/address/model/calendar/ReadOnlyCalendar.java
@@ -1,4 +1,4 @@
-package seedu.address.model;
+package seedu.address.model.calendar;
import javafx.collections.ObservableList;
import seedu.address.model.event.Event;
diff --git a/src/main/java/seedu/address/model/event/AllDaysEventListManager.java b/src/main/java/seedu/address/model/event/AllDaysEventListManager.java
index 6172f57f770..606c954e4f6 100644
--- a/src/main/java/seedu/address/model/event/AllDaysEventListManager.java
+++ b/src/main/java/seedu/address/model/event/AllDaysEventListManager.java
@@ -7,7 +7,10 @@
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.TreeMap;
+import java.util.stream.Collectors;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
import seedu.address.model.event.exceptions.EventNotFoundException;
/**
@@ -128,6 +131,17 @@ public boolean isEmpty() {
return this.dayToEventListMap.isEmpty();
}
+ /**
+ * Returns the event list as an unmodifiable {@code ObservableList}.
+ */
+ public ObservableList asUnmodifiableObservableList() {
+ List list = dayToEventListMap.values().stream()
+ .flatMap(singleDayEventList -> singleDayEventList.getDayEventList().stream())
+ .collect(Collectors.toList());
+
+ return FXCollections.observableList(list);
+ }
+
/**
* Checks if there are any events at all in the manager.
*
diff --git a/src/main/java/seedu/address/model/event/EventPeriod.java b/src/main/java/seedu/address/model/event/EventPeriod.java
index a0df2cc1e57..30608de1e15 100644
--- a/src/main/java/seedu/address/model/event/EventPeriod.java
+++ b/src/main/java/seedu/address/model/event/EventPeriod.java
@@ -129,6 +129,17 @@ public List getDates() {
return listOfDates;
}
+ /**
+ * Get the string representation of the EventPeriod.
+ *
+ * @return string representation of the period the eventPeriod spans.
+ */
+ public String getFormattedPeriod() {
+ String startString = start.format(DATE_TIME_STRING_FORMATTER);
+ String endString = end.format(DATE_TIME_STRING_FORMATTER);
+ return startString + " - " + endString;
+ }
+
@Override
public boolean equals(Object other) {
requireNonNull(other);
diff --git a/src/main/java/seedu/address/model/util/SampleCalendarUtil.java b/src/main/java/seedu/address/model/util/SampleCalendarUtil.java
new file mode 100644
index 00000000000..2f81fb20bcc
--- /dev/null
+++ b/src/main/java/seedu/address/model/util/SampleCalendarUtil.java
@@ -0,0 +1,32 @@
+package seedu.address.model.util;
+
+import seedu.address.model.calendar.Calendar;
+import seedu.address.model.calendar.ReadOnlyCalendar;
+import seedu.address.model.event.Event;
+import seedu.address.model.event.EventDescription;
+import seedu.address.model.event.EventPeriod;
+
+/**
+ * Contains utility methods for populating {@code Calendar} with sample data.
+ */
+public class SampleCalendarUtil {
+ public static Event[] getSampleEvents() {
+ return new Event[] {
+ new Event(new EventDescription("Weekly team meeting"),
+ new EventPeriod("2023-10-25 09:00", "2023-10-25 10:30")),
+ new Event(new EventDescription(" Annual health checkup"),
+ new EventPeriod("2023-11-10 15:15", "2023-11-10 16:00")),
+ new Event(new EventDescription(" Birthday celebration"),
+ new EventPeriod("2023-11-15 18:00", "2023-11-15 22:00"))
+ };
+ }
+
+ public static ReadOnlyCalendar getSampleCalendar() {
+ Calendar sampleCalendar = new Calendar();
+ for (Event sampleEvent : getSampleEvents()) {
+ sampleCalendar.addEvent(sampleEvent);
+ }
+ return sampleCalendar;
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/CalendarStorage.java b/src/main/java/seedu/address/storage/CalendarStorage.java
index 4040e35ab1c..2aa09aebb85 100644
--- a/src/main/java/seedu/address/storage/CalendarStorage.java
+++ b/src/main/java/seedu/address/storage/CalendarStorage.java
@@ -1,8 +1,45 @@
package seedu.address.storage;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import seedu.address.commons.exceptions.DataLoadingException;
+import seedu.address.model.calendar.ReadOnlyCalendar;
+
/**
* Represents a storage for the Calendar.
*/
public interface CalendarStorage {
+ /**
+ * Returns the file path of the data file.
+ */
+ Path getCalendarFilePath();
+
+ /**
+ * Returns AddressBook data as a {@link ReadOnlyCalendar}.
+ * Returns {@code Optional.empty()} if storage file is not found.
+ *
+ * @throws DataLoadingException if loading the data from storage failed.
+ */
+ Optional readCalendar() throws DataLoadingException;
+
+ /**
+ * @see #getCalendarFilePath()
+ */
+ Optional readCalendar(Path filePath) throws DataLoadingException;
+
+ /**
+ * Saves the given {@link ReadOnlyCalendar} to the storage.
+ * @param calendar cannot be null.
+ * @throws IOException if there was any problem writing to the file.
+ */
+ void saveCalendar(ReadOnlyCalendar calendar) throws IOException;
+
+ /**
+ * @see #saveCalendar(ReadOnlyCalendar)
+ */
+ void saveCalendar(ReadOnlyCalendar addressBook, Path filePath) throws IOException;
+
}
diff --git a/src/main/java/seedu/address/storage/JsonAdaptedEvent.java b/src/main/java/seedu/address/storage/JsonAdaptedEvent.java
new file mode 100644
index 00000000000..4e0a48e0cf6
--- /dev/null
+++ b/src/main/java/seedu/address/storage/JsonAdaptedEvent.java
@@ -0,0 +1,80 @@
+package seedu.address.storage;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.address.model.event.Event;
+import seedu.address.model.event.EventDescription;
+import seedu.address.model.event.EventPeriod;
+
+/**
+ * Jackson-friendly version of {@link Event}.
+ */
+class JsonAdaptedEvent {
+
+ public static final String MISSING_FIELD_MESSAGE_FORMAT = "Event's %s field is missing!";
+ public static final String INVALID_FIELD_MESSAGE_FORMAT = EventPeriod.MESSAGE_CONSTRAINTS;
+
+ private final String description;
+ private final String eventPeriod;
+
+ /**
+ * Constructs a {@code JsonAdaptedEvent} with the given event details.
+ */
+ @JsonCreator
+ public JsonAdaptedEvent(@JsonProperty("description") String description,
+ @JsonProperty("eventPeriod") String eventPeriod) {
+ this.description = description;
+ this.eventPeriod = eventPeriod;
+ }
+
+ /**
+ * Converts a given {@code Event} into this class for Jackson use.
+ */
+ public JsonAdaptedEvent(Event source) {
+ description = source.getDescription().getDescription();
+ eventPeriod = source.getEventPeriod().getFormattedPeriod();
+ }
+
+ /**
+ * Converts this Jackson-friendly adapted person object into the model's {@code Event} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated in the adapted event.
+ */
+ public Event toModelType() throws IllegalValueException {
+ if (description == null) {
+ throw new IllegalValueException(
+ String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ EventDescription.class.getSimpleName()));
+ }
+ if (!EventDescription.isValid(description)) {
+ throw new IllegalValueException(EventDescription.MESSAGE_CONSTRAINTS);
+ }
+ final EventDescription modelDescription = new EventDescription(description);
+
+ // Event Periods are expected to be saved in this format yyyy-MM-dd HH:mm - yyyy-MM-dd HH:mm
+ String start;
+ String end;
+ if (eventPeriod == null) {
+ throw new IllegalValueException(
+ String.format(MISSING_FIELD_MESSAGE_FORMAT,
+ EventPeriod.class.getSimpleName()));
+ }
+ String[] parts = eventPeriod.split(" - ");
+ if (parts.length == 2) {
+ start = parts[0];
+ end = parts[1];
+ } else {
+ throw new IllegalValueException(String.format(INVALID_FIELD_MESSAGE_FORMAT,
+ EventPeriod.class.getSimpleName()));
+ }
+ if (!EventPeriod.isValidPeriod(start, end)) {
+ throw new IllegalValueException(EventPeriod.MESSAGE_CONSTRAINTS);
+ }
+ final EventPeriod modelEventPeriod = new EventPeriod(start, end);
+
+ return new Event(modelDescription, modelEventPeriod);
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/JsonCalendarStorage.java b/src/main/java/seedu/address/storage/JsonCalendarStorage.java
new file mode 100644
index 00000000000..98405417432
--- /dev/null
+++ b/src/main/java/seedu/address/storage/JsonCalendarStorage.java
@@ -0,0 +1,80 @@
+package seedu.address.storage;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import seedu.address.commons.core.LogsCenter;
+import seedu.address.commons.exceptions.DataLoadingException;
+import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.address.commons.util.FileUtil;
+import seedu.address.commons.util.JsonUtil;
+import seedu.address.model.calendar.ReadOnlyCalendar;
+
+/**
+ * A class to access Calendar data stored as a json file on the hard disk.
+ */
+public class JsonCalendarStorage implements CalendarStorage {
+
+ private static final Logger logger = LogsCenter.getLogger(JsonCalendarStorage.class);
+
+ private Path filePath;
+
+ public JsonCalendarStorage(Path filePath) {
+ this.filePath = filePath;
+ }
+
+ public Path getCalendarFilePath() {
+ return filePath;
+ }
+
+ @Override
+ public Optional readCalendar() throws DataLoadingException {
+ return readCalendar(filePath);
+ }
+
+ /**
+ * Similar to {@link #readCalendar()}.
+ *
+ * @param filePath location of the data. Cannot be null.
+ * @throws DataLoadingException if loading the data from storage failed.
+ */
+ public Optional readCalendar(Path filePath) throws DataLoadingException {
+ requireNonNull(filePath);
+
+ Optional jsonCalendar = JsonUtil.readJsonFile(
+ filePath, JsonSerializableCalendar.class);
+ if (!jsonCalendar.isPresent()) {
+ return Optional.empty();
+ }
+
+ try {
+ return Optional.of(jsonCalendar.get().toModelType());
+ } catch (IllegalValueException ive) {
+ logger.info("Illegal values found in " + filePath + ": " + ive.getMessage());
+ throw new DataLoadingException(ive);
+ }
+ }
+
+ @Override
+ public void saveCalendar(ReadOnlyCalendar calendar) throws IOException {
+ saveCalendar(calendar, filePath);
+ }
+
+ /**
+ * Similar to {@link #saveCalendar(ReadOnlyCalendar)}.
+ *
+ * @param filePath location of the data. Cannot be null.
+ */
+ public void saveCalendar(ReadOnlyCalendar calendar, Path filePath) throws IOException {
+ requireNonNull(calendar);
+ requireNonNull(filePath);
+
+ FileUtil.createIfMissing(filePath);
+ JsonUtil.saveJsonFile(new JsonSerializableCalendar(calendar), filePath);
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/JsonSerializableCalendar.java b/src/main/java/seedu/address/storage/JsonSerializableCalendar.java
new file mode 100644
index 00000000000..2efbfba88cf
--- /dev/null
+++ b/src/main/java/seedu/address/storage/JsonSerializableCalendar.java
@@ -0,0 +1,59 @@
+package seedu.address.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonRootName;
+
+import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.address.model.calendar.Calendar;
+import seedu.address.model.calendar.ReadOnlyCalendar;
+import seedu.address.model.event.Event;
+
+/**
+ * An Immutable Calendar that is serializable to JSON format.
+ */
+@JsonRootName(value = "calendar")
+class JsonSerializableCalendar {
+ public static final String MESSAGE_DUPLICATE_EVENT = "Calendar contains duplicate event(s).";
+
+ private final List events = new ArrayList<>();
+
+ /**
+ * Constructs a {@code JsonSerializableCalendar} with the given events.
+ */
+ @JsonCreator
+ public JsonSerializableCalendar(@JsonProperty("events") List events) {
+ this.events.addAll(events);
+ }
+
+ /**
+ * Converts a given {@code ReadOnlyCalendar} into this class for Jackson use.
+ *
+ * @param source future changes to this will not affect the created {@code JsonSerializableCalendar}.
+ */
+ public JsonSerializableCalendar(ReadOnlyCalendar source) {
+ events.addAll(source.getEventList().stream().map(JsonAdaptedEvent::new).collect(Collectors.toList()));
+ }
+
+ /**
+ * Converts this address book into the model's {@code AddressBook} object.
+ *
+ * @throws IllegalValueException if there were any data constraints violated.
+ */
+ public Calendar toModelType() throws IllegalValueException {
+ Calendar calendar = new Calendar();
+ for (JsonAdaptedEvent jsonAdaptedEvent : events) {
+ Event event = jsonAdaptedEvent.toModelType();
+ if (calendar.contains(event)) {
+ throw new IllegalValueException(MESSAGE_DUPLICATE_EVENT);
+ }
+ calendar.addEvent(event);
+ }
+ return calendar;
+ }
+
+}
diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java
index 9fba0c7a1d6..e385559b189 100644
--- a/src/main/java/seedu/address/storage/Storage.java
+++ b/src/main/java/seedu/address/storage/Storage.java
@@ -8,11 +8,12 @@
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.UserPrefs;
+import seedu.address.model.calendar.ReadOnlyCalendar;
/**
* API of the Storage component
*/
-public interface Storage extends AddressBookStorage, UserPrefsStorage {
+public interface Storage extends AddressBookStorage, CalendarStorage, UserPrefsStorage {
@Override
Optional readUserPrefs() throws DataLoadingException;
@@ -29,4 +30,10 @@ public interface Storage extends AddressBookStorage, UserPrefsStorage {
@Override
void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException;
+ @Override
+ Optional readCalendar() throws DataLoadingException;
+
+ @Override
+ void saveCalendar(ReadOnlyCalendar calendar) throws IOException;
+
}
diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java
index 94bf0589c16..40ee593fa9d 100644
--- a/src/main/java/seedu/address/storage/StorageManager.java
+++ b/src/main/java/seedu/address/storage/StorageManager.java
@@ -10,6 +10,7 @@
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.UserPrefs;
+import seedu.address.model.calendar.ReadOnlyCalendar;
/**
* Manages storage of AddressBook data in local storage.
@@ -18,13 +19,17 @@ public class StorageManager implements Storage {
private static final Logger logger = LogsCenter.getLogger(StorageManager.class);
private AddressBookStorage addressBookStorage;
+ private CalendarStorage calendarStorage;
private UserPrefsStorage userPrefsStorage;
/**
* Creates a {@code StorageManager} with the given {@code AddressBookStorage} and {@code UserPrefStorage}.
*/
- public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) {
+ public StorageManager(AddressBookStorage addressBookStorage,
+ CalendarStorage calendarStorage,
+ UserPrefsStorage userPrefsStorage) {
this.addressBookStorage = addressBookStorage;
+ this.calendarStorage = calendarStorage;
this.userPrefsStorage = userPrefsStorage;
}
@@ -75,6 +80,31 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) thro
}
// ================ Calendar methods =================================
+ @Override
+ public Path getCalendarFilePath() {
+ return addressBookStorage.getAddressBookFilePath();
+ }
+
+ @Override
+ public Optional readCalendar() throws DataLoadingException {
+ return readCalendar(calendarStorage.getCalendarFilePath());
+ }
+
+ @Override
+ public Optional readCalendar(Path filePath) throws DataLoadingException {
+ logger.fine("Attempting to read data from file: " + filePath);
+ return calendarStorage.readCalendar(filePath);
+ }
+
+ @Override
+ public void saveCalendar(ReadOnlyCalendar calendar) throws IOException {
+ saveCalendar(calendar, calendarStorage.getCalendarFilePath());
+ }
+ @Override
+ public void saveCalendar(ReadOnlyCalendar calendar, Path filePath) throws IOException {
+ logger.fine("Attempting to write to data file: " + filePath);
+ calendarStorage.saveCalendar(calendar, filePath);
+ }
}
diff --git a/src/test/data/JsonCalendarStorageTest/invalidAndValidEventCalendar.json b/src/test/data/JsonCalendarStorageTest/invalidAndValidEventCalendar.json
new file mode 100644
index 00000000000..04c0664eb31
--- /dev/null
+++ b/src/test/data/JsonCalendarStorageTest/invalidAndValidEventCalendar.json
@@ -0,0 +1,9 @@
+{
+ "events" : [ {
+ "description" : "Valid",
+ "eventPeriod" : "2023-10-25 09:00 - 2023-10-25 10:30"
+ }, {
+ "description" : "",
+ "eventPeriod" : "2023-11-10 15:15 - 2023-11-10 16:00"
+ } ]
+}
diff --git a/src/test/data/JsonCalendarStorageTest/invalidEventCalendar.json b/src/test/data/JsonCalendarStorageTest/invalidEventCalendar.json
new file mode 100644
index 00000000000..c0c2b747ab8
--- /dev/null
+++ b/src/test/data/JsonCalendarStorageTest/invalidEventCalendar.json
@@ -0,0 +1,6 @@
+{
+ "events" : [ {
+ "description" : "",
+ "eventPeriod" : "2023-10-25 09:00 - 2023-10-25 10:30"
+ } ]
+}
diff --git a/src/test/data/JsonCalendarStorageTest/notJsonFormatCalendar.json b/src/test/data/JsonCalendarStorageTest/notJsonFormatCalendar.json
new file mode 100644
index 00000000000..a1097343b5d
--- /dev/null
+++ b/src/test/data/JsonCalendarStorageTest/notJsonFormatCalendar.json
@@ -0,0 +1 @@
+not json format!
diff --git a/src/test/data/JsonSerializableCalendarTest/duplicateEventCalendar.json b/src/test/data/JsonSerializableCalendarTest/duplicateEventCalendar.json
new file mode 100644
index 00000000000..24bcb850430
--- /dev/null
+++ b/src/test/data/JsonSerializableCalendarTest/duplicateEventCalendar.json
@@ -0,0 +1,9 @@
+{
+ "events" : [ {
+ "description" : "Weekly team meeting",
+ "eventPeriod" : "2023-10-25 09:00 - 2023-10-25 10:30"
+ }, {
+ "description" : "Weekly team meeting",
+ "eventPeriod" : "2023-10-25 09:00 - 2023-10-25 10:30"
+ } ]
+}
diff --git a/src/test/data/JsonSerializableCalendarTest/invalidEventCalendar.json b/src/test/data/JsonSerializableCalendarTest/invalidEventCalendar.json
new file mode 100644
index 00000000000..c0c2b747ab8
--- /dev/null
+++ b/src/test/data/JsonSerializableCalendarTest/invalidEventCalendar.json
@@ -0,0 +1,6 @@
+{
+ "events" : [ {
+ "description" : "",
+ "eventPeriod" : "2023-10-25 09:00 - 2023-10-25 10:30"
+ } ]
+}
diff --git a/src/test/data/JsonSerializableCalendarTest/typicalEventsCalendar.json b/src/test/data/JsonSerializableCalendarTest/typicalEventsCalendar.json
new file mode 100644
index 00000000000..67acc329e62
--- /dev/null
+++ b/src/test/data/JsonSerializableCalendarTest/typicalEventsCalendar.json
@@ -0,0 +1,19 @@
+{
+ "_comment": "Calendar save file which contains the same Event values as in TypicalEvents#getTypicalCalendar()",
+ "events" : [ {
+ "description" : "Conference",
+ "eventPeriod" : "2023-11-15 08:30 - 2023-11-15 17:00"
+ }, {
+ "description" : "Launch and Marketing Strategy Discussion",
+ "eventPeriod" : "2023-12-05 10:00 - 2023-12-05 12:00"
+ }, {
+ "description" : "Team Meeting",
+ "eventPeriod" : "2023-10-25 09:00 - 2023-10-25 10:30"
+ }, {
+ "description" : "Webinar",
+ "eventPeriod" : "2023-10-30 15:00 - 2023-10-30 16:30"
+ }, {
+ "description" : "Workshop",
+ "eventPeriod" : "2023-11-10 14:00 - 2023-11-10 16:30"
+ } ]
+}
diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java
index baf8ce336a2..ef217781bc4 100644
--- a/src/test/java/seedu/address/logic/LogicManagerTest.java
+++ b/src/test/java/seedu/address/logic/LogicManagerTest.java
@@ -29,6 +29,7 @@
import seedu.address.model.UserPrefs;
import seedu.address.model.person.Person;
import seedu.address.storage.JsonAddressBookStorage;
+import seedu.address.storage.JsonCalendarStorage;
import seedu.address.storage.JsonUserPrefsStorage;
import seedu.address.storage.StorageManager;
import seedu.address.testutil.PersonBuilder;
@@ -47,8 +48,9 @@ public class LogicManagerTest {
public void setUp() {
JsonAddressBookStorage addressBookStorage =
new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json"));
+ JsonCalendarStorage calendarStorage = new JsonCalendarStorage(temporaryFolder.resolve("calendar.json"));
JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json"));
- StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ StorageManager storage = new StorageManager(addressBookStorage, calendarStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
}
@@ -123,7 +125,7 @@ private void assertCommandException(String inputCommand, String expectedMessage)
*/
private void assertCommandFailure(String inputCommand, Class extends Throwable> expectedException,
String expectedMessage) {
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ Model expectedModel = new ModelManager(model.getAddressBook(), model.getCalendar(), new UserPrefs());
assertCommandFailure(inputCommand, expectedException, expectedMessage, expectedModel);
}
@@ -141,7 +143,8 @@ private void assertCommandFailure(String inputCommand, Class extends Throwable
}
/**
- * Tests the Logic component's handling of an {@code IOException} thrown by the Storage component.
+ * Tests the Logic component's handling of an {@code IOException} thrown by the Storage component
+ * when saving an AddressBook.
*
* @param e the exception to be thrown by the Storage component
* @param expectedMessage the message expected inside exception thrown by the Logic component
@@ -158,9 +161,11 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath)
}
};
+ JsonCalendarStorage calendarStorage =
+ new JsonCalendarStorage(temporaryFolder.resolve("ExceptionCalendar.json"));
JsonUserPrefsStorage userPrefsStorage =
new JsonUserPrefsStorage(temporaryFolder.resolve("ExceptionUserPrefs.json"));
- StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage);
+ StorageManager storage = new StorageManager(addressBookStorage, calendarStorage, userPrefsStorage);
logic = new LogicManager(model, storage);
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
index 162a0c86031..ddba00d5ed8 100644
--- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
+++ b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java
@@ -2,6 +2,7 @@
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
import org.junit.jupiter.api.BeforeEach;
@@ -23,14 +24,14 @@ public class AddCommandIntegrationTest {
@BeforeEach
public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ model = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
}
@Test
public void execute_newPerson_success() {
Person validPerson = new PersonBuilder().build();
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ Model expectedModel = new ModelManager(model.getAddressBook(), model.getCalendar(), new UserPrefs());
expectedModel.addPerson(validPerson);
assertCommandSuccess(new AddCommand(validPerson), model,
diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java
index 92285aafac7..306e96dcc4a 100644
--- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java
@@ -24,6 +24,7 @@
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.calendar.ReadOnlyCalendar;
import seedu.address.model.event.Event;
import seedu.address.model.event.exceptions.EventNotFoundException;
import seedu.address.model.person.Person;
@@ -122,6 +123,16 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public Path getCalendarFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setCalendarFilePath(Path addressBookFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
@Override
public void addPerson(Person person) {
throw new AssertionError("This method should not be called.");
@@ -137,6 +148,16 @@ public ReadOnlyAddressBook getAddressBook() {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public void setCalendar(ReadOnlyCalendar newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyCalendar getCalendar() {
+ throw new AssertionError("This method should not be called.");
+ }
+
@Override
public boolean hasPerson(Person person) {
throw new AssertionError("This method should not be called.");
diff --git a/src/test/java/seedu/address/logic/commands/AddEventCommandTest.java b/src/test/java/seedu/address/logic/commands/AddEventCommandTest.java
index 60ed8dada2a..de782973115 100644
--- a/src/test/java/seedu/address/logic/commands/AddEventCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/AddEventCommandTest.java
@@ -20,6 +20,7 @@
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.calendar.ReadOnlyCalendar;
import seedu.address.model.event.Event;
import seedu.address.model.event.exceptions.EventNotFoundException;
import seedu.address.model.person.Person;
@@ -86,6 +87,16 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public Path getCalendarFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setCalendarFilePath(Path addressBookFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
@Override
public void addPerson(Person person) {
throw new AssertionError("This method should not be called.");
@@ -101,6 +112,16 @@ public ReadOnlyAddressBook getAddressBook() {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public void setCalendar(ReadOnlyCalendar newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyCalendar getCalendar() {
+ throw new AssertionError("This method should not be called.");
+ }
+
@Override
public boolean hasPerson(Person person) {
throw new AssertionError("This method should not be called.");
diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
index 80d9110c03a..e46c6ffa36c 100644
--- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java
@@ -1,6 +1,7 @@
package seedu.address.logic.commands;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
import org.junit.jupiter.api.Test;
@@ -22,8 +23,8 @@ public void execute_emptyAddressBook_success() {
@Test
public void execute_nonEmptyAddressBook_success() {
- Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ Model model = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
+ Model expectedModel = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
expectedModel.setAddressBook(new AddressBook());
assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel);
diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
index b6f332eabca..e8a966b7bad 100644
--- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java
@@ -6,6 +6,7 @@
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
@@ -25,7 +26,7 @@
*/
public class DeleteCommandTest {
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model model = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
@Test
public void execute_validIndexUnfilteredList_success() {
@@ -35,7 +36,7 @@ public void execute_validIndexUnfilteredList_success() {
String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS,
Messages.format(personToDelete));
- ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ ModelManager expectedModel = new ModelManager(model.getAddressBook(), model.getCalendar(), new UserPrefs());
expectedModel.deletePerson(personToDelete);
assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel);
@@ -59,7 +60,7 @@ public void execute_validIndexFilteredList_success() {
String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS,
Messages.format(personToDelete));
- Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ Model expectedModel = new ModelManager(model.getAddressBook(), model.getCalendar(), new UserPrefs());
expectedModel.deletePerson(personToDelete);
showNoPerson(expectedModel);
diff --git a/src/test/java/seedu/address/logic/commands/DeleteEventCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteEventCommandTest.java
index c6ba85ee70e..8d7a47e7273 100644
--- a/src/test/java/seedu/address/logic/commands/DeleteEventCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/DeleteEventCommandTest.java
@@ -23,6 +23,7 @@
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
+import seedu.address.model.calendar.ReadOnlyCalendar;
import seedu.address.model.event.Event;
import seedu.address.model.event.exceptions.EventNotFoundException;
import seedu.address.model.person.Person;
@@ -118,6 +119,16 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public Path getCalendarFilePath() {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public void setCalendarFilePath(Path addressBookFilePath) {
+ throw new AssertionError("This method should not be called.");
+ }
+
@Override
public void addPerson(Person person) {
throw new AssertionError("This method should not be called.");
@@ -133,6 +144,16 @@ public ReadOnlyAddressBook getAddressBook() {
throw new AssertionError("This method should not be called.");
}
+ @Override
+ public void setCalendar(ReadOnlyCalendar newData) {
+ throw new AssertionError("This method should not be called.");
+ }
+
+ @Override
+ public ReadOnlyCalendar getCalendar() {
+ throw new AssertionError("This method should not be called.");
+ }
+
@Override
public boolean hasPerson(Person person) {
throw new AssertionError("This method should not be called.");
diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
index 469dd97daa7..3f25408a13d 100644
--- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java
@@ -11,6 +11,7 @@
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
@@ -33,7 +34,7 @@
*/
public class EditCommandTest {
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model model = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
@Test
public void execute_allFieldsSpecifiedUnfilteredList_success() {
@@ -43,7 +44,8 @@ public void execute_allFieldsSpecifiedUnfilteredList_success() {
String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()),
+ model.getCalendar(), new UserPrefs());
expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
@@ -64,7 +66,8 @@ public void execute_someFieldsSpecifiedUnfilteredList_success() {
String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()),
+ model.getCalendar(), new UserPrefs());
expectedModel.setPerson(lastPerson, editedPerson);
assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
@@ -77,7 +80,8 @@ public void execute_noFieldSpecifiedUnfilteredList_success() {
String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()),
+ model.getCalendar(), new UserPrefs());
assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
}
@@ -93,7 +97,8 @@ public void execute_filteredList_success() {
String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()),
+ model.getCalendar(), new UserPrefs());
expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson);
assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
diff --git a/src/test/java/seedu/address/logic/commands/FilterCommandTest.java b/src/test/java/seedu/address/logic/commands/FilterCommandTest.java
index 54ebc90ddd6..b81752298f8 100644
--- a/src/test/java/seedu/address/logic/commands/FilterCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/FilterCommandTest.java
@@ -7,6 +7,7 @@
import static seedu.address.logic.commands.CommandTestUtil.FILTER_AMY;
import static seedu.address.logic.commands.CommandTestUtil.FILTER_BOB;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalPersons.CARL;
import static seedu.address.testutil.TypicalPersons.ELLE;
import static seedu.address.testutil.TypicalPersons.FIONA;
@@ -27,8 +28,8 @@
*/
class FilterCommandTest {
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model model = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
@Test
public void execute_oneField_multiplePersonsDisplayed() {
diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
index b8b7dbba91a..e2b8787c515 100644
--- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java
@@ -5,6 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalPersons.CARL;
import static seedu.address.testutil.TypicalPersons.ELLE;
import static seedu.address.testutil.TypicalPersons.FIONA;
@@ -24,8 +25,8 @@
* Contains integration tests (interaction with the Model) for {@code FindCommand}.
*/
public class FindCommandTest {
- private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model model = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
@Test
public void equals() {
diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java
index 435ff1f7275..41cb6924e8d 100644
--- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java
@@ -2,6 +2,7 @@
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
@@ -22,8 +23,8 @@ public class ListCommandTest {
@BeforeEach
public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ model = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
+ expectedModel = new ModelManager(model.getAddressBook(), model.getCalendar(), new UserPrefs());
}
@Test
diff --git a/src/test/java/seedu/address/logic/commands/SortCommandTest.java b/src/test/java/seedu/address/logic/commands/SortCommandTest.java
index 39159d64e85..477bb05bd35 100644
--- a/src/test/java/seedu/address/logic/commands/SortCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/SortCommandTest.java
@@ -2,6 +2,7 @@
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
import static seedu.address.testutil.TypicalPersons.getTypicalUnsortedAddressBook;
@@ -25,10 +26,10 @@ public class SortCommandTest {
@BeforeEach
public void setUp() {
- model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
- expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
- unsortedModel = new ModelManager(getTypicalUnsortedAddressBook(), new UserPrefs());
- expectedSortedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ model = new ModelManager(getTypicalAddressBook(), getTypicalCalendar(), new UserPrefs());
+ expectedModel = new ModelManager(model.getAddressBook(), getTypicalCalendar(), new UserPrefs());
+ unsortedModel = new ModelManager(getTypicalUnsortedAddressBook(), getTypicalCalendar(), new UserPrefs());
+ expectedSortedModel = new ModelManager(model.getAddressBook(), getTypicalCalendar(), new UserPrefs());
}
@Test
diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java
index 926a06de475..0eac5ff8a23 100644
--- a/src/test/java/seedu/address/model/ModelManagerTest.java
+++ b/src/test/java/seedu/address/model/ModelManagerTest.java
@@ -7,6 +7,8 @@
import static seedu.address.model.event.EventPeriod.DATE_TIME_STRING_FORMATTER;
import static seedu.address.testutil.Assert.assertThrows;
import static seedu.address.testutil.EventBuilder.DEFAULT_START_TIME_STRING;
+import static seedu.address.testutil.TypicalEvents.TEST_EVENT_A;
+import static seedu.address.testutil.TypicalEvents.TEST_EVENT_B;
import static seedu.address.testutil.TypicalPersons.ALICE;
import static seedu.address.testutil.TypicalPersons.BENSON;
@@ -18,9 +20,11 @@
import org.junit.jupiter.api.Test;
import seedu.address.commons.core.GuiSettings;
+import seedu.address.model.calendar.Calendar;
import seedu.address.model.event.exceptions.EventNotFoundException;
import seedu.address.model.person.NameContainsKeywordsPredicate;
import seedu.address.testutil.AddressBookBuilder;
+import seedu.address.testutil.CalendarBuilder;
public class ModelManagerTest {
@@ -76,6 +80,18 @@ public void setAddressBookFilePath_validPath_setsAddressBookFilePath() {
assertEquals(path, modelManager.getAddressBookFilePath());
}
+ @Test
+ public void setCalendarFilePath_nullPath_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> modelManager.setCalendarFilePath(null));
+ }
+
+ @Test
+ public void setCalendarFilePath_validPath_setsAddressBookFilePath() {
+ Path path = Paths.get("calendar/file/path");
+ modelManager.setCalendarFilePath(path);
+ assertEquals(path, modelManager.getCalendarFilePath());
+ }
+
@Test
public void hasPerson_nullPerson_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> modelManager.hasPerson(null));
@@ -122,11 +138,13 @@ public void findEvent_throwsEventNotFoundException() {
public void equals() {
AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build();
AddressBook differentAddressBook = new AddressBook();
+ Calendar calendar = new CalendarBuilder().withEvent(TEST_EVENT_A).withEvent(TEST_EVENT_B).build();
+ Calendar differentCalendar = new Calendar();
UserPrefs userPrefs = new UserPrefs();
// same values -> returns true
- modelManager = new ModelManager(addressBook, userPrefs);
- ModelManager modelManagerCopy = new ModelManager(addressBook, userPrefs);
+ modelManager = new ModelManager(addressBook, calendar, userPrefs);
+ ModelManager modelManagerCopy = new ModelManager(addressBook, calendar, userPrefs);
assertTrue(modelManager.equals(modelManagerCopy));
// same object -> returns true
@@ -138,13 +156,19 @@ public void equals() {
// different types -> returns false
assertFalse(modelManager.equals(5));
- // different addressBook -> returns false
- assertFalse(modelManager.equals(new ModelManager(differentAddressBook, userPrefs)));
+ // different addressBook, same calendar -> returns false
+ assertFalse(modelManager.equals(new ModelManager(differentAddressBook, calendar, userPrefs)));
+
+ // same addressBook, different calendar -> returns false
+ assertFalse(modelManager.equals(new ModelManager(addressBook, differentCalendar, userPrefs)));
+
+ // different addressBook, different calendar -> returns false
+ assertFalse(modelManager.equals(new ModelManager(differentAddressBook, differentCalendar, userPrefs)));
// different filteredList -> returns false
String[] keywords = ALICE.getName().fullName.split("\\s+");
modelManager.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(keywords)));
- assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs)));
+ assertFalse(modelManager.equals(new ModelManager(addressBook, calendar, userPrefs)));
// resets modelManager to initial state for upcoming tests
modelManager.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
@@ -152,6 +176,6 @@ public void equals() {
// different userPrefs -> returns false
UserPrefs differentUserPrefs = new UserPrefs();
differentUserPrefs.setAddressBookFilePath(Paths.get("differentFilePath"));
- assertFalse(modelManager.equals(new ModelManager(addressBook, differentUserPrefs)));
+ assertFalse(modelManager.equals(new ModelManager(addressBook, calendar, differentUserPrefs)));
}
}
diff --git a/src/test/java/seedu/address/model/UserPrefsTest.java b/src/test/java/seedu/address/model/UserPrefsTest.java
index b1307a70d52..c6fcb85ac5f 100644
--- a/src/test/java/seedu/address/model/UserPrefsTest.java
+++ b/src/test/java/seedu/address/model/UserPrefsTest.java
@@ -18,4 +18,10 @@ public void setAddressBookFilePath_nullPath_throwsNullPointerException() {
assertThrows(NullPointerException.class, () -> userPrefs.setAddressBookFilePath(null));
}
+ @Test
+ public void setCalendarFilePath_nullPath_throwsNullPointerException() {
+ UserPrefs userPrefs = new UserPrefs();
+ assertThrows(NullPointerException.class, () -> userPrefs.setCalendarFilePath(null));
+ }
+
}
diff --git a/src/test/java/seedu/address/storage/JsonAdaptedEventTest.java b/src/test/java/seedu/address/storage/JsonAdaptedEventTest.java
new file mode 100644
index 00000000000..d72faddee7f
--- /dev/null
+++ b/src/test/java/seedu/address/storage/JsonAdaptedEventTest.java
@@ -0,0 +1,57 @@
+package seedu.address.storage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.storage.JsonAdaptedEvent.MISSING_FIELD_MESSAGE_FORMAT;
+import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.address.testutil.TypicalEvents.CONFERENCE;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.address.model.event.EventDescription;
+import seedu.address.model.event.EventPeriod;
+
+public class JsonAdaptedEventTest {
+ private static final String INVALID_DESCRIPTION = "";
+ private static final String INVALID_EVENT_PERIOD = "2010-10-10 10:00-2010-10-10 12:00";
+
+ private static final String VALID_DESCRIPTION = CONFERENCE.getDescription().getDescription();
+ private static final String VALID_EVENT_PERIOD = CONFERENCE.getEventPeriod().getFormattedPeriod();
+
+ @Test
+ public void toModelType_validEventDetails_returnsEvent() throws Exception {
+ JsonAdaptedEvent event = new JsonAdaptedEvent(CONFERENCE);
+ assertEquals(CONFERENCE, event.toModelType());
+ }
+
+ @Test
+ public void toModelType_invalidDescription_throwsIllegalValueException() {
+ JsonAdaptedEvent event =
+ new JsonAdaptedEvent(INVALID_DESCRIPTION, VALID_EVENT_PERIOD);
+ String expectedMessage = EventDescription.MESSAGE_CONSTRAINTS;
+ assertThrows(IllegalValueException.class, expectedMessage, event::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullDescription_throwsIllegalValueException() {
+ JsonAdaptedEvent event = new JsonAdaptedEvent(null, VALID_EVENT_PERIOD);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, EventDescription.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, event::toModelType);
+ }
+
+ @Test
+ public void toModelType_invalidEventPeriod_throwsIllegalValueException() {
+ JsonAdaptedEvent event =
+ new JsonAdaptedEvent(VALID_DESCRIPTION, INVALID_EVENT_PERIOD);
+ String expectedMessage = EventPeriod.MESSAGE_CONSTRAINTS;
+ assertThrows(IllegalValueException.class, expectedMessage, event::toModelType);
+ }
+
+ @Test
+ public void toModelType_nullEventPeriod_throwsIllegalValueException() {
+ JsonAdaptedEvent event = new JsonAdaptedEvent(VALID_DESCRIPTION, null);
+ String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, EventPeriod.class.getSimpleName());
+ assertThrows(IllegalValueException.class, expectedMessage, event::toModelType);
+ }
+
+}
diff --git a/src/test/java/seedu/address/storage/JsonCalendarStorageTest.java b/src/test/java/seedu/address/storage/JsonCalendarStorageTest.java
new file mode 100644
index 00000000000..67abe5c5974
--- /dev/null
+++ b/src/test/java/seedu/address/storage/JsonCalendarStorageTest.java
@@ -0,0 +1,108 @@
+package seedu.address.storage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.address.testutil.TypicalEvents.REVIEW;
+import static seedu.address.testutil.TypicalEvents.TRAINING;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import seedu.address.commons.exceptions.DataLoadingException;
+import seedu.address.model.calendar.Calendar;
+import seedu.address.model.calendar.ReadOnlyCalendar;
+
+public class JsonCalendarStorageTest {
+ private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonCalendarStorageTest");
+
+ @TempDir
+ public Path testFolder;
+
+ @Test
+ public void readCalendar_nullFilePath_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> readCalendar(null));
+ }
+
+ private java.util.Optional readCalendar(String filePath) throws Exception {
+ return new JsonCalendarStorage(Paths.get(filePath)).readCalendar(addToTestDataPathIfNotNull(filePath));
+ }
+
+ private Path addToTestDataPathIfNotNull(String prefsFileInTestDataFolder) {
+ return prefsFileInTestDataFolder != null
+ ? TEST_DATA_FOLDER.resolve(prefsFileInTestDataFolder)
+ : null;
+ }
+
+ @Test
+ public void read_missingFile_emptyResult() throws Exception {
+ assertFalse(readCalendar("NonExistentFile.json").isPresent());
+ }
+
+ @Test
+ public void read_notJsonFormat_exceptionThrown() {
+ assertThrows(DataLoadingException.class, () -> readCalendar("notJsonFormatCalendar.json"));
+ }
+
+ @Test
+ public void readCalendar_invalidEventCalendar_throwDataLoadingException() {
+ assertThrows(DataLoadingException.class, () -> readCalendar("invalidEventCalendar.json"));
+ }
+
+ @Test
+ public void readAddressBook_invalidAndValidEventCalendar_throwDataLoadingException() {
+ assertThrows(DataLoadingException.class, () -> readCalendar("invalidAndValidEventCalendar.json"));
+ }
+
+ @Test
+ public void readAndSaveCalendar_allInOrder_success() throws Exception {
+ Path filePath = testFolder.resolve("TempCalendar.json");
+ Calendar original = getTypicalCalendar();
+ JsonCalendarStorage jsonCalendarStorage = new JsonCalendarStorage(filePath);
+
+ // Save in new file and read back
+ jsonCalendarStorage.saveCalendar(original, filePath);
+ ReadOnlyCalendar readBack = jsonCalendarStorage.readCalendar(filePath).get();
+ assertEquals(original, new Calendar(readBack));
+
+ // Modify data, overwrite exiting file, and read back
+ original.addEvent(TRAINING);
+ jsonCalendarStorage.saveCalendar(original, filePath);
+ readBack = jsonCalendarStorage.readCalendar(filePath).get();
+ assertEquals(original, new Calendar(readBack));
+
+ // Save and read without specifying file path
+ original.addEvent(REVIEW);
+ jsonCalendarStorage.saveCalendar(original); // file path not specified
+ readBack = jsonCalendarStorage.readCalendar().get(); // file path not specified
+ assertEquals(original, new Calendar(readBack));
+
+ }
+
+ @Test
+ public void saveCalendar_nullCalendar_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> saveCalendar(null, "SomeFile.json"));
+ }
+
+ /**
+ * Saves {@code calendar} at the specified {@code filePath}.
+ */
+ private void saveCalendar(ReadOnlyCalendar calendar, String filePath) {
+ try {
+ new JsonCalendarStorage(Paths.get(filePath))
+ .saveCalendar(calendar, addToTestDataPathIfNotNull(filePath));
+ } catch (IOException ioe) {
+ throw new AssertionError("There should not be an error writing to the file.", ioe);
+ }
+ }
+
+ @Test
+ public void saveAddressBook_nullFilePath_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> saveCalendar(new Calendar(), null));
+ }
+}
diff --git a/src/test/java/seedu/address/storage/JsonSerializableCalendarTest.java b/src/test/java/seedu/address/storage/JsonSerializableCalendarTest.java
new file mode 100644
index 00000000000..e3025a22413
--- /dev/null
+++ b/src/test/java/seedu/address/storage/JsonSerializableCalendarTest.java
@@ -0,0 +1,47 @@
+package seedu.address.storage;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.testutil.Assert.assertThrows;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.exceptions.IllegalValueException;
+import seedu.address.commons.util.JsonUtil;
+import seedu.address.model.calendar.Calendar;
+import seedu.address.testutil.TypicalEvents;
+
+public class JsonSerializableCalendarTest {
+
+ private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonSerializableCalendarTest");
+ private static final Path TYPICAL_EVENTS_FILE = TEST_DATA_FOLDER.resolve("typicalEventsCalendar.json");
+ private static final Path INVALID_EVENT_FILE = TEST_DATA_FOLDER.resolve("invalidEventCalendar.json");
+ private static final Path DUPLICATE_EVENT_FILE = TEST_DATA_FOLDER.resolve("duplicateEventCalendar.json");
+
+ @Test
+ public void toModelType_typicalEventsFile_success() throws Exception {
+ JsonSerializableCalendar dataFromFile = JsonUtil.readJsonFile(TYPICAL_EVENTS_FILE,
+ JsonSerializableCalendar.class).get();
+ Calendar calendarFromFile = dataFromFile.toModelType();
+ Calendar typicalEventsCalendar = TypicalEvents.getTypicalCalendar();
+ assertEquals(calendarFromFile, typicalEventsCalendar);
+ }
+
+ @Test
+ public void toModelType_invalidEventFile_throwsIllegalValueException() throws Exception {
+ JsonSerializableCalendar dataFromFile = JsonUtil.readJsonFile(INVALID_EVENT_FILE,
+ JsonSerializableCalendar.class).get();
+ assertThrows(IllegalValueException.class, dataFromFile::toModelType);
+ }
+
+ @Test
+ public void toModelType_duplicateEvents_throwsIllegalValueException() throws Exception {
+ JsonSerializableCalendar dataFromFile = JsonUtil.readJsonFile(DUPLICATE_EVENT_FILE,
+ JsonSerializableCalendar.class).get();
+ assertThrows(IllegalValueException.class, JsonSerializableCalendar.MESSAGE_DUPLICATE_EVENT,
+ dataFromFile::toModelType);
+ }
+
+}
diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/seedu/address/storage/StorageManagerTest.java
index 99a16548970..143c225aae5 100644
--- a/src/test/java/seedu/address/storage/StorageManagerTest.java
+++ b/src/test/java/seedu/address/storage/StorageManagerTest.java
@@ -2,6 +2,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static seedu.address.testutil.TypicalEvents.getTypicalCalendar;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
import java.nio.file.Path;
@@ -14,6 +15,8 @@
import seedu.address.model.AddressBook;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.UserPrefs;
+import seedu.address.model.calendar.Calendar;
+import seedu.address.model.calendar.ReadOnlyCalendar;
public class StorageManagerTest {
@@ -25,8 +28,9 @@ public class StorageManagerTest {
@BeforeEach
public void setUp() {
JsonAddressBookStorage addressBookStorage = new JsonAddressBookStorage(getTempFilePath("ab"));
+ JsonCalendarStorage calendarStorage = new JsonCalendarStorage(getTempFilePath("calendar"));
JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(getTempFilePath("prefs"));
- storageManager = new StorageManager(addressBookStorage, userPrefsStorage);
+ storageManager = new StorageManager(addressBookStorage, calendarStorage, userPrefsStorage);
}
private Path getTempFilePath(String fileName) {
@@ -60,9 +64,32 @@ public void addressBookReadSave() throws Exception {
assertEquals(original, new AddressBook(retrieved));
}
+ @Test
+ public void calendarReadSave() throws Exception {
+ /*
+ * Note: This is an integration test that verifies the StorageManager is properly wired to the
+ * {@link JsonCalendarStorage} class.
+ * More extensive testing of UserPref saving/reading is done in {@link JsonCalendarStorageTest} class.
+ */
+ Calendar original = getTypicalCalendar();
+ storageManager.saveCalendar(original);
+ ReadOnlyCalendar retrieved = storageManager.readCalendar().get();
+ assertEquals(original, new Calendar(retrieved));
+ }
+
+ @Test
+ public void getUserPrefsFilePath() {
+ assertNotNull(storageManager.getUserPrefsFilePath());
+ }
+
@Test
public void getAddressBookFilePath() {
assertNotNull(storageManager.getAddressBookFilePath());
}
+ @Test
+ public void getCalendarFilePath() {
+ assertNotNull(storageManager.getCalendarFilePath());
+ }
+
}
diff --git a/src/test/java/seedu/address/testutil/CalendarBuilder.java b/src/test/java/seedu/address/testutil/CalendarBuilder.java
new file mode 100644
index 00000000000..85161280eb2
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/CalendarBuilder.java
@@ -0,0 +1,35 @@
+package seedu.address.testutil;
+
+import seedu.address.model.calendar.Calendar;
+import seedu.address.model.event.Event;
+
+/**
+ * A utility class to help with building Calendar objects.
+ * Example usage:
+ * {@code Calendar c = new CalendarBuilder().withEvent("Description", "2000-01-01 00:00", "2000-01-01 12:00")
+ * .build();}
+ */
+public class CalendarBuilder {
+
+ private Calendar calendar;
+
+ public CalendarBuilder() {
+ calendar = new Calendar();
+ }
+
+ public CalendarBuilder(Calendar calendar) {
+ this.calendar = calendar;
+ }
+
+ /**
+ * Adds a new {@code Person} to the {@code Calendar} that we are building.
+ */
+ public CalendarBuilder withEvent(Event event) {
+ calendar.addEvent(event);
+ return this;
+ }
+
+ public Calendar build() {
+ return calendar;
+ }
+}
diff --git a/src/test/java/seedu/address/testutil/TypicalEvents.java b/src/test/java/seedu/address/testutil/TypicalEvents.java
new file mode 100644
index 00000000000..1ae7547ff53
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/TypicalEvents.java
@@ -0,0 +1,69 @@
+package seedu.address.testutil;
+
+import static seedu.address.logic.commands.CommandTestUtil.VALID_DESCRIPTION;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_END_DATE_EARLIER;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_END_DATE_LATER;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_START_DATE_EARLIER;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_START_DATE_LATER;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_UNUSED_DESCRIPTION;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.address.model.calendar.Calendar;
+import seedu.address.model.event.Event;
+
+/**
+ * A utility class containing a list of {@code Event} objects to be used in tests.
+ */
+public class TypicalEvents {
+
+ public static final Event CONFERENCE = new EventBuilder().withDescription("Conference")
+ .withStartEndDate("2023-11-15 08:30", "2023-11-15 17:00").build();
+
+ public static final Event LAUNCH = new EventBuilder()
+ .withDescription("Launch and Marketing Strategy Discussion")
+ .withStartEndDate("2023-12-05 10:00", "2023-12-05 12:00").build();
+
+ public static final Event MEETING = new EventBuilder().withDescription("Team Meeting")
+ .withStartEndDate("2023-10-25 09:00", "2023-10-25 10:30").build();
+
+ public static final Event WEBINAR = new EventBuilder()
+ .withDescription("Webinar")
+ .withStartEndDate("2023-10-30 15:00", "2023-10-30 16:30").build();
+
+ public static final Event WORKSHOP = new EventBuilder()
+ .withDescription("Workshop")
+ .withStartEndDate("2023-11-10 14:00", "2023-11-10 16:30").build();
+
+ // Manually added
+ public static final Event TRAINING = new EventBuilder().withDescription("Customer Support Training")
+ .withStartEndDate("2023-11-20 09:00", "2023-11-20 12:00").build();
+ public static final Event REVIEW = new EventBuilder().withDescription("Project Review")
+ .withStartEndDate("2023-10-29 15:00", "2023-10-29 16:30").build();
+
+ // Manually added - Event's details found in {@code CommandTestUtil}
+ public static final Event TEST_EVENT_A = new EventBuilder().withDescription(VALID_DESCRIPTION)
+ .withStartEndDate(VALID_START_DATE_EARLIER, VALID_END_DATE_EARLIER).build();
+
+ public static final Event TEST_EVENT_B = new EventBuilder().withDescription(VALID_UNUSED_DESCRIPTION)
+ .withStartEndDate(VALID_START_DATE_LATER, VALID_END_DATE_LATER).build();
+
+ private TypicalEvents() {} // prevents instantiation
+
+ /**
+ * Returns an {@code Calendar} with all the typical events.
+ */
+ public static Calendar getTypicalCalendar() {
+ Calendar calendar = new Calendar();
+ for (Event event : getTypicalEvents()) {
+ calendar.addEvent(event);
+ }
+ return calendar;
+ }
+
+ public static List getTypicalEvents() {
+ return new ArrayList<>(Arrays.asList(CONFERENCE, LAUNCH, MEETING, WEBINAR, WORKSHOP));
+ }
+}