From ecf563679fc5a197854dc1a14244ff37c394f379 Mon Sep 17 00:00:00 2001 From: "Henry\\Henry" Date: Wed, 26 Oct 2016 21:37:46 +0800 Subject: [PATCH 1/3] Fix modify command parser not accepting empty values --- .../savvytasker/logic/parser/DateParser.java | 2 +- .../logic/parser/ModifyCommandParser.java | 27 ++++++++++++------- .../logic/parser/TaskFieldParser.java | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/savvytasker/logic/parser/DateParser.java b/src/main/java/seedu/savvytasker/logic/parser/DateParser.java index a1da821738b8..66549fd40200 100644 --- a/src/main/java/seedu/savvytasker/logic/parser/DateParser.java +++ b/src/main/java/seedu/savvytasker/logic/parser/DateParser.java @@ -19,7 +19,7 @@ public class InferredDate { private final boolean dateInferred; private final boolean timeInferred; - private InferredDate(Date inferredDateTime, boolean dateInferred, boolean timeInferred) { + public InferredDate(Date inferredDateTime, boolean dateInferred, boolean timeInferred) { this.inferredDateTime = inferredDateTime; this.dateInferred = dateInferred; this.timeInferred = timeInferred; diff --git a/src/main/java/seedu/savvytasker/logic/parser/ModifyCommandParser.java b/src/main/java/seedu/savvytasker/logic/parser/ModifyCommandParser.java index 784c2443587f..17bec39e9e0b 100644 --- a/src/main/java/seedu/savvytasker/logic/parser/ModifyCommandParser.java +++ b/src/main/java/seedu/savvytasker/logic/parser/ModifyCommandParser.java @@ -1,6 +1,7 @@ //@@author A0139916U package seedu.savvytasker.logic.parser; +import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -29,15 +30,15 @@ public class ModifyCommandParser implements CommandParser { private static final Pattern REGEX_PATTERN = Pattern.compile( HEADER+"\\s+(?<"+REGEX_REF_INDEX+">([^/]+?(\\s+|$))+)((?<=\\s)(" + - "(t/(?<"+REGEX_REF_TASK_NAME+">[^/]+)(?!.*\\st/))|" + - "(s/(?<"+REGEX_REF_START_DATE+">[^/]+)(?!.*\\ss/))|" + - "(e/(?<"+REGEX_REF_END_DATE+">[^/]+)(?!.*\\se/))|" + - "(l/(?<"+REGEX_REF_LOCATION+">[^/]+)(?!.*\\sl/))|" + + "(t/(?<"+REGEX_REF_TASK_NAME+">[^/]*)(?!.*\\st/))|" + + "(s/(?<"+REGEX_REF_START_DATE+">[^/]*)(?!.*\\ss/))|" + + "(e/(?<"+REGEX_REF_END_DATE+">[^/]*)(?!.*\\se/))|" + + "(l/(?<"+REGEX_REF_LOCATION+">[^/]*)(?!.*\\sl/))|" + "(p/(?<"+REGEX_REF_PRIORITY_LEVEL+">[^/]+)(?!.*\\sp/))|" + "(r/(?<"+REGEX_REF_RECURRING_TYPE+">[^/]+)(?!.*\\sr/))|" + - "(n/(?<"+REGEX_REF_NUMBER_OF_RECURRENCE+">[^/]+?)(?!.*\\sn/))|" + - "(c/(?<"+REGEX_REF_CATEGORY+">[^/]+)(?!.*\\sc/))|" + - "(d/(?<"+REGEX_REF_DESCRIPTION+">[^/]+)(?!.*\\sd/))" + + "(n/(?<"+REGEX_REF_NUMBER_OF_RECURRENCE+">[^/]+)(?!.*\\sn/))|" + + "(c/(?<"+REGEX_REF_CATEGORY+">[^/]*)(?!.*\\sc/))|" + + "(d/(?<"+REGEX_REF_DESCRIPTION+">[^/]*)(?!.*\\sd/))" + ")(\\s|$)){0,11}", Pattern.CASE_INSENSITIVE); private static final TaskFieldParser TASK_PARSER = new TaskFieldParser(); @@ -59,8 +60,8 @@ public ModifyCommand parse(String commandText) throws ParseException { if (matcher.matches()) { int index = parseIndex(matcher.group(REGEX_REF_INDEX)); - InferredDate startDate = TASK_PARSER.parseStartDate(matcher.group(REGEX_REF_START_DATE)); - InferredDate endDate = TASK_PARSER.parseEndDate(matcher.group(REGEX_REF_END_DATE)); + InferredDate startDate = parseDate(matcher.group(REGEX_REF_START_DATE)); + InferredDate endDate = parseDate(matcher.group(REGEX_REF_END_DATE)); String taskName = TASK_PARSER.parseTaskName(matcher.group(REGEX_REF_TASK_NAME)); String location = TASK_PARSER.parseLocation(matcher.group(REGEX_REF_LOCATION)); PriorityLevel priority = TASK_PARSER.parsePriorityLevel(matcher.group(REGEX_REF_PRIORITY_LEVEL)); @@ -86,4 +87,12 @@ private int parseIndex(String indexText) throws ParseException { throw new ParseException(indexText, "INDEX: " + ex.getFailureDetails()); } } + + private InferredDate parseDate(String dateText) throws ParseException { + if (dateText.trim().isEmpty()) { + return TASK_PARSER.dateParser.new InferredDate(new Date(), true, true); + } + + return TASK_PARSER.parseStartDate(dateText); + } } diff --git a/src/main/java/seedu/savvytasker/logic/parser/TaskFieldParser.java b/src/main/java/seedu/savvytasker/logic/parser/TaskFieldParser.java index 2c8612366fdd..4e981b3dd4ba 100644 --- a/src/main/java/seedu/savvytasker/logic/parser/TaskFieldParser.java +++ b/src/main/java/seedu/savvytasker/logic/parser/TaskFieldParser.java @@ -9,7 +9,7 @@ * This class contains common parsing methods for parsing Task fields. */ public class TaskFieldParser { - private DateParser dateParser; + protected final DateParser dateParser; public TaskFieldParser() { this.dateParser = new DateParser(); From 0d0d0e80172320835a85975d112fb74b96201d16 Mon Sep 17 00:00:00 2001 From: qhng Date: Wed, 26 Oct 2016 22:50:19 +0800 Subject: [PATCH 2/3] Fix removing fields that were setted previously and needs to be "unset" --- .../commons/util/SmartDefaultDates.java | 16 +++- .../logic/commands/AddCommand.java | 4 +- .../logic/commands/ModifyCommand.java | 8 +- .../logic/parser/ModifyCommandParser.java | 2 +- .../seedu/savvytasker/model/task/Task.java | 82 ++++++++++++++++++- 5 files changed, 95 insertions(+), 17 deletions(-) diff --git a/src/main/java/seedu/savvytasker/commons/util/SmartDefaultDates.java b/src/main/java/seedu/savvytasker/commons/util/SmartDefaultDates.java index 387916024f48..cf6133f1c763 100644 --- a/src/main/java/seedu/savvytasker/commons/util/SmartDefaultDates.java +++ b/src/main/java/seedu/savvytasker/commons/util/SmartDefaultDates.java @@ -19,10 +19,10 @@ public class SmartDefaultDates { private final Calendar today; /** - * + * Determines the smart defaults for the dates provided. Can set both + * start and end dates as null to get a basic smart default. * @param startDateTime Starting date time * @param endDateTime Ending date time - * @throws InvalidDateException If endDateTime is earlier than startDateTime */ public SmartDefaultDates(InferredDate startDateTime, InferredDate endDateTime) { calendar = Calendar.getInstance(); @@ -50,7 +50,11 @@ public SmartDefaultDates(InferredDate startDateTime, InferredDate endDateTime) { public Date getEnd(InferredDate endDateTime) { if (endDateTime == null) return null; calendar.setTime(endDateTime.getInferredDateTime()); - if (endDateTime.isDateInferred()) { + if (endDateTime.isDateInferred() && endDateTime.isTimeInferred()) { + // user didn't specify anything + // remove date field + return null; + } else if (endDateTime.isDateInferred()) { // date not supplied // defaults to today calendar.set(Calendar.DATE, today.get(Calendar.DATE)); @@ -94,7 +98,11 @@ private void parseEnd(InferredDate endDateTime) { public Date getStart(InferredDate startDateTime) { if (startDateTime == null) return null; calendar.setTime(startDateTime.getInferredDateTime()); - if (startDateTime.isDateInferred()) { + if (startDateTime.isDateInferred() && startDateTime.isTimeInferred()) { + // user didn't specify anything + // remove date field + return null; + } else if (startDateTime.isDateInferred()) { // date not supplied // defaults to today calendar.set(Calendar.DATE, today.get(Calendar.DATE)); diff --git a/src/main/java/seedu/savvytasker/logic/commands/AddCommand.java b/src/main/java/seedu/savvytasker/logic/commands/AddCommand.java index 15223526e149..67c1a948db24 100644 --- a/src/main/java/seedu/savvytasker/logic/commands/AddCommand.java +++ b/src/main/java/seedu/savvytasker/logic/commands/AddCommand.java @@ -1,7 +1,6 @@ package seedu.savvytasker.logic.commands; import seedu.savvytasker.commons.core.UnmodifiableObservableList; -import seedu.savvytasker.commons.util.SmartDefaultDates; import seedu.savvytasker.logic.parser.DateParser.InferredDate; import seedu.savvytasker.model.task.PriorityLevel; import seedu.savvytasker.model.task.ReadOnlyTask; @@ -62,8 +61,7 @@ private void createTask() { final boolean isArchived = false; // all tasks are first added as active tasks final int taskId = 0; // taskId to be assigned by ModelManager, leave as 0 - SmartDefaultDates sdd = new SmartDefaultDates(startDateTime, endDateTime); - this.toAdd = new Task(taskId, taskName, sdd.getStartDate(), sdd.getEndDate(), + this.toAdd = new Task(taskId, taskName, startDateTime, endDateTime, location, priority, recurringType, numberOfRecurrence, category, description, isArchived); } diff --git a/src/main/java/seedu/savvytasker/logic/commands/ModifyCommand.java b/src/main/java/seedu/savvytasker/logic/commands/ModifyCommand.java index 53405f7fe77a..6deea98ad6c2 100644 --- a/src/main/java/seedu/savvytasker/logic/commands/ModifyCommand.java +++ b/src/main/java/seedu/savvytasker/logic/commands/ModifyCommand.java @@ -2,7 +2,6 @@ import seedu.savvytasker.commons.core.Messages; import seedu.savvytasker.commons.core.UnmodifiableObservableList; -import seedu.savvytasker.commons.util.SmartDefaultDates; import seedu.savvytasker.logic.parser.DateParser.InferredDate; import seedu.savvytasker.model.task.PriorityLevel; import seedu.savvytasker.model.task.ReadOnlyTask; @@ -70,13 +69,10 @@ public CommandResult execute() { indicateAttemptToExecuteIncorrectCommand(); return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX); } - - - SmartDefaultDates sdd = new SmartDefaultDates(null, null); ReadOnlyTask taskToModify = lastShownList.get(index - 1); - replacement = new Task(taskToModify, taskName, sdd.getStart(startDateTime), - sdd.getEnd(endDateTime), location, priority, + replacement = new Task(taskToModify, taskName, startDateTime, + endDateTime, location, priority, recurringType, numberOfRecurrence, category, description); diff --git a/src/main/java/seedu/savvytasker/logic/parser/ModifyCommandParser.java b/src/main/java/seedu/savvytasker/logic/parser/ModifyCommandParser.java index 17bec39e9e0b..4bb317bdbde2 100644 --- a/src/main/java/seedu/savvytasker/logic/parser/ModifyCommandParser.java +++ b/src/main/java/seedu/savvytasker/logic/parser/ModifyCommandParser.java @@ -89,7 +89,7 @@ private int parseIndex(String indexText) throws ParseException { } private InferredDate parseDate(String dateText) throws ParseException { - if (dateText.trim().isEmpty()) { + if (dateText != null && dateText.trim().isEmpty()) { return TASK_PARSER.dateParser.new InferredDate(new Date(), true, true); } diff --git a/src/main/java/seedu/savvytasker/model/task/Task.java b/src/main/java/seedu/savvytasker/model/task/Task.java index d3aa92c7be22..e70d8763336c 100644 --- a/src/main/java/seedu/savvytasker/model/task/Task.java +++ b/src/main/java/seedu/savvytasker/model/task/Task.java @@ -3,6 +3,9 @@ import java.util.Date; import java.util.Objects; +import seedu.savvytasker.commons.util.SmartDefaultDates; +import seedu.savvytasker.logic.parser.DateParser.InferredDate; + //@@author A0139915W /** * Represents a Task in the task list. @@ -21,9 +24,46 @@ public class Task implements ReadOnlyTask { private String description; private boolean isArchived; + /** + * Constructor with smart defaults + */ + public Task(int id, String taskName, InferredDate startDateTime, InferredDate endDateTime, String location, + PriorityLevel priority, RecurrenceType recurringType, Integer numberOfRecurrence, + String category, String description, boolean isArchived) { + + SmartDefaultDates sdd = new SmartDefaultDates(startDateTime, endDateTime); + this.id = id; + this.taskName = taskName; + this.startDateTime = sdd.getStartDate(); + this.endDateTime = sdd.getEndDate(); + this.location = location; + if (priority == null) { + this.priority = PriorityLevel.Medium; + } else { + this.priority = priority; + } + if (recurringType == null) { + this.recurringType = RecurrenceType.None; + } else { + this.recurringType = recurringType; + } + if (numberOfRecurrence == null) { + this.numberOfRecurrence = 0; + } else { + this.numberOfRecurrence = numberOfRecurrence.intValue(); + } + this.category = category; + this.description = description; + this.isArchived = isArchived; + } + + /** + * Constructor without smart defaults + */ public Task(int id, String taskName, Date startDateTime, Date endDateTime, String location, PriorityLevel priority, RecurrenceType recurringType, Integer numberOfRecurrence, String category, String description, boolean isArchived) { + this.id = id; this.taskName = taskName; this.startDateTime = startDateTime; @@ -70,7 +110,7 @@ public Task(ReadOnlyTask source) { /** * Copy and modify constructor */ - public Task(ReadOnlyTask source, String taskName, Date startDateTime, Date endDateTime, String location, + public Task(ReadOnlyTask source, String taskName, InferredDate startDateTime, InferredDate endDateTime, String location, PriorityLevel priority, RecurrenceType recurringType, Integer numberOfRecurrence, String category, String description) { this(source.getId(), source.getTaskName(), source.getStartDateTime(), @@ -81,8 +121,8 @@ public Task(ReadOnlyTask source, String taskName, Date startDateTime, Date endDa //this.id should follow that of the source. //this.isArchived should follow that of the source. this.taskName = taskName == null ? this.taskName : taskName; - this.startDateTime = startDateTime == null ? this.startDateTime : startDateTime; - this.endDateTime = endDateTime == null ? this.endDateTime : endDateTime; + setStartDate(startDateTime); + setEndDate(endDateTime); this.location = location == null ? this.location : location; this.priority = priority == null ? this.priority : priority; this.recurringType = recurringType == null ? this.recurringType : recurringType; @@ -90,6 +130,42 @@ public Task(ReadOnlyTask source, String taskName, Date startDateTime, Date endDa this.category = category == null ? this.category : category; this.description = description == null ? this.description : description; } + + private void setStartDate(InferredDate inferredDate) { + if (inferredDate == null) { + // user didn't specify s/ + // keep existing start date + } else { + if (inferredDate.isDateInferred() && inferredDate.isTimeInferred()) { + // user specified s/ but with nothing tagged to it + // remove existing start date + this.startDateTime = null; + } else { + // user specified s/ with something tagged to it + // update existing start date + SmartDefaultDates sdd = new SmartDefaultDates(null, null); + this.startDateTime = sdd.getStart(inferredDate); + } + } + } + + private void setEndDate(InferredDate inferredDate) { + if (inferredDate == null) { + // user didn't specify e/ + // keep existing end date + } else { + if (inferredDate.isDateInferred() && inferredDate.isTimeInferred()) { + // user specified e/ but with nothing tagged to it + // remove existing end date + this.endDateTime = null; + } else { + // user specified e/ with something tagged to it + // update existing end date + SmartDefaultDates sdd = new SmartDefaultDates(null, null); + this.endDateTime = sdd.getStart(inferredDate); + } + } + } @Override public int getId() { From 6df335e0b4685cf42b61b3cce75d35d37f2c1a09 Mon Sep 17 00:00:00 2001 From: qhng Date: Wed, 26 Oct 2016 22:50:45 +0800 Subject: [PATCH 3/3] Update unknown command to show help message. Update SUT to reflect changes. --- .../java/seedu/savvytasker/logic/parser/MasterParser.java | 2 +- src/test/java/guitests/AddCommandTest.java | 4 +++- src/test/java/guitests/FindCommandTest.java | 4 +++- src/test/java/guitests/ListCommandTest.java | 4 +++- src/test/java/seedu/savvytasker/logic/LogicManagerTest.java | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/savvytasker/logic/parser/MasterParser.java b/src/main/java/seedu/savvytasker/logic/parser/MasterParser.java index 2d2cb57188a8..753b62808fe3 100644 --- a/src/main/java/seedu/savvytasker/logic/parser/MasterParser.java +++ b/src/main/java/seedu/savvytasker/logic/parser/MasterParser.java @@ -36,7 +36,7 @@ public Command parse(String userInput) { String trueHeader = extractHeader(header); CommandParser parser = commandParsers.get(trueHeader); if (parser == null) - return new IncorrectCommand(header + body, MESSAGE_UNKNOWN_COMMAND); + return new IncorrectCommand(header + body, String.format(MESSAGE_UNKNOWN_COMMAND, HelpCommand.MESSAGE_USAGE)); if (parser.shouldPreprocess()) body = preprocessBody(body); diff --git a/src/test/java/guitests/AddCommandTest.java b/src/test/java/guitests/AddCommandTest.java index 90c915061984..41984bea99f6 100644 --- a/src/test/java/guitests/AddCommandTest.java +++ b/src/test/java/guitests/AddCommandTest.java @@ -5,10 +5,12 @@ import org.junit.Test; import seedu.savvytasker.commons.core.Messages; +import seedu.savvytasker.logic.commands.HelpCommand; import seedu.savvytasker.testutil.TestTask; import seedu.savvytasker.testutil.TestUtil; import static org.junit.Assert.assertTrue; +import static seedu.savvytasker.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; //@@author A0139915W public class AddCommandTest extends SavvyTaskerGuiTest { @@ -32,7 +34,7 @@ public void add() { //invalid command commandBox.runCommand("adds Bad Command Task"); - assertResultMessage(Messages.MESSAGE_UNKNOWN_COMMAND); + assertResultMessage(String.format(MESSAGE_UNKNOWN_COMMAND, HelpCommand.MESSAGE_USAGE)); } private void assertAddSuccess(TestTask taskToAdd, TestTask... currentList) { diff --git a/src/test/java/guitests/FindCommandTest.java b/src/test/java/guitests/FindCommandTest.java index 66db1b19546f..fc884bb9e436 100644 --- a/src/test/java/guitests/FindCommandTest.java +++ b/src/test/java/guitests/FindCommandTest.java @@ -3,9 +3,11 @@ import org.junit.Test; import seedu.savvytasker.commons.core.Messages; +import seedu.savvytasker.logic.commands.HelpCommand; import seedu.savvytasker.testutil.TestTask; import static org.junit.Assert.assertTrue; +import static seedu.savvytasker.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; //@@author A0139915W public class FindCommandTest extends SavvyTaskerGuiTest { @@ -45,7 +47,7 @@ public void find_emptyList(){ @Test public void find_invalidCommand_fail() { commandBox.runCommand("findmyring"); - assertResultMessage(Messages.MESSAGE_UNKNOWN_COMMAND); + assertResultMessage(String.format(MESSAGE_UNKNOWN_COMMAND, HelpCommand.MESSAGE_USAGE)); } private void assertFindResult(String command, TestTask... expectedHits) { diff --git a/src/test/java/guitests/ListCommandTest.java b/src/test/java/guitests/ListCommandTest.java index 5ea0310418ac..990f475711c9 100644 --- a/src/test/java/guitests/ListCommandTest.java +++ b/src/test/java/guitests/ListCommandTest.java @@ -3,9 +3,11 @@ import org.junit.Test; import seedu.savvytasker.commons.core.Messages; +import seedu.savvytasker.logic.commands.HelpCommand; import seedu.savvytasker.testutil.TestTask; import static org.junit.Assert.assertTrue; +import static seedu.savvytasker.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; //@@author A0139915W public class ListCommandTest extends SavvyTaskerGuiTest { @@ -46,7 +48,7 @@ public void list_emptyList(){ @Test public void find_invalidCommand_fail() { commandBox.runCommand("listmytasks"); - assertResultMessage(Messages.MESSAGE_UNKNOWN_COMMAND); + assertResultMessage(String.format(MESSAGE_UNKNOWN_COMMAND, HelpCommand.MESSAGE_USAGE)); } private void assertListResult(String command, TestTask... expectedHits ) { diff --git a/src/test/java/seedu/savvytasker/logic/LogicManagerTest.java b/src/test/java/seedu/savvytasker/logic/LogicManagerTest.java index 30776f5af566..eec2e4ca6fd3 100644 --- a/src/test/java/seedu/savvytasker/logic/LogicManagerTest.java +++ b/src/test/java/seedu/savvytasker/logic/LogicManagerTest.java @@ -128,7 +128,7 @@ private void assertCommandBehavior(String inputCommand, String expectedMessage, @Test public void execute_unknownCommandWord() throws Exception { String unknownCommand = "uicfhmowqewca"; - assertCommandBehavior(unknownCommand, MESSAGE_UNKNOWN_COMMAND); + assertCommandBehavior(unknownCommand, String.format(MESSAGE_UNKNOWN_COMMAND, HelpCommand.MESSAGE_USAGE)); } @Test