Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Undo command #147

Merged
merged 3 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/main/java/seedu/address/logic/commands/UndoCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;

/**
* Clears the address book.
*/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be updated!

public class UndoCommand extends Command {

public static final String COMMAND_WORD = "undo";
public static final String MESSAGE_SUCCESS = "Your latest command has been undone.";
public static final String MESSAGE_NO_COMMAND_TO_UNDO = "Please input a command first in order to undo it.";

@Override
protected CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
if (!model.hasPreviousCommand()) {
throw new CommandException(MESSAGE_NO_COMMAND_TO_UNDO);
}
model.undoCommand();
return new CommandResult(MESSAGE_SUCCESS);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import seedu.address.logic.commands.FilterCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.commands.UndoCommand;
import seedu.address.logic.commands.ViewCommand;
import seedu.address.logic.parser.exceptions.ParseException;

Expand Down Expand Up @@ -86,6 +87,9 @@ public Command parseCommand(String userInput) throws ParseException {
case CloseCommand.COMMAND_WORD:
return new CloseCommand();

case UndoCommand.COMMAND_WORD:
return new UndoCommand();

default:
logger.finer("This user input caused a ParseException: " + userInput);
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/seedu/address/model/AgentAssist.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ public void removePerson(Person key) {
persons.remove(key);
}

/**
* Gets a copy of the current AgentAssist.
*/
public AgentAssist getCopy() {
AgentAssist newAgentAssist = new AgentAssist();
newAgentAssist.setPersons(this.getPersonList());
return newAgentAssist;
}

//// util methods

@Override
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ public interface Model {
*/
void setPerson(Person target, Person editedPerson);

/**
* Undos previous command by setting currentAddressBook to historyAddressBook.
*/
void undoCommand();

/**
* Returns true if a command has been executed before.
*/
boolean hasPreviousCommand();

/** Returns an unmodifiable view of the filtered person list */
ObservableList<Person> getFilteredPersonList();

Expand Down
42 changes: 32 additions & 10 deletions src/main/java/seedu/address/model/ModelManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
public class ModelManager implements Model {
private static final Logger logger = LogsCenter.getLogger(ModelManager.class);

private final AgentAssist agentAssist;
private AgentAssist historyAgentAssist = null;
private AgentAssist currentAgentAssist;
private final UserPrefs userPrefs;
private final FilteredList<Person> filteredPersons;
private final SimpleObjectProperty<Person> selectedPerson = new SimpleObjectProperty<>();
Expand All @@ -37,15 +38,22 @@ public ModelManager(ReadOnlyAgentAssist agentAssist, ReadOnlyUserPrefs userPrefs

logger.fine("Initializing with address book: " + agentAssist + " and user prefs " + userPrefs);

this.agentAssist = new AgentAssist(agentAssist);
this.currentAgentAssist = new AgentAssist(agentAssist);
this.userPrefs = new UserPrefs(userPrefs);
filteredPersons = new FilteredList<>(this.agentAssist.getPersonList());
filteredPersons = new FilteredList<>(this.currentAgentAssist.getPersonList());
}

public ModelManager() {
this(new AgentAssist(), new UserPrefs());
}

/**
* Save the history of the AgentAssist.
*/
private void safeHistory() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be a minor typo? saveHistory

FionaQY marked this conversation as resolved.
Show resolved Hide resolved
historyAgentAssist = currentAgentAssist.getCopy();
}


//=========== UserPrefs ==================================================================================

Expand Down Expand Up @@ -86,36 +94,50 @@ public void setAgentAssistFilePath(Path agentAssistFilePath) {

@Override
public void setAgentAssist(ReadOnlyAgentAssist agentAssist) {
this.agentAssist.resetData(agentAssist);
safeHistory();
FionaQY marked this conversation as resolved.
Show resolved Hide resolved
this.currentAgentAssist.resetData(agentAssist);
}

@Override
public ReadOnlyAgentAssist getAgentAssist() {
return agentAssist;
return currentAgentAssist;
}

@Override
public boolean hasPerson(Person person) {
requireNonNull(person);
return agentAssist.hasPerson(person);
return currentAgentAssist.hasPerson(person);
}

@Override
public void deletePerson(Person target) {
agentAssist.removePerson(target);
safeHistory();
FionaQY marked this conversation as resolved.
Show resolved Hide resolved
currentAgentAssist.removePerson(target);
}

@Override
public void addPerson(Person person) {
agentAssist.addPerson(person);
safeHistory();
FionaQY marked this conversation as resolved.
Show resolved Hide resolved
currentAgentAssist.addPerson(person);
updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
}

@Override
public void setPerson(Person target, Person editedPerson) {
requireAllNonNull(target, editedPerson);
safeHistory();
FionaQY marked this conversation as resolved.
Show resolved Hide resolved
currentAgentAssist.setPerson(target, editedPerson);
}

agentAssist.setPerson(target, editedPerson);
@Override
public void undoCommand() {
requireNonNull(this.historyAgentAssist);
this.setAgentAssist(this.historyAgentAssist);
}

@Override
public boolean hasPreviousCommand() {
return this.historyAgentAssist != null;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great use of abstraction! Liked how clean this is with just adding saveHistory into each command works.


//=========== Selected Person ===========================================================================
Expand Down Expand Up @@ -185,7 +207,7 @@ public boolean equals(Object other) {
}

ModelManager otherModelManager = (ModelManager) other;
return agentAssist.equals(otherModelManager.agentAssist)
return currentAgentAssist.equals(otherModelManager.currentAgentAssist)
&& userPrefs.equals(otherModelManager.userPrefs)
&& filteredPersons.equals(otherModelManager.filteredPersons);
}
Expand Down
10 changes: 10 additions & 0 deletions src/test/java/seedu/address/logic/commands/AddCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,16 @@ public void setPerson(Person target, Person editedPerson) {
throw new AssertionError("This method should not be called.");
}

@Override
public void undoCommand() {
throw new AssertionError("This method should not be called.");
}

@Override
public boolean hasPreviousCommand() {
throw new AssertionError("This method should not be called.");
}

@Override
public ObservableList<Person> getFilteredPersonList() {
throw new AssertionError("This method should not be called.");
Expand Down
45 changes: 45 additions & 0 deletions src/test/java/seedu/address/logic/commands/UndoCommandTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package seedu.address.logic.commands;

import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalPersons.getTypicalAgentAssist;

import org.junit.jupiter.api.Test;

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
import seedu.address.model.person.Person;
import seedu.address.testutil.EditPersonDescriptorBuilder;
import seedu.address.testutil.PersonBuilder;

public class UndoCommandTest {

private Model model = new ModelManager(getTypicalAgentAssist(), new UserPrefs());

@Test
public void execute_undo_success() {
Person editedPerson = new PersonBuilder().build();
EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build();
EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor);
try {
CommandResult result = editCommand.execute(model);
} catch (CommandException ce) {
throw new AssertionError("Execution of command should not fail.", ce);
}

UndoCommand undoCommand = new UndoCommand();
Model expectedModel = new ModelManager(getTypicalAgentAssist(), new UserPrefs());

assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel);
}

@Test
public void execute_noPreviousCommand_failure() {
Model model = new ModelManager();
assertCommandFailure(new UndoCommand(), model, UndoCommand.MESSAGE_NO_COMMAND_TO_UNDO);
}

}