Skip to content

Commit

Permalink
Fix AddParser (#204)
Browse files Browse the repository at this point in the history
* A fix for the add parser

* cleanup

* Update to check for quotaiton

* Parse tests

* Update schedule format

* Change escape character to single quotation only, only allow by/from and to format, update logic manager test to test escape character
  • Loading branch information
burnflare authored Nov 6, 2016
1 parent 1c6265b commit 529a4b8
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 21 deletions.
90 changes: 69 additions & 21 deletions src/main/java/seedu/agendum/logic/parser/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,15 @@ public class Parser {
private static final Pattern UNALIAS_ARGS_FORMAT = Pattern.compile("(?<shorthand>[\\p{Alnum}]+)");

//@@author A0003878Y
private static final Pattern QUOTATION_FORMAT = Pattern.compile("\'([^\']*)\'");
private static final Pattern ADD_SCHEDULE_ARGS_FORMAT = Pattern.compile("(?:.+?(?=(?:(?:(?i)by|from|to)\\s|$)))+?");

private static final String ARGS_FROM = "from";
private static final String ARGS_BY = "by";
private static final String ARGS_TO = "to";
private static final String FILLER_WORD = "FILLER ";
private static final String SINGLE_QUOTE = "\'";

private static final String[] TIME_TOKENS = new String[] { ARGS_FROM, ARGS_TO, ARGS_BY };

private CommandLibrary commandLibrary;
Expand Down Expand Up @@ -145,16 +149,31 @@ public Command parseCommand(String userInput) {
* @return the prepared command
*/
private Command prepareAdd(String args) {

// Create title and dateTimeMap
StringBuilder titleBuilder = new StringBuilder();
HashMap<String, Optional<LocalDateTime>> dateTimeMap = new HashMap<>();

// Check for quotation in args. If so, they're set as title
Optional<String> quotationCheck = checkForQuotation(args);
if (quotationCheck.isPresent()) {
titleBuilder.append(quotationCheck.get().replace(SINGLE_QUOTE,""));
args = FILLER_WORD + args.replace(quotationCheck.get(),""); // This will get removed later by regex
}

// Start parsing for datetime in args
Matcher matcher = ADD_SCHEDULE_ARGS_FORMAT.matcher(args.trim());

if (!matcher.matches()) {
return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
}

try {
matcher.reset();
matcher.find();
StringBuilder titleBuilder = new StringBuilder(matcher.group(0));
HashMap<String, Optional<LocalDateTime>> dateTimeMap = new HashMap<>();
if (titleBuilder.length() == 0) {
titleBuilder.append(matcher.group(0));
}

// Run this function on all matched groups
BiConsumer<String, String> consumer = (matchedGroup, token) -> {
Expand All @@ -165,21 +184,31 @@ private Command prepareAdd(String args) {
titleBuilder.append(matchedGroup);
}
};
scheduleMatcherOnConsumer(matcher, consumer);
executeOnEveryMatcherToken(matcher, consumer);

String title = titleBuilder.toString();

if (dateTimeMap.containsKey(ARGS_BY)) {
if (title.length() == 0) {
return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
}

boolean hasDeadlineKeyword = dateTimeMap.containsKey(ARGS_BY);
boolean hasStartTimeKeyword = dateTimeMap.containsKey(ARGS_FROM);
boolean hasEndTimeKeyword = dateTimeMap.containsKey(ARGS_TO);

if (hasDeadlineKeyword && !hasStartTimeKeyword && !hasEndTimeKeyword) {
return new AddCommand(title, dateTimeMap.get(ARGS_BY));
} else if (dateTimeMap.containsKey(ARGS_FROM) && dateTimeMap.containsKey(ARGS_TO)) {
}

if (!hasDeadlineKeyword && hasStartTimeKeyword && hasEndTimeKeyword) {
return new AddCommand(title, dateTimeMap.get(ARGS_FROM), dateTimeMap.get(ARGS_TO));
} else if (!dateTimeMap.containsKey(ARGS_FROM) && !dateTimeMap.containsKey(ARGS_TO)
&& !dateTimeMap.containsKey(ARGS_BY)) {
}

if (!hasDeadlineKeyword && !hasStartTimeKeyword && !hasEndTimeKeyword) {
return new AddCommand(title);
} else {
return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
AddCommand.MESSAGE_USAGE));
}

return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
} catch (IllegalValueException ive) {
return new IncorrectCommand(ive.getMessage());
}
Expand Down Expand Up @@ -218,19 +247,38 @@ private Command prepareSchedule(String args) {
dateTimeMap.put(token, DateTimeUtils.parseNaturalLanguageDateTimeString(time));
}
};
scheduleMatcherOnConsumer(matcher, consumer);
executeOnEveryMatcherToken(matcher, consumer);

if (dateTimeMap.containsKey(ARGS_BY)) {
boolean hasDeadlineKeyword = dateTimeMap.containsKey(ARGS_BY);
boolean hasStartTimeKeyword = dateTimeMap.containsKey(ARGS_FROM);
boolean hasEndTimeKeyword = dateTimeMap.containsKey(ARGS_TO);

if (hasDeadlineKeyword && !hasStartTimeKeyword && !hasEndTimeKeyword) {
return new ScheduleCommand(index, Optional.empty(), dateTimeMap.get(ARGS_BY));
} else if (dateTimeMap.containsKey(ARGS_FROM) && dateTimeMap.containsKey(ARGS_TO)) {
return new ScheduleCommand(index, dateTimeMap.get(ARGS_FROM), dateTimeMap.get(ARGS_TO));
} else if (!dateTimeMap.containsKey(ARGS_FROM) && !dateTimeMap.containsKey(ARGS_TO)
&& !dateTimeMap.containsKey(ARGS_BY)) {
return new ScheduleCommand(index, Optional.empty(), Optional.empty());
} else {
return new IncorrectCommand(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, ScheduleCommand.MESSAGE_USAGE));
}

if (!hasDeadlineKeyword && hasStartTimeKeyword && hasEndTimeKeyword) {
return new ScheduleCommand(index, dateTimeMap.get(ARGS_FROM), dateTimeMap.get(ARGS_TO));}

if (!hasDeadlineKeyword && !hasStartTimeKeyword && !hasEndTimeKeyword) {
return new ScheduleCommand(index, Optional.empty(), Optional.empty());
}

return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ScheduleCommand.MESSAGE_USAGE));
}

/**
* Checks if there are any quotation marks in the given string
*
* @param str
* @return returns the string inside the quote.
*/
private Optional<String> checkForQuotation(String str) {
Matcher matcher = QUOTATION_FORMAT.matcher(str.trim());
if (!matcher.find()) {
return Optional.empty();
}
return Optional.of(matcher.group(0));
}

/**
Expand All @@ -240,7 +288,7 @@ private Command prepareSchedule(String args) {
* @param matcher matcher for current command context
* @param consumer <String, String> closure to execute on
*/
private void scheduleMatcherOnConsumer(Matcher matcher, BiConsumer<String, String> consumer) {
private void executeOnEveryMatcherToken(Matcher matcher, BiConsumer<String, String> consumer) {
while (matcher.find()) {
for (String token : TIME_TOKENS) {
String matchedGroup = matcher.group(0).toLowerCase();
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/seedu/agendum/logic/LogicManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,21 @@ public void execute_addEventTask_successful() throws Exception {
expectedTDL.getTaskList());
}

@Test
public void execute_addEscapeDateTimeParsing() throws Exception {
TestDataHelper helper = new TestDataHelper();
Task toBeAdded = helper.generateTaskWithName("drop from 21 to 1");
ToDoList expectedTDL = new ToDoList();
expectedTDL.addTask(toBeAdded);

// execute command and verify result
assertCommandBehavior("add 'drop from 21 to 1'",
String.format(AddCommand.MESSAGE_SUCCESS, toBeAdded),
expectedTDL,
expectedTDL.getTaskList());
}


@Test
public void executeAddDuplicateNotAllowed() throws Exception {
// setup expectations
Expand Down

0 comments on commit 529a4b8

Please sign in to comment.