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

Add set bin item expiry time functionality #196

Merged
merged 10 commits into from
Nov 7, 2019
42 changes: 39 additions & 3 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,8 @@ Format: `delete INDEX`
* Deletes 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, ...
* Deleted persons are moved into the bin, where they stay there for 30 days before being removed permanently.
* Deleted persons are moved into the bin, where they stay there for a default of 30 days before being removed
permanently. This default value can be changed with the <<binitemexpiry, binitemexpiry>> command.
****
[NOTE]
Deleted items will expire in 10 seconds for testing purposes. Expired items are removed on restart of application.
Expand All @@ -391,6 +392,8 @@ Format: `deletepolicy INDEX`
* Deletes the policy at the specified `INDEX`.
* The index refers to the index number shown in the displayed policy list.
* The index *must be a positive integer* 1, 2, 3, ...
* Deleted persons are moved into the bin, where they stay there for a default of 30 days before being removed
permanently. This default value can be changed with the <<binitemexpiry, binitemexpiry>> command.
****
[NOTE]
Deleted items will expire in 10 seconds for testing purposes. Expired items are removed on restart of application.
Expand Down Expand Up @@ -495,7 +498,7 @@ Deletes a `high_risk` tag from the 1st policy in the results of the `find` comma
// end::delete[]
=== Clearing all entries : `clear`

Clears all entries from the address book. +
Clears all entries from the address book, including the bin.+
Format: `clear`

// tag::inputvalidation[]
Expand Down Expand Up @@ -697,7 +700,6 @@ Format:
* Restores the item at the specified INDEX.
* The index refers to the index number shown in the displayed bin list.
* The index must be a positive integer 1, 2, 3, …​
* Mass restoration by field is also possible by specifying `field:value`.
****

Examples:
Expand All @@ -713,6 +715,38 @@ Date of birth: 5 March 1980 Gender: Male Date deleted: 22 Oct 2019 at 09:57 PM E
```
// end::restore[]


// tag::binitemexpiry[]
[#binitemexpiry]
=== Set expiry time of bin items: `binitemexpiry`
User can set the amount of time bin items stay in the bin before they are permanently removed.

Format:
`binitemexpiry UNIT/AMOUNT`

****
* `UNIT` can take the following values:
** s
** mins
** hrs
** days
** months
** years
* `AMOUNT` *must be a positive integer* 1, 2, 3, ...
****

Example:

`binitemexpiry days/30` +

Set all BinItems to expire 30 days their deletion. They will be removed permanently once they exceed their expiry date.

Expected Output: +
```
Changed bin item expiry time! Items in the Bin will be removed permanently 30 days after their deletion.
```
// end::binitemexpiry[]

=== Undo recently entered commands
User can simply enter the command `undo` to undo the most recent address book change.

Expand Down Expand Up @@ -815,5 +849,7 @@ e.g. `expandpolicy 1`
e.g. `display i/policy-popularity-breakdown f/piechart`
* *Undo the most recent command*: `undo`
* *Redo the most recent undone command*: `redo`
* *Set expiry time of bin items*: `binitemexpiry` +
e.g. `binitemexpiry days/30`
* *Clear* : `clear`
* *Help* : `help`
2 changes: 2 additions & 0 deletions src/main/java/seedu/address/commons/core/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class Messages {
public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
public static final String MESSAGE_INVALID_POLICY_DISPLAYED_INDEX = "The policy index provided is invalid";
public static final String MESSAGE_INVALID_BIN_ITEM_DISPLAYED_INDEX = "The bin item index provided is invalid";
public static final String MESSAGE_NULL_ARGUMENTS_COMMAND = "This command does not take in additional arguments! "
+ " Do you mean \"%s\"?";
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_POLICIES_LISTED_OVERVIEW = "%1$d policies listed!";
public static final String MESSAGE_UNKNOWN_MERGE_COMMAND = "Unknown command. %1$s. If you wish to stop merging"
Expand Down
17 changes: 16 additions & 1 deletion src/main/java/seedu/address/commons/core/UserSettings.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package seedu.address.commons.core;

import java.io.Serializable;
import java.time.temporal.ChronoUnit;
import java.util.Objects;

/**
Expand All @@ -10,19 +11,33 @@
public class UserSettings implements Serializable {

private final boolean suggestionsOn;
private final int timeToLiveAmount;
private final ChronoUnit timeToLiveUnit;

public UserSettings() {
suggestionsOn = true;
timeToLiveAmount = 30;
timeToLiveUnit = ChronoUnit.DAYS;
}

public UserSettings(boolean suggestionsOn) {
public UserSettings(boolean suggestionsOn, int amount, ChronoUnit unit) {
this.suggestionsOn = suggestionsOn;
this.timeToLiveAmount = amount;
this.timeToLiveUnit = unit;
}

public boolean isSuggestionsOn() {
return suggestionsOn;
}

public int getTimeToLiveAmount() {
return timeToLiveAmount;
}

public ChronoUnit getTimeToLiveUnit() {
return timeToLiveUnit;
}

@Override
public boolean equals(Object other) {
if (other == this) {
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/seedu/address/logic/LogicManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,9 @@ public void setUserSettings(UserSettings userSettings) {
@Override
public void setUserSettings() {
boolean suggestionOn = addressBookParser.isSuggestionOn();
UserSettings userSettings = new UserSettings(suggestionOn);
UserSettings userSettings = new UserSettings(suggestionOn,
model.getUserSettings().getTimeToLiveAmount(),
model.getUserSettings().getTimeToLiveUnit());
model.setUserSettings(userSettings);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package seedu.address.logic.commands;

import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DAYS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_HOURS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_MINUTES;
import static seedu.address.logic.parser.CliSyntax.PREFIX_MONTHS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_SECONDS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_YEARS;
import static seedu.address.model.binitem.BinItem.DATE_TIME_FORMATTER;

import java.time.temporal.ChronoUnit;

import seedu.address.commons.core.UserSettings;
import seedu.address.commons.util.BinItemBuilder;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.binitem.BinItem;

/**
* Sets the expiry time of bin items in the bin.
*/
public class BinItemExpiryCommand extends Command {

public static final String COMMAND_WORD = "binitemexpiry";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Sets the expiry time of items in the Bin. "
+ "Parameters: "
+ "UNIT/AMOUNT\n"
+ "Available UNITs: "
+ PREFIX_SECONDS + ", "
+ PREFIX_MINUTES + ", "
+ PREFIX_HOURS + ", "
+ PREFIX_DAYS + ", "
+ PREFIX_MONTHS + ", "
+ PREFIX_YEARS + "\n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_DAYS + "30";

public static final String MESSAGE_SUCCESS = "Changed bin item expiry time! Items in the Bin will be removed"
+ " permanently %s %s after their deletion.";

private final int timeToLiveAmount;
private final ChronoUnit timeToLiveUnit;

public BinItemExpiryCommand(int amount, ChronoUnit unit) {
requireAllNonNull(amount, unit);

this.timeToLiveAmount = amount;
this.timeToLiveUnit = unit;
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireAllNonNull(model);

// Set time to live in binItem class
BinItem.setTimeToLive(timeToLiveAmount, timeToLiveUnit);
for (BinItem b : model.getAddressBook().getBinItemList()) {
BinItem newBinItem = (new BinItemBuilder(b)
.withExpiryDate(b.generateExpiryDate().format(DATE_TIME_FORMATTER))).build();
model.setBinItem(b, newBinItem);
}

// Update user settings
UserSettings userSettings = new UserSettings(model.getUserSettings().isSuggestionsOn(),
timeToLiveAmount, timeToLiveUnit);
model.setUserSettings(userSettings);
return new CommandResult(String.format(MESSAGE_SUCCESS,
timeToLiveAmount, timeToLiveUnit.toString().toLowerCase()));
}

}
20 changes: 20 additions & 0 deletions src/main/java/seedu/address/logic/parser/AddressBookParser.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package seedu.address.logic.parser;

import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.commons.core.Messages.MESSAGE_NULL_ARGUMENTS_COMMAND;
import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_MERGE_COMMAND;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ARGUMENTS;
Expand All @@ -16,6 +17,7 @@
import seedu.address.logic.commands.AddPolicyTagCommand;
import seedu.address.logic.commands.AddTagCommand;
import seedu.address.logic.commands.AssignPolicyCommand;
import seedu.address.logic.commands.BinItemExpiryCommand;
import seedu.address.logic.commands.ClearCommand;
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.DeleteCommand;
Expand Down Expand Up @@ -86,6 +88,12 @@ public AddressBookParser(boolean suggestionOn) {
public AddressBookParser() {
}

private void handleTrailingArguments(String arguments, String commandWord) throws ParseException {
if (!arguments.trim().isEmpty()) {
throw new ParseException(String.format(MESSAGE_NULL_ARGUMENTS_COMMAND, commandWord));
}
}

/**
* Parses user input and obtains the command word which determines the command being executed.
*
Expand Down Expand Up @@ -180,6 +188,7 @@ public Command parseCommand(String userInput, boolean isSystemInput) throws Pars
return new DeleteCriteriaCommandParser().parse(arguments);

case ClearCommand.COMMAND_WORD:
handleTrailingArguments(arguments, ClearCommand.COMMAND_WORD);
return new ClearCommand();

case FindCommand.COMMAND_WORD:
Expand All @@ -198,30 +207,38 @@ public Command parseCommand(String userInput, boolean isSystemInput) throws Pars
return new FindTagPolicyCommandParser().parse(arguments);

case ListPeopleCommand.COMMAND_WORD:
handleTrailingArguments(arguments, ListPeopleCommand.COMMAND_WORD);
return new ListPeopleCommand();

case ListPolicyCommand.COMMAND_WORD:
handleTrailingArguments(arguments, ListPolicyCommand.COMMAND_WORD);
return new ListPolicyCommand();

case ListBinCommand.COMMAND_WORD:
handleTrailingArguments(arguments, ListBinCommand.COMMAND_WORD);
return new ListBinCommand();

case UndoCommand.COMMAND_WORD:
handleTrailingArguments(arguments, UndoCommand.COMMAND_WORD);
return new UndoCommand();

case RedoCommand.COMMAND_WORD:
handleTrailingArguments(arguments, RedoCommand.COMMAND_WORD);
return new RedoCommand();

case HistoryCommand.COMMAND_WORD:
handleTrailingArguments(arguments, HistoryCommand.COMMAND_WORD);
return new HistoryCommand();

case RestoreCommand.COMMAND_WORD:
return new RestoreCommandParser().parse(arguments);

case ExitCommand.COMMAND_WORD:
handleTrailingArguments(arguments, ExitCommand.COMMAND_WORD);
return new ExitCommand();

case HelpCommand.COMMAND_WORD:
handleTrailingArguments(arguments, HelpCommand.COMMAND_WORD);
return new HelpCommand();

case MergePersonCommand.COMMAND_WORD:
Expand Down Expand Up @@ -279,6 +296,9 @@ public Command parseCommand(String userInput, boolean isSystemInput) throws Pars
}
return command;

case BinItemExpiryCommand.COMMAND_WORD:
return new BinItemExpiryCommandParser().parse(arguments);

default:
if (commandWord.length() == 0) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package seedu.address.logic.parser;

import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DAYS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_HOURS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_MINUTES;
import static seedu.address.logic.parser.CliSyntax.PREFIX_MONTHS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_SECONDS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_YEARS;

import java.time.temporal.ChronoUnit;
import java.util.stream.Stream;

import seedu.address.logic.commands.BinItemExpiryCommand;
import seedu.address.logic.parser.exceptions.ParseException;

/**
* Parses input arguments and creates a new BinItemExpiryCommand
*/
public class BinItemExpiryCommandParser implements Parser<BinItemExpiryCommand> {

private static Prefix[] prefixes = { PREFIX_SECONDS, PREFIX_MINUTES, PREFIX_HOURS, PREFIX_DAYS, PREFIX_MONTHS,
PREFIX_YEARS };

private static boolean areAnyPrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).anyMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}

private static boolean onlyOnePrefixValue(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).filter(prefix -> argumentMultimap.getValue(prefix).isPresent()).count() == 1;
}

/**
* Parses the given {@code String} of arguments in the context of the RestoreCommand
* and returns a RestoreCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public BinItemExpiryCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, prefixes);

if (!areAnyPrefixesPresent(argMultimap, prefixes) || !onlyOnePrefixValue(argMultimap, prefixes)
|| !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, BinItemExpiryCommand.MESSAGE_USAGE));
}

int timeToLiveAmount;
ChronoUnit timeToLiveUnit;
if (argMultimap.getValue(PREFIX_SECONDS).isPresent()) {
timeToLiveAmount = ParserUtil.parsePositiveInt(argMultimap.getValue(PREFIX_SECONDS).get());
timeToLiveUnit = ChronoUnit.SECONDS;
} else if (argMultimap.getValue(PREFIX_MINUTES).isPresent()) {
timeToLiveAmount = ParserUtil.parsePositiveInt(argMultimap.getValue(PREFIX_MINUTES).get());
timeToLiveUnit = ChronoUnit.MINUTES;
} else if (argMultimap.getValue(PREFIX_HOURS).isPresent()) {
timeToLiveAmount = ParserUtil.parsePositiveInt(argMultimap.getValue(PREFIX_HOURS).get());
timeToLiveUnit = ChronoUnit.HOURS;
} else if (argMultimap.getValue(PREFIX_DAYS).isPresent()) {
timeToLiveAmount = ParserUtil.parsePositiveInt(argMultimap.getValue(PREFIX_DAYS).get());
timeToLiveUnit = ChronoUnit.DAYS;
} else if (argMultimap.getValue(PREFIX_MONTHS).isPresent()) {
timeToLiveAmount = ParserUtil.parsePositiveInt(argMultimap.getValue(PREFIX_MONTHS).get());
timeToLiveUnit = ChronoUnit.MONTHS;
} else if (argMultimap.getValue(PREFIX_YEARS).isPresent()) {
timeToLiveAmount = ParserUtil.parsePositiveInt(argMultimap.getValue(PREFIX_YEARS).get());
timeToLiveUnit = ChronoUnit.YEARS;
} else {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, BinItemExpiryCommand.MESSAGE_USAGE));
}

return new BinItemExpiryCommand(timeToLiveAmount, timeToLiveUnit);
}
}
Loading