Skip to content

Commit

Permalink
Merge pull request #57 from yongxiangng/branch-feature-details
Browse files Browse the repository at this point in the history
Update details to accept INDEX as args
  • Loading branch information
yongxiangng authored Oct 13, 2021
2 parents ea2a7ce + 4034fbe commit 8d876ca
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 33 deletions.
23 changes: 14 additions & 9 deletions docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,25 +147,30 @@ Examples:

Shows the details of a particular member in the IG.

Format: `details NAME`
Format: `details NAME` or `details INDEX`

* The argument interprets as an `INDEX` if it is a positive integer, `NAME` otherwise.
* Displays the details of the person at the specified `INDEX`.
* The index refers to the index number shown in the displayed person list.
* The index **must be a positive integer** 1, 2, 3, …​
* The NAME entered must match the member’s name exactly (case-sensitive).

Examples:
* `list` followed by `details 3` displays details of the 3rd person in the displayed person list.
* `details Xiao Ming` will output:
```
Name: Xiao Ming
Phone: 61234567
Tele: @xiao_ming
Email: xiaoming@gmail.com
Xiao Ming details
61234567
@xiao_ming
xiaoming@gmail.com
```

* `details John Doe` will output:
```
Name: John Doe
Phone: NIL
Tele: NIL
Email: NIL
John Doe details
NIL
NIL
NIL
```

### Clearing all entries : `clear`
Expand Down
53 changes: 46 additions & 7 deletions src/main/java/seedu/address/logic/commands/DetailsCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

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.NameEqualKeywordPredicate;
import seedu.address.model.person.Person;

/**
* Finds and displays the details of person whose name matches the keyword exactly.
Expand All @@ -15,18 +20,41 @@ public class DetailsCommand extends Command {
public static final String COMMAND_WORD = "details";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Displays the details of a member from the "
+ "specified keywords (case-sensitive and exact match).\n"
+ "Parameters: NAME (case-sensitive)\n"
+ "specified keywords (case-sensitive and exact match of name) or index (must be a positive integer).\n"
+ "Parameters: NAME (case-sensitive) or INDEX (must be a positive integer)\n"
+ "Example: " + COMMAND_WORD + " Xiao Ming";

private final NameEqualKeywordPredicate predicate;
private NameEqualKeywordPredicate predicate;
private Index targetIndex;

public DetailsCommand(NameEqualKeywordPredicate predicate) {
this.predicate = predicate;
}

public DetailsCommand(Index targetIndex) {
this.targetIndex = targetIndex;
}

@Override
public CommandResult execute(Model model) {
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
convertIndexToPredicate(model);
return executePredicate(model);
}

private void convertIndexToPredicate(Model model) throws CommandException {
requireNonNull(model);
if (targetIndex != null) {
List<Person> lastShownList = model.getFilteredPersonList();
if (targetIndex.getZeroBased() >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}
Person personToDisplay = lastShownList.get(targetIndex.getZeroBased());
predicate = new NameEqualKeywordPredicate(personToDisplay.getName());
}
}

private CommandResult executePredicate(Model model) {
requireNonNull(model);
model.updateFilteredPersonList(predicate);
assert model.getFilteredPersonList().size() < 2;
Expand All @@ -43,8 +71,19 @@ public CommandResult execute(Model model) {

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof DetailsCommand // instanceof handles nulls
&& predicate.equals(((DetailsCommand) other).predicate)); // state check
if (other == this) {
return true;
}
if (!(other instanceof DetailsCommand)) {
return false;
}
DetailsCommand o = (DetailsCommand) other;
if (predicate == null) {
return o.predicate == null && targetIndex.equals(o.targetIndex);
}
if (targetIndex == null) {
return o.targetIndex == null && predicate.equals(o.predicate);
}
return targetIndex.equals(o.targetIndex) && predicate.equals(o.predicate);
}
}
14 changes: 10 additions & 4 deletions src/main/java/seedu/address/logic/parser/DetailsCommandParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.commands.DetailsCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.Name;
Expand All @@ -19,11 +20,16 @@ public class DetailsCommandParser implements Parser<DetailsCommand> {
*/
public DetailsCommand parse(String args) throws ParseException {
try {
Name name = ParserUtil.parseName(args);
return new DetailsCommand(new NameEqualKeywordPredicate(name));
Index index = ParserUtil.parseIndex(args);
return new DetailsCommand(index);
} catch (ParseException pe) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DetailsCommand.MESSAGE_USAGE));
try {
Name name = ParserUtil.parseName(args);
return new DetailsCommand(new NameEqualKeywordPredicate(name));
} catch (ParseException e) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DetailsCommand.MESSAGE_USAGE));
}
}
}

Expand Down
82 changes: 74 additions & 8 deletions src/test/java/seedu/address/logic/commands/DetailsCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.commons.core.Messages.MESSAGE_PERSON_DETAILS_FOUND;
import static seedu.address.commons.core.Messages.MESSAGE_PERSON_DETAILS_NOT_FOUND;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
import static seedu.address.testutil.TypicalPersons.CARL;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;

import java.util.Collections;

import org.junit.jupiter.api.Test;

import seedu.address.commons.core.Messages;
import seedu.address.commons.core.index.Index;
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
import seedu.address.model.person.Name;
import seedu.address.model.person.NameEqualKeywordPredicate;
import seedu.address.model.person.Person;

/**
* Contains integration tests (interaction with the Model) for {@code DetailsCommand}.
Expand All @@ -33,24 +40,34 @@ public void equals() {
NameEqualKeywordPredicate secondPredicate =
new NameEqualKeywordPredicate(new Name("second"));

DetailsCommand findFirstCommand = new DetailsCommand(firstPredicate);
DetailsCommand findSecondCommand = new DetailsCommand(secondPredicate);
DetailsCommand detailsFirstCommand = new DetailsCommand(firstPredicate);
DetailsCommand detailsSecondCommand = new DetailsCommand(secondPredicate);
DetailsCommand detailsThirdCommand = new DetailsCommand(Index.fromOneBased(1));
DetailsCommand detailsFourthCommand = new DetailsCommand(Index.fromOneBased(2));

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

// same values -> returns true
DetailsCommand findFirstCommandCopy = new DetailsCommand(firstPredicate);
assertTrue(findFirstCommand.equals(findFirstCommandCopy));
DetailsCommand detailsFirstCommandCopy = new DetailsCommand(firstPredicate);
assertTrue(detailsFirstCommand.equals(detailsFirstCommandCopy));

// different types -> returns false
assertFalse(findFirstCommand.equals(1));
assertFalse(detailsFirstCommand.equals(1));
assertFalse(detailsThirdCommand.equals(1));

// null -> returns false
assertFalse(findFirstCommand.equals(null));
assertFalse(detailsFirstCommand.equals(null));
assertFalse(detailsThirdCommand.equals(null));

// different person -> returns false
assertFalse(findFirstCommand.equals(findSecondCommand));
assertFalse(detailsFirstCommand.equals(detailsSecondCommand));

// same index -> returns true
assertTrue(detailsThirdCommand.equals(new DetailsCommand(Index.fromOneBased(1))));

// different index -> returns false
assertFalse(detailsThirdCommand.equals(detailsFourthCommand));
}

@Test
Expand All @@ -74,4 +91,53 @@ public void execute_multipleKeywords_multiplePersonsFound() {
assertCommandSuccess(command, model, expectedMessage, expectedModel);
assertEquals(Collections.singletonList(CARL), model.getFilteredPersonList());
}

@Test
public void execute_validIndexUnfilteredList_success() {
Person personToDisplay = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
DetailsCommand detailsCommand = new DetailsCommand(INDEX_FIRST_PERSON);

String expectedMessage = String.format(Messages.MESSAGE_PERSON_DETAILS_FOUND, personToDisplay.getName());

ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
expectedModel.updateFilteredPersonList(x -> x.getName().equals(personToDisplay.getName()));

assertCommandSuccess(detailsCommand, model, expectedMessage, expectedModel);
}

@Test
public void execute_invalidIndexUnfilteredList_throwsCommandException() {
Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1);
DetailsCommand detailsCommand = new DetailsCommand(outOfBoundIndex);

assertCommandFailure(detailsCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}

@Test
public void execute_validIndexFilteredList_success() {
showPersonAtIndex(model, INDEX_FIRST_PERSON);

Person personToDisplay = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
DetailsCommand detailsCommand = new DetailsCommand(INDEX_FIRST_PERSON);

String expectedMessage = String.format(Messages.MESSAGE_PERSON_DETAILS_FOUND, personToDisplay.getName());

Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
expectedModel.updateFilteredPersonList(x -> x.getName().equals(personToDisplay.getName()));

assertCommandSuccess(detailsCommand, model, expectedMessage, expectedModel);
}

@Test
public void execute_invalidIndexFilteredList_throwsCommandException() {
showPersonAtIndex(model, INDEX_FIRST_PERSON);

Index outOfBoundIndex = INDEX_SECOND_PERSON;
// ensures that outOfBoundIndex is still in bounds of address book list
assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());

DetailsCommand detailsCommand = new DetailsCommand(outOfBoundIndex);

assertCommandFailure(detailsCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import org.junit.jupiter.api.Test;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.commands.DetailsCommand;
import seedu.address.model.person.Name;
import seedu.address.model.person.NameEqualKeywordPredicate;
Expand All @@ -22,19 +23,25 @@ public void parse_emptyArg_throwsParseException() {

@Test
public void parse_validArgs_returnsDetailsCommand() {
DetailsCommand expectedFindCommand =
DetailsCommand firstExpectedDetailsCommand =
new DetailsCommand(new NameEqualKeywordPredicate(new Name("Alice Bob")));
DetailsCommand secondExpectedDetailsCommand =
new DetailsCommand(Index.fromOneBased(3));

// No trailing and leading whitespace
assertParseSuccess(parser, "Alice Bob", expectedFindCommand);
assertParseSuccess(parser, "Alice Bob", firstExpectedDetailsCommand);
assertParseSuccess(parser, "3", secondExpectedDetailsCommand);

// Leading whitespace
assertParseSuccess(parser, " Alice Bob", expectedFindCommand);
assertParseSuccess(parser, " Alice Bob", firstExpectedDetailsCommand);
assertParseSuccess(parser, " 3", secondExpectedDetailsCommand);

// Trailing whitespace
assertParseSuccess(parser, "Alice Bob ", expectedFindCommand);
assertParseSuccess(parser, "Alice Bob ", firstExpectedDetailsCommand);
assertParseSuccess(parser, "3 ", secondExpectedDetailsCommand);

// Leading and trailing whitespace
assertParseSuccess(parser, " Alice Bob ", expectedFindCommand);
assertParseSuccess(parser, " Alice Bob ", firstExpectedDetailsCommand);
assertParseSuccess(parser, " 3 ", secondExpectedDetailsCommand);
}
}

0 comments on commit 8d876ca

Please sign in to comment.