Skip to content

Commit

Permalink
Merge pull request #50 from tengcharmaine/addnote
Browse files Browse the repository at this point in the history
Add addnote command to add a note to a Person's entry in the addressbook
  • Loading branch information
tengcharmaine authored Mar 18, 2024
2 parents 3aabcf1 + 7c5baee commit 5c57592
Show file tree
Hide file tree
Showing 12 changed files with 319 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/main/java/seedu/address/logic/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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_PERSON = "The ic number provided is invalid";
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_DUPLICATE_FIELDS =
"Multiple values specified for the following single-valued field(s): ";
Expand Down
105 changes: 105 additions & 0 deletions src/main/java/seedu/address/logic/commands/AddNoteCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package seedu.address.logic.commands;

import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_IC;
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.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.IdentityCardNumberMatchesPredicate;
import seedu.address.model.person.Note;
import seedu.address.model.person.Person;

/**
* Changes the note of an existing person in the address book.
*/
public class AddNoteCommand extends Command {

public static final String COMMAND_WORD = "addnote";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the note of the person whose profile matches "
+ "the specified IC (case-insensitive). "
+ "Existing remark will be appended by default. To replace the original note, add -replace at "
+ "the end of your command. E.g. addnote i/S0123456Q n/Diabetes -replace\n"
+ "Parameters: "
+ PREFIX_IC + "IC "
+ PREFIX_NOTE + "NOTE \n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_IC + " S0123456Q "
+ PREFIX_NOTE + "Healthy.";


public static final String MESSAGE_MODIFY_NOTE_SUCCESS = "%1$s's note modified successfully!";
private final IdentityCardNumberMatchesPredicate icPredicate;
private final Note note;
private final boolean isReplace;

/**
* @param icPredicate of the person in the filtered person list to edit the note
* @param note of the person to be updated to
*/
public AddNoteCommand(IdentityCardNumberMatchesPredicate icPredicate, Note note, boolean isReplace) {
requireAllNonNull(icPredicate, note);

this.icPredicate = icPredicate;
this.note = note;
this.isReplace = isReplace;
}

@Override
public CommandResult execute(Model model) throws CommandException {
model.updateFilteredPersonList(icPredicate);
List<Person> lastShownList = model.getFilteredPersonList();

if (lastShownList.isEmpty()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON);
}

Person personToEdit = lastShownList.get(0);
Person editedPerson;

if (isReplace) {
editedPerson = new Person(personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
personToEdit.getIdentityCardNumber(), personToEdit.getAge(), personToEdit.getSex(),
personToEdit.getAddress(), note, personToEdit.getTags());
} else {
Note updatedNote = personToEdit.getNote().append("\n" + note.toString());
editedPerson = new Person(personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
personToEdit.getIdentityCardNumber(), personToEdit.getAge(), personToEdit.getSex(),
personToEdit.getAddress(), updatedNote, 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 remark is added to or removed from
* {@code personToEdit}.
*/
private String generateSuccessMessage(Person personToEdit) {
return String.format(MESSAGE_MODIFY_NOTE_SUCCESS, personToEdit);
}

@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}

// instanceof handles nulls
if (!(other instanceof AddNoteCommand)) {
return false;
}

AddNoteCommand e = (AddNoteCommand) other;
return icPredicate.equals(e.icPredicate)
&& note.equals(e.note)
&& isReplace == e.isReplace;
}
}
64 changes: 64 additions & 0 deletions src/main/java/seedu/address/logic/parser/AddNoteCommandParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package seedu.address.logic.parser;

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_FLAG;
import static seedu.address.logic.parser.CliSyntax.PREFIX_IC;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE;

import java.util.stream.Stream;

import seedu.address.commons.exceptions.IllegalValueException;
import seedu.address.logic.commands.AddNoteCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.IdentityCardNumber;
import seedu.address.model.person.IdentityCardNumberMatchesPredicate;
import seedu.address.model.person.Note;

/**
* Parses input arguments and creates a new {@code AddNoteCommand} object
*/
public class AddNoteCommandParser implements Parser<AddNoteCommand> {
/**
* Parses the given {@code String} of arguments in the context of the {@code AddNoteCommand}
* and returns a {@code AddNoteCommand} object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public AddNoteCommand parse(String args) throws ParseException {
requireNonNull(args);
ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_IC, PREFIX_NOTE, PREFIX_FLAG);

if (!arePrefixesPresent(argMultimap, PREFIX_IC, PREFIX_NOTE)
|| !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddNoteCommand.MESSAGE_USAGE));
}

IdentityCardNumber ic;
try {
String note = "";
boolean isReplace = false;

if (argMultimap.getValue(PREFIX_FLAG).isPresent()) {
int startIndex = args.indexOf(PREFIX_NOTE.getPrefix()) + PREFIX_NOTE.getPrefix().length();
int endIndex = args.indexOf(PREFIX_FLAG.getPrefix());
note = args.substring(startIndex, endIndex).trim();
isReplace = true;
} else {
note = argMultimap.getValue(PREFIX_NOTE).orElse("");
}

ic = ParserUtil.parseIC(argMultimap.getValue(PREFIX_IC).get());
return new AddNoteCommand(new IdentityCardNumberMatchesPredicate(ic), new Note(note), isReplace);
} catch (IllegalValueException ive) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddNoteCommand.MESSAGE_USAGE), ive);
}
}

/**
* Returns true if none of the prefixes contains empty {@code Optional} values in the given
* {@code ArgumentMultimap}.
*/
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import seedu.address.commons.core.LogsCenter;
import seedu.address.logic.commands.AddCommand;
import seedu.address.logic.commands.AddNoteCommand;
import seedu.address.logic.commands.ClearCommand;
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.DeleteCommand;
Expand Down Expand Up @@ -68,6 +69,9 @@ public Command parseCommand(String userInput) throws ParseException {
case FindCommand.COMMAND_WORD:
return new FindCommandParser().parse(arguments);

case AddNoteCommand.COMMAND_WORD:
return new AddNoteCommandParser().parse(arguments);

case ListCommand.COMMAND_WORD:
return new ListCommand();

Expand Down
4 changes: 3 additions & 1 deletion src/main/java/seedu/address/logic/parser/CliSyntax.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ public class CliSyntax {
public static final Prefix PREFIX_EMAIL = new Prefix("e/");
public static final Prefix PREFIX_PHONE = new Prefix("p/");
public static final Prefix PREFIX_TAG = new Prefix("t/");

public static final Prefix PREFIX_NOTE = new Prefix("n/");
public static final Prefix PREFIX_IC = new Prefix("i/");
public static final Prefix PREFIX_FLAG = new Prefix("-replace");
}
10 changes: 10 additions & 0 deletions src/main/java/seedu/address/model/person/Note.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ public static boolean isValidNote(String test) {
return true;
}

/**
* Appends text to the current note.
*
* @param text The text to append.
*/
public Note append(String text) {
requireNonNull(text);
return new Note(value + text);
}

@Override
public String toString() {
return value;
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/seedu/address/ui/PersonCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public class PersonCard extends UiPart<Region> {
@FXML
private Label email;
@FXML
private Label note;
@FXML
private Label age;
@FXML
private Label sex;
Expand All @@ -57,6 +59,7 @@ public PersonCard(Person person, int displayedIndex) {
name.setText(person.getName().fullName);
phone.setText(person.getPhone().value);
email.setText(person.getEmail().value);
note.setText(person.getNote().value);
ic.setText(person.getIdentityCardNumber().value);
age.setText(String.valueOf(person.getAge().value));
sex.setText(person.getSex().value);
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/view/PersonListCard.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<Label fx:id="phone" styleClass="cell_small_label" text="\$phone" />
<Label fx:id="address" styleClass="cell_small_label" text="\$address" />
<Label fx:id="email" styleClass="cell_small_label" text="\$email" />
<Label fx:id="note" styleClass="cell_small_label" text="\$note" />
</VBox>
</GridPane>
</HBox>
50 changes: 50 additions & 0 deletions src/test/java/seedu/address/logic/commands/AddNoteCommandTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package seedu.address.logic.commands;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NOTE_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NOTE_BOB;

import org.junit.jupiter.api.Test;

import seedu.address.model.person.IdentityCardNumber;
import seedu.address.model.person.IdentityCardNumberMatchesPredicate;
import seedu.address.model.person.Note;

/**
* Contains integration tests (interaction with the Model) and unit tests for AddNoteCommand.
*/
public class AddNoteCommandTest {
@Test
public void equals() {
IdentityCardNumberMatchesPredicate firstPredicate =
new IdentityCardNumberMatchesPredicate(new IdentityCardNumber("S1234567A"));
IdentityCardNumberMatchesPredicate secondPredicate =
new IdentityCardNumberMatchesPredicate(new IdentityCardNumber("S9876543B"));

final AddNoteCommand standardCommand = new AddNoteCommand(firstPredicate,
new Note(VALID_NOTE_AMY), false);

// same values -> returns true
AddNoteCommand commandWithSameValues = new AddNoteCommand(firstPredicate,
new Note(VALID_NOTE_AMY), false);
assertTrue(standardCommand.equals(commandWithSameValues));

// same object -> returns true
assertTrue(standardCommand.equals(standardCommand));

// null -> returns false
assertFalse(standardCommand.equals(null));

// different types -> returns false
assertFalse(standardCommand.equals(new ClearCommand()));

// different index -> returns false
assertFalse(standardCommand.equals(new AddNoteCommand(secondPredicate,
new Note(VALID_NOTE_AMY), false)));

// different remark -> returns false
assertFalse(standardCommand.equals(new AddNoteCommand(firstPredicate,
new Note(VALID_NOTE_BOB), false)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package seedu.address.logic.parser;

import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;

import org.junit.jupiter.api.Test;

import seedu.address.logic.commands.AddNoteCommand;

public class AddNoteCommandParserTest {
private AddNoteCommandParser parser = new AddNoteCommandParser();
private final String nonEmptyNote = "Some note.";

@Test
public void parse_missingCompulsoryField_failure() {
String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddNoteCommand.MESSAGE_USAGE);

// no parameters
assertParseFailure(parser, AddNoteCommand.COMMAND_WORD, expectedMessage);

// no index
assertParseFailure(parser, AddNoteCommand.COMMAND_WORD + " " + nonEmptyNote, expectedMessage);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.Messages.MESSAGE_UNKNOWN_COMMAND;
import static seedu.address.logic.parser.CliSyntax.PREFIX_FLAG;
import static seedu.address.logic.parser.CliSyntax.PREFIX_IC;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NOTE;
import static seedu.address.testutil.Assert.assertThrows;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import seedu.address.logic.commands.AddCommand;
import seedu.address.logic.commands.AddNoteCommand;
import seedu.address.logic.commands.ClearCommand;
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.EditCommand;
Expand All @@ -22,6 +26,7 @@
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.IdentityCardNumber;
import seedu.address.model.person.IdentityCardNumberMatchesPredicate;
import seedu.address.model.person.Note;
import seedu.address.model.person.Person;
import seedu.address.testutil.EditPersonDescriptorBuilder;
import seedu.address.testutil.PersonBuilder;
Expand Down Expand Up @@ -86,6 +91,24 @@ public void parseCommand_list() throws Exception {
assertTrue(parser.parseCommand(ListCommand.COMMAND_WORD + " 3") instanceof ListCommand);
}

@Test
public void parseCommand_addNote_withReplaceFlag() throws Exception {
final Note note = new Note("Some note.");
AddNoteCommand command = (AddNoteCommand) parser.parseCommand(AddNoteCommand.COMMAND_WORD + " "
+ PREFIX_IC + "S0123456Q " + PREFIX_NOTE + note.value + " " + PREFIX_FLAG);
assertEquals(new AddNoteCommand(new IdentityCardNumberMatchesPredicate(new IdentityCardNumber("S0123456Q")),
note, true), command);
}

@Test
public void parseCommand_addNote_withoutReplaceFlag() throws Exception {
final Note note = new Note("Some note.");
AddNoteCommand command = (AddNoteCommand) parser.parseCommand(AddNoteCommand.COMMAND_WORD + " "
+ PREFIX_IC + "S0123456Q " + PREFIX_NOTE + note.value);
assertEquals(new AddNoteCommand(new IdentityCardNumberMatchesPredicate(new IdentityCardNumber("S0123456Q")),
note, false), command);
}

@Test
public void parseCommand_unrecognisedInput_throwsParseException() {
assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), ()
Expand Down
Loading

0 comments on commit 5c57592

Please sign in to comment.