Skip to content

Commit 11a8003

Browse files
Merge pull request #144 from AY2021S1-CS2103-F10-2/branch-Label-Rework
Branch label rework
2 parents 0bd0708 + 04d8d32 commit 11a8003

14 files changed

+619
-73
lines changed

src/main/java/seedu/address/logic/commands/AddLabelCommand.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import seedu.address.commons.core.Messages;
1515
import seedu.address.logic.commands.exceptions.CommandException;
1616
import seedu.address.model.Model;
17+
import seedu.address.model.meeting.Meeting;
1718
import seedu.address.model.person.Name;
1819
import seedu.address.model.person.Person;
1920
import seedu.address.model.tag.Tag;
@@ -72,17 +73,36 @@ public CommandResult execute(Model model) throws CommandException {
7273

7374
model.setPerson(personToLabel, labelledPerson);
7475
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
76+
77+
// update meeting book
78+
List<Meeting> filteredMeetingList = model.getFilteredMeetingList().stream()
79+
.filter(meeting -> meeting.getMembers().contains(personToLabel)).map(meeting -> {
80+
Set<Person> updatedMembers = new HashSet<>(meeting.getMembers());
81+
updatedMembers.remove(personToLabel);
82+
updatedMembers.add(labelledPerson);
83+
Meeting updatedMeeting = new Meeting(meeting.getMeetingName(), meeting.getDate(),
84+
meeting.getTime(), updatedMembers);
85+
model.setMeeting(meeting, updatedMeeting);
86+
return updatedMeeting;
87+
}).collect(Collectors.toList());
88+
89+
// todo update module book
90+
7591
return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, labelledPerson));
7692
}
7793

7894
/**
79-
* Creates and returns a {@code Person} with the details of {@code personToEdit}
80-
* edited with {@code editPersonDescriptor}.
95+
* Creates and returns a {@code Person} with the details of {@code personToLabel}
96+
* edited with {@code labelPersonDescriptor}.
8197
*/
8298
private static Person createLabelledPerson(Person personToLabel, LabelPersonDescriptor labelPersonDescriptor) {
8399
assert personToLabel != null;
84100

85-
Set<Tag> updatedTags = labelPersonDescriptor.getTags().orElse(personToLabel.getTags());
101+
Set<Tag> updatedTags = new HashSet<>(personToLabel.getTags());
102+
103+
if (labelPersonDescriptor.getTags().isPresent()) {
104+
updatedTags.addAll(labelPersonDescriptor.getTags().get());
105+
}
86106

87107
return new Person(personToLabel.getName(), personToLabel.getPhone(), personToLabel.getEmail(), updatedTags);
88108
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package seedu.address.logic.commands;
2+
3+
import static java.util.Objects.requireNonNull;
4+
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
5+
6+
import java.util.HashSet;
7+
import java.util.List;
8+
import java.util.Set;
9+
import java.util.stream.Collectors;
10+
11+
import seedu.address.commons.core.Messages;
12+
import seedu.address.logic.commands.exceptions.CommandException;
13+
import seedu.address.model.Model;
14+
import seedu.address.model.meeting.Meeting;
15+
import seedu.address.model.person.Name;
16+
import seedu.address.model.person.Person;
17+
18+
public class ClearLabelCommand extends Command {
19+
public static final String COMMAND_WORD = "label clear";
20+
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Clears all labels of the person specified.\n"
21+
+ "Parameters: NAME (must be name of person existing in ModDuke) "
22+
+ "Example: " + COMMAND_WORD + " "
23+
+ "Roy";
24+
25+
private final Name targetName;
26+
27+
/**
28+
* @param targetName the specified person
29+
*/
30+
public ClearLabelCommand(Name targetName) {
31+
requireNonNull(targetName);
32+
this.targetName = targetName;
33+
}
34+
35+
@Override
36+
public CommandResult execute(Model model) throws CommandException {
37+
requireNonNull(model);
38+
// check if Person exists in address book
39+
boolean isValidContact = model.hasPersonName(targetName);
40+
if (!isValidContact) {
41+
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED);
42+
}
43+
44+
List<Person> filteredList = model.getFilteredPersonList().stream()
45+
.filter(person -> person.isSameName(targetName)).collect(Collectors.toList());
46+
Person personToClear = filteredList.get(0);
47+
Person clearedPerson = createClearedPerson(personToClear); // clears all labels from Person
48+
model.setPerson(personToClear, clearedPerson);
49+
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
50+
51+
// update meeting book
52+
List<Meeting> filteredMeetingList = model.getFilteredMeetingList().stream()
53+
.filter(meeting -> meeting.getMembers().contains(personToClear)).map(meeting -> {
54+
Set<Person> updatedMembers = new HashSet<>(meeting.getMembers());
55+
updatedMembers.remove(personToClear);
56+
updatedMembers.add(clearedPerson);
57+
Meeting updatedMeeting = new Meeting(meeting.getMeetingName(), meeting.getDate(),
58+
meeting.getTime(), updatedMembers);
59+
model.setMeeting(meeting, updatedMeeting);
60+
return updatedMeeting;
61+
}).collect(Collectors.toList());
62+
63+
// todo update module book
64+
65+
return new CommandResult(String.format("All labels of person '%s' have been cleared!", targetName.toString()));
66+
}
67+
68+
/**
69+
* Creates and returns a {@code Person} with the details of {@code personToClear}
70+
* but with cleared Labels.
71+
*/
72+
private static Person createClearedPerson(Person personToClear) {
73+
assert personToClear != null;
74+
75+
return new Person(personToClear.getName(), personToClear.getPhone(), personToClear.getEmail(), new HashSet<>());
76+
}
77+
78+
@Override
79+
public boolean equals(Object other) {
80+
// short circuit if same object
81+
if (other == this) {
82+
return true;
83+
}
84+
85+
// instanceof handles nulls
86+
if (!(other instanceof ClearLabelCommand)) {
87+
return false;
88+
}
89+
90+
// state check
91+
ClearLabelCommand e = (ClearLabelCommand) other;
92+
return targetName.equals(e.targetName);
93+
}
94+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package seedu.address.logic.commands;
2+
3+
import static java.util.Objects.requireNonNull;
4+
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
5+
6+
import java.util.HashSet;
7+
import java.util.List;
8+
import java.util.Set;
9+
import java.util.stream.Collectors;
10+
11+
import seedu.address.commons.core.Messages;
12+
import seedu.address.logic.commands.exceptions.CommandException;
13+
import seedu.address.model.Model;
14+
import seedu.address.model.meeting.Meeting;
15+
import seedu.address.model.person.Name;
16+
import seedu.address.model.person.Person;
17+
import seedu.address.model.tag.Tag;
18+
19+
public class DeleteLabelCommand extends Command {
20+
public static final String COMMAND_WORD = "label delete";
21+
22+
public static final String MESSAGE_USAGE = COMMAND_WORD
23+
+ ": Deletes the given tag(s) from the person identified by the name used in the displayed person list.\n"
24+
+ "Parameters: NAME (must be name of person existing in ModDuke) "
25+
+ "[" + PREFIX_TAG + "TAG]...\n"
26+
+ "Example: " + COMMAND_WORD + " "
27+
+ "Roy "
28+
+ PREFIX_TAG + "classmate";
29+
30+
public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Labelled Person: %1$s";
31+
32+
private final Name targetName;
33+
private final Set<Tag> tags;
34+
35+
/**
36+
* @param targetName of the person in the filtered person list to edit
37+
* @param tags the set of tags to be removed from the person
38+
*/
39+
public DeleteLabelCommand(Name targetName, Set<Tag> tags) {
40+
this.targetName = targetName;
41+
this.tags = tags;
42+
}
43+
44+
@Override
45+
public CommandResult execute(Model model) throws CommandException {
46+
requireNonNull(model);
47+
boolean isValidContact = model.hasPersonName(targetName);
48+
// check if Person exists in address book
49+
if (!isValidContact) {
50+
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED);
51+
}
52+
53+
// Update address book
54+
List<Person> filteredList = model.getFilteredPersonList().stream()
55+
.filter(person -> person.isSameName(targetName)).collect(Collectors.toList());
56+
Person personToEdit = filteredList.get(0);
57+
Person editedPerson = createEditedPerson(personToEdit, tags); // deletes the given labels from Person
58+
59+
model.setPerson(personToEdit, editedPerson);
60+
61+
// Update meeting book
62+
List<Meeting> filteredMeetingList = model.getFilteredMeetingList().stream()
63+
.filter(meeting -> meeting.getMembers().contains(personToEdit)).map(meeting -> {
64+
Set<Person> updatedMembers = new HashSet<>(meeting.getMembers());
65+
updatedMembers.remove(personToEdit);
66+
updatedMembers.add(editedPerson);
67+
Meeting updatedMeeting = new Meeting(meeting.getMeetingName(), meeting.getDate(),
68+
meeting.getTime(), updatedMembers);
69+
model.setMeeting(meeting, updatedMeeting);
70+
return updatedMeeting;
71+
}).collect(Collectors.toList());
72+
73+
// todo update module book
74+
75+
return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, editedPerson));
76+
}
77+
78+
/**
79+
* Creates and returns a {@code Person} with the details of {@code personToEdit}
80+
* with labels in {@code tags} removed.
81+
*/
82+
private static Person createEditedPerson(Person personToEdit, Set<Tag> tags) throws CommandException {
83+
assert personToEdit != null;
84+
85+
if (tags.stream().allMatch(tag -> personToEdit.getTags().contains(tag))) {
86+
// Person has all tags to be deleted
87+
Set<Tag> updatedTags = new HashSet<>(personToEdit.getTags());
88+
updatedTags.removeAll(tags);
89+
return new Person(personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(), updatedTags);
90+
} else {
91+
// Person does not have all tags to be deleted
92+
throw new CommandException(
93+
String.format("The person '%s' does not have all the tags provided.",
94+
personToEdit.getName().toString()));
95+
}
96+
}
97+
98+
@Override
99+
public boolean equals(Object other) {
100+
return other == this // short circuit if same object
101+
|| (other instanceof DeleteLabelCommand // instanceof handles nulls
102+
&& targetName.equals(((DeleteLabelCommand) other).targetName)); // state check
103+
}
104+
}

src/main/java/seedu/address/logic/parser/AddLabelCommandParser.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ public AddLabelCommand parse(String args) throws ParseException {
4242

4343
parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(labelPersonDescriptor::setTags);
4444

45+
if (labelPersonDescriptor.getTags().isEmpty()) {
46+
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddLabelCommand.MESSAGE_USAGE));
47+
}
48+
4549
return new AddLabelCommand(name, labelPersonDescriptor);
4650
}
4751

@@ -53,7 +57,7 @@ public AddLabelCommand parse(String args) throws ParseException {
5357
private Optional<Set<Tag>> parseTagsForEdit(Collection<String> tags) throws ParseException {
5458
assert tags != null;
5559

56-
if (tags.isEmpty()) {
60+
if (tags.size() == 1 && tags.contains("")) {
5761
return Optional.empty();
5862
}
5963
Collection<String> tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;

src/main/java/seedu/address/logic/parser/AddressBookParser.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import seedu.address.logic.commands.AddCommand;
1010
import seedu.address.logic.commands.AddLabelCommand;
1111
import seedu.address.logic.commands.ClearCommand;
12+
import seedu.address.logic.commands.ClearLabelCommand;
1213
import seedu.address.logic.commands.Command;
1314
import seedu.address.logic.commands.DeleteCommand;
15+
import seedu.address.logic.commands.DeleteLabelCommand;
1416
import seedu.address.logic.commands.EditCommand;
1517
import seedu.address.logic.commands.ExitCommand;
1618
import seedu.address.logic.commands.FindCommand;
@@ -82,6 +84,12 @@ public Command parseCommand(String userInput) throws ParseException {
8284
case AddLabelCommand.COMMAND_WORD:
8385
return new AddLabelCommandParser().parse(arguments);
8486

87+
case DeleteLabelCommand.COMMAND_WORD:
88+
return new DeleteLabelCommandParser().parse(arguments);
89+
90+
case ClearLabelCommand.COMMAND_WORD:
91+
return new ClearLabelCommandParser().parse(arguments);
92+
8593
default:
8694
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
8795
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package seedu.address.logic.parser;
2+
3+
import seedu.address.logic.commands.ClearLabelCommand;
4+
import seedu.address.logic.parser.exceptions.ParseException;
5+
import seedu.address.model.person.Name;
6+
7+
public class ClearLabelCommandParser implements Parser<ClearLabelCommand> {
8+
/**
9+
* Parses the given {@code String} of arguments in the context of the ClearLabelCommand
10+
* and returns a ClearLabelCommand object for execution.
11+
* @throws ParseException if the user input does not conform the expected format
12+
*/
13+
public ClearLabelCommand parse(String args) throws ParseException {
14+
Name targetName = ParserUtil.parseName(args);
15+
return new ClearLabelCommand(targetName);
16+
}
17+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package seedu.address.logic.parser;
2+
3+
import static java.util.Objects.requireNonNull;
4+
import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
5+
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
6+
7+
import java.util.Collection;
8+
import java.util.HashSet;
9+
import java.util.Optional;
10+
import java.util.Set;
11+
import java.util.stream.Stream;
12+
13+
import seedu.address.logic.commands.DeleteLabelCommand;
14+
import seedu.address.logic.parser.exceptions.ParseException;
15+
import seedu.address.model.person.Name;
16+
import seedu.address.model.tag.Tag;
17+
18+
public class DeleteLabelCommandParser implements Parser<DeleteLabelCommand> {
19+
20+
@Override
21+
public DeleteLabelCommand parse(String args) throws ParseException {
22+
requireNonNull(args);
23+
ArgumentMultimap argMultimap =
24+
ArgumentTokenizer.tokenize(args, PREFIX_TAG);
25+
// check if required prefixes are present
26+
if (!arePrefixesPresent(argMultimap, PREFIX_TAG)) {
27+
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteLabelCommand.MESSAGE_USAGE));
28+
}
29+
30+
Name name;
31+
32+
name = ParserUtil.parseName(argMultimap.getPreamble());
33+
34+
Set<Tag> tagsToDelete = new HashSet<>();
35+
// retrieve tags to delete
36+
parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(tags -> tagsToDelete.addAll(tags));
37+
38+
if (tagsToDelete.isEmpty()) {
39+
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteLabelCommand.MESSAGE_USAGE));
40+
}
41+
42+
return new DeleteLabelCommand(name, tagsToDelete);
43+
}
44+
45+
/**
46+
* Parses {@code Collection<String> tags} into a {@code Set<Tag>} if {@code tags} is non-empty.
47+
* If {@code tags} contain only one element which is an empty string, it will be parsed into a
48+
* {@code Set<Tag>} containing zero tags.
49+
*/
50+
private Optional<Set<Tag>> parseTagsForEdit(Collection<String> tags) throws ParseException {
51+
assert tags != null;
52+
53+
if (tags.size() == 1 && tags.contains("")) {
54+
// no tags were given in user input
55+
return Optional.empty();
56+
}
57+
Collection<String> tagSet = tags;
58+
return Optional.of(ParserUtil.parseTags(tagSet));
59+
}
60+
61+
/**
62+
* Returns true if none of the prefixes contains empty {@code Optional} values in the given
63+
* {@code ArgumentMultimap}.
64+
*/
65+
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
66+
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
67+
}
68+
}

0 commit comments

Comments
 (0)