Skip to content

Commit 935b6ca

Browse files
committed
[Refact] - Add a CommandParser and improve SLAP
1 parent 104df3e commit 935b6ca

File tree

14 files changed

+296
-230
lines changed

14 files changed

+296
-230
lines changed
Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,63 @@
11
package duke.commands;
22

3-
import duke.ui.Ui;
4-
import duke.tasks.TaskList;
3+
import duke.parsers.CommandParser;
54
import duke.storage.Storage;
5+
import duke.tasks.TaskList;
6+
import duke.ui.Ui;
7+
8+
import java.io.IOException;
9+
610
import duke.exceptions.DukeException;
711

812
/**
913
* Represents a command that can be run by Duke.
1014
*/
11-
public interface Command {
15+
public abstract class Command {
16+
protected CommandParser commandParser;
17+
18+
/**
19+
* Creates a Command object.
20+
*
21+
* @param commandParser CommandParser to help parse arguments.
22+
*/
23+
public Command(CommandParser commandParser) {
24+
this.commandParser = commandParser;
25+
}
26+
27+
/**
28+
* Saves the TaskList to Storage.
29+
*
30+
* @param storage The storage medium.
31+
* @param tasks The in-memory list of tasks.
32+
*/
33+
protected void save(Storage storage, TaskList tasks) throws DukeException {
34+
try {
35+
storage.save(tasks.getAllTasks());
36+
} catch (IOException e) {
37+
throw new DukeException("Error when saving to disk!");
38+
}
39+
}
40+
41+
/**
42+
* Separates a given string by a the first occurrence of a delimiter.
43+
*
44+
* @param str String to be split.
45+
* @param delimiter Delimiter that divides the string.
46+
* @return Array of the two halves of the given string split by the delimiter,
47+
* or array of the original string if delimiter is not present.
48+
*/
49+
protected String[] split(String str, String delimiter) {
50+
return commandParser.splitByDelimiter(str, delimiter);
51+
}
52+
1253
/**
13-
* Parses the given argument string and executes the Command.
54+
* Executes the given command based on the argument string.
1455
*
15-
* @param arg Arguments for the command (may be empty).
16-
* @param tasks List of Tasks.
17-
* @param ui User interface for Duke.
56+
* @param arg Argument string for the command (may be empty).
57+
* @param tasks List of Tasks.
58+
* @param ui User interface for Duke.
1859
* @param storage Storage for Duke.
1960
* @throws DukeException If inputs are invalid.
2061
*/
21-
void execute(String arg, TaskList tasks, Ui ui, Storage storage) throws DukeException;
62+
abstract void execute(String arg, TaskList tasks, Ui ui, Storage storage) throws DukeException;
2263
}

src/main/java/duke/commands/CommandHandler.java

Lines changed: 27 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,52 @@
22

33
import java.util.HashMap;
44

5-
import javafx.util.Pair;
6-
75
import duke.ui.Ui;
86
import duke.tasks.TaskList;
97
import duke.storage.Storage;
10-
import duke.parsers.DateTimeParser;
8+
import duke.parsers.CommandParser;
119
import duke.exceptions.DukeException;
1210

1311
/**
14-
* Parses user-entered strings and executes them as Commands.
15-
* Remains active until user deactivates with "bye"
12+
* Parses user-entered strings and executes them as Commands. Remains active
13+
* until user deactivates with "bye"
1614
*/
1715
public class CommandHandler {
1816
private TaskList tasks;
1917
private Ui ui;
2018
private Storage storage;
2119
private HashMap<String, Command> commands;
20+
private CommandParser commandParser;
2221
private boolean isActive;
2322

2423
/**
2524
* Creates a CommandHandler.
26-
* @param tasks List of tasks.
27-
* @param ui User interface.
25+
*
26+
* @param tasks List of tasks.
27+
* @param ui User interface.
2828
* @param storage Persistent storage.
2929
*/
3030
public CommandHandler(TaskList tasks, Ui ui, Storage storage) {
3131
this.tasks = tasks;
3232
this.ui = ui;
3333
this.storage = storage;
3434
this.commands = new HashMap<>();
35+
this.commandParser = new CommandParser();
3536
isActive = true;
3637

37-
// Create parsers
38-
DateTimeParser dtParser = new DateTimeParser();
39-
4038
// Register commands
41-
commands.put("list", new ListAll());
42-
commands.put("done", new MarkTaskAsDone());
43-
commands.put("todo", new CreateTodo());
44-
commands.put("deadline", new CreateDeadline(dtParser));
45-
commands.put("event", new CreateEvent(dtParser));
46-
commands.put("delete", new DeleteTask());
47-
commands.put("find", new FindTasks());
48-
commands.put("reschedule", new RescheduleTask(dtParser));
39+
commands.put("list", new ListAll(commandParser));
40+
commands.put("done", new MarkTaskAsDone(commandParser));
41+
commands.put("todo", new CreateTodo(commandParser));
42+
commands.put("deadline", new CreateDeadline(commandParser));
43+
commands.put("event", new CreateEvent(commandParser));
44+
commands.put("delete", new DeleteTask(commandParser));
45+
commands.put("find", new FindTasks(commandParser));
46+
commands.put("reschedule", new RescheduleTask(commandParser));
47+
}
48+
49+
public boolean isActive() {
50+
return isActive;
4951
}
5052

5153
/**
@@ -61,28 +63,16 @@ public void handleCommand(String command) {
6163
}
6264

6365
// Extract out command word and arguments
64-
Pair<String, String> commandAndArg = getCommandAndArg(command);
65-
String commandWord = commandAndArg.getKey();
66-
String arg = commandAndArg.getValue();
66+
String[] commandAndArg = commandParser.splitByDelimiter(command, " ");
67+
String commandWord = commandAndArg[0].toLowerCase().strip();
6768

6869
// Execute command
69-
executeCommand(commandWord, arg);
70-
}
71-
72-
public boolean isActive() {
73-
return isActive;
74-
}
75-
76-
private Pair<String, String> getCommandAndArg(String str) {
77-
int spaceIndex = str.indexOf(" ");
78-
if (spaceIndex == -1) {
79-
// No spaces found, so must be single-word command
80-
return new Pair<String, String>(str.toLowerCase(), "");
70+
if (commandAndArg.length < 2) {
71+
// No args provided
72+
executeCommand(commandWord, "");
8173
} else {
82-
// Split string into command word and arguments
83-
String commandWord = str.substring(0, spaceIndex).toLowerCase();
84-
String arg = str.substring(spaceIndex + 1);
85-
return new Pair<String, String>(commandWord, arg);
74+
// Use provided args
75+
executeCommand(commandWord, commandAndArg[1]);
8676
}
8777
}
8878

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,48 @@
11
package duke.commands;
22

3-
import java.io.IOException;
3+
import java.time.LocalDateTime;
44

55
import duke.ui.Ui;
66
import duke.tasks.Task;
77
import duke.tasks.TaskList;
88
import duke.tasks.Deadline;
99
import duke.storage.Storage;
10-
import duke.parsers.DateTimeParser;
10+
import duke.parsers.CommandParser;
1111
import duke.exceptions.DukeException;
1212

1313
/**
1414
* Creates a Deadline Task and adds it to the TaskList.
1515
*/
16-
class CreateDeadline extends TimedCommand {
16+
class CreateDeadline extends Command {
1717

18-
public CreateDeadline(DateTimeParser dtParser) {
19-
super(dtParser);
18+
public CreateDeadline(CommandParser commandParser) {
19+
super(commandParser);
2020
}
2121

2222
public void execute(String arg, TaskList tasks, Ui ui, Storage storage) throws DukeException {
23-
// Perform parsing of arguments
24-
String[] args = arg.split("/by");
25-
if (args.length < 2) {
26-
throw new DukeException("Usage: deadline [task name] /by [datetime]");
27-
}
28-
29-
String taskName = args[0].strip();
30-
String dateTime = args[1].strip();
31-
if (taskName.length() == 0 || dateTime.length() == 0) {
32-
throw new DukeException("Usage: deadline [task name] /by [datetime]");
33-
}
23+
// Obtain command arguments from argument string
24+
String[] args = split(arg, "/by");
25+
String taskName = getTaskName(args);
26+
LocalDateTime dateTime = getDateTime(args);
3427

35-
// Create parsed Deadline
36-
Task newTask = new Deadline(taskName, dtParser.parse(dateTime));
28+
Task newTask = new Deadline(taskName, dateTime);
3729
tasks.add(newTask);
3830

39-
// Save new Deadline to disk
40-
try {
41-
storage.save(tasks.getAllTasks());
42-
} catch (IOException e) {
43-
throw new DukeException("Error when saving to disk!");
44-
}
31+
save(storage, tasks);
4532

46-
// Display reply
4733
ui.showReply(String.format("Got it. I've added this task:\n %s\nNow you have %d tasks in the list.", newTask,
4834
tasks.size()));
4935
}
50-
}
36+
37+
private String getTaskName(String[] args) throws DukeException {
38+
String taskName = args[0].strip();
39+
if (args.length < 2 || taskName.length() == 0) {
40+
throw new DukeException("Usage: deadline [task name] /by [due date]");
41+
}
42+
return taskName;
43+
}
44+
45+
private LocalDateTime getDateTime(String[] args) throws DukeException {
46+
return commandParser.parse(args[1].strip());
47+
}
48+
}
Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,56 @@
11
package duke.commands;
22

3-
import java.io.IOException;
3+
import java.time.LocalDateTime;
44

55
import duke.ui.Ui;
66
import duke.tasks.Task;
77
import duke.tasks.TaskList;
88
import duke.tasks.Event;
99
import duke.storage.Storage;
10-
import duke.parsers.DateTimeParser;
10+
import duke.parsers.CommandParser;
1111
import duke.exceptions.DukeException;
1212

1313
/**
1414
* Creates an Event Task and adds it to the TaskList.
1515
*/
16-
class CreateEvent extends TimedCommand {
16+
class CreateEvent extends Command {
1717

18-
public CreateEvent(DateTimeParser dtParser) {
19-
super(dtParser);
18+
public CreateEvent(CommandParser commandParser) {
19+
super(commandParser);
2020
}
2121

2222
public void execute(String arg, TaskList tasks, Ui ui, Storage storage) throws DukeException {
23-
// Perform parsing of arguments
24-
String[] args = arg.split("/at");
25-
if (args.length < 2) {
26-
throw new DukeException("Usage: event [task name] /at [start datetime] to [end datetime]");
27-
}
23+
// Obtain command arguments from argument string
24+
String[] args = split(arg, "/at");
25+
String taskName = getTaskName(args);
26+
LocalDateTime[] dateTimes = getDateTimes(args);
2827

29-
String taskName = args[0].strip();
30-
String[] dateTimes = args[1].strip().split("to");
31-
if (taskName.length() == 0 || dateTimes.length < 2) {
32-
throw new DukeException("Usage: event [task name] /at [start datetime] to [end datetime]");
33-
}
34-
35-
// Create parsed Event
36-
Task newTask = new Event(taskName, dtParser.parse(dateTimes[0].strip()), dtParser.parse(dateTimes[1].strip()));
28+
Task newTask = new Event(taskName, dateTimes[0], dateTimes[1]);
3729
tasks.add(newTask);
3830

39-
// Save new Event to disk
40-
try {
41-
storage.save(tasks.getAllTasks());
42-
} catch (IOException e) {
43-
throw new DukeException("Error when saving to disk!");
44-
}
31+
save(storage, tasks);
4532

46-
// Display reply
4733
ui.showReply(String.format("Got it. I've added this task:\n %s\nNow you have %d tasks in the list.", newTask,
4834
tasks.size()));
4935
}
50-
}
36+
37+
private String getTaskName(String[] args) throws DukeException {
38+
String taskName = args[0].strip();
39+
if (args.length < 2 || taskName.length() == 0) {
40+
throw new DukeException("Usage: event [task name] /at [start datetime] to [end datetime]");
41+
}
42+
return taskName;
43+
}
44+
45+
private LocalDateTime[] getDateTimes(String[] args) throws DukeException {
46+
String[] dateTimeStrings = split(args[1].strip(), "to");
47+
if (dateTimeStrings.length < 2) {
48+
throw new DukeException("Usage: event [task name] /at [start datetime] to [end datetime]");
49+
}
50+
LocalDateTime[] dateTimes = new LocalDateTime[2];
51+
for (int i = 0; i < 2; i++) {
52+
dateTimes[i] = commandParser.parse(dateTimeStrings[i].strip());
53+
}
54+
return dateTimes;
55+
}
56+
}
Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,39 @@
11
package duke.commands;
22

3-
import java.io.IOException;
4-
53
import duke.ui.Ui;
64
import duke.tasks.Task;
75
import duke.tasks.Todo;
86
import duke.tasks.TaskList;
97
import duke.storage.Storage;
8+
import duke.parsers.CommandParser;
109
import duke.exceptions.DukeException;
1110

1211
/**
1312
* Creates a Todo Task and adds it to the TaskList.
1413
*/
15-
class CreateTodo implements Command {
14+
class CreateTodo extends Command {
15+
16+
public CreateTodo(CommandParser commandParser) {
17+
super(commandParser);
18+
}
19+
1620
public void execute(String arg, TaskList tasks, Ui ui, Storage storage) throws DukeException {
17-
if (arg.length() == 0) {
18-
throw new DukeException("Usage: todo [task name]");
19-
}
21+
String taskName = getTaskName(arg);
2022

21-
// Create new Task
22-
Task newTask = new Todo(arg);
23+
Task newTask = new Todo(taskName);
2324
tasks.add(newTask);
2425

25-
// Save new Todo to disk
26-
try {
27-
storage.save(tasks.getAllTasks());
28-
} catch (IOException e) {
29-
throw new DukeException("Error when saving to disk!");
30-
}
26+
save(storage, tasks);
3127

32-
// Display reply
3328
ui.showReply(String.format("Got it. I've added this task:\n %s\nNow you have %d tasks in the list.", newTask,
3429
tasks.size()));
3530
}
36-
}
31+
32+
private String getTaskName(String arg) throws DukeException {
33+
String taskName = arg.strip();
34+
if (arg.length() == 0) {
35+
throw new DukeException("Usage: todo [task name]");
36+
}
37+
return taskName;
38+
}
39+
}

0 commit comments

Comments
 (0)