Skip to content

Commit 6ef830c

Browse files
liawsyKalsyc
authored andcommitted
Refactor and add tests
* Refactor and add tests for Quantity * Refactor DeleteCommand * Add CommandUtil * Refactor tests and relevant classes * Update tests for shift commands * Add tests for CommandUtil * Add tests for ReplenishList and related classes * Update index error message * Update ShiftToMainCommand test * Fix bugs in commands
1 parent c9778c4 commit 6ef830c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1422
-384
lines changed

build.gradle

+4-4
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,12 @@ task copyStylesheets(type: Copy) {
155155
}
156156
asciidoctor.dependsOn copyStylesheets
157157

158-
/*
159-
gradle.projectsEvaluated {
158+
159+
/*gradle.projectsEvaluated {
160160
tasks.withType(JavaCompile) {
161161
options.compilerArgs << "-Xlint:unchecked"
162162
}
163-
}
164-
*/
163+
}*/
164+
165165

166166
defaultTasks 'clean', 'test', 'coverage', 'asciidoctor'

src/main/java/io/xpire/MainApp.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public class MainApp extends Application {
4949
protected Storage storage;
5050
protected Model model;
5151
protected Config config;
52-
protected ItemManager itemManager;
52+
//protected ItemManager itemManager;
5353

5454
@Override
5555
public void init() throws Exception {
@@ -72,9 +72,9 @@ public void init() throws Exception {
7272

7373
logic = new LogicManager(model, storage);
7474

75-
itemManager = new ItemManager(model, storage);
75+
//itemManager = new ItemManager(model, storage);
7676

77-
initItemManager();
77+
//initItemManager();
7878

7979
ui = new UiManager(logic);
8080

@@ -120,9 +120,9 @@ private void initLogging(Config config) {
120120
LogsCenter.init(config);
121121
}
122122

123-
private void initItemManager() {
123+
/* private void initItemManager() {
124124
itemManager.updateItemTags();
125-
}
125+
} */
126126

127127
/**
128128
* Returns a {@code Config} using the file at {@code configFilePath}. <br>

src/main/java/io/xpire/commons/core/Messages.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ public class Messages {
88
public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command.";
99
public static final String MESSAGE_XPIRE_COMMAND_ONLY = "Command can only be used in the main list.";
1010
public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
11-
public static final String MESSAGE_INVALID_ITEM_DISPLAYED_INDEX = "The item index provided is invalid.";
11+
public static final String MESSAGE_INVALID_INDEX = "The item index provided is invalid.\n"
12+
+ "The index must be present on the list.\n";
13+
public static final String MESSAGE_INVALID_REMINDER_THRESHOLD = "%s is not a valid reminder threshold.";
1214
public static final String MESSAGE_INVALID_TAGS = "Tags are not in the item specified!";
13-
public static final String MESSAGE_UNKNOWN_DELETE_MODE = "Unknown Delete mode.";
1415
public static final String MESSAGE_SUGGESTIONS = " Did you mean %s?";
15-
public static final String MESSAGE_REPLENISH_SHIFT_SUCCESS = "%s is shifted into the replenish list.";
1616
public static final String MESSAGE_EMPTY_LIST = "Command not executed. The current list is empty!";
17+
1718
}

src/main/java/io/xpire/commons/util/JsonUtil.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import io.xpire.commons.exceptions.DataConversionException;
2525

2626
/**
27-
* Converts a Java object instance to JSON and vice versa
27+
* Converts a Java object instance to JSON and vice versa.
2828
*/
2929
public class JsonUtil {
3030

src/main/java/io/xpire/commons/util/StringUtil.java

+32-20
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,9 @@
2929
*/
3030
public class StringUtil {
3131

32-
private static final String NUMERIC_VALIDATION_REGEX = "^[0-9]+$";
32+
private static final String UNSIGNED_NUMERIC_VALIDATION_REGEX = "^[1-9][0-9]*$";
33+
private static final String NUMERIC_VALIDATION_REGEX = "^[+-]*[0-9]*$";
3334

34-
/**
35-
* Returns a detailed message of the t, including the stack trace.
36-
*/
37-
public static String getDetails(Throwable t) {
38-
requireNonNull(t);
39-
StringWriter sw = new StringWriter();
40-
t.printStackTrace(new PrintWriter(sw));
41-
return t.getMessage() + "\n" + sw.toString();
42-
}
43-
44-
/**
45-
* Returns true if {@code s} is numeric.
46-
*
47-
* @return true if {@code s} matches validation regex.
48-
*/
49-
public static boolean isNumeric(String s) {
50-
return s.matches(NUMERIC_VALIDATION_REGEX);
51-
}
5235

5336
//@@author JermyTan
5437
/**
@@ -72,6 +55,36 @@ public static boolean containsPhraseIgnoreCase(String sentence, String phrase) {
7255
return sentence.toLowerCase().contains(trimmedPhrase.toLowerCase());
7356
}
7457

58+
/**
59+
* Returns a detailed message of the t, including the stack trace.
60+
*/
61+
public static String getDetails(Throwable t) {
62+
requireNonNull(t);
63+
StringWriter sw = new StringWriter();
64+
t.printStackTrace(new PrintWriter(sw));
65+
return t.getMessage() + "\n" + sw.toString();
66+
}
67+
68+
//@author liawsy
69+
/**
70+
* Returns true if {@code s} is an unsigned number with no leading 0s.
71+
*
72+
* @return true if {@code s} matches validation regex.
73+
*/
74+
public static boolean isUnsignedNumericWithoutLeadingZeroes(String s) {
75+
return s.matches(UNSIGNED_NUMERIC_VALIDATION_REGEX);
76+
}
77+
78+
/**
79+
* Returns true if {@code s} is numeric.
80+
*
81+
* @return true if {@code s} matches validation regex.
82+
*/
83+
public static boolean isNumeric(String s) {
84+
return s.matches(NUMERIC_VALIDATION_REGEX);
85+
}
86+
//@author
87+
7588
/**
7689
* Returns true if {@code s} represents a non-negative integer.
7790
* e.g. 0, 1, 2, 3, ..., {@code Integer.MAX_VALUE} <br>.
@@ -82,7 +95,6 @@ public static boolean containsPhraseIgnoreCase(String sentence, String phrase) {
8295
*/
8396
public static boolean isNonNegativeInteger(String s) {
8497
requireNonNull(s);
85-
8698
try {
8799
int value = Integer.parseInt(s);
88100
return value >= 0 && !s.startsWith("+"); // "+1" is successfully parsed by Integer#parseInt(String)

src/main/java/io/xpire/logic/Logic.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public interface Logic {
4444
ObservableList<Item> getReplenishItemList();
4545

4646
/**
47-
* Returns the user prefs' xpire file path.
47+
* Returns the user prefs' file path.
4848
*/
4949
Path getListFilePath();
5050

src/main/java/io/xpire/logic/commands/AddCommand.java

+8-48
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
import static io.xpire.commons.util.CollectionUtil.requireAllNonNull;
44
import static io.xpire.model.ListType.XPIRE;
5-
import static java.util.Objects.requireNonNull;
6-
7-
import java.util.List;
85

6+
import io.xpire.logic.commands.exceptions.CommandException;
7+
import io.xpire.logic.commands.util.CommandUtil;
98
import io.xpire.logic.parser.exceptions.ParseException;
109
import io.xpire.model.Model;
1110
import io.xpire.model.item.ExpiryDate;
12-
import io.xpire.model.item.Item;
1311
import io.xpire.model.item.Name;
1412
import io.xpire.model.item.Quantity;
1513
import io.xpire.model.item.XpireItem;
@@ -29,18 +27,16 @@ public class AddCommand extends Command {
2927
+ "Example: " + COMMAND_WORD + "|Strawberry|11/12/1999|2";
3028

3129
public static final String MESSAGE_SUCCESS = "New item added to tracking list: %s";
32-
public static final String MESSAGE_SUCCESS_ITEM_UPDATED = "Quantity for item is increased to %s";
30+
public static final String MESSAGE_SUCCESS_ITEM_UPDATED = "Quantity for item %s is increased to %s";
3331
public static final String MESSAGE_SUCCESS_ITEM_ADDED = "New item added to tracking list: %s";
34-
public static final String MESSAGE_DUPLICATE_ITEM = "This item already exists";
3532

36-
private String result = "";
3733
private XpireItem toAdd;
3834
private final Name name;
3935
private final Quantity quantity;
4036
private final ExpiryDate expiryDate;
4137

4238
/**
43-
* Creates an AddCommand to add the specified {@code XpireItem}
39+
* Creates an AddCommand to add the specified {@code XpireItem}.
4440
*/
4541
public AddCommand(Name name, ExpiryDate expiryDate, Quantity quantity) {
4642
this.name = name;
@@ -58,18 +54,15 @@ public AddCommand(Name name, ExpiryDate expiryDate, Quantity quantity) {
5854
* @throws ParseException if xpireItem added is a duplicate.
5955
*/
6056
@Override
61-
public CommandResult execute(Model model, StateManager stateManager) throws ParseException {
57+
public CommandResult execute(Model model, StateManager stateManager) throws CommandException {
6258
requireAllNonNull(model, stateManager);
63-
stateManager.saveState(new ModifiedState(model));
64-
6559
if (model.hasItem(XPIRE, this.toAdd)) {
66-
XpireItem itemToReplace = retrieveXpireItem(this.toAdd, model.getItemList(XPIRE));
67-
XpireItem itemWithUpdatedQuantity = increaseItemQuantity(new XpireItem(itemToReplace), this.quantity);
68-
model.setItem(XPIRE, itemToReplace, itemWithUpdatedQuantity);
60+
XpireItem itemWithUpdatedQuantity = CommandUtil.updateItemQuantity(stateManager, model, this.toAdd);
6961
setShowInHistory(true);
7062
return new CommandResult(String.format(MESSAGE_SUCCESS_ITEM_UPDATED,
71-
itemWithUpdatedQuantity.getQuantity()));
63+
itemWithUpdatedQuantity.getName(), itemWithUpdatedQuantity.getQuantity()));
7264
} else {
65+
stateManager.saveState(new ModifiedState(model));
7366
model.addItem(XPIRE, toAdd);
7467
setShowInHistory(true);
7568
return new CommandResult(String.format(MESSAGE_SUCCESS_ITEM_ADDED, toAdd));
@@ -98,37 +91,4 @@ public String toString() {
9891
return "Add command";
9992
}
10093

101-
/**
102-
* Retrieves item that is the same as item inputted by user.
103-
*
104-
* @param item existing in the tracking list.
105-
* @param list where item is retrieved from.
106-
* @return exact item which is the same as input item.
107-
**/
108-
private XpireItem retrieveXpireItem(XpireItem item, List<? extends Item> list) {
109-
requireNonNull(item);
110-
int index = -1;
111-
for (int i = 0; i < list.size(); i++) {
112-
if (list.get(i).isSameItem(item)) {
113-
index = i;
114-
}
115-
}
116-
return (XpireItem) list.get(index);
117-
}
118-
119-
/**
120-
* Increases the item quantity for any duplicate items.
121-
*
122-
* @param targetItem the target item to increase the quantity of.
123-
* @param quantity how much to increase the item quantity by.
124-
* @return The new item with revised quantity.
125-
* @throws ParseException if
126-
*/
127-
private XpireItem increaseItemQuantity(XpireItem targetItem, Quantity quantity) throws ParseException {
128-
Quantity prevQuantity = targetItem.getQuantity();
129-
Quantity updatedQuantity = prevQuantity.increaseQuantity(quantity);
130-
targetItem.setQuantity(updatedQuantity);
131-
return targetItem;
132-
}
133-
13494
}

src/main/java/io/xpire/logic/commands/DeleteCommand.java

+11-31
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package io.xpire.logic.commands;
22

3-
import static io.xpire.commons.core.Messages.MESSAGE_REPLENISH_SHIFT_SUCCESS;
43
import static io.xpire.commons.util.CollectionUtil.requireAllNonNull;
4+
import static io.xpire.logic.commands.util.CommandUtil.MESSAGE_REPLENISH_SHIFT_SUCCESS;
55
import static io.xpire.model.ListType.REPLENISH;
66
import static io.xpire.model.ListType.XPIRE;
77

@@ -11,6 +11,7 @@
1111
import io.xpire.commons.core.Messages;
1212
import io.xpire.commons.core.index.Index;
1313
import io.xpire.logic.commands.exceptions.CommandException;
14+
import io.xpire.logic.commands.util.CommandUtil;
1415
import io.xpire.logic.parser.exceptions.ParseException;
1516
import io.xpire.model.ListType;
1617
import io.xpire.model.Model;
@@ -35,6 +36,7 @@ private enum DeleteMode { ITEM, QUANTITY, TAGS }
3536

3637
public static final String COMMAND_WORD = "delete";
3738
public static final String COMMAND_SHORTHAND = "d";
39+
public static final String MESSAGE_UNKNOWN_DELETE_MODE = "Unknown Delete mode.";
3840

3941
public static final String MESSAGE_USAGE =
4042
"Three formats available for " + COMMAND_WORD + ":\n"
@@ -50,15 +52,13 @@ private enum DeleteMode { ITEM, QUANTITY, TAGS }
5052
public static final String MESSAGE_DELETE_ITEM_SUCCESS = "Deleted item: %s";
5153
public static final String MESSAGE_DELETE_TAGS_SUCCESS = "Deleted tags from item: %s";
5254
public static final String MESSAGE_DELETE_QUANTITY_SUCCESS = "Reduced quantity by %s from item: %s";
53-
public static final String MESSAGE_DELETE_QUANTITY_FAILURE = "Invalid quantity specified. \n"
54-
+ "Quantity must be positive and less than or equals to item's quantity.";
5555

5656
private final Index targetIndex;
5757
private final Set<Tag> tagSet;
5858
private final Quantity quantity;
5959
private final DeleteMode mode;
6060
private final ListType listType;
61-
private Item item = null;
61+
private Item item;
6262
private String result = "";
6363

6464
public DeleteCommand(ListType listType, Index targetIndex) {
@@ -92,7 +92,7 @@ public CommandResult execute(Model model, StateManager stateManager) throws Comm
9292
ObservableList<? extends Item> currentList = model.getCurrentList();
9393

9494
if (this.targetIndex.getZeroBased() >= currentList.size()) {
95-
throw new CommandException(Messages.MESSAGE_INVALID_ITEM_DISPLAYED_INDEX);
95+
throw new CommandException(Messages.MESSAGE_INVALID_INDEX);
9696
}
9797

9898
Item targetItem = currentList.get(this.targetIndex.getZeroBased());
@@ -106,22 +106,22 @@ public CommandResult execute(Model model, StateManager stateManager) throws Comm
106106
case QUANTITY:
107107
return executeDeleteQuantity(model, targetItem, stateManager);
108108
default:
109-
throw new CommandException(Messages.MESSAGE_UNKNOWN_DELETE_MODE);
109+
throw new CommandException(MESSAGE_UNKNOWN_DELETE_MODE);
110110
}
111111
}
112112

113113
/**
114114
* Executes the command and returns the result message.
115115
*
116116
* @param model model {@code Model} which the command should operate on.
117-
* @param targetItem target item to reduce the quantity of,
117+
* @param targetItem target item to reduce the quantity of.
118118
* @return feedback message of the operation result for display.
119119
* @throws CommandException If an error occurs during command execution.
120120
*/
121121
private CommandResult executeDeleteQuantity(Model model, Item targetItem, StateManager stateManager)
122-
throws CommandException, ParseException {
122+
throws CommandException {
123123
assert this.quantity != null;
124-
XpireItem updatedItem = reduceItemQuantity(new XpireItem((XpireItem) targetItem), this.quantity);
124+
XpireItem updatedItem = CommandUtil.reduceItemQuantity((XpireItem) targetItem, this.quantity);
125125
stateManager.saveState(new ModifiedState(model));
126126
model.setItem(listType, targetItem, updatedItem);
127127
// transfer item to replenish list
@@ -132,7 +132,7 @@ private CommandResult executeDeleteQuantity(Model model, Item targetItem, StateM
132132
setShowInHistory(true);
133133
return new CommandResult(this.result);
134134
}
135-
this.result = String.format(MESSAGE_DELETE_QUANTITY_SUCCESS, quantity.toString(), targetItem);
135+
this.result = String.format(MESSAGE_DELETE_QUANTITY_SUCCESS, quantity.toString(), targetItem.getName());
136136
setShowInHistory(true);
137137
return new CommandResult(this.result);
138138
}
@@ -161,8 +161,7 @@ private CommandResult executeDeleteTags(Model model, Item targetItem, StateManag
161161
return new CommandResult(this.result);
162162
}
163163

164-
/**
165-
* Executes the command and returns the result message.
164+
/** Executes the command and returns the result message.
166165
*
167166
* @param model model {@code Model} which the command should operate on.
168167
* @param targetItem target item to delete completely.
@@ -220,25 +219,6 @@ private Item removeTagsFromReplenishItem(Item targetReplenishItem, Set<Tag> tagS
220219
return targetReplenishItem;
221220
}
222221

223-
/**
224-
* Reduces xpireItem's quantity by amount specified.
225-
*
226-
* @param targetXpireItem XpireItem which amount will be reduced.
227-
* @param reduceByQuantity Quantity to be reduced.
228-
* @return The new XpireItem with its quantity reduced.
229-
* @throws ParseException if
230-
*/
231-
private XpireItem reduceItemQuantity(XpireItem targetXpireItem, Quantity reduceByQuantity) throws CommandException,
232-
ParseException {
233-
Quantity originalQuantity = targetXpireItem.getQuantity();
234-
if (originalQuantity.isLessThan(reduceByQuantity)) {
235-
throw new CommandException(MESSAGE_DELETE_QUANTITY_FAILURE);
236-
}
237-
Quantity updatedQuantity = originalQuantity.deductQuantity(reduceByQuantity);
238-
targetXpireItem.setQuantity(updatedQuantity);
239-
return targetXpireItem;
240-
}
241-
242222
/**
243223
* Shifts Item to ReplenishList.
244224
*/

src/main/java/io/xpire/logic/commands/SetReminderCommand.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public CommandResult execute(Model model, StateManager stateManager) throws Comm
5858
ObservableList<? extends Item> currentList = model.getCurrentList();
5959

6060
if (this.index.getZeroBased() >= currentList.size()) {
61-
throw new CommandException(Messages.MESSAGE_INVALID_ITEM_DISPLAYED_INDEX);
61+
throw new CommandException(Messages.MESSAGE_INVALID_INDEX);
6262
}
6363

6464
XpireItem targetItem = (XpireItem) currentList.get(this.index.getZeroBased());

0 commit comments

Comments
 (0)