From 2e988b360c902982e28f472a5370028f12330ad0 Mon Sep 17 00:00:00 2001 From: hingen <1627313-hingen@users.noreply.gitlab.com> Date: Wed, 8 Mar 2023 18:27:17 +0800 Subject: [PATCH 1/7] UserPrefs class: replace mentions of address book with Le Tracker --- src/main/java/seedu/address/MainApp.java | 2 +- .../seedu/address/model/ModelManager.java | 4 ++-- .../address/model/ReadOnlyUserPrefs.java | 2 +- .../java/seedu/address/model/UserPrefs.java | 20 +++++++++---------- .../ExtraValuesUserPref.json | 2 +- .../TypicalUserPref.json | 2 +- .../seedu/address/model/ModelManagerTest.java | 6 +++--- .../seedu/address/model/UserPrefsTest.java | 2 +- .../storage/JsonUserPrefsStorageTest.java | 2 +- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index 4133aaa0151..fc38d900a67 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -56,7 +56,7 @@ public void init() throws Exception { UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath()); UserPrefs userPrefs = initPrefs(userPrefsStorage); - AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath()); + AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getTrackerFilePath()); storage = new StorageManager(addressBookStorage, userPrefsStorage); initLogging(config); diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 86c1df298d7..6f2fac10e38 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -66,13 +66,13 @@ public void setGuiSettings(GuiSettings guiSettings) { @Override public Path getAddressBookFilePath() { - return userPrefs.getAddressBookFilePath(); + return userPrefs.getTrackerFilePath(); } @Override public void setAddressBookFilePath(Path addressBookFilePath) { requireNonNull(addressBookFilePath); - userPrefs.setAddressBookFilePath(addressBookFilePath); + userPrefs.setTrackerFilePath(addressBookFilePath); } //=========== AddressBook ================================================================================ diff --git a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java b/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java index befd58a4c73..ad714955e32 100644 --- a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java +++ b/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java @@ -11,6 +11,6 @@ public interface ReadOnlyUserPrefs { GuiSettings getGuiSettings(); - Path getAddressBookFilePath(); + Path getTrackerFilePath(); } diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java index 25a5fd6eab9..336f7f26b68 100644 --- a/src/main/java/seedu/address/model/UserPrefs.java +++ b/src/main/java/seedu/address/model/UserPrefs.java @@ -14,7 +14,7 @@ public class UserPrefs implements ReadOnlyUserPrefs { private GuiSettings guiSettings = new GuiSettings(); - private Path addressBookFilePath = Paths.get("data" , "addressbook.json"); + private Path trackerFilePath = Paths.get("data" , "letracker.json"); /** * Creates a {@code UserPrefs} with default values. @@ -35,7 +35,7 @@ public UserPrefs(ReadOnlyUserPrefs userPrefs) { public void resetData(ReadOnlyUserPrefs newUserPrefs) { requireNonNull(newUserPrefs); setGuiSettings(newUserPrefs.getGuiSettings()); - setAddressBookFilePath(newUserPrefs.getAddressBookFilePath()); + setTrackerFilePath(newUserPrefs.getTrackerFilePath()); } public GuiSettings getGuiSettings() { @@ -47,13 +47,13 @@ public void setGuiSettings(GuiSettings guiSettings) { this.guiSettings = guiSettings; } - public Path getAddressBookFilePath() { - return addressBookFilePath; + public Path getTrackerFilePath() { + return trackerFilePath; } - public void setAddressBookFilePath(Path addressBookFilePath) { - requireNonNull(addressBookFilePath); - this.addressBookFilePath = addressBookFilePath; + public void setTrackerFilePath(Path trackerFilePath) { + requireNonNull(trackerFilePath); + this.trackerFilePath = trackerFilePath; } @Override @@ -68,19 +68,19 @@ public boolean equals(Object other) { UserPrefs o = (UserPrefs) other; return guiSettings.equals(o.guiSettings) - && addressBookFilePath.equals(o.addressBookFilePath); + && trackerFilePath.equals(o.trackerFilePath); } @Override public int hashCode() { - return Objects.hash(guiSettings, addressBookFilePath); + return Objects.hash(guiSettings, trackerFilePath); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Gui Settings : " + guiSettings); - sb.append("\nLocal data file location : " + addressBookFilePath); + sb.append("\nLocal data file location : " + trackerFilePath); return sb.toString(); } diff --git a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json index 1037548a9cd..af6461c5df7 100644 --- a/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json +++ b/src/test/data/JsonUserPrefsStorageTest/ExtraValuesUserPref.json @@ -9,5 +9,5 @@ "z" : 99 } }, - "addressBookFilePath" : "addressbook.json" + "trackerFilePath" : "letracker.json" } diff --git a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json index b819bed900a..995e32df1c3 100644 --- a/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json +++ b/src/test/data/JsonUserPrefsStorageTest/TypicalUserPref.json @@ -7,5 +7,5 @@ "y" : 100 } }, - "addressBookFilePath" : "addressbook.json" + "trackerFilePath" : "letracker.json" } diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/seedu/address/model/ModelManagerTest.java index 2cf1418d116..06140d7728f 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/seedu/address/model/ModelManagerTest.java @@ -37,14 +37,14 @@ public void setUserPrefs_nullUserPrefs_throwsNullPointerException() { @Test public void setUserPrefs_validUserPrefs_copiesUserPrefs() { UserPrefs userPrefs = new UserPrefs(); - userPrefs.setAddressBookFilePath(Paths.get("address/book/file/path")); + userPrefs.setTrackerFilePath(Paths.get("address/book/file/path")); userPrefs.setGuiSettings(new GuiSettings(1, 2, 3, 4)); modelManager.setUserPrefs(userPrefs); assertEquals(userPrefs, modelManager.getUserPrefs()); // Modifying userPrefs should not modify modelManager's userPrefs UserPrefs oldUserPrefs = new UserPrefs(userPrefs); - userPrefs.setAddressBookFilePath(Paths.get("new/address/book/file/path")); + userPrefs.setTrackerFilePath(Paths.get("new/address/book/file/path")); assertEquals(oldUserPrefs, modelManager.getUserPrefs()); } @@ -126,7 +126,7 @@ public void equals() { // different userPrefs -> returns false UserPrefs differentUserPrefs = new UserPrefs(); - differentUserPrefs.setAddressBookFilePath(Paths.get("differentFilePath")); + differentUserPrefs.setTrackerFilePath(Paths.get("differentFilePath")); assertFalse(modelManager.equals(new ModelManager(addressBook, differentUserPrefs))); } } diff --git a/src/test/java/seedu/address/model/UserPrefsTest.java b/src/test/java/seedu/address/model/UserPrefsTest.java index b1307a70d52..8418a850db8 100644 --- a/src/test/java/seedu/address/model/UserPrefsTest.java +++ b/src/test/java/seedu/address/model/UserPrefsTest.java @@ -15,7 +15,7 @@ public void setGuiSettings_nullGuiSettings_throwsNullPointerException() { @Test public void setAddressBookFilePath_nullPath_throwsNullPointerException() { UserPrefs userPrefs = new UserPrefs(); - assertThrows(NullPointerException.class, () -> userPrefs.setAddressBookFilePath(null)); + assertThrows(NullPointerException.class, () -> userPrefs.setTrackerFilePath(null)); } } diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java index 16f33f4a6bb..0860a3f337b 100644 --- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java +++ b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java @@ -73,7 +73,7 @@ public void readUserPrefs_extraValuesInFile_extraValuesIgnored() throws DataConv private UserPrefs getTypicalUserPrefs() { UserPrefs userPrefs = new UserPrefs(); userPrefs.setGuiSettings(new GuiSettings(1000, 500, 300, 100)); - userPrefs.setAddressBookFilePath(Paths.get("addressbook.json")); + userPrefs.setTrackerFilePath(Paths.get("letracker.json")); return userPrefs; } From 77de0853c36afa99ee3d5e44ae2b2005e577e325 Mon Sep 17 00:00:00 2001 From: hingen <1627313-hingen@users.noreply.gitlab.com> Date: Wed, 8 Mar 2023 22:51:07 +0800 Subject: [PATCH 2/7] Add model for module --- .../seedu/address/model/module/Module.java | 108 ++++++++++++++ .../address/model/module/ModuleCode.java | 52 +++++++ .../address/model/module/ModuleName.java | 48 ++++++ .../model/module/UniqueModuleList.java | 137 ++++++++++++++++++ .../exceptions/DuplicateModuleException.java | 11 ++ .../exceptions/ModuleNotFoundException.java | 6 + 6 files changed, 362 insertions(+) create mode 100644 src/main/java/seedu/address/model/module/Module.java create mode 100644 src/main/java/seedu/address/model/module/ModuleCode.java create mode 100644 src/main/java/seedu/address/model/module/ModuleName.java create mode 100644 src/main/java/seedu/address/model/module/UniqueModuleList.java create mode 100644 src/main/java/seedu/address/model/module/exceptions/DuplicateModuleException.java create mode 100644 src/main/java/seedu/address/model/module/exceptions/ModuleNotFoundException.java diff --git a/src/main/java/seedu/address/model/module/Module.java b/src/main/java/seedu/address/model/module/Module.java new file mode 100644 index 00000000000..c729d4161ab --- /dev/null +++ b/src/main/java/seedu/address/model/module/Module.java @@ -0,0 +1,108 @@ +package seedu.address.model.module; + +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import seedu.address.model.tag.Tag; + + +/** + * Represents a module in the tracker. + * Guarantees: details are not null, field values are validated, immutable. + */ +public class Module { + + private final ModuleCode code; + private final ModuleName name; + + private final Set tags = new HashSet<>(); + + /** + * Every field must be not null. + * + * @param code The module's code. + * @param name The name of the module. + */ + public Module(ModuleCode code, ModuleName name) { + requireAllNonNull(code, name); + this.code = code; + this.name = name; + } + + public ModuleCode getCode() { + return code; + } + + public ModuleName getName() { + return name; + } + + /** + * Returns an immutable tag set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + public Set getTags() { + return Collections.unmodifiableSet(tags); + } + + /** + * Returns true if both modules have the same code. + * This defines a weaker notion of equality between two modules. + */ + public boolean isSameModule(Module other) { + if (other == this) { + return true; + } + + return other != null + && other.getCode().equals(getCode()); + } + + /** + * Returns true if both modules have the same fields. + * This defines a stronger notion of equality between two modules. + */ + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Module)) { + return false; + } + + Module otherModule = (Module) other; + return otherModule.getCode().equals(getCode()) + && otherModule.getName().equals(getName()) + && otherModule.getTags().equals(getTags()); + } + + @Override + public int hashCode() { + // use this method for custom fields hashing instead of implementing your own + return Objects.hash(code, name, tags); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(getCode()); + + if (!name.isEmpty()) { + builder.append("; Name: ") + .append(getName()); + } + + Set tags = getTags(); + if (!tags.isEmpty()) { + builder.append("; Tags: "); + tags.forEach(builder::append); + } + return builder.toString(); + } +} diff --git a/src/main/java/seedu/address/model/module/ModuleCode.java b/src/main/java/seedu/address/model/module/ModuleCode.java new file mode 100644 index 00000000000..bd2f91d4e56 --- /dev/null +++ b/src/main/java/seedu/address/model/module/ModuleCode.java @@ -0,0 +1,52 @@ +package seedu.address.model.module; + +import static java.util.Objects.requireNonNull; + +/** + * Represents a module's code in the tracker. + * Guarantees: immutable. + */ +public class ModuleCode { + + public static final String MESSAGE_CONSTRAINTS = + "Module codes should begin with uppercase alphabet characters, followed by numeric characters, optionally " + + "followed by more uppercase alphabet characters, and it should not be blank"; + + public static final String VALIDATION_REGEX = "[A-Z]+[0-9]+[A-Z]*"; + + private final String code; + + /** + * Constructs a {@code ModuleCode}. + * + * @param code A valid code. + */ + public ModuleCode(String code) { + requireNonNull(code); + this.code = code; + } + + /** + * Returns true if a given string is a valid module code. + */ + public static boolean isValidCode(String test) { + return test.matches(VALIDATION_REGEX); + } + + @Override + public String toString() { + return code; + } + + @Override + public boolean equals(Object other) { + return other == this + || (other instanceof ModuleCode + && code.equals(((ModuleCode) other).code)); + } + + @Override + public int hashCode() { + return code.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/module/ModuleName.java b/src/main/java/seedu/address/model/module/ModuleName.java new file mode 100644 index 00000000000..677128d0bea --- /dev/null +++ b/src/main/java/seedu/address/model/module/ModuleName.java @@ -0,0 +1,48 @@ +package seedu.address.model.module; + +import static java.util.Objects.requireNonNull; + +/** + * Represents a module's name in the tracker. + * Guarantees: immutable. + */ +public class ModuleName { + + private final String name; + + /** + * Constructs a {@code ModuleName}. + * + * @param name A possibly empty, but non-NULL, name. + */ + public ModuleName(String name) { + requireNonNull(name); + this.name = name; + } + + /** + * Returns true if the name is empty. Otherwise, returns false. + * + * @return true if the name is empty. Otherwise, false. + */ + public boolean isEmpty() { + return name.isEmpty(); + } + + @Override + public String toString() { + return name; + } + + @Override + public boolean equals(Object other) { + return other == this + || (other instanceof ModuleName + && name.equals(((ModuleName) other).name)); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/module/UniqueModuleList.java b/src/main/java/seedu/address/model/module/UniqueModuleList.java new file mode 100644 index 00000000000..7556972af80 --- /dev/null +++ b/src/main/java/seedu/address/model/module/UniqueModuleList.java @@ -0,0 +1,137 @@ +package seedu.address.model.module; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.Iterator; +import java.util.List; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.model.module.exceptions.DuplicateModuleException; +import seedu.address.model.module.exceptions.ModuleNotFoundException; + +/** + * A list of modules that enforces uniqueness between its elements and does not allow nulls. + * A module is considered unique by comparing using {@code Module#isSameModule(Module)}. As such, adding and updating of + * modules uses Module#isSameModule(Module) for equality so as to ensure that the module being added or updated is + * unique in terms of code in the UniqueModuleList. However, the removal of a module uses Module#equals(Object) so + * as to ensure that the module with exactly the same fields will be removed. + * + * Supports a minimal set of list operations. + * + * @see Module#isSameModule(Module) + */ +public class UniqueModuleList implements Iterable { + + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = + FXCollections.unmodifiableObservableList(internalList); + + /** + * Returns true if the list contains an equivalent module as the given argument. + */ + public boolean contains(Module toCheck) { + requireNonNull(toCheck); + return internalList.stream().anyMatch(toCheck::isSameModule); + } + + /** + * Adds a module to the list. + * The module must not already exist in the list. + */ + public void add(Module toAdd) { + requireNonNull(toAdd); + if (contains(toAdd)) { + throw new DuplicateModuleException(); + } + internalList.add(toAdd); + } + + /** + * Replaces the module {@code target} in the list with {@code editedModule}. + * {@code target} must exist in the list. + * The module code of {@code editedModule} must not be the same as another existing module in the list. + */ + public void setModule(Module target, Module editedModule) { + requireAllNonNull(target, editedModule); + + int index = internalList.indexOf(target); + if (index == -1) { + throw new ModuleNotFoundException(); + } + + if (!target.isSameModule(editedModule) && contains(editedModule)) { + throw new DuplicateModuleException(); + } + + internalList.set(index, editedModule); + } + + /** + * Removes the equivalent module from the list. + * The module must exist in the list. + */ + public void remove(Module toRemove) { + requireNonNull(toRemove); + if (!internalList.remove(toRemove)) { + throw new ModuleNotFoundException(); + } + } + + public void setModules(UniqueModuleList replacement) { + requireNonNull(replacement); + internalList.setAll(replacement.internalList); + } + + /** + * Replaces the contents of this list with {@code modules}. + * {@code modules} must not contain duplicate modules. + */ + public void setModules(List modules) { + requireAllNonNull(modules); + if (!modulesAreUnique(modules)) { + throw new DuplicateModuleException(); + } + + internalList.setAll(modules); + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList asUnmodifiableObservableList() { + return internalUnmodifiableList; + } + + @Override + public Iterator iterator() { + return internalList.iterator(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof UniqueModuleList // instanceof handles nulls + && internalList.equals(((UniqueModuleList) other).internalList)); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } + + /** + * Returns true if {@code modules} contains only unique modules. + */ + private boolean modulesAreUnique(List modules) { + for (int i = 0; i < modules.size() - 1; i++) { + for (int j = i + 1; j < modules.size(); j++) { + if (modules.get(i).isSameModule(modules.get(j))) { + return false; + } + } + } + return true; + } +} diff --git a/src/main/java/seedu/address/model/module/exceptions/DuplicateModuleException.java b/src/main/java/seedu/address/model/module/exceptions/DuplicateModuleException.java new file mode 100644 index 00000000000..95677a16ff1 --- /dev/null +++ b/src/main/java/seedu/address/model/module/exceptions/DuplicateModuleException.java @@ -0,0 +1,11 @@ +package seedu.address.model.module.exceptions; + +/** + * Signals that the operation will result in duplicate Modules (Modules are considered duplicates if they have the same + * code). + */ +public class DuplicateModuleException extends RuntimeException { + public DuplicateModuleException() { + super("Operation would result in duplicate modules"); + } +} diff --git a/src/main/java/seedu/address/model/module/exceptions/ModuleNotFoundException.java b/src/main/java/seedu/address/model/module/exceptions/ModuleNotFoundException.java new file mode 100644 index 00000000000..52abdad64ea --- /dev/null +++ b/src/main/java/seedu/address/model/module/exceptions/ModuleNotFoundException.java @@ -0,0 +1,6 @@ +package seedu.address.model.module.exceptions; + +/** + * Signals that the operation is unable to find the specified module. + */ +public class ModuleNotFoundException extends RuntimeException {} From 8337da63fa869382581a16702f27000c9515a548 Mon Sep 17 00:00:00 2001 From: hingen <1627313-hingen@users.noreply.gitlab.com> Date: Wed, 8 Mar 2023 22:51:48 +0800 Subject: [PATCH 3/7] Add tracker which holds the modules being tracked --- .../seedu/address/model/ReadOnlyTracker.java | 15 +++ .../java/seedu/address/model/Tracker.java | 119 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/main/java/seedu/address/model/ReadOnlyTracker.java create mode 100644 src/main/java/seedu/address/model/Tracker.java diff --git a/src/main/java/seedu/address/model/ReadOnlyTracker.java b/src/main/java/seedu/address/model/ReadOnlyTracker.java new file mode 100644 index 00000000000..8f559f7396e --- /dev/null +++ b/src/main/java/seedu/address/model/ReadOnlyTracker.java @@ -0,0 +1,15 @@ +package seedu.address.model; + +import javafx.collections.ObservableList; + +/** + * Unmodifiable view of a tracker + */ +public interface ReadOnlyTracker { + + /** + * Returns an unmodifiable view of the module list. + * This list will not contain any duplicate modules. + */ + ObservableList getModuleList(); +} diff --git a/src/main/java/seedu/address/model/Tracker.java b/src/main/java/seedu/address/model/Tracker.java new file mode 100644 index 00000000000..ad8c4ca3751 --- /dev/null +++ b/src/main/java/seedu/address/model/Tracker.java @@ -0,0 +1,119 @@ +package seedu.address.model; + +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import javafx.collections.ObservableList; +import seedu.address.model.module.Module; +import seedu.address.model.module.UniqueModuleList; + +/** + * Wraps all data at the tracker level + * Duplicate modules are not allowed (by .isSameModule comparison) + */ +public class Tracker implements ReadOnlyTracker { + private final UniqueModuleList modules; + + /* + * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication + * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html + * + * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication + * among constructors. + */ + { + modules = new UniqueModuleList(); + } + + public Tracker() {} + + /** + * Creates a Tracker using the Modules in the {@code toBeCopied} + */ + public Tracker(ReadOnlyTracker toBeCopied) { + this(); + resetData(toBeCopied); + } + + //// list overwrite operations + + /** + * Replaces the contents of the module list with {@code modules}. + * {@code modules} must not contain duplicate modules. + */ + public void setModules(List modules) { + this.modules.setModules(modules); + } + + /** + * Resets the existing data of this {@code Tracker} with {@code newData}. + */ + public void resetData(ReadOnlyTracker newData) { + requireNonNull(newData); + + setModules(newData.getModuleList()); + } + + //// module-level operations + + /** + * Returns true if a module with the same code as {@code module} exists in the tracker. + */ + public boolean hasModule(Module module) { + requireNonNull(module); + return modules.contains(module); + } + + /** + * Adds a module to the tracker. + * The module must not already exist in the tracker. + */ + public void addModule(Module module) { + modules.add(module); + } + + /** + * Replaces the given module {@code target} in the list with {@code editedModule}. + * {@code target} must exist in the tracker. + * The module of {@code editedModule} must not be the same as another existing module in the tracker. + */ + public void setModule(Module target, Module editedModule) { + requireNonNull(editedModule); + + modules.setModule(target, editedModule); + } + + /** + * Removes {@code key} from this {@code Tracker}. + * {@code key} must exist in the tracker. + */ + public void removeModule(Module key) { + modules.remove(key); + } + + //// util methods + + @Override + public String toString() { + return modules.asUnmodifiableObservableList().size() + " modules"; + // TODO: refine later + } + + @Override + public ObservableList getModuleList() { + return modules.asUnmodifiableObservableList(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Tracker // instanceof handles nulls + && modules.equals(((Tracker) other).modules)); + } + + @Override + public int hashCode() { + return modules.hashCode(); + } +} From 641787e7f3e219f7df7d15e266273e95c98034bb Mon Sep 17 00:00:00 2001 From: hingen <1627313-hingen@users.noreply.gitlab.com> Date: Thu, 9 Mar 2023 13:38:44 +0800 Subject: [PATCH 4/7] Add tracking of lecture models --- .../seedu/address/model/UniqueDataList.java | 155 ++++++++++++++++++ .../seedu/address/model/lecture/Lecture.java | 95 +++++++++++ .../address/model/lecture/LectureName.java | 59 +++++++ .../model/lecture/UniqueLectureList.java | 72 ++++++++ .../exceptions/DuplicateLectureException.java | 11 ++ .../exceptions/LectureNotFoundException.java | 6 + .../seedu/address/model/module/Module.java | 26 ++- .../model/module/UniqueModuleList.java | 93 ++--------- 8 files changed, 435 insertions(+), 82 deletions(-) create mode 100644 src/main/java/seedu/address/model/UniqueDataList.java create mode 100644 src/main/java/seedu/address/model/lecture/Lecture.java create mode 100644 src/main/java/seedu/address/model/lecture/LectureName.java create mode 100644 src/main/java/seedu/address/model/lecture/UniqueLectureList.java create mode 100644 src/main/java/seedu/address/model/lecture/exceptions/DuplicateLectureException.java create mode 100644 src/main/java/seedu/address/model/lecture/exceptions/LectureNotFoundException.java diff --git a/src/main/java/seedu/address/model/UniqueDataList.java b/src/main/java/seedu/address/model/UniqueDataList.java new file mode 100644 index 00000000000..97b68edeb41 --- /dev/null +++ b/src/main/java/seedu/address/model/UniqueDataList.java @@ -0,0 +1,155 @@ +package seedu.address.model; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.Iterator; +import java.util.List; +import java.util.function.BiPredicate; +import java.util.function.Supplier; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +/** + * A list of data that enforces uniqueness between its elements and does not allow nulls. + * A data is considered unique by comparing using {@code isSameChecker.test(T, T)}. As such, adding and updating of + * data uses {@code isSameChecker.test(T, T)} for equality so as to ensure that the data being added or updated is + * unique in the UniqueDataList. However, the removal of a data uses {@code T#equals(Object)} so as to ensure that + * the data with exactly the same fields will be removed. + * + * Supports a minimal set of list operations. + */ +public class UniqueDataList implements Iterable { + + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = + FXCollections.unmodifiableObservableList(internalList); + + private final BiPredicate isSameChecker; + private final Supplier duplicateExceptionCreator; + private final Supplier notFoundExceptionCreator; + + /** + * Constructs a {@code UniqueDataList}. + * + * @param isSameChecker Use to check if 2 data are the same. + * @param duplicateExceptionCreator Creates any exception thrown due to duplicate data. + * @param notFoundExceptionCreator Creates any exception thrown due to data not found. + */ + public UniqueDataList(BiPredicate isSameChecker, + Supplier duplicateExceptionCreator, + Supplier notFoundExceptionCreator) { + + this.isSameChecker = isSameChecker; + this.duplicateExceptionCreator = duplicateExceptionCreator; + this.notFoundExceptionCreator = notFoundExceptionCreator; + } + + /** + * Returns true if the list contains an equivalent data as the given argument. + */ + public boolean contains(T toCheck) { + requireNonNull(toCheck); + return internalList.stream().anyMatch((data) -> isSameChecker.test(toCheck, data)); + } + + /** + * Adds a data to the list. + * The data must not already exist in the list. + */ + public void add(T toAdd) { + requireNonNull(toAdd); + if (contains(toAdd)) { + throw duplicateExceptionCreator.get(); + } + internalList.add(toAdd); + } + + /** + * Replaces the data {@code target} in the list with {@code editedData}. + * {@code target} must exist in the list. + * {@code editedData} must not be the same as another existing data in the list. + */ + public void setData(T target, T editedData) { + requireAllNonNull(target, editedData); + + int index = internalList.indexOf(target); + if (index == -1) { + throw notFoundExceptionCreator.get(); + } + + if (!isSameChecker.test(target, editedData) && contains(editedData)) { + throw duplicateExceptionCreator.get(); + } + + internalList.set(index, editedData); + } + + /** + * Removes the equivalent data from the list. + * The data must exist in the list. + */ + public void remove(T toRemove) { + requireNonNull(toRemove); + if (!internalList.remove(toRemove)) { + throw notFoundExceptionCreator.get(); + } + } + + public void setAllData(UniqueDataList replacement) { + requireNonNull(replacement); + internalList.setAll(replacement.internalList); + } + + /** + * Replaces the contents of this list with {@code data}. + * {@code data} must not contain duplicate data. + */ + public void setAllData(List data) { + requireAllNonNull(data); + if (!dataAreUnique(data)) { + throw duplicateExceptionCreator.get(); + } + + internalList.setAll(data); + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList asUnmodifiableObservableList() { + return internalUnmodifiableList; + } + + @Override + public Iterator iterator() { + return internalList.iterator(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof UniqueDataList // instanceof handles nulls + && internalList.equals(((UniqueDataList) other).internalList)); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } + + /** + * Returns true if {@code data} contains only unique data. + */ + private boolean dataAreUnique(List data) { + for (int i = 0; i < data.size() - 1; i++) { + for (int j = i + 1; j < data.size(); j++) { + if (isSameChecker.test(data.get(i), data.get(j))) { + return false; + } + } + } + return true; + } +} diff --git a/src/main/java/seedu/address/model/lecture/Lecture.java b/src/main/java/seedu/address/model/lecture/Lecture.java new file mode 100644 index 00000000000..7fec23a644c --- /dev/null +++ b/src/main/java/seedu/address/model/lecture/Lecture.java @@ -0,0 +1,95 @@ +package seedu.address.model.lecture; + +import static java.util.Objects.requireNonNull; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import seedu.address.model.tag.Tag; + +/** + * Represents a lecture of a module that is in the tracker.. + * Guarantees: details are present and not null, field values are validated, immutable. + */ +public class Lecture { + + private final LectureName name; + + private final Set tags = new HashSet<>(); + + /** + * Constructs a {@code Lecture}. + * + * @param name The name of the lecture. + */ + public Lecture(LectureName name) { + requireNonNull(name); + this.name = name; + } + + public LectureName getName() { + return name; + } + + /** + * Returns an immutable tag set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + public Set getTags() { + return Collections.unmodifiableSet(tags); + } + + /** + * Returns true if both lectures have the same name. + * This defines a weaker notion of equality between two lectures. + */ + public boolean isSameLecture(Lecture other) { + if (other == this) { + return true; + } + + return other != null + && other.getName().equals(getName()); + } + + /** + * Returns true if both lectures have the same fields. + * This defines a stronger notion of equality between two lectures. + */ + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Lecture)) { + return false; + } + + Lecture otherLecture = (Lecture) other; + return otherLecture.getName().equals(getName()) + && otherLecture.getTags().equals(getTags()); + } + + @Override + public int hashCode() { + // use this method for custom fields hashing instead of implementing your own + return Objects.hash(name, tags); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append(getName()); + + Set tags = getTags(); + if (!tags.isEmpty()) { + builder.append("; Tags: "); + tags.forEach(builder::append); + } + + return builder.toString(); + } +} diff --git a/src/main/java/seedu/address/model/lecture/LectureName.java b/src/main/java/seedu/address/model/lecture/LectureName.java new file mode 100644 index 00000000000..29421688e26 --- /dev/null +++ b/src/main/java/seedu/address/model/lecture/LectureName.java @@ -0,0 +1,59 @@ +package seedu.address.model.lecture; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +/** + * Represents a lecture's name in the tracker. + * Guarantees: immutable, is valid as declared in {@link #isValidName(String)}. + */ +public class LectureName { + + public static final String MESSAGE_CONSTRAINTS = + "Names should only contain alphanumeric characters and spaces, and it should not be blank"; + + /* + * The first character of the name must not be a whitespace, + * otherwise " " (a blank string) becomes a valid input. + */ + public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; + + public final String fullName; + + /** + * Constructs a {@code LectureName}. + * + * @param name A valid name. + */ + public LectureName(String name) { + requireNonNull(name); + checkArgument(isValidName(name), MESSAGE_CONSTRAINTS); + fullName = name; + } + + /** + * Returns true if a given string is a valid name. + */ + public static boolean isValidName(String test) { + return test.matches(VALIDATION_REGEX); + } + + + @Override + public String toString() { + return fullName; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof LectureName // instanceof handles nulls + && fullName.equals(((LectureName) other).fullName)); // state check + } + + @Override + public int hashCode() { + return fullName.hashCode(); + } + +} diff --git a/src/main/java/seedu/address/model/lecture/UniqueLectureList.java b/src/main/java/seedu/address/model/lecture/UniqueLectureList.java new file mode 100644 index 00000000000..5594fd80960 --- /dev/null +++ b/src/main/java/seedu/address/model/lecture/UniqueLectureList.java @@ -0,0 +1,72 @@ +package seedu.address.model.lecture; + +import java.util.List; + +import seedu.address.model.UniqueDataList; +import seedu.address.model.lecture.exceptions.DuplicateLectureException; +import seedu.address.model.lecture.exceptions.LectureNotFoundException; + +/** + * A list of lectures that enforces uniqueness between its elements and does not allow nulls. + * A lecture is considered unique by comparing using {@code Lecture#isSameLecture(Lecture)}. As such, adding and + * updating of lectures uses Lecture#isSameLecture(Lecture) for equality so as to ensure that the lecture being added or + * updated is unique in terms of code in the UniqueLectureList. However, the removal of a lecture uses + * Lecture#equals(Object) so as to ensure that the lecture with exactly the same fields will be removed. + * + * Supports a minimal set of list operations. + * + * @see Lecture#isSameLecture(Lecture) + */ +public class UniqueLectureList extends UniqueDataList { + + public UniqueLectureList() { + super((a, b) -> a.isSameLecture(b), DuplicateLectureException::new, LectureNotFoundException::new); + } + + /** + * Returns true if the list contains an equivalent module as the given argument. + */ + @Override + public boolean contains(Lecture toCheck) { + return super.contains(toCheck); + } + + /** + * Adds a lecture to the list. + * The lecture must not already exist in the list. + */ + @Override + public void add(Lecture toAdd) { + super.add(toAdd); + } + + /** + * Replaces the lecture {@code target} in the list with {@code editedLecture}. + * {@code target} must exist in the list. + * The name of {@code editedLecture} must not be the same as another existing lecture in the list. + */ + public void setLecture(Lecture target, Lecture editedLecture) { + super.setData(target, editedLecture); + } + + /** + * Removes the equivalent lecture from the list. + * The lecture must exist in the list. + */ + @Override + public void remove(Lecture toRemove) { + super.remove(toRemove); + } + + public void setLectures(UniqueLectureList replacement) { + super.setAllData(replacement); + } + + /** + * Replaces the contents of this list with {@code lectures}. + * {@code lectures} must not contain duplicate lectures. + */ + public void setLectures(List lectures) { + super.setAllData(lectures); + } +} diff --git a/src/main/java/seedu/address/model/lecture/exceptions/DuplicateLectureException.java b/src/main/java/seedu/address/model/lecture/exceptions/DuplicateLectureException.java new file mode 100644 index 00000000000..2ddfef49993 --- /dev/null +++ b/src/main/java/seedu/address/model/lecture/exceptions/DuplicateLectureException.java @@ -0,0 +1,11 @@ +package seedu.address.model.lecture.exceptions; + +/** + * Signals that the operation will result in duplicate Lectures (Lectures are considered duplicates if they have the + * same name). + */ +public class DuplicateLectureException extends RuntimeException { + public DuplicateLectureException() { + super("Operation would result in duplicate lectures"); + } +} diff --git a/src/main/java/seedu/address/model/lecture/exceptions/LectureNotFoundException.java b/src/main/java/seedu/address/model/lecture/exceptions/LectureNotFoundException.java new file mode 100644 index 00000000000..17543236060 --- /dev/null +++ b/src/main/java/seedu/address/model/lecture/exceptions/LectureNotFoundException.java @@ -0,0 +1,6 @@ +package seedu.address.model.lecture.exceptions; + +/** + * Signals that the operation is unable to find the specified lecture. + */ +public class LectureNotFoundException extends RuntimeException {} diff --git a/src/main/java/seedu/address/model/module/Module.java b/src/main/java/seedu/address/model/module/Module.java index c729d4161ab..d9ee7ca50b4 100644 --- a/src/main/java/seedu/address/model/module/Module.java +++ b/src/main/java/seedu/address/model/module/Module.java @@ -7,9 +7,11 @@ import java.util.Objects; import java.util.Set; +import javafx.collections.ObservableList; +import seedu.address.model.lecture.Lecture; +import seedu.address.model.lecture.UniqueLectureList; import seedu.address.model.tag.Tag; - /** * Represents a module in the tracker. * Guarantees: details are not null, field values are validated, immutable. @@ -21,6 +23,8 @@ public class Module { private final Set tags = new HashSet<>(); + private final UniqueLectureList lectures = new UniqueLectureList(); + /** * Every field must be not null. * @@ -49,6 +53,14 @@ public Set getTags() { return Collections.unmodifiableSet(tags); } + /** + * Returns an immutable lecture list, which throws {@code UnsupportedOperationException} + * if modification is attempted. + */ + public ObservableList getLectures() { + return lectures.asUnmodifiableObservableList(); + } + /** * Returns true if both modules have the same code. * This defines a weaker notion of equality between two modules. @@ -79,13 +91,14 @@ public boolean equals(Object other) { Module otherModule = (Module) other; return otherModule.getCode().equals(getCode()) && otherModule.getName().equals(getName()) - && otherModule.getTags().equals(getTags()); + && otherModule.getTags().equals(getTags()) + && otherModule.getLectures().equals(getLectures()); } @Override public int hashCode() { // use this method for custom fields hashing instead of implementing your own - return Objects.hash(code, name, tags); + return Objects.hash(code, name, tags, lectures); } @Override @@ -103,6 +116,13 @@ public String toString() { builder.append("; Tags: "); tags.forEach(builder::append); } + + ObservableList lectures = getLectures(); + if (!lectures.isEmpty()) { + builder.append("; Lectures: "); + lectures.forEach(builder::append); + } + return builder.toString(); } } diff --git a/src/main/java/seedu/address/model/module/UniqueModuleList.java b/src/main/java/seedu/address/model/module/UniqueModuleList.java index 7556972af80..92ab83d97f1 100644 --- a/src/main/java/seedu/address/model/module/UniqueModuleList.java +++ b/src/main/java/seedu/address/model/module/UniqueModuleList.java @@ -1,13 +1,8 @@ package seedu.address.model.module; -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; - -import java.util.Iterator; import java.util.List; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; +import seedu.address.model.UniqueDataList; import seedu.address.model.module.exceptions.DuplicateModuleException; import seedu.address.model.module.exceptions.ModuleNotFoundException; @@ -22,30 +17,27 @@ * * @see Module#isSameModule(Module) */ -public class UniqueModuleList implements Iterable { +public class UniqueModuleList extends UniqueDataList { - private final ObservableList internalList = FXCollections.observableArrayList(); - private final ObservableList internalUnmodifiableList = - FXCollections.unmodifiableObservableList(internalList); + public UniqueModuleList() { + super((a, b) -> a.isSameModule(b), DuplicateModuleException::new, ModuleNotFoundException::new); + } /** * Returns true if the list contains an equivalent module as the given argument. */ + @Override public boolean contains(Module toCheck) { - requireNonNull(toCheck); - return internalList.stream().anyMatch(toCheck::isSameModule); + return super.contains(toCheck); } /** * Adds a module to the list. * The module must not already exist in the list. */ + @Override public void add(Module toAdd) { - requireNonNull(toAdd); - if (contains(toAdd)) { - throw new DuplicateModuleException(); - } - internalList.add(toAdd); + super.add(toAdd); } /** @@ -54,34 +46,20 @@ public void add(Module toAdd) { * The module code of {@code editedModule} must not be the same as another existing module in the list. */ public void setModule(Module target, Module editedModule) { - requireAllNonNull(target, editedModule); - - int index = internalList.indexOf(target); - if (index == -1) { - throw new ModuleNotFoundException(); - } - - if (!target.isSameModule(editedModule) && contains(editedModule)) { - throw new DuplicateModuleException(); - } - - internalList.set(index, editedModule); + super.setData(target, editedModule); } /** * Removes the equivalent module from the list. * The module must exist in the list. */ + @Override public void remove(Module toRemove) { - requireNonNull(toRemove); - if (!internalList.remove(toRemove)) { - throw new ModuleNotFoundException(); - } + super.remove(toRemove); } public void setModules(UniqueModuleList replacement) { - requireNonNull(replacement); - internalList.setAll(replacement.internalList); + super.setAllData(replacement); } /** @@ -89,49 +67,6 @@ public void setModules(UniqueModuleList replacement) { * {@code modules} must not contain duplicate modules. */ public void setModules(List modules) { - requireAllNonNull(modules); - if (!modulesAreUnique(modules)) { - throw new DuplicateModuleException(); - } - - internalList.setAll(modules); - } - - /** - * Returns the backing list as an unmodifiable {@code ObservableList}. - */ - public ObservableList asUnmodifiableObservableList() { - return internalUnmodifiableList; - } - - @Override - public Iterator iterator() { - return internalList.iterator(); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof UniqueModuleList // instanceof handles nulls - && internalList.equals(((UniqueModuleList) other).internalList)); - } - - @Override - public int hashCode() { - return internalList.hashCode(); - } - - /** - * Returns true if {@code modules} contains only unique modules. - */ - private boolean modulesAreUnique(List modules) { - for (int i = 0; i < modules.size() - 1; i++) { - for (int j = i + 1; j < modules.size(); j++) { - if (modules.get(i).isSameModule(modules.get(j))) { - return false; - } - } - } - return true; + super.setAllData(modules); } } From 2a704856aa652d9ae788e0ae77538881b5290114 Mon Sep 17 00:00:00 2001 From: hingen <1627313-hingen@users.noreply.gitlab.com> Date: Thu, 9 Mar 2023 18:26:47 +0800 Subject: [PATCH 5/7] Fix unable to update module tags and lectures --- .../java/seedu/address/model/UniqueDataList.java | 8 ++++++++ .../seedu/address/model/lecture/Lecture.java | 4 +++- .../address/model/lecture/UniqueLectureList.java | 2 +- .../java/seedu/address/model/module/Module.java | 16 ++++++++++------ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/address/model/UniqueDataList.java b/src/main/java/seedu/address/model/UniqueDataList.java index 97b68edeb41..bc4ad8a97da 100644 --- a/src/main/java/seedu/address/model/UniqueDataList.java +++ b/src/main/java/seedu/address/model/UniqueDataList.java @@ -3,6 +3,7 @@ import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.function.BiPredicate; @@ -122,6 +123,13 @@ public ObservableList asUnmodifiableObservableList() { return internalUnmodifiableList; } + /** + * Returns the backing list as an unmodifiable {@code List}. + */ + public List asUnmodifiableList() { + return Collections.unmodifiableList(internalList); + } + @Override public Iterator iterator() { return internalList.iterator(); diff --git a/src/main/java/seedu/address/model/lecture/Lecture.java b/src/main/java/seedu/address/model/lecture/Lecture.java index 7fec23a644c..5c9548f6611 100644 --- a/src/main/java/seedu/address/model/lecture/Lecture.java +++ b/src/main/java/seedu/address/model/lecture/Lecture.java @@ -23,10 +23,12 @@ public class Lecture { * Constructs a {@code Lecture}. * * @param name The name of the lecture. + * @param tags The tags applied to the module. */ - public Lecture(LectureName name) { + public Lecture(LectureName name, Set tags) { requireNonNull(name); this.name = name; + this.tags.addAll(tags); } public LectureName getName() { diff --git a/src/main/java/seedu/address/model/lecture/UniqueLectureList.java b/src/main/java/seedu/address/model/lecture/UniqueLectureList.java index 5594fd80960..f1a6ce023f2 100644 --- a/src/main/java/seedu/address/model/lecture/UniqueLectureList.java +++ b/src/main/java/seedu/address/model/lecture/UniqueLectureList.java @@ -24,7 +24,7 @@ public UniqueLectureList() { } /** - * Returns true if the list contains an equivalent module as the given argument. + * Returns true if the list contains an equivalent lecture as the given argument. */ @Override public boolean contains(Lecture toCheck) { diff --git a/src/main/java/seedu/address/model/module/Module.java b/src/main/java/seedu/address/model/module/Module.java index d9ee7ca50b4..3c3cbb960f0 100644 --- a/src/main/java/seedu/address/model/module/Module.java +++ b/src/main/java/seedu/address/model/module/Module.java @@ -4,10 +4,10 @@ import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; -import javafx.collections.ObservableList; import seedu.address.model.lecture.Lecture; import seedu.address.model.lecture.UniqueLectureList; import seedu.address.model.tag.Tag; @@ -30,11 +30,15 @@ public class Module { * * @param code The module's code. * @param name The name of the module. + * @param tags The tags applied to the module. + * @param lectures The lectures of the module. */ - public Module(ModuleCode code, ModuleName name) { - requireAllNonNull(code, name); + public Module(ModuleCode code, ModuleName name, Set tags, List lectures) { + requireAllNonNull(code, name, tags, lectures); this.code = code; this.name = name; + this.tags.addAll(tags); + this.lectures.setLectures(lectures); } public ModuleCode getCode() { @@ -57,8 +61,8 @@ public Set getTags() { * Returns an immutable lecture list, which throws {@code UnsupportedOperationException} * if modification is attempted. */ - public ObservableList getLectures() { - return lectures.asUnmodifiableObservableList(); + public List getLectures() { + return lectures.asUnmodifiableList(); } /** @@ -117,7 +121,7 @@ public String toString() { tags.forEach(builder::append); } - ObservableList lectures = getLectures(); + List lectures = getLectures(); if (!lectures.isEmpty()) { builder.append("; Lectures: "); lectures.forEach(builder::append); From 1eac378809b397f84392eb1fe58eb1faaafbacf7 Mon Sep 17 00:00:00 2001 From: hingen <1627313-hingen@users.noreply.gitlab.com> Date: Thu, 9 Mar 2023 18:46:31 +0800 Subject: [PATCH 6/7] Add tracking of video models --- .../seedu/address/model/lecture/Lecture.java | 31 +++++- .../address/model/video/UniqueVideoList.java | 72 ++++++++++++++ .../java/seedu/address/model/video/Video.java | 97 +++++++++++++++++++ .../seedu/address/model/video/VideoName.java | 59 +++++++++++ .../exceptions/DuplicateVideoException.java | 11 +++ .../exceptions/VideoNotFoundException.java | 6 ++ 6 files changed, 271 insertions(+), 5 deletions(-) create mode 100644 src/main/java/seedu/address/model/video/UniqueVideoList.java create mode 100644 src/main/java/seedu/address/model/video/Video.java create mode 100644 src/main/java/seedu/address/model/video/VideoName.java create mode 100644 src/main/java/seedu/address/model/video/exceptions/DuplicateVideoException.java create mode 100644 src/main/java/seedu/address/model/video/exceptions/VideoNotFoundException.java diff --git a/src/main/java/seedu/address/model/lecture/Lecture.java b/src/main/java/seedu/address/model/lecture/Lecture.java index 5c9548f6611..841f74849e4 100644 --- a/src/main/java/seedu/address/model/lecture/Lecture.java +++ b/src/main/java/seedu/address/model/lecture/Lecture.java @@ -1,13 +1,16 @@ package seedu.address.model.lecture; -import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; import seedu.address.model.tag.Tag; +import seedu.address.model.video.UniqueVideoList; +import seedu.address.model.video.Video; /** * Represents a lecture of a module that is in the tracker.. @@ -19,16 +22,19 @@ public class Lecture { private final Set tags = new HashSet<>(); + private final UniqueVideoList videos = new UniqueVideoList(); + /** * Constructs a {@code Lecture}. * * @param name The name of the lecture. * @param tags The tags applied to the module. */ - public Lecture(LectureName name, Set tags) { - requireNonNull(name); + public Lecture(LectureName name, Set tags, List