diff --git a/docs/tutorials/TracingCode.md b/docs/tutorials/TracingCode.md index 0c3f9a308f5..0bd06f34fac 100644 --- a/docs/tutorials/TracingCode.md +++ b/docs/tutorials/TracingCode.md @@ -231,7 +231,7 @@ Try to keep track of what happens inside the component and where the execution t public CommandResult execute(Model model) throws CommandException { ... Person personToEdit = lastShownList.get(index.getZeroBased()); - Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); + Person editedPerson = createEditedPerson(personToEdit, personEditDescriptor); if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) { throw new CommandException(MESSAGE_DUPLICATE_PERSON); } diff --git a/src/main/java/seedu/address/Main.java b/src/main/java/seedu/address/Main.java index 052a5068631..4208153a631 100644 --- a/src/main/java/seedu/address/Main.java +++ b/src/main/java/seedu/address/Main.java @@ -8,7 +8,7 @@ * This is a workaround for the following error when MainApp is made the * entry point of the application: * - * Error: JavaFX runtime components are missing, and are required to run this application + * Error: JavaFX runtime components are missing, and are required to run this application * * The reason is that MainApp extends Application. In that case, the * LauncherHelper will check for the javafx.graphics module to be present diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java index 6c3e5d4a670..5a9a6c36b63 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/seedu/address/MainApp.java @@ -16,6 +16,7 @@ import seedu.address.commons.util.StringUtil; import seedu.address.logic.Logic; import seedu.address.logic.LogicManager; +import seedu.address.logic.executors.Executor; import seedu.address.model.AddressBook; import seedu.address.model.Model; import seedu.address.model.ModelManager; @@ -69,6 +70,8 @@ public void init() throws Exception { logic = new LogicManager(model, storage); ui = new UiManager(logic); + + Executor.setup(model); } /** diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/seedu/address/commons/core/LogsCenter.java index 431e7185e76..1177cef1b1d 100644 --- a/src/main/java/seedu/address/commons/core/LogsCenter.java +++ b/src/main/java/seedu/address/commons/core/LogsCenter.java @@ -12,8 +12,8 @@ * Configures and manages loggers and handlers, including their logging level * Named {@link Logger}s can be obtained from this class
* These loggers have been configured to output messages to the console and a {@code .log} file by default, - * at the {@code INFO} level. A new {@code .log} file with a new numbering will be created after the log - * file reaches 5MB big, up to a maximum of 5 files.
+ * at the {@code INFO} level. A new {@code .log} file with a new numbering will be created after the log + * file reaches 5MB big, up to a maximum of 5 files.
*/ public class LogsCenter { private static final int MAX_FILE_COUNT = 5; @@ -95,6 +95,7 @@ private static void addFileHandler(Logger logger) { /** * Creates a {@code FileHandler} for the log file. + * * @throws IOException if there are problems opening the file. */ private static FileHandler createFileHandler() throws IOException { diff --git a/src/main/java/seedu/address/commons/core/Messages.java b/src/main/java/seedu/address/commons/core/Messages.java index 1deb3a1e469..4d54b47f853 100644 --- a/src/main/java/seedu/address/commons/core/Messages.java +++ b/src/main/java/seedu/address/commons/core/Messages.java @@ -8,6 +8,8 @@ public class Messages { public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command"; public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s"; public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid"; + public static final String MESSAGE_INVALID_GROUP_DISPLAYED_INDEX = "The group index provided is invalid"; public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; + public static final String MESSAGE_GROUPS_LISTED_OVERVIEW = "%1$d groups listed!"; } diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/seedu/address/commons/core/Version.java index 9416b9e8486..46cc181b603 100644 --- a/src/main/java/seedu/address/commons/core/Version.java +++ b/src/main/java/seedu/address/commons/core/Version.java @@ -50,6 +50,7 @@ public boolean isEarlyAccess() { /** * Parses a version number string in the format V1.2.3. + * * @param versionString version number string * @return a Version object */ diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/seedu/address/commons/util/CollectionUtil.java index eafe4dfd681..942edda97d7 100644 --- a/src/main/java/seedu/address/commons/util/CollectionUtil.java +++ b/src/main/java/seedu/address/commons/util/CollectionUtil.java @@ -12,7 +12,9 @@ */ public class CollectionUtil { - /** @see #requireAllNonNull(Collection) */ + /** + * @see #requireAllNonNull(Collection) + */ public static void requireAllNonNull(Object... items) { requireNonNull(items); Stream.of(items).forEach(Objects::requireNonNull); diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/seedu/address/commons/util/FileUtil.java index b1e2767cdd9..f811215474c 100644 --- a/src/main/java/seedu/address/commons/util/FileUtil.java +++ b/src/main/java/seedu/address/commons/util/FileUtil.java @@ -20,6 +20,7 @@ public static boolean isFileExists(Path file) { /** * Returns true if {@code path} can be converted into a {@code Path} via {@link Paths#get(String)}, * otherwise returns false. + * * @param path A string representing the file path. Cannot be null. */ public static boolean isValidPath(String path) { @@ -33,6 +34,7 @@ public static boolean isValidPath(String path) { /** * Creates a file if it does not exist along with its missing parent directories. + * * @throws IOException if the file or directory cannot be created. */ public static void createIfMissing(Path file) throws IOException { diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/seedu/address/commons/util/JsonUtil.java index e6a132215b8..bf225ed0bdf 100644 --- a/src/main/java/seedu/address/commons/util/JsonUtil.java +++ b/src/main/java/seedu/address/commons/util/JsonUtil.java @@ -51,6 +51,7 @@ static T deserializeObjectFromJsonFile(Path jsonFile, Class classOfObject /** * Returns the Json object from the given file or {@code Optional.empty()} object if the file is not found. * If any values are missing from the file, default values will be used, as long as the file is a valid json file. + * * @param filePath cannot be null. * @param classOfObjectToDeserialize Json file has to correspond to the structure in the class given here. * @throws DataConversionException if the file format is not as expected. @@ -79,6 +80,7 @@ public static Optional readJsonFile( /** * Saves the Json object to the specified file. * Overwrites existing file if it exists, creates a new file if it doesn't. + * * @param jsonFile cannot be null * @param filePath cannot be null * @throws IOException if there was an error during writing to the file @@ -93,6 +95,7 @@ public static void saveJsonFile(T jsonFile, Path filePath) throws IOExceptio /** * Converts a given string representation of a JSON data to instance of a class + * * @param The generic type to create an instance of * @return The instance of T with the specified values in the JSON string */ @@ -102,6 +105,7 @@ public static T fromJsonString(String json, Class instanceClass) throws I /** * Converts a given instance of a class into its JSON data string representation + * * @param instance The T object to be converted into the JSON string * @param The generic type to create an instance of * @return JSON data representation of the given class instance, in string @@ -128,7 +132,6 @@ protected Level _deserialize(String value, DeserializationContext ctxt) { * Gets the logging level that matches loggingLevelString *

* Returns null if there are no matches - * */ private Level getLoggingLevel(String loggingLevelString) { return Level.parse(loggingLevelString); diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/seedu/address/commons/util/StringUtil.java index e0717c40fc2..b8690b530c7 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/seedu/address/commons/util/StringUtil.java @@ -14,12 +14,13 @@ public class StringUtil { /** * Returns true if the {@code sentence} contains the {@code word}. - * Ignores case, but a full word match is required. - *
examples:

+     * Ignores case, but a full word match is required.
+     * 
examples:
      *       containsWordIgnoreCase("ABc def", "abc") == true
      *       containsWordIgnoreCase("ABc def", "DEF") == true
      *       containsWordIgnoreCase("ABc def", "AB") == false //not a full word match
      *       
+ * * @param sentence cannot be null * @param word cannot be null, cannot be empty, must be a single word */ @@ -53,6 +54,7 @@ public static String getDetails(Throwable t) { * e.g. 1, 2, 3, ..., {@code Integer.MAX_VALUE}
* Will return false for any other non-null string input * e.g. empty string, "-1", "0", "+1", and " 2 " (untrimmed), "3 0" (contains whitespace), "1 a" (contains letters) + * * @throws NullPointerException if {@code s} is null. */ public static boolean isNonZeroUnsignedInteger(String s) { diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 92cd8fa605a..eab85b5280e 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -6,6 +6,7 @@ import seedu.address.commons.core.GuiSettings; import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.executors.exceptions.ExecuteException; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.ReadOnlyAddressBook; import seedu.address.model.person.Person; @@ -16,12 +17,13 @@ public interface Logic { /** * Executes the command and returns the result. + * * @param commandText The command as entered by the user. * @return the result of the command execution. * @throws CommandException If an error occurs during command execution. * @throws ParseException If an error occurs during parsing. */ - CommandResult execute(String commandText) throws CommandException, ParseException; + CommandResult execute(String commandText) throws CommandException, ParseException, ExecuteException; /** * Returns the AddressBook. @@ -30,7 +32,9 @@ public interface Logic { */ ReadOnlyAddressBook getAddressBook(); - /** Returns an unmodifiable view of the filtered list of persons */ + /** + * Returns an unmodifiable view of the filtered list of persons + */ ObservableList getFilteredPersonList(); /** diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 9d9c6d15bdc..d59d7d2e56a 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -10,6 +10,7 @@ import seedu.address.logic.commands.Command; import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.executors.exceptions.ExecuteException; import seedu.address.logic.parser.AddressBookParser; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.Model; @@ -38,7 +39,7 @@ public LogicManager(Model model, Storage storage) { } @Override - public CommandResult execute(String commandText) throws CommandException, ParseException { + public CommandResult execute(String commandText) throws CommandException, ParseException, ExecuteException { logger.info("----------------[USER COMMAND][" + commandText + "]"); CommandResult commandResult; diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java index 9c86b1fa6e4..255644e59e6 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/seedu/address/logic/commands/ClearCommand.java @@ -9,11 +9,9 @@ * Clears the address book. */ public class ClearCommand extends Command { - public static final String COMMAND_WORD = "clear"; public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; - @Override public CommandResult execute(Model model) { requireNonNull(model); diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java index 64f18992160..4b76aa4ee4b 100644 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ b/src/main/java/seedu/address/logic/commands/Command.java @@ -1,20 +1,18 @@ package seedu.address.logic.commands; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.executors.exceptions.ExecuteException; import seedu.address.model.Model; /** * Represents a command with hidden internal logic and the ability to be executed. */ public abstract class Command { - /** * Executes the command and returns the result message. * - * @param model {@code Model} which the command should operate on. * @return feedback message of the operation result for display * @throws CommandException If an error occurs during command execution. */ - public abstract CommandResult execute(Model model) throws CommandException; - + public abstract CommandResult execute(Model model) throws CommandException, ExecuteException; } diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java index 92f900b7916..4f06a6069db 100644 --- a/src/main/java/seedu/address/logic/commands/CommandResult.java +++ b/src/main/java/seedu/address/logic/commands/CommandResult.java @@ -11,10 +11,14 @@ public class CommandResult { private final String feedbackToUser; - /** Help information should be shown to the user. */ + /** + * Help information should be shown to the user. + */ private final boolean showHelp; - /** The application should exit. */ + /** + * The application should exit. + */ private final boolean exit; /** diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java deleted file mode 100644 index 02fd256acba..00000000000 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -package seedu.address.logic.commands; - -import static java.util.Objects.requireNonNull; - -import java.util.List; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; - -/** - * Deletes a person identified using it's displayed index from the address book. - */ -public class DeleteCommand extends Command { - - public static final String COMMAND_WORD = "delete"; - - public static final String MESSAGE_USAGE = COMMAND_WORD - + ": Deletes the person identified by the index number used in the displayed person list.\n" - + "Parameters: INDEX (must be a positive integer)\n" - + "Example: " + COMMAND_WORD + " 1"; - - public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s"; - - private final Index targetIndex; - - public DeleteCommand(Index targetIndex) { - this.targetIndex = targetIndex; - } - - @Override - public CommandResult execute(Model model) throws CommandException { - requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); - - if (targetIndex.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - Person personToDelete = lastShownList.get(targetIndex.getZeroBased()); - model.deletePerson(personToDelete); - return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete)); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof DeleteCommand // instanceof handles nulls - && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check - } -} diff --git a/src/main/java/seedu/address/logic/commands/NoteCommand.java b/src/main/java/seedu/address/logic/commands/NoteCommand.java deleted file mode 100644 index 40592cb5738..00000000000 --- a/src/main/java/seedu/address/logic/commands/NoteCommand.java +++ /dev/null @@ -1,90 +0,0 @@ -package seedu.address.logic.commands; - -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; - -import java.util.List; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Note; -import seedu.address.model.person.Person; - -/** - * - */ -public class NoteCommand extends Command { - public static final String COMMAND_WORD = "note"; - - public static final String MESSAGE_ADD_NOTE_SUCCESS = "Added note to Person: %1$s"; - public static final String MESSAGE_DELETE_NOTE_SUCCESS = "Removed note from Person: %1$s"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the notes of the person identified " - + "by the index number used in the last person listing. " - + "Existing notes will be overwritten by the input.\n" - + "Parameters: INDEX (must be a positive integer) " - + PREFIX_NOTE + "[NOTE]\n" - + "Example: " + COMMAND_WORD + " 1 " - + PREFIX_NOTE + "Likes to swim."; - - private final Index index; - private final Note note; - - /** - * @param index Index of the person in currently displayed person list to edit note for. - * @param note New note to be updated to. - */ - public NoteCommand(Index index, Note note) { - requireAllNonNull(index, note); - - this.index = index; - this.note = note; - } - - @Override - public CommandResult execute(Model model) throws CommandException { - List lastShownList = model.getFilteredPersonList(); - - if (index.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - Person personToEdit = lastShownList.get(index.getZeroBased()); - Person editedPerson = new Person( - personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(), note, personToEdit.getTags()); - - model.setPerson(personToEdit, editedPerson); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - - return new CommandResult(generateSuccessMessage(editedPerson)); - } - - /** - * Generates a command execution success message based on whether - * the note is added to or removed from - * {@code personToEdit}. - */ - private String generateSuccessMessage(Person personToEdit) { - String message = !note.value.isEmpty() ? MESSAGE_ADD_NOTE_SUCCESS : MESSAGE_DELETE_NOTE_SUCCESS; - return String.format(message, personToEdit); - } - - @Override - public boolean equals(Object other) { - // short circuit if same object - if (other == this) { - return true; - } - // instanceof handles nulls - if (!(other instanceof NoteCommand)) { - return false; - } - // state check - NoteCommand e = (NoteCommand) other; - return index.equals(e.index) - && note.equals(e.note); - } -} diff --git a/src/main/java/seedu/address/logic/commands/TargetedCommand.java b/src/main/java/seedu/address/logic/commands/TargetedCommand.java new file mode 100644 index 00000000000..bf601637d57 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/TargetedCommand.java @@ -0,0 +1,14 @@ +package seedu.address.logic.commands; + +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.model.Model; + +public abstract class TargetedCommand extends Command { + public abstract CommandResult execute() throws CommandException, ExecuteException; + + @Override + public CommandResult execute(Model model) throws CommandException, ExecuteException { + return this.execute(); + } +} diff --git a/src/main/java/seedu/address/logic/commands/group/GroupCommand.java b/src/main/java/seedu/address/logic/commands/group/GroupCommand.java new file mode 100644 index 00000000000..d59eecf894c --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/group/GroupCommand.java @@ -0,0 +1,8 @@ +package seedu.address.logic.commands.group; + +import seedu.address.logic.commands.Command; +import seedu.address.model.group.Group; + +public abstract class GroupCommand extends Command { + private Group target; +} diff --git a/src/main/java/seedu/address/logic/commands/person/PersonCommand.java b/src/main/java/seedu/address/logic/commands/person/PersonCommand.java new file mode 100644 index 00000000000..4100c79983b --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/person/PersonCommand.java @@ -0,0 +1,30 @@ +package seedu.address.logic.commands.person; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.TargetedCommand; + +public abstract class PersonCommand extends TargetedCommand { + public static final String COMMAND_WORD = "person"; + protected final Index index; + + public PersonCommand(Index index) { + this.index = index; + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof PersonCommand)) { + return false; + } + + // state check + PersonCommand e = (PersonCommand) other; + return index.equals(e.index); + } +} diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/person/PersonCreateCommand.java similarity index 57% rename from src/main/java/seedu/address/logic/commands/AddCommand.java rename to src/main/java/seedu/address/logic/commands/person/PersonCreateCommand.java index a6cff3044b6..01b2814a747 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/person/PersonCreateCommand.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package seedu.address.logic.commands.person; import static java.util.Objects.requireNonNull; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; @@ -6,15 +6,17 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.logic.executors.person.PersonCreateExecutor; +import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.Person; /** * Adds a person to the address book. */ -public class AddCommand extends Command { - +public class PersonCreateCommand extends PersonCommand { public static final String COMMAND_WORD = "add"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. " @@ -30,35 +32,26 @@ public class AddCommand extends Command { + PREFIX_TAG + "friends " + PREFIX_TAG + "owesMoney"; - public static final String MESSAGE_SUCCESS = "New person added: %1$s"; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; - - private final Person toAdd; + private final PersonCreateExecutor executor; /** * Creates an AddCommand to add the specified {@code Person} */ - public AddCommand(Person person) { + public PersonCreateCommand(Index index, Person person) throws ParseException { + super(index); requireNonNull(person); - toAdd = person; + this.executor = new PersonCreateExecutor(index, person); } @Override - public CommandResult execute(Model model) throws CommandException { - requireNonNull(model); - - if (model.hasPerson(toAdd)) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); - } - - model.addPerson(toAdd); - return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); + public CommandResult execute() throws ExecuteException { + return executor.execute(); } @Override public boolean equals(Object other) { return other == this // short circuit if same object - || (other instanceof AddCommand // instanceof handles nulls - && toAdd.equals(((AddCommand) other).toAdd)); + || (other instanceof PersonCreateCommand // instanceof handles nulls + && executor.equals(((PersonCreateCommand) other).executor)); } } diff --git a/src/main/java/seedu/address/logic/commands/person/PersonDeleteCommand.java b/src/main/java/seedu/address/logic/commands/person/PersonDeleteCommand.java new file mode 100644 index 00000000000..50221863a04 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/person/PersonDeleteCommand.java @@ -0,0 +1,46 @@ +package seedu.address.logic.commands.person; + +import static java.util.Objects.requireNonNull; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.logic.executors.person.PersonDeleteExecutor; + +/** + * Deletes a person identified using it's displayed index from the address book. + */ +public class PersonDeleteCommand extends PersonCommand { + + public static final String COMMAND_WORD = "delete"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Deletes the person identified by the index number used in the displayed person list.\n" + + "Parameters: INDEX (must be a positive integer)\n" + + "Example: " + COMMAND_WORD + " 1"; + + private final PersonDeleteExecutor executor; + + /** + * Constructor for a PersonDeleteCommand. + * + * @param index Index of the person to be deleted. + */ + public PersonDeleteCommand(Index index) { + super(index); + requireNonNull(index); + this.executor = new PersonDeleteExecutor(index); + } + + @Override + public CommandResult execute() throws ExecuteException { + return executor.execute(); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof PersonDeleteCommand // instanceof handles nulls + && executor.equals(((PersonDeleteCommand) other).executor)); // state check + } +} diff --git a/src/main/java/seedu/address/logic/commands/person/PersonEditCommand.java b/src/main/java/seedu/address/logic/commands/person/PersonEditCommand.java new file mode 100644 index 00000000000..4e93879409a --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/person/PersonEditCommand.java @@ -0,0 +1,69 @@ +package seedu.address.logic.commands.person; + +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; +import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; +import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.logic.executors.person.PersonEditExecutor; +import seedu.address.logic.executors.person.PersonExecutor; + +/** + * Edits the details of an existing person in the address book. + */ +public class PersonEditCommand extends PersonCommand { + + public static final String COMMAND_WORD = "edit"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified " + + "by the index number used in the displayed person list. " + + "Existing values will be overwritten by the input values.\n" + + "Parameters: INDEX (must be a positive integer) " + + "[" + PREFIX_NAME + "NAME] " + + "[" + PREFIX_PHONE + "PHONE] " + + "[" + PREFIX_EMAIL + "EMAIL] " + + "[" + PREFIX_TAG + "TAG]...\n" + + "Example: " + COMMAND_WORD + " 1 " + + PREFIX_PHONE + "91234567 " + + PREFIX_EMAIL + "johndoe@example.com"; + + public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; + + private final PersonExecutor executor; + + /** + * @param index Index of the person in the filtered person list to edit. + * @param personEditDescriptor Details to edit the person with. + */ + public PersonEditCommand(Index index, PersonEditExecutor.PersonEditDescriptor personEditDescriptor) { + super(index); + requireAllNonNull(index, personEditDescriptor); + this.executor = new PersonEditExecutor(index, personEditDescriptor); + } + + @Override + public CommandResult execute() throws ExecuteException { + return executor.execute(); + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof PersonEditCommand)) { + return false; + } + + // state check + PersonEditCommand e = (PersonEditCommand) other; + return super.equals(other) && executor.equals(e.executor); + } +} diff --git a/src/main/java/seedu/address/logic/commands/person/PersonNoteCommand.java b/src/main/java/seedu/address/logic/commands/person/PersonNoteCommand.java new file mode 100644 index 00000000000..02522facb76 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/person/PersonNoteCommand.java @@ -0,0 +1,57 @@ +package seedu.address.logic.commands.person; + +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.logic.executors.person.PersonNoteExecutor; +import seedu.address.model.person.Note; + +/** + * + */ +public class PersonNoteCommand extends PersonCommand { + public static final String COMMAND_WORD = "note"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the notes of the person identified " + + "by the index number used in the last person listing. " + + "Existing notes will be overwritten by the input.\n" + + "Parameters: INDEX (must be a positive integer) " + + PREFIX_NOTE + "[NOTE]\n" + + "Example: " + COMMAND_WORD + " 1 " + + PREFIX_NOTE + "Likes to swim."; + + private final PersonNoteExecutor executor; + + /** + * @param index Index of the person to edit note for. + * @param note New note to be updated to. + */ + public PersonNoteCommand(Index index, Note note) { + super(index); + requireAllNonNull(index, note); + this.executor = new PersonNoteExecutor(index, note); + } + + @Override + public CommandResult execute() throws ExecuteException { + return executor.execute(); + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + // instanceof handles nulls + if (!(other instanceof PersonNoteCommand)) { + return false; + } + // state check + PersonNoteCommand e = (PersonNoteCommand) other; + return executor.equals(e.executor); + } +} diff --git a/src/main/java/seedu/address/logic/executors/Executor.java b/src/main/java/seedu/address/logic/executors/Executor.java new file mode 100644 index 00000000000..10f374c50fb --- /dev/null +++ b/src/main/java/seedu/address/logic/executors/Executor.java @@ -0,0 +1,18 @@ +package seedu.address.logic.executors; + +import static java.util.Objects.requireNonNull; + +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.model.Model; + +public abstract class Executor { + protected static Model model; + + public static void setup(Model model) { + requireNonNull(model); + Executor.model = model; + } + + public abstract CommandResult execute() throws ExecuteException; +} diff --git a/src/main/java/seedu/address/logic/executors/exceptions/ExecuteException.java b/src/main/java/seedu/address/logic/executors/exceptions/ExecuteException.java new file mode 100644 index 00000000000..584aebe055c --- /dev/null +++ b/src/main/java/seedu/address/logic/executors/exceptions/ExecuteException.java @@ -0,0 +1,15 @@ +package seedu.address.logic.executors.exceptions; + +/** + * Represents a parse error encountered by a parser. + */ +public class ExecuteException extends Exception { + + public ExecuteException(String message) { + super(message); + } + + public ExecuteException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/seedu/address/logic/executors/group/GroupExecutor.java b/src/main/java/seedu/address/logic/executors/group/GroupExecutor.java new file mode 100644 index 00000000000..af6468adf9a --- /dev/null +++ b/src/main/java/seedu/address/logic/executors/group/GroupExecutor.java @@ -0,0 +1,6 @@ +package seedu.address.logic.executors.group; + +import seedu.address.logic.executors.Executor; + +public abstract class GroupExecutor extends Executor { +} diff --git a/src/main/java/seedu/address/logic/executors/person/PersonCreateExecutor.java b/src/main/java/seedu/address/logic/executors/person/PersonCreateExecutor.java new file mode 100644 index 00000000000..01537621696 --- /dev/null +++ b/src/main/java/seedu/address/logic/executors/person/PersonCreateExecutor.java @@ -0,0 +1,58 @@ +package seedu.address.logic.executors.person; + +import static java.util.Objects.requireNonNull; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.model.person.Person; + +/** + * Executor for a PersonCreateCommand. + */ +public class PersonCreateExecutor extends PersonExecutor { + public static final String MESSAGE_SUCCESS = "New person added: %1$s"; + public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; + + protected Person person; + + /** + * Constructor for a PersonCreateExecutor instance. + * + * @param index Always null value for this command. Ignored for operations. + * @param person Person to be created. + */ + public PersonCreateExecutor(Index index, Person person) { + super(index); + requireNonNull(person); + this.person = person; + } + + @Override + public CommandResult execute() throws ExecuteException { + if (model.hasPerson(person)) { + throw new ExecuteException(MESSAGE_DUPLICATE_PERSON); + } + + model.createPerson(person); + return new CommandResult(String.format(MESSAGE_SUCCESS, person)); + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof PersonCreateExecutor)) { + return false; + } + + PersonCreateExecutor e = (PersonCreateExecutor) other; + + // state check + return super.equals(other) && person.equals(e.person); + } +} diff --git a/src/main/java/seedu/address/logic/executors/person/PersonDeleteExecutor.java b/src/main/java/seedu/address/logic/executors/person/PersonDeleteExecutor.java new file mode 100644 index 00000000000..30b7cb58ca0 --- /dev/null +++ b/src/main/java/seedu/address/logic/executors/person/PersonDeleteExecutor.java @@ -0,0 +1,21 @@ +package seedu.address.logic.executors.person; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.model.person.Person; + +public class PersonDeleteExecutor extends PersonExecutor { + public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s"; + + public PersonDeleteExecutor(Index index) { + super(index); + } + + @Override + public CommandResult execute() throws ExecuteException { + Person deletedPerson = super.getPerson(); + model.deletePerson(deletedPerson); + return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, deletedPerson)); + } +} diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/executors/person/PersonEditExecutor.java similarity index 56% rename from src/main/java/seedu/address/logic/commands/EditCommand.java rename to src/main/java/seedu/address/logic/executors/person/PersonEditExecutor.java index 6d55badb754..6a0fd3d0b83 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/executors/person/PersonEditExecutor.java @@ -1,23 +1,17 @@ -package seedu.address.logic.commands; +package seedu.address.logic.executors.person; -import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Optional; import java.util.Set; -import seedu.address.commons.core.Messages; import seedu.address.commons.core.index.Index; import seedu.address.commons.util.CollectionUtil; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; import seedu.address.model.person.Email; import seedu.address.model.person.Name; import seedu.address.model.person.Note; @@ -26,60 +20,36 @@ import seedu.address.model.tag.Tag; /** - * Edits the details of an existing person in the address book. + * Executor for a PersonEditCommand. */ -public class EditCommand extends Command { - - public static final String COMMAND_WORD = "edit"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified " - + "by the index number used in the displayed person list. " - + "Existing values will be overwritten by the input values.\n" - + "Parameters: INDEX (must be a positive integer) " - + "[" + PREFIX_NAME + "NAME] " - + "[" + PREFIX_PHONE + "PHONE] " - + "[" + PREFIX_EMAIL + "EMAIL] " - + "[" + PREFIX_TAG + "TAG]...\n" - + "Example: " + COMMAND_WORD + " 1 " - + PREFIX_PHONE + "91234567 " - + PREFIX_EMAIL + "johndoe@example.com"; - +public class PersonEditExecutor extends PersonExecutor { public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s"; - public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book."; - private final Index index; - private final EditPersonDescriptor editPersonDescriptor; + private final PersonEditDescriptor personEditDescriptor; /** - * @param index of the person in the filtered person list to edit - * @param editPersonDescriptor details to edit the person with + * Constructor for a PersonEditExecutor instance. + * + * @param index Index of the person to be edited. + * @param personEditDescriptor Descriptor for the edited person. */ - public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) { - requireNonNull(index); - requireNonNull(editPersonDescriptor); - - this.index = index; - this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor); + public PersonEditExecutor(Index index, PersonEditDescriptor personEditDescriptor) { + super(index); + requireAllNonNull(index, personEditDescriptor); + this.personEditDescriptor = personEditDescriptor; } @Override - public CommandResult execute(Model model) throws CommandException { - requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); - - if (index.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - Person personToEdit = lastShownList.get(index.getZeroBased()); - Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); + public CommandResult execute() throws ExecuteException { + Person person = super.getPerson(); + Person editedPerson = createEditedPerson(person, personEditDescriptor); - if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); + if (!person.isSame(editedPerson) && model.hasPerson(editedPerson)) { + throw new ExecuteException(MESSAGE_DUPLICATE_PERSON); } - model.setPerson(personToEdit, editedPerson); + model.setPerson(person, editedPerson); model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson)); } @@ -88,14 +58,14 @@ public CommandResult execute(Model model) throws CommandException { * Creates and returns a {@code Person} with the details of {@code personToEdit} * edited with {@code editPersonDescriptor}. */ - private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) { + private static Person createEditedPerson(Person personToEdit, PersonEditDescriptor personEditDescriptor) { assert personToEdit != null; - Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName()); - Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone()); - Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); - Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); - Note updatedNote = editPersonDescriptor.getNote().orElse(personToEdit.getNote()); + Name updatedName = personEditDescriptor.getName().orElse(personToEdit.getName()); + Phone updatedPhone = personEditDescriptor.getPhone().orElse(personToEdit.getPhone()); + Email updatedEmail = personEditDescriptor.getEmail().orElse(personToEdit.getEmail()); + Set updatedTags = personEditDescriptor.getTags().orElse(personToEdit.getTags()); + Note updatedNote = personEditDescriptor.getNote().orElse(personToEdit.getNote()); return new Person(updatedName, updatedPhone, updatedEmail, updatedNote, updatedTags); } @@ -108,34 +78,34 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof EditCommand)) { + if (!(other instanceof PersonEditExecutor)) { return false; } + PersonEditExecutor e = (PersonEditExecutor) other; + // state check - EditCommand e = (EditCommand) other; - return index.equals(e.index) - && editPersonDescriptor.equals(e.editPersonDescriptor); + return super.equals(other) && personEditDescriptor.equals(e.personEditDescriptor); } /** * Stores the details to edit the person with. Each non-empty field value will replace the * corresponding field value of the person. */ - public static class EditPersonDescriptor { + public static class PersonEditDescriptor { private Name name; private Phone phone; private Email email; private Set tags; private Note note; - public EditPersonDescriptor() {} + public PersonEditDescriptor() {} /** * Copy constructor. * A defensive copy of {@code tags} is used internally. */ - public EditPersonDescriptor(EditPersonDescriptor toCopy) { + public PersonEditDescriptor(PersonEditDescriptor toCopy) { setName(toCopy.name); setPhone(toCopy.phone); setEmail(toCopy.email); @@ -207,12 +177,12 @@ public boolean equals(Object other) { } // instanceof handles nulls - if (!(other instanceof EditPersonDescriptor)) { + if (!(other instanceof PersonEditDescriptor)) { return false; } // state check - EditPersonDescriptor e = (EditPersonDescriptor) other; + PersonEditDescriptor e = (PersonEditDescriptor) other; return getName().equals(e.getName()) && getPhone().equals(e.getPhone()) diff --git a/src/main/java/seedu/address/logic/executors/person/PersonExecutor.java b/src/main/java/seedu/address/logic/executors/person/PersonExecutor.java new file mode 100644 index 00000000000..1a883abdcc0 --- /dev/null +++ b/src/main/java/seedu/address/logic/executors/person/PersonExecutor.java @@ -0,0 +1,49 @@ +package seedu.address.logic.executors.person; + +import java.util.List; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.executors.Executor; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.model.person.Person; + +public abstract class PersonExecutor extends Executor { + protected final Index index; + + public PersonExecutor(Index index) { + this.index = index; + } + + protected Person getPerson() throws ExecuteException { + List lastShownList = model.getFilteredPersonList(); + + if (index.getZeroBased() >= lastShownList.size()) { + throw new ExecuteException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + return lastShownList.get(index.getZeroBased()); + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof PersonExecutor)) { + return false; + } + + PersonExecutor e = (PersonExecutor) other; + + if (index == null) { + return e.index == null; + } + + // state check + return index.equals(e.index); + } +} diff --git a/src/main/java/seedu/address/logic/executors/person/PersonNoteExecutor.java b/src/main/java/seedu/address/logic/executors/person/PersonNoteExecutor.java new file mode 100644 index 00000000000..c776f5d7add --- /dev/null +++ b/src/main/java/seedu/address/logic/executors/person/PersonNoteExecutor.java @@ -0,0 +1,72 @@ +package seedu.address.logic.executors.person; + +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.executors.exceptions.ExecuteException; +import seedu.address.model.person.Note; +import seedu.address.model.person.Person; + +/** + * Executor for a PersonNoteCommand. + */ +public class PersonNoteExecutor extends PersonExecutor { + public static final String MESSAGE_ADD_NOTE_SUCCESS = "Added note to Person: %1$s"; + public static final String MESSAGE_DELETE_NOTE_SUCCESS = "Removed note from Person: %1$s"; + + private final Note note; + + /** + * Constructor for a PersonNoteExecutor instance. + * + * @param index Index of the person to add a note to. + * @param note Note to be added to the person. + */ + public PersonNoteExecutor(Index index, Note note) { + super(index); + requireAllNonNull(index, note); + this.note = note; + } + + @Override + public CommandResult execute() throws ExecuteException { + Person storedPerson = super.getPerson(); + Person editedPerson = new Person( + storedPerson.getName(), storedPerson.getPhone(), storedPerson.getEmail(), note, storedPerson.getTags()); + + model.setPerson(storedPerson, editedPerson); + model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + + return new CommandResult(generateSuccessMessage(editedPerson)); + } + + /** + * Generates a command execution success message based on whether + * the note is added to or removed from + * {@code personToEdit}. + */ + private String generateSuccessMessage(Person personToEdit) { + String message = !note.value.isEmpty() ? MESSAGE_ADD_NOTE_SUCCESS : MESSAGE_DELETE_NOTE_SUCCESS; + return String.format(message, personToEdit); + } + + @Override + public boolean equals(Object other) { + // short circuit if same object + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof PersonNoteExecutor)) { + return false; + } + + PersonNoteExecutor e = (PersonNoteExecutor) other; + + // state check + return super.equals(other) && note.equals(e.note); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 412761f0230..c954b3e8584 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -6,23 +6,26 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import seedu.address.logic.commands.AddCommand; import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.Command; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.ExitCommand; import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; -import seedu.address.logic.commands.NoteCommand; +import seedu.address.logic.commands.person.PersonCreateCommand; +import seedu.address.logic.commands.person.PersonDeleteCommand; +import seedu.address.logic.commands.person.PersonEditCommand; +import seedu.address.logic.commands.person.PersonNoteCommand; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.logic.parser.person.PersonCreateCommandParser; +import seedu.address.logic.parser.person.PersonDeleteCommandParser; +import seedu.address.logic.parser.person.PersonEditCommandParser; +import seedu.address.logic.parser.person.PersonNoteCommandParser; /** * Parses user input. */ public class AddressBookParser { - /** * Used for initial separation of command word and args. */ @@ -43,16 +46,20 @@ public Command parseCommand(String userInput) throws ParseException { final String commandWord = matcher.group("commandWord"); final String arguments = matcher.group("arguments"); + switch (commandWord) { - case AddCommand.COMMAND_WORD: - return new AddCommandParser().parse(arguments); + case PersonCreateCommand.COMMAND_WORD: + return new PersonCreateCommandParser().parse(arguments); - case EditCommand.COMMAND_WORD: - return new EditCommandParser().parse(arguments); + case PersonEditCommand.COMMAND_WORD: + return new PersonEditCommandParser().parse(arguments); - case DeleteCommand.COMMAND_WORD: - return new DeleteCommandParser().parse(arguments); + case PersonDeleteCommand.COMMAND_WORD: + return new PersonDeleteCommandParser().parse(arguments); + + case PersonNoteCommand.COMMAND_WORD: + return new PersonNoteCommandParser().parse(arguments); case ClearCommand.COMMAND_WORD: return new ClearCommand(); @@ -69,9 +76,6 @@ public Command parseCommand(String userInput) throws ParseException { case HelpCommand.COMMAND_WORD: return new HelpCommand(); - case NoteCommand.COMMAND_WORD: - return new NoteCommandParser().parse(arguments); - default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java b/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java index 954c8e18f8e..0a150cc5a7c 100644 --- a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java +++ b/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java @@ -15,14 +15,16 @@ */ public class ArgumentMultimap { - /** Prefixes mapped to their respective arguments**/ + /** + * Prefixes mapped to their respective arguments + **/ private final Map> argMultimap = new HashMap<>(); /** * Associates the specified argument value with {@code prefix} key in this map. * If the map previously contained a mapping for the key, the new value is appended to the list of existing values. * - * @param prefix Prefix key with which the specified argument value is to be associated + * @param prefix Prefix key with which the specified argument value is to be associated * @param argValue Argument value to be associated with the specified prefix key */ public void put(Prefix prefix, String argValue) { diff --git a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java b/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java index 58fed1227d3..7f6cbece258 100644 --- a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java +++ b/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java @@ -8,11 +8,11 @@ /** * Tokenizes arguments string of the form: {@code preamble value value ...}
- * e.g. {@code some preamble text t/ 11.00 t/12.00 k/ m/ July} where prefixes are {@code t/ k/ m/}.
+ * e.g. {@code some preamble text t/ 11.00 t/12.00 k/ m/ July} where prefixes are {@code t/ k/ m/}.
* 1. An argument's value can be an empty string e.g. the value of {@code k/} in the above example.
* 2. Leading and trailing whitespaces of an argument value will be discarded.
* 3. An argument may be repeated and all its values will be accumulated e.g. the value of {@code t/} - * in the above example.
+ * in the above example.
*/ public class ArgumentTokenizer { @@ -21,8 +21,8 @@ public class ArgumentTokenizer { * respective argument values. Only the given prefixes will be recognized in the arguments string. * * @param argsString Arguments string of the form: {@code preamble value value ...} - * @param prefixes Prefixes to tokenize the arguments string with - * @return ArgumentMultimap object that maps prefixes to their arguments + * @param prefixes Prefixes to tokenize the arguments string with + * @return ArgumentMultimap object that maps prefixes to their arguments */ public static ArgumentMultimap tokenize(String argsString, Prefix... prefixes) { List positions = findAllPrefixPositions(argsString, prefixes); @@ -33,8 +33,8 @@ public static ArgumentMultimap tokenize(String argsString, Prefix... prefixes) { * Finds all zero-based prefix positions in the given arguments string. * * @param argsString Arguments string of the form: {@code preamble value value ...} - * @param prefixes Prefixes to find in the arguments string - * @return List of zero-based prefix positions in the given arguments string + * @param prefixes Prefixes to find in the arguments string + * @return List of zero-based prefix positions in the given arguments string */ private static List findAllPrefixPositions(String argsString, Prefix... prefixes) { return Arrays.stream(prefixes) @@ -81,9 +81,9 @@ private static int findPrefixPosition(String argsString, String prefix, int from * extracted prefixes to their respective arguments. Prefixes are extracted based on their zero-based positions in * {@code argsString}. * - * @param argsString Arguments string of the form: {@code preamble value value ...} + * @param argsString Arguments string of the form: {@code preamble value value ...} * @param prefixPositions Zero-based positions of all prefixes in {@code argsString} - * @return ArgumentMultimap object that maps prefixes to their arguments + * @return ArgumentMultimap object that maps prefixes to their arguments */ private static ArgumentMultimap extractArguments(String argsString, List prefixPositions) { @@ -115,8 +115,8 @@ private static ArgumentMultimap extractArguments(String argsString, List { - - /** - * Parses the given {@code String} of arguments in the context of the DeleteCommand - * and returns a DeleteCommand object for execution. - * @throws ParseException if the user input does not conform the expected format - */ - public DeleteCommand parse(String args) throws ParseException { - try { - Index index = ParserUtil.parseIndex(args); - return new DeleteCommand(index); - } catch (ParseException pe) { - throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe); - } - } - -} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 4fb71f23103..212cdd7cf7d 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -11,11 +11,12 @@ /** * Parses input arguments and creates a new FindCommand object */ -public class FindCommandParser implements Parser { +public class FindCommandParser extends Parser { /** * Parses the given {@code String} of arguments in the context of the FindCommand * and returns a FindCommand object for execution. + * * @throws ParseException if the user input does not conform the expected format */ public FindCommand parse(String args) throws ParseException { diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/seedu/address/logic/parser/Parser.java index d6551ad8e3f..6baf173c261 100644 --- a/src/main/java/seedu/address/logic/parser/Parser.java +++ b/src/main/java/seedu/address/logic/parser/Parser.java @@ -6,11 +6,11 @@ /** * Represents a Parser that is able to parse user input into a {@code Command} of type {@code T}. */ -public interface Parser { - +public abstract class Parser { /** * Parses {@code userInput} into a command and returns it. + * * @throws ParseException if {@code userInput} does not conform the expected format */ - T parse(String userInput) throws ParseException; + public abstract T parse(String userInput) throws ParseException; } diff --git a/src/main/java/seedu/address/logic/parser/group/GroupCommandParser.java b/src/main/java/seedu/address/logic/parser/group/GroupCommandParser.java new file mode 100644 index 00000000000..5a5c8eb62b4 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/group/GroupCommandParser.java @@ -0,0 +1,20 @@ +package seedu.address.logic.parser.group; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.group.GroupCommand; +import seedu.address.logic.parser.Parser; +import seedu.address.model.group.Group; + +public abstract class GroupCommandParser extends Parser { + /** + * TODO: Stub method. + */ + public Group parseGroup(Index index) { + // List lastShownList = model.getFilteredGroupList(); + // if (index.getZeroBased() >= lastShownList.size()) { + // throw new ParseException(Messages.MESSAGE_INVALID_GROUP_DISPLAYED_INDEX); + // } + // return lastShownList.get(index.getZeroBased()); + return null; + } +} diff --git a/src/main/java/seedu/address/logic/parser/person/PersonCommandParser.java b/src/main/java/seedu/address/logic/parser/person/PersonCommandParser.java new file mode 100644 index 00000000000..376c43b54c2 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/person/PersonCommandParser.java @@ -0,0 +1,35 @@ +package seedu.address.logic.parser.person; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.person.PersonCommand; +import seedu.address.logic.commands.person.PersonEditCommand; +import seedu.address.logic.parser.ArgumentMultimap; +import seedu.address.logic.parser.Parser; +import seedu.address.logic.parser.ParserUtil; +import seedu.address.logic.parser.exceptions.ParseException; + +public abstract class PersonCommandParser extends Parser { + protected Index parseIndex(ArgumentMultimap argMultimap) throws ParseException { + Index index; + try { + index = ParserUtil.parseIndex(argMultimap.getPreamble()); + } catch (ParseException pe) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, PersonEditCommand.MESSAGE_USAGE), + pe); + } + return index; + } + + protected Index parseIndex(String args) throws ParseException { + Index index; + try { + index = ParserUtil.parseIndex(args); + } catch (ParseException pe) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, PersonEditCommand.MESSAGE_USAGE), + pe); + } + return index; + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/person/PersonCreateCommandParser.java similarity index 77% rename from src/main/java/seedu/address/logic/parser/AddCommandParser.java rename to src/main/java/seedu/address/logic/parser/person/PersonCreateCommandParser.java index 302e2870c4a..63995b89907 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/person/PersonCreateCommandParser.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package seedu.address.logic.parser.person; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; @@ -9,7 +9,13 @@ import java.util.Set; import java.util.stream.Stream; -import seedu.address.logic.commands.AddCommand; +import seedu.address.logic.commands.person.PersonCommand; +import seedu.address.logic.commands.person.PersonCreateCommand; +import seedu.address.logic.parser.ArgumentMultimap; +import seedu.address.logic.parser.ArgumentTokenizer; +import seedu.address.logic.parser.Parser; +import seedu.address.logic.parser.ParserUtil; +import seedu.address.logic.parser.Prefix; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.Email; import seedu.address.model.person.Name; @@ -18,24 +24,20 @@ import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; -/** - * Parses input arguments and creates a new AddCommand object - */ -public class AddCommandParser implements Parser { - +public class PersonCreateCommandParser extends Parser { /** * Parses the given {@code String} of arguments in the context of the AddCommand * and returns an AddCommand object for execution. * * @throws ParseException if the user input does not conform the expected format */ - public AddCommand parse(String args) throws ParseException { + public PersonCreateCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_TAG); if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL) || !argMultimap.getPreamble().isEmpty()) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, PersonCreateCommand.MESSAGE_USAGE)); } assert argMultimap.getValue(PREFIX_NAME).isPresent(); @@ -50,7 +52,7 @@ public AddCommand parse(String args) throws ParseException { Person person = new Person(name, phone, email, note, tagList); - return new AddCommand(person); + return new PersonCreateCommand(null, person); } /** diff --git a/src/main/java/seedu/address/logic/parser/person/PersonDeleteCommandParser.java b/src/main/java/seedu/address/logic/parser/person/PersonDeleteCommandParser.java new file mode 100644 index 00000000000..1bfad7ee2ae --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/person/PersonDeleteCommandParser.java @@ -0,0 +1,24 @@ +package seedu.address.logic.parser.person; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.person.PersonDeleteCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +public class PersonDeleteCommandParser extends PersonCommandParser { + /** + * Parses the given {@code String} of arguments in the context of the DeleteCommand + * and returns a DeleteCommand object for execution. + * + * @throws ParseException if the user input does not conform the expected format + */ + public PersonDeleteCommand parse(String args) throws ParseException { + try { + Index index = super.parseIndex(args); + return new PersonDeleteCommand(index); + } catch (ParseException pe) { + throw new ParseException( + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, PersonDeleteCommand.MESSAGE_USAGE), pe); + } + } +} diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/person/PersonEditCommandParser.java similarity index 62% rename from src/main/java/seedu/address/logic/parser/EditCommandParser.java rename to src/main/java/seedu/address/logic/parser/person/PersonEditCommandParser.java index bdfe5ad1978..adcfefab76f 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/person/PersonEditCommandParser.java @@ -1,7 +1,6 @@ -package seedu.address.logic.parser; +package seedu.address.logic.parser.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; @@ -12,23 +11,24 @@ import java.util.Optional; import java.util.Set; +import seedu.address.commons.core.Messages; import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; +import seedu.address.logic.commands.person.PersonEditCommand; +import seedu.address.logic.executors.person.PersonEditExecutor; +import seedu.address.logic.parser.ArgumentMultimap; +import seedu.address.logic.parser.ArgumentTokenizer; +import seedu.address.logic.parser.ParserUtil; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.tag.Tag; -/** - * Parses input arguments and creates a new EditCommand object - */ -public class EditCommandParser implements Parser { - +public class PersonEditCommandParser extends PersonCommandParser { /** * Parses the given {@code String} of arguments in the context of the EditCommand * and returns an EditCommand object for execution. + * * @throws ParseException if the user input does not conform the expected format */ - public EditCommand parse(String args) throws ParseException { + public PersonEditCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_TAG); @@ -36,28 +36,29 @@ public EditCommand parse(String args) throws ParseException { Index index; try { - index = ParserUtil.parseIndex(argMultimap.getPreamble()); + index = super.parseIndex(argMultimap); } catch (ParseException pe) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe); + throw new ParseException( + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, PersonEditCommand.MESSAGE_USAGE), pe); } - EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); + PersonEditExecutor.PersonEditDescriptor personEditDescriptor = new PersonEditExecutor.PersonEditDescriptor(); if (argMultimap.getValue(PREFIX_NAME).isPresent()) { - editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get())); + personEditDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get())); } if (argMultimap.getValue(PREFIX_PHONE).isPresent()) { - editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get())); + personEditDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get())); } if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) { - editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get())); + personEditDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get())); } - parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); + parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(personEditDescriptor::setTags); - if (!editPersonDescriptor.isAnyFieldEdited()) { - throw new ParseException(EditCommand.MESSAGE_NOT_EDITED); + if (!personEditDescriptor.isAnyFieldEdited()) { + throw new ParseException(PersonEditCommand.MESSAGE_NOT_EDITED); } - return new EditCommand(index, editPersonDescriptor); + return new PersonEditCommand(index, personEditDescriptor); } /** @@ -74,5 +75,4 @@ private Optional> parseTagsForEdit(Collection tags) throws Pars Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags; return Optional.of(ParserUtil.parseTags(tagSet)); } - } diff --git a/src/main/java/seedu/address/logic/parser/NoteCommandParser.java b/src/main/java/seedu/address/logic/parser/person/PersonNoteCommandParser.java similarity index 54% rename from src/main/java/seedu/address/logic/parser/NoteCommandParser.java rename to src/main/java/seedu/address/logic/parser/person/PersonNoteCommandParser.java index ecb56312c30..0eeadc8637f 100644 --- a/src/main/java/seedu/address/logic/parser/NoteCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/person/PersonNoteCommandParser.java @@ -1,38 +1,39 @@ -package seedu.address.logic.parser; +package seedu.address.logic.parser.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE; +import seedu.address.commons.core.Messages; import seedu.address.commons.core.index.Index; import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.logic.commands.NoteCommand; +import seedu.address.logic.commands.person.PersonNoteCommand; +import seedu.address.logic.parser.ArgumentMultimap; +import seedu.address.logic.parser.ArgumentTokenizer; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.Note; -public class NoteCommandParser implements Parser { - +public class PersonNoteCommandParser extends PersonCommandParser { /** * Parses the given {@code String} of arguments in the context of the NoteCommand * and returns a NoteCommand object for execution. * * @throws ParseException if the user input does not conform the expected format */ - public NoteCommand parse(String args) throws ParseException { + public PersonNoteCommand parse(String args) throws ParseException { requireNonNull(args); - ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, - PREFIX_NOTE); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NOTE); Index index; + try { - index = ParserUtil.parseIndex(argMultimap.getPreamble()); + index = super.parseIndex(argMultimap.getPreamble()); } catch (IllegalValueException ive) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, - NoteCommand.MESSAGE_USAGE), ive); + throw new ParseException(String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + PersonNoteCommand.MESSAGE_USAGE), ive); } String note = argMultimap.getValue(PREFIX_NOTE).orElse(""); - return new NoteCommand(index, new Note(note)); + return new PersonNoteCommand(index, new Note(note)); } } diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index 1a943a0781a..fd75a113ee4 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -3,10 +3,12 @@ import static java.util.Objects.requireNonNull; import java.util.List; +import java.util.Objects; import javafx.collections.ObservableList; +import seedu.address.model.group.Group; import seedu.address.model.person.Person; -import seedu.address.model.person.UniquePersonList; +import seedu.address.model.util.UniqueList; /** * Wraps all data at the address-book level @@ -14,8 +16,10 @@ */ public class AddressBook implements ReadOnlyAddressBook { - private final UniquePersonList persons; + private final UniqueList persons; + private final UniqueList groups; + // @formatter:off /* * 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 @@ -24,7 +28,8 @@ public class AddressBook implements ReadOnlyAddressBook { * among constructors. */ { - persons = new UniquePersonList(); + persons = new UniqueList<>(); + groups = new UniqueList<>(); } public AddressBook() {} @@ -44,7 +49,11 @@ public AddressBook(ReadOnlyAddressBook toBeCopied) { * {@code persons} must not contain duplicate persons. */ public void setPersons(List persons) { - this.persons.setPersons(persons); + this.persons.setItems(persons); + } + + public void setGroups(List groups) { + this.groups.setItems(groups); } /** @@ -54,6 +63,7 @@ public void resetData(ReadOnlyAddressBook newData) { requireNonNull(newData); setPersons(newData.getPersonList()); + setGroups(newData.getGroupList()); } //// person-level operations @@ -66,12 +76,28 @@ public boolean hasPerson(Person person) { return persons.contains(person); } + /** + * Returns true if a group with the same identity as {@code group} exists in the address book. + */ + public boolean hasGroup(Group group) { + requireNonNull(group); + return groups.contains(group); + } + /** * Adds a person to the address book. * The person must not already exist in the address book. */ - public void addPerson(Person p) { - persons.add(p); + public void addPerson(Person person) { + persons.add(person); + } + + /** + * Adds a group to the address book. + * The group must not already exist in the address book. + */ + public void addGroup(Group group) { + groups.add(group); } /** @@ -82,7 +108,18 @@ public void addPerson(Person p) { public void setPerson(Person target, Person editedPerson) { requireNonNull(editedPerson); - persons.setPerson(target, editedPerson); + persons.setItem(target, editedPerson); + } + + /** + * Replaces the given group {@code target} in the list with {@code editedGroup}. + * {@code target} must exist in the address book. + * The group identity of {@code editedGroup} must not be the same as another existing group in the address book. + */ + public void setGroup(Group target, Group editedGroup) { + requireNonNull(editedGroup); + + groups.setItem(target, editedGroup); } /** @@ -93,11 +130,20 @@ public void removePerson(Person key) { persons.remove(key); } + /** + * Removes {@code key} from this {@code AddressBook}. + * {@code key} must exist in the address book. + */ + public void removeGroup(Group key) { + groups.remove(key); + } + //// util methods @Override public String toString() { - return persons.asUnmodifiableObservableList().size() + " persons"; + return persons.asUnmodifiableObservableList().size() + " persons, " + + groups.asUnmodifiableObservableList().size() + " groups"; // TODO: refine later } @@ -106,15 +152,21 @@ public ObservableList getPersonList() { return persons.asUnmodifiableObservableList(); } + @Override + public ObservableList getGroupList() { + return groups.asUnmodifiableObservableList(); + } + @Override public boolean equals(Object other) { return other == this // short circuit if same object || (other instanceof AddressBook // instanceof handles nulls - && persons.equals(((AddressBook) other).persons)); + && persons.equals(((AddressBook) other).persons) + && groups.equals(((AddressBook) other).groups)); } @Override public int hashCode() { - return persons.hashCode(); + return Objects.hash(persons, groups); } } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index d54df471c1f..ca99dab33e4 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -5,15 +5,20 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; +import seedu.address.model.group.Group; import seedu.address.model.person.Person; /** * The API of the Model component. */ public interface Model { - /** {@code Predicate} that always evaluate to true */ + /** + * {@code Predicate} that always evaluate to true + */ Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; + Predicate PREDICATE_SHOW_ALL_GROUPS = unused -> true; + /** * Replaces user prefs data with the data in {@code userPrefs}. */ @@ -49,7 +54,9 @@ public interface Model { */ void setAddressBook(ReadOnlyAddressBook addressBook); - /** Returns the AddressBook */ + /** + * Returns the AddressBook + */ ReadOnlyAddressBook getAddressBook(); /** @@ -57,17 +64,23 @@ public interface Model { */ boolean hasPerson(Person person); + boolean hasGroup(Group group); + /** * Deletes the given person. * The person must exist in the address book. */ void deletePerson(Person target); + void deleteGroup(Group target); + /** * Adds the given person. * {@code person} must not already exist in the address book. */ - void addPerson(Person person); + void createPerson(Person person); + + void createGroup(Group group); /** * Replaces the given person {@code target} with {@code editedPerson}. @@ -76,12 +89,21 @@ public interface Model { */ void setPerson(Person target, Person editedPerson); - /** Returns an unmodifiable view of the filtered person list */ + void setGroup(Group group, Group editedGroup); + + /** + * Returns an unmodifiable view of the filtered person list + */ ObservableList getFilteredPersonList(); + ObservableList getFilteredGroupList(); + /** * Updates the filter of the filtered person list to filter by the given {@code predicate}. + * * @throws NullPointerException if {@code predicate} is null. */ void updateFilteredPersonList(Predicate predicate); + + void updateFilteredGroupList(Predicate predicate); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 0650c954f5c..565caaf035a 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -11,6 +11,7 @@ import javafx.collections.transformation.FilteredList; import seedu.address.commons.core.GuiSettings; import seedu.address.commons.core.LogsCenter; +import seedu.address.model.group.Group; import seedu.address.model.person.Person; /** @@ -22,6 +23,7 @@ public class ModelManager implements Model { private final AddressBook addressBook; private final UserPrefs userPrefs; private final FilteredList filteredPersons; + private final FilteredList filteredGroups; /** * Initializes a ModelManager with the given addressBook and userPrefs. @@ -35,6 +37,7 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs this.addressBook = new AddressBook(addressBook); this.userPrefs = new UserPrefs(userPrefs); filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); + filteredGroups = new FilteredList<>(this.addressBook.getGroupList()); } public ModelManager() { @@ -94,17 +97,34 @@ public boolean hasPerson(Person person) { return addressBook.hasPerson(person); } + @Override + public boolean hasGroup(Group group) { + requireNonNull(group); + return addressBook.hasGroup(group); + } + @Override public void deletePerson(Person target) { addressBook.removePerson(target); } @Override - public void addPerson(Person person) { + public void deleteGroup(Group target) { + addressBook.removeGroup(target); + } + + @Override + public void createPerson(Person person) { addressBook.addPerson(person); updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); } + @Override + public void createGroup(Group group) { + addressBook.addGroup(group); + updateFilteredGroupList(PREDICATE_SHOW_ALL_GROUPS); + } + @Override public void setPerson(Person target, Person editedPerson) { requireAllNonNull(target, editedPerson); @@ -112,6 +132,12 @@ public void setPerson(Person target, Person editedPerson) { addressBook.setPerson(target, editedPerson); } + @Override public void setGroup(Group target, Group editedGroup) { + requireAllNonNull(target, editedGroup); + + addressBook.setGroup(target, editedGroup); + } + //=========== Filtered Person List Accessors ============================================================= /** @@ -123,12 +149,23 @@ public ObservableList getFilteredPersonList() { return filteredPersons; } + @Override + public ObservableList getFilteredGroupList() { + return filteredGroups; + } + @Override public void updateFilteredPersonList(Predicate predicate) { requireNonNull(predicate); filteredPersons.setPredicate(predicate); } + @Override + public void updateFilteredGroupList(Predicate predicate) { + requireNonNull(predicate); + filteredGroups.setPredicate(predicate); + } + @Override public boolean equals(Object obj) { // short circuit if same object diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java index 6ddc2cd9a29..d1bad685bf3 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java @@ -1,6 +1,7 @@ package seedu.address.model; import javafx.collections.ObservableList; +import seedu.address.model.group.Group; import seedu.address.model.person.Person; /** @@ -14,4 +15,10 @@ public interface ReadOnlyAddressBook { */ ObservableList getPersonList(); + /** + * Returns an unmodifiable view of the groups list. + * This list will not contain any duplicate groups. + */ + ObservableList getGroupList(); + } diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java index 7d9ab5b1f3c..0bff4393cf0 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" , "notor.json"); + private Path addressBookFilePath = Paths.get("data", "notor.json"); /** * Creates a {@code UserPrefs} with default values. diff --git a/src/main/java/seedu/address/model/exceptions/DuplicateItemException.java b/src/main/java/seedu/address/model/exceptions/DuplicateItemException.java new file mode 100644 index 00000000000..47170e71cf4 --- /dev/null +++ b/src/main/java/seedu/address/model/exceptions/DuplicateItemException.java @@ -0,0 +1,11 @@ +package seedu.address.model.exceptions; + +/** + * Signals that the operation will result in duplicate Persons/Groups (Persons/Groups are considered duplicates if they + * have the same identity). + */ +public class DuplicateItemException extends RuntimeException { + public DuplicateItemException() { + super("Operation would result in duplicated persons/groups."); + } +} diff --git a/src/main/java/seedu/address/model/exceptions/ItemNotFoundException.java b/src/main/java/seedu/address/model/exceptions/ItemNotFoundException.java new file mode 100644 index 00000000000..939fa4a52a1 --- /dev/null +++ b/src/main/java/seedu/address/model/exceptions/ItemNotFoundException.java @@ -0,0 +1,6 @@ +package seedu.address.model.exceptions; + +/** + * Signals that the operation is unable to find the specified person/group. + */ +public class ItemNotFoundException extends RuntimeException {} diff --git a/src/main/java/seedu/address/model/group/Group.java b/src/main/java/seedu/address/model/group/Group.java new file mode 100644 index 00000000000..c38e9ce7187 --- /dev/null +++ b/src/main/java/seedu/address/model/group/Group.java @@ -0,0 +1,20 @@ +package seedu.address.model.group; + +import seedu.address.model.util.Unique; + +/** + * Stub class right now, used to make commands. + */ +public class Group implements Unique { + + /** + * Stub implementation, just allows all groups to be added. + * + * @param other Other group to check for similarity. + * @return Whether the other group is the same as the current group. + */ + @Override + public boolean isSame(Group other) { + return false; + } +} diff --git a/src/main/java/seedu/address/model/group/SubGroup.java b/src/main/java/seedu/address/model/group/SubGroup.java new file mode 100644 index 00000000000..329e4adff7d --- /dev/null +++ b/src/main/java/seedu/address/model/group/SubGroup.java @@ -0,0 +1,4 @@ +package seedu.address.model.group; + +public class SubGroup extends Group { +} diff --git a/src/main/java/seedu/address/model/group/SuperGroup.java b/src/main/java/seedu/address/model/group/SuperGroup.java new file mode 100644 index 00000000000..31b4b013528 --- /dev/null +++ b/src/main/java/seedu/address/model/group/SuperGroup.java @@ -0,0 +1,7 @@ +package seedu.address.model.group; + +import java.util.List; + +public class SuperGroup extends Group { + private List children; +} diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index 73c519503c3..e856af0206a 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -8,12 +8,13 @@ import java.util.Set; import seedu.address.model.tag.Tag; +import seedu.address.model.util.Unique; /** * Represents a Person in the address book. * Guarantees: details are present and not null, field values are validated, immutable. */ -public class Person { +public class Person implements Unique { // Identity fields private final Name name; @@ -64,7 +65,7 @@ public Set getTags() { * Returns true if both persons have the same name. * This defines a weaker notion of equality between two persons. */ - public boolean isSamePerson(Person otherPerson) { + public boolean isSame(Person otherPerson) { if (otherPerson == this) { return true; } diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/person/UniquePersonList.java deleted file mode 100644 index 0fee4fe57e6..00000000000 --- a/src/main/java/seedu/address/model/person/UniquePersonList.java +++ /dev/null @@ -1,137 +0,0 @@ -package seedu.address.model.person; - -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.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; - -/** - * A list of persons that enforces uniqueness between its elements and does not allow nulls. - * A person is considered unique by comparing using {@code Person#isSamePerson(Person)}. As such, adding and updating of - * persons uses Person#isSamePerson(Person) for equality so as to ensure that the person being added or updated is - * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) so - * as to ensure that the person with exactly the same fields will be removed. - * - * Supports a minimal set of list operations. - * - * @see Person#isSamePerson(Person) - */ -public class UniquePersonList implements Iterable { - - private final ObservableList internalList = FXCollections.observableArrayList(); - private final ObservableList internalUnmodifiableList = - FXCollections.unmodifiableObservableList(internalList); - - /** - * Returns true if the list contains an equivalent person as the given argument. - */ - public boolean contains(Person toCheck) { - requireNonNull(toCheck); - return internalList.stream().anyMatch(toCheck::isSamePerson); - } - - /** - * Adds a person to the list. - * The person must not already exist in the list. - */ - public void add(Person toAdd) { - requireNonNull(toAdd); - if (contains(toAdd)) { - throw new DuplicatePersonException(); - } - internalList.add(toAdd); - } - - /** - * Replaces the person {@code target} in the list with {@code editedPerson}. - * {@code target} must exist in the list. - * The person identity of {@code editedPerson} must not be the same as another existing person in the list. - */ - public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); - - int index = internalList.indexOf(target); - if (index == -1) { - throw new PersonNotFoundException(); - } - - if (!target.isSamePerson(editedPerson) && contains(editedPerson)) { - throw new DuplicatePersonException(); - } - - internalList.set(index, editedPerson); - } - - /** - * Removes the equivalent person from the list. - * The person must exist in the list. - */ - public void remove(Person toRemove) { - requireNonNull(toRemove); - if (!internalList.remove(toRemove)) { - throw new PersonNotFoundException(); - } - } - - public void setPersons(UniquePersonList replacement) { - requireNonNull(replacement); - internalList.setAll(replacement.internalList); - } - - /** - * Replaces the contents of this list with {@code persons}. - * {@code persons} must not contain duplicate persons. - */ - public void setPersons(List persons) { - requireAllNonNull(persons); - if (!personsAreUnique(persons)) { - throw new DuplicatePersonException(); - } - - internalList.setAll(persons); - } - - /** - * 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 UniquePersonList // instanceof handles nulls - && internalList.equals(((UniquePersonList) other).internalList)); - } - - @Override - public int hashCode() { - return internalList.hashCode(); - } - - /** - * Returns true if {@code persons} contains only unique persons. - */ - private boolean personsAreUnique(List persons) { - for (int i = 0; i < persons.size() - 1; i++) { - for (int j = i + 1; j < persons.size(); j++) { - if (persons.get(i).isSamePerson(persons.get(j))) { - return false; - } - } - } - return true; - } -} diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java deleted file mode 100644 index d7290f59442..00000000000 --- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java +++ /dev/null @@ -1,11 +0,0 @@ -package seedu.address.model.person.exceptions; - -/** - * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same - * identity). - */ -public class DuplicatePersonException extends RuntimeException { - public DuplicatePersonException() { - super("Operation would result in duplicate persons"); - } -} diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java deleted file mode 100644 index fa764426ca7..00000000000 --- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java +++ /dev/null @@ -1,6 +0,0 @@ -package seedu.address.model.person.exceptions; - -/** - * Signals that the operation is unable to find the specified person. - */ -public class PersonNotFoundException extends RuntimeException {} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index 828f52b4ed3..f76942c835e 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -19,6 +19,7 @@ public class SampleDataUtil { public static final Note EMPTY_NOTE = new Note(""); + // @formatter:off public static Person[] getSamplePersons() { return new Person[]{ new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), diff --git a/src/main/java/seedu/address/model/util/Unique.java b/src/main/java/seedu/address/model/util/Unique.java new file mode 100644 index 00000000000..706ba7b78fe --- /dev/null +++ b/src/main/java/seedu/address/model/util/Unique.java @@ -0,0 +1,5 @@ +package seedu.address.model.util; + +public interface Unique { + boolean isSame(T other); +} diff --git a/src/main/java/seedu/address/model/util/UniqueList.java b/src/main/java/seedu/address/model/util/UniqueList.java new file mode 100644 index 00000000000..86d3aba4113 --- /dev/null +++ b/src/main/java/seedu/address/model/util/UniqueList.java @@ -0,0 +1,125 @@ +package seedu.address.model.util; + +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.exceptions.DuplicateItemException; +import seedu.address.model.exceptions.ItemNotFoundException; + +public class UniqueList> implements Iterable { + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = + FXCollections.unmodifiableObservableList(internalList); + + /** + * Returns true if the list contains an equivalent item as the given argument. + */ + public boolean contains(T toCheck) { + requireNonNull(toCheck); + return internalList.stream().anyMatch(toCheck::isSame); + } + + /** + * Adds an item to the list. + * The item must not already exist in the list. + */ + public void add(T toAdd) { + requireNonNull(toAdd); + if (contains(toAdd)) { + throw new DuplicateItemException(); + } + internalList.add(toAdd); + } + + /** + * Replaces the item {@code target} in the list with {@code editedItem}. + * {@code target} must exist in the list. + * The item {@code editedItem} must not be the same as another existing item in the list. + */ + public void setItem(T target, T editedItem) { + requireAllNonNull(target, editedItem); + + int index = internalList.indexOf(target); + if (index == -1) { + throw new ItemNotFoundException(); + } + + if (!target.isSame(editedItem) && contains(editedItem)) { + throw new DuplicateItemException(); + } + + internalList.set(index, editedItem); + } + + /** + * Removes the equivalent person from the list. + * The person must exist in the list. + */ + public void remove(T toRemove) { + requireNonNull(toRemove); + if (!internalList.remove(toRemove)) { + throw new ItemNotFoundException(); + } + } + + public void setItems(UniqueList replacement) { + requireNonNull(replacement); + internalList.setAll(replacement.internalList); + } + + /** + * Replaces the contents of this list with {@code persons}. + * {@code persons} must not contain duplicate persons. + */ + public void setItems(List items) { + requireAllNonNull(items); + if (!onlyContainsUnique(items)) { + throw new DuplicateItemException(); + } + + internalList.setAll(items); + } + + /** + * 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 UniqueList // instanceof handles nulls + && internalList.equals(((UniqueList) other).internalList)); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } + + /** + * Returns true if {@code persons} contains only unique persons. + */ + private boolean onlyContainsUnique(List items) { + for (int i = 0; i < items.size() - 1; i++) { + for (int j = i + 1; j < items.size(); j++) { + if (items.get(i).isSame(items.get(j))) { + return false; + } + } + } + return true; + } +} diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java index 4599182b3f9..ee4cf2c0e74 100644 --- a/src/main/java/seedu/address/storage/AddressBookStorage.java +++ b/src/main/java/seedu/address/storage/AddressBookStorage.java @@ -19,7 +19,8 @@ public interface AddressBookStorage { /** * Returns AddressBook data as a {@link ReadOnlyAddressBook}. - * Returns {@code Optional.empty()} if storage file is not found. + * Returns {@code Optional.empty()} if storage file is not found. + * * @throws DataConversionException if the data in storage is not in the expected format. * @throws IOException if there was any problem when reading from the storage. */ @@ -32,6 +33,7 @@ public interface AddressBookStorage { /** * Saves the given {@link ReadOnlyAddressBook} to the storage. + * * @param addressBook cannot be null. * @throws IOException if there was any problem writing to the file. */ diff --git a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java b/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java index 83dc3452394..40f48a3fbe9 100644 --- a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java +++ b/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java @@ -32,6 +32,7 @@ public Optional readUserPrefs() throws DataConversionException { /** * Similar to {@link #readUserPrefs()} + * * @param prefsFilePath location of the data. Cannot be null. * @throws DataConversionException if the file format is not as expected. */ diff --git a/src/main/java/seedu/address/storage/UserPrefsStorage.java b/src/main/java/seedu/address/storage/UserPrefsStorage.java index 29eef178dbc..1eb07ff2880 100644 --- a/src/main/java/seedu/address/storage/UserPrefsStorage.java +++ b/src/main/java/seedu/address/storage/UserPrefsStorage.java @@ -20,7 +20,8 @@ public interface UserPrefsStorage { /** * Returns UserPrefs data from storage. - * Returns {@code Optional.empty()} if storage file is not found. + * Returns {@code Optional.empty()} if storage file is not found. + * * @throws DataConversionException if the data in storage is not in the expected format. * @throws IOException if there was any problem when reading from the storage. */ @@ -28,6 +29,7 @@ public interface UserPrefsStorage { /** * Saves the given {@link seedu.address.model.ReadOnlyUserPrefs} to the storage. + * * @param userPrefs cannot be null. * @throws IOException if there was any problem writing to the file. */ diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/seedu/address/ui/CommandBox.java index 9e75478664b..1f4ccfe9fde 100644 --- a/src/main/java/seedu/address/ui/CommandBox.java +++ b/src/main/java/seedu/address/ui/CommandBox.java @@ -6,6 +6,7 @@ import javafx.scene.layout.Region; import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.executors.exceptions.ExecuteException; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -44,7 +45,7 @@ private void handleCommandEntered() { try { commandExecutor.execute(commandText); commandTextField.setText(""); - } catch (CommandException | ParseException e) { + } catch (CommandException | ParseException | ExecuteException e) { setStyleToIndicateCommandFailure(); } } @@ -79,7 +80,7 @@ public interface CommandExecutor { * * @see seedu.address.logic.Logic#execute(String) */ - CommandResult execute(String commandText) throws CommandException, ParseException; + CommandResult execute(String commandText) throws CommandException, ParseException, ExecuteException; } } diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/seedu/address/ui/HelpWindow.java index 9a665915949..e5ea7399918 100644 --- a/src/main/java/seedu/address/ui/HelpWindow.java +++ b/src/main/java/seedu/address/ui/HelpWindow.java @@ -46,20 +46,20 @@ public HelpWindow() { /** * Shows the help window. - * @throws IllegalStateException - *
    - *
  • - * if this method is called on a thread other than the JavaFX Application Thread. - *
  • - *
  • - * if this method is called during animation or layout processing. - *
  • - *
  • - * if this method is called on the primary stage. - *
  • - *
  • - * if {@code dialogStage} is already showing. - *
  • + * + * @throws IllegalStateException
      + *
    • + * if this method is called on a thread other than the JavaFX Application Thread. + *
    • + *
    • + * if this method is called during animation or layout processing. + *
    • + *
    • + * if this method is called on the primary stage. + *
    • + *
    • + * if {@code dialogStage} is already showing. + *
    • *
    */ public void show() { diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 54c2be3d6bc..f44f45130c5 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -15,6 +15,7 @@ import seedu.address.logic.Logic; import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.executors.exceptions.ExecuteException; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -78,6 +79,7 @@ private void setAccelerators() { /** * Sets the accelerator of a MenuItem. + * * @param keyCombination the KeyCombination value of the accelerator */ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) { @@ -172,7 +174,7 @@ public PersonListPanel getPersonListPanel() { * * @see seedu.address.logic.Logic#execute(String) */ - private CommandResult executeCommand(String commandText) throws CommandException, ParseException { + private CommandResult executeCommand(String commandText) throws CommandException, ParseException, ExecuteException { try { CommandResult commandResult = logic.execute(commandText); logger.info("Result: " + commandResult.getFeedbackToUser()); @@ -187,7 +189,7 @@ private CommandResult executeCommand(String commandText) throws CommandException } return commandResult; - } catch (CommandException | ParseException e) { + } catch (CommandException | ParseException | ExecuteException e) { logger.info("Invalid command: " + commandText); resultDisplay.setFeedbackToUser(e.getMessage()); throw e; diff --git a/src/main/java/seedu/address/ui/Ui.java b/src/main/java/seedu/address/ui/Ui.java index 17aa0b494fe..e28dae7e990 100644 --- a/src/main/java/seedu/address/ui/Ui.java +++ b/src/main/java/seedu/address/ui/Ui.java @@ -7,7 +7,9 @@ */ public interface Ui { - /** Starts the UI (and the App). */ + /** + * Starts the UI (and the App). + */ void start(Stage primaryStage); } diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/address/ui/UiManager.java index b67b0ba1a22..beb1d21b108 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/seedu/address/ui/UiManager.java @@ -64,7 +64,7 @@ void showAlertDialogAndWait(Alert.AlertType type, String title, String headerTex * This method only returns after the user has closed the alert dialog. */ private static void showAlertDialogAndWait(Stage owner, AlertType type, String title, String headerText, - String contentText) { + String contentText) { final Alert alert = new Alert(type); alert.getDialogPane().getStylesheets().add("view/DarkTheme.css"); alert.initOwner(owner); diff --git a/src/main/java/seedu/address/ui/UiPart.java b/src/main/java/seedu/address/ui/UiPart.java index fc820e01a9c..2231075051b 100644 --- a/src/main/java/seedu/address/ui/UiPart.java +++ b/src/main/java/seedu/address/ui/UiPart.java @@ -14,7 +14,9 @@ */ public abstract class UiPart { - /** Resource folder where FXML files are stored. */ + /** + * Resource folder where FXML files are stored. + */ public static final String FXML_FILE_FOLDER = "/view/"; private final FXMLLoader fxmlLoader = new FXMLLoader(); @@ -29,6 +31,7 @@ public UiPart(URL fxmlFileUrl) { /** * Constructs a UiPart using the specified FXML file within {@link #FXML_FILE_FOLDER}. + * * @see #UiPart(URL) */ public UiPart(String fxmlFileName) { @@ -45,6 +48,7 @@ public UiPart(URL fxmlFileUrl, T root) { /** * Constructs a UiPart with the specified FXML file within {@link #FXML_FILE_FOLDER} and root object. + * * @see #UiPart(URL, T) */ public UiPart(String fxmlFileName, T root) { @@ -60,6 +64,7 @@ public T getRoot() { /** * Loads the object hierarchy from a FXML document. + * * @param location Location of the FXML document. * @param root Specifies the root of the object hierarchy. */ diff --git a/src/main/resources/view/CommandBox.fxml b/src/main/resources/view/CommandBox.fxml index 09f6d6fe9e4..a7c75aebcc5 100644 --- a/src/main/resources/view/CommandBox.fxml +++ b/src/main/resources/view/CommandBox.fxml @@ -2,8 +2,7 @@ - - + diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css index 9ce9bcfb569..75e9fccab4c 100644 --- a/src/main/resources/view/DarkTheme.css +++ b/src/main/resources/view/DarkTheme.css @@ -56,11 +56,7 @@ -fx-size: 35; -fx-border-width: 0 0 1 0; -fx-background-color: transparent; - -fx-border-color: - transparent - transparent - derive(-fx-base, 80%) - transparent; + -fx-border-color: transparent transparent derive(-fx-base, 80%) transparent; -fx-border-insets: 0 10 1 0; } @@ -95,7 +91,7 @@ .list-cell { -fx-label-padding: 0 0 0 0; - -fx-graphic-text-gap : 0; + -fx-graphic-text-gap: 0; -fx-padding: 0 0 0 0; } @@ -133,13 +129,13 @@ } .stack-pane { - -fx-background-color: derive(#1d1d1d, 20%); + -fx-background-color: derive(#1d1d1d, 20%); } .pane-with-border { - -fx-background-color: derive(#1d1d1d, 20%); - -fx-border-color: derive(#1d1d1d, 10%); - -fx-border-top-width: 1px; + -fx-background-color: derive(#1d1d1d, 20%); + -fx-border-color: derive(#1d1d1d, 10%); + -fx-border-top-width: 1px; } .status-bar { @@ -229,8 +225,8 @@ } .button:pressed, .button:default:hover:pressed { - -fx-background-color: white; - -fx-text-fill: #1d1d1d; + -fx-background-color: white; + -fx-text-fill: #1d1d1d; } .button:focused { diff --git a/src/main/resources/view/HelpWindow.fxml b/src/main/resources/view/HelpWindow.fxml index c9a38f2b105..f673c9d9738 100644 --- a/src/main/resources/view/HelpWindow.fxml +++ b/src/main/resources/view/HelpWindow.fxml @@ -2,44 +2,44 @@ - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 32bcf2c8e70..e1ee70a0d5c 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -2,60 +2,60 @@ - - - + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index f745ee0d676..70e43bdf065 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -8,29 +8,28 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/src/main/resources/view/PersonListPanel.fxml b/src/main/resources/view/PersonListPanel.fxml index 8836d323cc5..3dffe9efdc5 100644 --- a/src/main/resources/view/PersonListPanel.fxml +++ b/src/main/resources/view/PersonListPanel.fxml @@ -2,7 +2,6 @@ - - + diff --git a/src/main/resources/view/ResultDisplay.fxml b/src/main/resources/view/ResultDisplay.fxml index 58d5ad3dc56..ea978cc6fa4 100644 --- a/src/main/resources/view/ResultDisplay.fxml +++ b/src/main/resources/view/ResultDisplay.fxml @@ -2,8 +2,7 @@ - -