diff --git a/src/test/resources/model.session.ImportSessionTest/CS2103-testsheet.xlsx b/CS2103-testsheet.xlsx similarity index 71% rename from src/test/resources/model.session.ImportSessionTest/CS2103-testsheet.xlsx rename to CS2103-testsheet.xlsx index 789f8640ff24..bbd89fb18b33 100644 Binary files a/src/test/resources/model.session.ImportSessionTest/CS2103-testsheet.xlsx and b/CS2103-testsheet.xlsx differ diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 5c12597dc9db..3d0b88012cdf 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -437,7 +437,7 @@ image::SessionComponentClassDiagram.png[width="800"] with a timestamp added to the back of the filename. `ImportSession` is designed to be stateless on its own, with all data stored in `SessionData`. This helps to -support `UndoableCommand` +support `UndoableCommand`. Currently, `SessionData` is not persistent in the event of a crash. The flow of using `ImportSession` is as follows: diff --git a/src/main/java/seedu/carvicim/MainApp.java b/src/main/java/seedu/carvicim/MainApp.java index b167e9f49ec9..356a25a80fa2 100644 --- a/src/main/java/seedu/carvicim/MainApp.java +++ b/src/main/java/seedu/carvicim/MainApp.java @@ -34,6 +34,7 @@ import seedu.carvicim.storage.UserPrefsStorage; import seedu.carvicim.storage.XmlArchiveJobStorage; import seedu.carvicim.storage.XmlCarvicimStorage; +import seedu.carvicim.storage.session.ImportSession; import seedu.carvicim.ui.Ui; import seedu.carvicim.ui.UiManager; @@ -211,6 +212,7 @@ public void stop() { } catch (IOException e) { logger.severe("Failed to save preferences " + StringUtil.getDetails(e)); } + ImportSession.getInstance().getSessionData().freeResources(); Platform.exit(); System.exit(0); } diff --git a/src/main/java/seedu/carvicim/commons/events/ui/DisplayAllJobsEvent.java b/src/main/java/seedu/carvicim/commons/events/ui/DisplayAllJobsEvent.java new file mode 100644 index 000000000000..c0a214b436bb --- /dev/null +++ b/src/main/java/seedu/carvicim/commons/events/ui/DisplayAllJobsEvent.java @@ -0,0 +1,28 @@ +package seedu.carvicim.commons.events.ui; + +import javafx.collections.ObservableList; +import seedu.carvicim.commons.events.BaseEvent; +import seedu.carvicim.model.job.Job; + +/** + * Represents a selection change in the Employee List Panel + */ +//@@author yuhongherald +public class DisplayAllJobsEvent extends BaseEvent { + + + private final ObservableList jobList; + + public DisplayAllJobsEvent(ObservableList jobList) { + this.jobList = jobList; + } + + @Override + public String toString() { + return this.getClass().getSimpleName(); + } + + public ObservableList getJobList() { + return jobList; + } +} diff --git a/src/main/java/seedu/carvicim/logic/commands/AcceptAllCommand.java b/src/main/java/seedu/carvicim/logic/commands/AcceptAllCommand.java new file mode 100644 index 000000000000..7ebfac86c75d --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/commands/AcceptAllCommand.java @@ -0,0 +1,56 @@ +package seedu.carvicim.logic.commands; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import seedu.carvicim.logic.commands.exceptions.CommandException; +import seedu.carvicim.model.job.Job; +import seedu.carvicim.storage.session.ImportSession; +import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; +import seedu.carvicim.storage.session.exceptions.UnitializedException; + +//@@author yuhongherald + +/** + * Accepts all remaining unreviewed job entries into Servicing Manager + */ +public class AcceptAllCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "acceptAll"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Accepts all unreviewed job entries. " + + "Example: " + COMMAND_WORD; + + public static final String MESSAGE_SUCCESS = "%d job entries accepted!"; + + public String getMessageSuccess(int entries) { + return String.format(MESSAGE_SUCCESS, entries); + } + + @Override + public CommandResult executeUndoableCommand() throws CommandException { + ImportSession importSession = ImportSession.getInstance(); + try { + importSession.reviewAllRemainingJobEntries(true); + List jobs = new ArrayList<>(importSession.getSessionData().getReviewedJobEntries()); + model.addJobs(jobs); + importSession.closeSession(); + return new CommandResult(getMessageSuccess(jobs.size())); + } catch (DataIndexOutOfBoundsException e) { + throw new CommandException("Excel file has bad format. Try copying the cell values into a new excel file " + + "before trying again"); + } catch (IOException e) { + throw new CommandException("Unable to export file. Please close the application and try again."); + } catch (UnitializedException e) { + throw new CommandException(e.getMessage()); + } + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof AcceptAllCommand); // instanceof handles nulls + } + +} diff --git a/src/main/java/seedu/carvicim/logic/commands/AcceptCommand.java b/src/main/java/seedu/carvicim/logic/commands/AcceptCommand.java new file mode 100644 index 000000000000..afe008c97c0a --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/commands/AcceptCommand.java @@ -0,0 +1,65 @@ +package seedu.carvicim.logic.commands; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.carvicim.commons.core.EventsCenter; +import seedu.carvicim.commons.events.ui.DisplayAllJobsEvent; +import seedu.carvicim.logic.commands.exceptions.CommandException; +import seedu.carvicim.model.job.Job; +import seedu.carvicim.storage.session.ImportSession; +import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; +import seedu.carvicim.storage.session.exceptions.InvalidDataException; + +//@@author yuhongherald + +/** + * Accepts an unreviewed job entry using job number and adds into servicing manager + */ +public class AcceptCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "accept"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Accepts job entry using job number. " + + "Example: " + COMMAND_WORD + " JOB_NUMBER"; + + public static final String MESSAGE_SUCCESS = "Job #%d accepted!"; + + private int jobNumber; + + public AcceptCommand(int jobNumber) { + this.jobNumber = jobNumber; + } + + public String getMessageSuccess() { + return String.format(MESSAGE_SUCCESS, jobNumber); + } + + @Override + public CommandResult executeUndoableCommand() throws CommandException { + ImportSession importSession = ImportSession.getInstance(); + try { + importSession.getSessionData().reviewJobEntryUsingJobNumber(jobNumber, true, ""); + + } catch (DataIndexOutOfBoundsException e) { + throw new CommandException("Excel file has bad format. Try copying the cell values into a new excel file " + + "before trying again"); + } catch (InvalidDataException e) { + throw new CommandException(e.getMessage()); + } + ObservableList jobList = FXCollections.observableList( + ImportSession.getInstance().getSessionData().getUnreviewedJobEntries()); + if (!model.isViewingImportedJobs()) { + model.switchJobView(); + } + EventsCenter.getInstance().post( + new DisplayAllJobsEvent(FXCollections.unmodifiableObservableList(jobList))); + return new CommandResult(getMessageSuccess()); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof AcceptCommand); // instanceof handles nulls + } + +} diff --git a/src/main/java/seedu/carvicim/logic/commands/CommandWords.java b/src/main/java/seedu/carvicim/logic/commands/CommandWords.java index b66a40370938..86858116297d 100644 --- a/src/main/java/seedu/carvicim/logic/commands/CommandWords.java +++ b/src/main/java/seedu/carvicim/logic/commands/CommandWords.java @@ -38,7 +38,15 @@ public class CommandWords implements Serializable { SetCommand.COMMAND_WORD, UndoCommand.COMMAND_WORD, ThemeCommand.COMMAND_WORD, - SortCommand.COMMAND_WORD + SortCommand.COMMAND_WORD, + ImportCommand.COMMAND_WORD, + SaveCommand.COMMAND_WORD, + ListJobCommand.COMMAND_WORD, + SwitchCommand.COMMAND_WORD, + AcceptAllCommand.COMMAND_WORD, + RejectAllCommand.COMMAND_WORD, + RejectCommand.COMMAND_WORD, + AcceptCommand.COMMAND_WORD }; public final HashMap commands; @@ -126,7 +134,7 @@ public String getCommandKey(String value) throws CommandWordException { */ public void setCommandWord(String currentWord, String newWord) throws CommandWordException { requireNonNull(currentWord, newWord); - checkCommandWordValidity(currentWord, newWord); + throwExceptionIfCommandWordsNotValid(currentWord, newWord); if (isDefaultCommandWord(currentWord)) { commands.remove(currentWord); commands.put(currentWord, newWord); @@ -146,9 +154,12 @@ public void setCommandWord(String currentWord, String newWord) throws CommandWor } /** - * throws a (@code CommandWordException) if (@code currentWord) or (@code newWord) is not valid + * throws a (@code CommandWordException) if: + * 1. Both words are the same + * 2. (@code newWord) overwrites the default word for another command + * 3. (@code newWord) is already in use */ - private void checkCommandWordValidity(String currentWord, String newWord) throws CommandWordException { + private void throwExceptionIfCommandWordsNotValid(String currentWord, String newWord) throws CommandWordException { if (currentWord.equals(newWord)) { throw new CommandWordException(getMessageNoChange()); } diff --git a/src/main/java/seedu/carvicim/logic/commands/ImportAllCommand.java b/src/main/java/seedu/carvicim/logic/commands/ImportAllCommand.java index e3d52c09219c..1d4bfaa17f05 100644 --- a/src/main/java/seedu/carvicim/logic/commands/ImportAllCommand.java +++ b/src/main/java/seedu/carvicim/logic/commands/ImportAllCommand.java @@ -13,6 +13,7 @@ import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; import seedu.carvicim.storage.session.exceptions.FileAccessException; import seedu.carvicim.storage.session.exceptions.FileFormatException; +import seedu.carvicim.storage.session.exceptions.UnitializedException; //@@author yuhongherald /** @@ -45,7 +46,7 @@ public CommandResult executeUndoableCommand() throws CommandException { try { importSession.initializeSession(filePath); } catch (FileAccessException e) { - e.printStackTrace(); + throw new CommandException(e.getMessage()); } catch (FileFormatException e) { throw new CommandException("Excel file first row headers are not defined properly. " + "Type 'help' to read more."); @@ -61,6 +62,8 @@ public CommandResult executeUndoableCommand() throws CommandException { + "before trying again"); } catch (IOException e) { throw new CommandException("Unable to export file. Please close the application and try again."); + } catch (UnitializedException e) { + throw new CommandException(e.getMessage()); } } diff --git a/src/main/java/seedu/carvicim/logic/commands/ImportCommand.java b/src/main/java/seedu/carvicim/logic/commands/ImportCommand.java new file mode 100644 index 000000000000..a0ac4cc75037 --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/commands/ImportCommand.java @@ -0,0 +1,71 @@ +package seedu.carvicim.logic.commands; + +import static java.util.Objects.requireNonNull; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.carvicim.commons.core.EventsCenter; +import seedu.carvicim.commons.events.ui.DisplayAllJobsEvent; +import seedu.carvicim.logic.commands.exceptions.CommandException; +import seedu.carvicim.model.job.Job; +import seedu.carvicim.storage.session.ImportSession; +import seedu.carvicim.storage.session.exceptions.FileAccessException; +import seedu.carvicim.storage.session.exceptions.FileFormatException; + +//@@author yuhongherald + +/** + * Attempts to import specified file into Servicing Manager + */ +public class ImportCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "import"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Imports an excel file for reviewing. " + + "Parameters: FILEPATH\n" + + "Example: " + COMMAND_WORD + "yourfile.xls"; + + public static final String MESSAGE_SUCCESS = "%s has been imported, with %d job entries!"; + + private final String filePath; + + public ImportCommand(String filePath) { + requireNonNull(filePath); + this.filePath = filePath; + } + + public String getMessageSuccess(int entries) { + return String.format(MESSAGE_SUCCESS, filePath, entries); + } + + @Override + public CommandResult executeUndoableCommand() throws CommandException { + ImportSession importSession = ImportSession.getInstance(); + try { + importSession.initializeSession(filePath); + } catch (FileAccessException e) { + throw new CommandException(e.getMessage()); + } catch (FileFormatException e) { + throw new CommandException("Excel file first row headers are not defined properly. " + + "Type 'help' to read more."); + } + + ObservableList jobList = FXCollections.observableList( + ImportSession.getInstance().getSessionData().getUnreviewedJobEntries()); + if (!model.isViewingImportedJobs()) { + model.switchJobView(); + } + EventsCenter.getInstance().post( + new DisplayAllJobsEvent(FXCollections.unmodifiableObservableList(jobList))); + return new CommandResult(getMessageSuccess(importSession.getSessionData() + .getUnreviewedJobEntries().size())); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof ImportCommand // instanceof handles nulls + && filePath.equals(((ImportCommand) other).filePath)); + } + +} diff --git a/src/main/java/seedu/carvicim/logic/commands/ListJobCommand.java b/src/main/java/seedu/carvicim/logic/commands/ListJobCommand.java new file mode 100644 index 000000000000..f37aa49fc119 --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/commands/ListJobCommand.java @@ -0,0 +1,34 @@ +package seedu.carvicim.logic.commands; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.carvicim.commons.core.EventsCenter; +import seedu.carvicim.commons.events.ui.DisplayAllJobsEvent; +import seedu.carvicim.model.job.Job; +import seedu.carvicim.storage.session.ImportSession; + +/** + * Lists all jobs in the carvicim book to the user. + */ +//@@author yuhongherald +public class ListJobCommand extends Command { + + public static final String COMMAND_WORD = "listj"; + + public static final String MESSAGE_SUCCESS = "Listed all jobs"; + + + @Override + public CommandResult execute() { + ObservableList jobList; + if (model.isViewingImportedJobs()) { + jobList = FXCollections.observableList( + ImportSession.getInstance().getSessionData().getUnreviewedJobEntries()); + } else { + jobList = model.getFilteredJobList(); + } + EventsCenter.getInstance().post( + new DisplayAllJobsEvent(FXCollections.unmodifiableObservableList(jobList))); + return new CommandResult(MESSAGE_SUCCESS); + } +} diff --git a/src/main/java/seedu/carvicim/logic/commands/RejectAllCommand.java b/src/main/java/seedu/carvicim/logic/commands/RejectAllCommand.java new file mode 100644 index 000000000000..cbcb494d4047 --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/commands/RejectAllCommand.java @@ -0,0 +1,56 @@ +package seedu.carvicim.logic.commands; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import seedu.carvicim.logic.commands.exceptions.CommandException; +import seedu.carvicim.model.job.Job; +import seedu.carvicim.storage.session.ImportSession; +import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; +import seedu.carvicim.storage.session.exceptions.UnitializedException; + +//@@author yuhongherald + +/** + * Rejects all remaining unreviewed job entries into Servicing Manager + */ +public class RejectAllCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "rejectAll"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Rejects all unreviewed job entries. " + + "Example: " + COMMAND_WORD; + + public static final String MESSAGE_SUCCESS = "%d job entries rejected!"; + + public String getMessageSuccess(int entries) { + return String.format(MESSAGE_SUCCESS, entries); + } + + @Override + public CommandResult executeUndoableCommand() throws CommandException { + ImportSession importSession = ImportSession.getInstance(); + try { + importSession.reviewAllRemainingJobEntries(false); + List jobs = new ArrayList<>(importSession.getSessionData().getReviewedJobEntries()); + model.addJobs(jobs); + importSession.closeSession(); + return new CommandResult(getMessageSuccess(jobs.size())); + } catch (DataIndexOutOfBoundsException e) { + throw new CommandException("Excel file has bad format. Try copying the cell values into a new excel file " + + "before trying again"); + } catch (IOException e) { + throw new CommandException("Unable to export file. Please close the application and try again."); + } catch (UnitializedException e) { + throw new CommandException(e.getMessage()); + } + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof RejectAllCommand); // instanceof handles nulls + } + +} diff --git a/src/main/java/seedu/carvicim/logic/commands/RejectCommand.java b/src/main/java/seedu/carvicim/logic/commands/RejectCommand.java new file mode 100644 index 000000000000..8d4b4d3e29e6 --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/commands/RejectCommand.java @@ -0,0 +1,64 @@ +package seedu.carvicim.logic.commands; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.carvicim.commons.core.EventsCenter; +import seedu.carvicim.commons.events.ui.DisplayAllJobsEvent; +import seedu.carvicim.logic.commands.exceptions.CommandException; +import seedu.carvicim.model.job.Job; +import seedu.carvicim.storage.session.ImportSession; +import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; +import seedu.carvicim.storage.session.exceptions.InvalidDataException; + +//@@author yuhongherald + +/** + * Rejects an unreviewed job entry using job number + */ +public class RejectCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "reject"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Rejects job entry using job number. " + + "Example: " + COMMAND_WORD + " JOB_NUMBER"; + + public static final String MESSAGE_SUCCESS = "Job #%d rejected!"; + + private int jobNumber; + + public RejectCommand(int jobNumber) { + this.jobNumber = jobNumber; + } + + public String getMessageSuccess() { + return String.format(MESSAGE_SUCCESS, jobNumber); + } + + @Override + public CommandResult executeUndoableCommand() throws CommandException { + ImportSession importSession = ImportSession.getInstance(); + try { + importSession.getSessionData().reviewJobEntryUsingJobNumber(jobNumber, false, ""); + } catch (DataIndexOutOfBoundsException e) { + throw new CommandException("Excel file has bad format. Try copying the cell values into a new excel file " + + "before trying again"); + } catch (InvalidDataException e) { + throw new CommandException(e.getMessage()); + } + ObservableList jobList = FXCollections.observableList( + ImportSession.getInstance().getSessionData().getUnreviewedJobEntries()); + if (!model.isViewingImportedJobs()) { + model.switchJobView(); + } + EventsCenter.getInstance().post( + new DisplayAllJobsEvent(FXCollections.unmodifiableObservableList(jobList))); + return new CommandResult(getMessageSuccess()); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof RejectCommand); // instanceof handles nulls + } + +} diff --git a/src/main/java/seedu/carvicim/logic/commands/SaveCommand.java b/src/main/java/seedu/carvicim/logic/commands/SaveCommand.java new file mode 100644 index 000000000000..35310b23328e --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/commands/SaveCommand.java @@ -0,0 +1,69 @@ +package seedu.carvicim.logic.commands; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.carvicim.commons.core.EventsCenter; +import seedu.carvicim.commons.events.ui.DisplayAllJobsEvent; +import seedu.carvicim.logic.commands.exceptions.CommandException; +import seedu.carvicim.model.job.Job; +import seedu.carvicim.storage.session.ImportSession; +import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; +import seedu.carvicim.storage.session.exceptions.UnitializedException; + +//@@author yuhongherald + +/** + * Attempts to write reviewed jobs with feedback into an excel file + */ +public class SaveCommand extends UndoableCommand { + + public static final String COMMAND_WORD = "save"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Saves your reviewed job entries as an excel file.\n" + + "Example: " + COMMAND_WORD; + + public static final String MESSAGE_SUCCESS = "Your reviewed job entries have been saved to %s!"; + + public String getMessageSuccess(String filePath) { + return String.format(MESSAGE_SUCCESS, filePath); + } + + @Override + public CommandResult executeUndoableCommand() throws CommandException { + ImportSession importSession = ImportSession.getInstance(); + String message; + if (!importSession.getSessionData().getUnreviewedJobEntries().isEmpty()) { + throw new CommandException("Please review all remaining job entries before saving!"); + } + try { + importSession.reviewAllRemainingJobEntries(true); + List jobs = new ArrayList<>(importSession.getSessionData().getReviewedJobEntries()); + model.addJobs(jobs); + message = importSession.closeSession(); + } catch (IOException e) { + throw new CommandException("Unable to export file. Please close the application and try again."); + } catch (UnitializedException e) { + throw new CommandException(e.getMessage()); + } catch (DataIndexOutOfBoundsException e) { + throw new CommandException((e.getMessage())); + } + ObservableList jobList = model.getFilteredJobList(); + if (model.isViewingImportedJobs()) { + model.switchJobView(); + } + EventsCenter.getInstance().post( + new DisplayAllJobsEvent(FXCollections.unmodifiableObservableList(jobList))); + return new CommandResult(getMessageSuccess(message)); + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof SaveCommand); // instanceof handles nulls + } + +} diff --git a/src/main/java/seedu/carvicim/logic/commands/SwitchCommand.java b/src/main/java/seedu/carvicim/logic/commands/SwitchCommand.java new file mode 100644 index 000000000000..c49cb5c1c407 --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/commands/SwitchCommand.java @@ -0,0 +1,35 @@ +package seedu.carvicim.logic.commands; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.carvicim.commons.core.EventsCenter; +import seedu.carvicim.commons.events.ui.DisplayAllJobsEvent; +import seedu.carvicim.model.job.Job; +import seedu.carvicim.storage.session.ImportSession; + +/** + * Lists all persons in the carvicim book to the user. + */ +//@@author yuhongherald +public class SwitchCommand extends Command { + + public static final String COMMAND_WORD = "switch"; + + public static final String MESSAGE_SUCCESS = "Switched job lists."; + + + @Override + public CommandResult execute() { + model.switchJobView(); + ObservableList jobList; + if (model.isViewingImportedJobs()) { + jobList = FXCollections.observableList( + ImportSession.getInstance().getSessionData().getUnreviewedJobEntries()); + } else { + jobList = model.getFilteredJobList(); + } + EventsCenter.getInstance().post( + new DisplayAllJobsEvent(FXCollections.unmodifiableObservableList(jobList))); + return new CommandResult(MESSAGE_SUCCESS); + } +} diff --git a/src/main/java/seedu/carvicim/logic/commands/UndoableCommand.java b/src/main/java/seedu/carvicim/logic/commands/UndoableCommand.java index 21a524864140..c6ee71cc5807 100644 --- a/src/main/java/seedu/carvicim/logic/commands/UndoableCommand.java +++ b/src/main/java/seedu/carvicim/logic/commands/UndoableCommand.java @@ -7,6 +7,8 @@ import seedu.carvicim.logic.commands.exceptions.CommandException; import seedu.carvicim.model.Carvicim; import seedu.carvicim.model.ReadOnlyCarvicim; +import seedu.carvicim.storage.session.ImportSession; +import seedu.carvicim.storage.session.SessionData; /** * Represents a command which can be undone and redone. @@ -14,6 +16,7 @@ public abstract class UndoableCommand extends Command { private ReadOnlyCarvicim previousAddressBook; private CommandWords previousCommandWords; + private SessionData sessionData; protected abstract CommandResult executeUndoableCommand() throws CommandException; @@ -24,6 +27,7 @@ private void saveAddressBookSnapshot() { requireNonNull(model); this.previousAddressBook = new Carvicim(model.getCarvicim()); this.previousCommandWords = new CommandWords(model.getCommandWords()); + this.sessionData = ImportSession.getInstance().getSessionData(); } /** @@ -41,6 +45,7 @@ protected final void undo() { requireAllNonNull(model, previousAddressBook); model.resetData(previousAddressBook, previousCommandWords); model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + ImportSession.getInstance().setSessionData(sessionData); } /** diff --git a/src/main/java/seedu/carvicim/logic/parser/AcceptCommandParser.java b/src/main/java/seedu/carvicim/logic/parser/AcceptCommandParser.java new file mode 100644 index 000000000000..b2ed6b3284d9 --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/parser/AcceptCommandParser.java @@ -0,0 +1,32 @@ +package seedu.carvicim.logic.parser; + +import static seedu.carvicim.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.carvicim.logic.parser.ParserUtil.parseInteger; + +import seedu.carvicim.commons.exceptions.IllegalValueException; +import seedu.carvicim.logic.commands.AcceptCommand; +import seedu.carvicim.logic.parser.exceptions.ParseException; + +//@@author yuhongherald + +/** + * Parses input arguments and creates a new ImporatAllCommand object + */ +public class AcceptCommandParser implements Parser { + + /** + * Parses the given {@code String} of arg + * uments in the context of the ImportAllCommand + * and returns an ImportAllCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public AcceptCommand parse(String args) throws ParseException { + try { + int jobNumber = parseInteger(args); + return new AcceptCommand(jobNumber); + } catch (IllegalValueException ive) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AcceptCommand.MESSAGE_USAGE)); + } + } + +} diff --git a/src/main/java/seedu/carvicim/logic/parser/CarvicimParser.java b/src/main/java/seedu/carvicim/logic/parser/CarvicimParser.java index b19da49b3c6e..934fa69c191c 100644 --- a/src/main/java/seedu/carvicim/logic/parser/CarvicimParser.java +++ b/src/main/java/seedu/carvicim/logic/parser/CarvicimParser.java @@ -6,6 +6,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import seedu.carvicim.logic.commands.AcceptAllCommand; +import seedu.carvicim.logic.commands.AcceptCommand; import seedu.carvicim.logic.commands.AddEmployeeCommand; import seedu.carvicim.logic.commands.AddJobCommand; import seedu.carvicim.logic.commands.ArchiveCommand; @@ -19,12 +21,18 @@ import seedu.carvicim.logic.commands.HelpCommand; import seedu.carvicim.logic.commands.HistoryCommand; import seedu.carvicim.logic.commands.ImportAllCommand; +import seedu.carvicim.logic.commands.ImportCommand; import seedu.carvicim.logic.commands.ListEmployeeCommand; +import seedu.carvicim.logic.commands.ListJobCommand; import seedu.carvicim.logic.commands.LoginCommand; import seedu.carvicim.logic.commands.RedoCommand; +import seedu.carvicim.logic.commands.RejectAllCommand; +import seedu.carvicim.logic.commands.RejectCommand; +import seedu.carvicim.logic.commands.SaveCommand; import seedu.carvicim.logic.commands.SelectCommand; import seedu.carvicim.logic.commands.SetCommand; import seedu.carvicim.logic.commands.SortCommand; +import seedu.carvicim.logic.commands.SwitchCommand; import seedu.carvicim.logic.commands.ThemeCommand; import seedu.carvicim.logic.commands.UndoCommand; @@ -137,6 +145,30 @@ public Command parseCommand(String userInput) throws ParseException { case LoginCommand.COMMAND_WORD: return new LoginCommand(); + case ImportCommand.COMMAND_WORD: + return new ImportCommandParser().parse(arguments); + + case SaveCommand.COMMAND_WORD: + return new SaveCommand(); + + case ListJobCommand.COMMAND_WORD: + return new ListJobCommand(); + + case SwitchCommand.COMMAND_WORD: + return new SwitchCommand(); + + case AcceptAllCommand.COMMAND_WORD: + return new AcceptAllCommand(); + + case RejectAllCommand.COMMAND_WORD: + return new RejectAllCommand(); + + case RejectCommand.COMMAND_WORD: + return new RejectCommandParser().parse(arguments); + + case AcceptCommand.COMMAND_WORD: + return new AcceptCommandParser().parse(arguments); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/seedu/carvicim/logic/parser/ImportAllCommandParser.java b/src/main/java/seedu/carvicim/logic/parser/ImportAllCommandParser.java index 7eebff4cfdfd..d78e35f1b47e 100644 --- a/src/main/java/seedu/carvicim/logic/parser/ImportAllCommandParser.java +++ b/src/main/java/seedu/carvicim/logic/parser/ImportAllCommandParser.java @@ -10,7 +10,7 @@ //@@author yuhongherald /** - * Parses input arguments and creates a new AddEmployeeCommand object + * Parses input arguments and creates a new ImporatAllCommand object */ public class ImportAllCommandParser implements Parser { diff --git a/src/main/java/seedu/carvicim/logic/parser/ImportCommandParser.java b/src/main/java/seedu/carvicim/logic/parser/ImportCommandParser.java new file mode 100644 index 000000000000..71b73a3c73b0 --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/parser/ImportCommandParser.java @@ -0,0 +1,32 @@ +package seedu.carvicim.logic.parser; + +import static seedu.carvicim.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.carvicim.logic.parser.ParserUtil.parseFilename; + +import seedu.carvicim.commons.exceptions.IllegalValueException; +import seedu.carvicim.logic.commands.ImportCommand; +import seedu.carvicim.logic.parser.exceptions.ParseException; + +//@@author yuhongherald + +/** + * Parses input arguments and creates a new ImporatAllCommand object + */ +public class ImportCommandParser implements Parser { + + /** + * Parses the given {@code String} of arg + * uments in the context of the ImportAllCommand + * and returns an ImportAllCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public ImportCommand parse(String args) throws ParseException { + try { + String filePath = parseFilename(args); + return new ImportCommand(filePath); + } catch (IllegalValueException ive) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ImportCommand.MESSAGE_USAGE)); + } + } + +} diff --git a/src/main/java/seedu/carvicim/logic/parser/ParserUtil.java b/src/main/java/seedu/carvicim/logic/parser/ParserUtil.java index 97681cae6037..ff556ac851e1 100644 --- a/src/main/java/seedu/carvicim/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/carvicim/logic/parser/ParserUtil.java @@ -67,6 +67,19 @@ public static String parseFilename(String filePath) throws IllegalValueException } + /** + * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be + * trimmed. + * @throws IllegalValueException if the specified index is invalid (not non-zero unsigned integer). + */ + public static int parseInteger(String integer) throws IllegalValueException { + String trimmedIndex = integer.trim(); + if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { + throw new IllegalValueException(MESSAGE_INVALID_INDEX); + } + return Integer.parseInt(trimmedIndex); + } + /** * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be * trimmed. diff --git a/src/main/java/seedu/carvicim/logic/parser/RejectCommandParser.java b/src/main/java/seedu/carvicim/logic/parser/RejectCommandParser.java new file mode 100644 index 000000000000..4b2bff39c8e1 --- /dev/null +++ b/src/main/java/seedu/carvicim/logic/parser/RejectCommandParser.java @@ -0,0 +1,32 @@ +package seedu.carvicim.logic.parser; + +import static seedu.carvicim.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.carvicim.logic.parser.ParserUtil.parseInteger; + +import seedu.carvicim.commons.exceptions.IllegalValueException; +import seedu.carvicim.logic.commands.RejectCommand; +import seedu.carvicim.logic.parser.exceptions.ParseException; + +//@@author yuhongherald + +/** + * Parses input arguments and creates a new ImporatAllCommand object + */ +public class RejectCommandParser implements Parser { + + /** + * Parses the given {@code String} of arg + * uments in the context of the ImportAllCommand + * and returns an ImportAllCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public RejectCommand parse(String args) throws ParseException { + try { + int jobNumber = parseInteger(args); + return new RejectCommand(jobNumber); + } catch (IllegalValueException ive) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, RejectCommand.MESSAGE_USAGE)); + } + } + +} diff --git a/src/main/java/seedu/carvicim/model/Model.java b/src/main/java/seedu/carvicim/model/Model.java index fa4df4aa89d2..f7c5fd0272f4 100644 --- a/src/main/java/seedu/carvicim/model/Model.java +++ b/src/main/java/seedu/carvicim/model/Model.java @@ -17,12 +17,17 @@ * The API of the Model component. */ public interface Model { + /** {@code Predicate} that always evaluate to true */ Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; /** {@code Predicate} that always evaluate to true */ Predicate PREDICATE_SHOW_ALL_JOBS = unused -> true; + boolean isViewingImportedJobs(); + + void switchJobView(); + /** Clears existing backing model and replaces with the provided new data. */ void resetData(ReadOnlyCarvicim newData, CommandWords newCommandWords); diff --git a/src/main/java/seedu/carvicim/model/ModelManager.java b/src/main/java/seedu/carvicim/model/ModelManager.java index 3ff61b93c747..7b9c4b32e963 100644 --- a/src/main/java/seedu/carvicim/model/ModelManager.java +++ b/src/main/java/seedu/carvicim/model/ModelManager.java @@ -37,6 +37,8 @@ public class ModelManager extends ComponentManager implements Model { private final FilteredList filteredJobs; private final CommandWords commandWords; + private boolean isViewingImportedJobs; + /** * Initializes a ModelManager with the given carvicim and userPrefs. */ @@ -50,12 +52,21 @@ public ModelManager(ReadOnlyCarvicim carvicim, UserPrefs userPrefs) { filteredEmployees = new FilteredList<>(this.carvicim.getEmployeeList()); filteredJobs = new FilteredList<>(this.carvicim.getJobList()); this.commandWords = userPrefs.getCommandWords(); + isViewingImportedJobs = false; } public ModelManager() { this(new Carvicim(), new UserPrefs()); } + public boolean isViewingImportedJobs() { + return isViewingImportedJobs; + } + + public void switchJobView() { + isViewingImportedJobs = !isViewingImportedJobs; + } + //@@author whenzei /** * Initializes the running job number based on the past job numbers. diff --git a/src/main/java/seedu/carvicim/storage/session/ExcelColumnSpannable.java b/src/main/java/seedu/carvicim/storage/session/ExcelColumnSpannable.java deleted file mode 100644 index b98ce9dfe44e..000000000000 --- a/src/main/java/seedu/carvicim/storage/session/ExcelColumnSpannable.java +++ /dev/null @@ -1,20 +0,0 @@ -package seedu.carvicim.storage.session; - -import java.util.ArrayList; - -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; - -import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; - -//@@author yuhongherald -/** - * For fields that resides in one or more columns - */ -public interface ExcelColumnSpannable { - public int getStartIndex(); - public int getEndIndex(); - public ArrayList readData(Workbook workbook, int sheetNumber, int rowNumber) - throws DataIndexOutOfBoundsException; - public ArrayList readDataFromSheet(Sheet sheet, int rowNumber) throws DataIndexOutOfBoundsException; -} diff --git a/src/main/java/seedu/carvicim/storage/session/ExcelRowReference.java b/src/main/java/seedu/carvicim/storage/session/ExcelRowReference.java deleted file mode 100644 index 12f9096e5798..000000000000 --- a/src/main/java/seedu/carvicim/storage/session/ExcelRowReference.java +++ /dev/null @@ -1,18 +0,0 @@ -package seedu.carvicim.storage.session; - -/** - * For row entries of an excel sheet - */ -public interface ExcelRowReference { - - /** - * Returns the excel sheet number of this element. - */ - public int getSheetNumber(); - - /** - * Returns the excel row number of this element - * @return - */ - public int getRowNumber(); -} diff --git a/src/main/java/seedu/carvicim/storage/session/ImportSession.java b/src/main/java/seedu/carvicim/storage/session/ImportSession.java index 1db79bd6ddf1..5eacc5c65487 100644 --- a/src/main/java/seedu/carvicim/storage/session/ImportSession.java +++ b/src/main/java/seedu/carvicim/storage/session/ImportSession.java @@ -1,19 +1,13 @@ package seedu.carvicim.storage.session; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; +import static java.util.Objects.requireNonNull; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.WorkbookFactory; +import java.io.IOException; import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; import seedu.carvicim.storage.session.exceptions.FileAccessException; import seedu.carvicim.storage.session.exceptions.FileFormatException; +import seedu.carvicim.storage.session.exceptions.UnitializedException; //@@author yuhongherald /** @@ -21,97 +15,32 @@ * exporting (@code Job) with commens to (@code outFile). Implements a Singleton design pattern. */ public class ImportSession { - public static final String ERROR_MESSAGE_FILE_OPEN = "An excel file is already open."; - public static final String ERROR_MESSAGE_INVALID_FILEPATH = "Please check the path to your file."; - public static final String ERROR_MESSAGE_READ_PERMISSION = "Please enable file read permission."; - public static final String ERROR_MESSAGE_FILE_FORMAT = "Unable to read the format of file. " - + "Please ensure the file is in .xls or .xlsx format"; - public static final String ERROR_MESSAGE_IO_EXCEPTION = "Unable to read file. Please close the file and try again."; - private static ImportSession session; - private boolean initialized; - private File inFile; - private File tempFile; - private Workbook workbook; // write comments to column after last row, with approval status + private static ImportSession importSession; + private SessionData sessionData; - private File outFile; private ImportSession() { - initialized = false; + sessionData = new SessionData(); } public static ImportSession getInstance() { - if (session == null) { - session = new ImportSession(); + if (importSession == null) { + importSession = new ImportSession(); } - return session; + return importSession; } - public static String getTimeStamp() { - return new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date()); - } - - /** - * Returns whether (@code ImportSession) has been initialized with an excel spreadsheet - */ - public boolean isInitialized() { - return initialized; + public void setSessionData(SessionData sessionData) { + requireNonNull(sessionData); + this.sessionData = sessionData; } /** * Opens excel file specified by (@code filepath) and initializes (@code SessionData) to support import operations */ public void initializeSession(String filePath) throws FileAccessException, FileFormatException { - if (inFile != null) { - throw new FileAccessException(ERROR_MESSAGE_FILE_OPEN); - } - File file = new File (filePath); - if (!file.exists()) { - throw new FileAccessException(ERROR_MESSAGE_INVALID_FILEPATH); - } else if (!file.canRead()) { - throw new FileFormatException(ERROR_MESSAGE_READ_PERMISSION); - } - try { - workbook = createWorkBook(file); - } catch (InvalidFormatException e) { - throw new FileFormatException(ERROR_MESSAGE_FILE_FORMAT); - } catch (IOException e) { - throw new FileFormatException(ERROR_MESSAGE_IO_EXCEPTION); - } - // the file is good to go - inFile = file; - initializeSessionData(); - initialized = true; - } - - /** - * Attempts to parse the column headers and retrieve job entries - */ - private void initializeSessionData() throws FileFormatException { - SheetWithHeaderFields sheetWithHeaderFields; - SheetParser sheetParser; - Sheet sheet; - sessionData = new SessionData(); - - for (int i = 0; i < workbook.getNumberOfSheets(); i++) { - sheet = workbook.getSheetAt(workbook.getFirstVisibleTab() + i); - sheetParser = new SheetParser(sheet); - sheetWithHeaderFields = sheetParser.parseSheetWithHeaderField(); - sessionData.addSheet(sheetWithHeaderFields); - } - } - - /** - * Attempts to create a (@code Workbook) for a given (@code File) - */ - private Workbook createWorkBook(File file) throws IOException, InvalidFormatException { - tempFile = new File(file.getPath() + getTimeStamp() + file.getName()); - FileOutputStream fileOutputStream = new FileOutputStream(tempFile); - Workbook workbook = WorkbookFactory.create(file); - workbook.write(fileOutputStream); - workbook.close(); - workbook = WorkbookFactory.create(tempFile); - return workbook; + sessionData.loadFile(filePath); } public void reviewAllRemainingJobEntries(boolean approve) throws DataIndexOutOfBoundsException { @@ -125,30 +54,7 @@ public SessionData getSessionData() { /** * Flushes feedback to (@code outFile) and releases resources. Currently not persistent. */ - public void closeSession() throws DataIndexOutOfBoundsException, IOException { - if (!initialized) { - return; - } - if (outFile == null) { // does not check if a file exists - String timeStamp = getTimeStamp(); - outFile = new File(inFile.getPath() + timeStamp + inFile.getName()); - } - FileOutputStream fileOut = new FileOutputStream(outFile); - System.out.println(outFile.getName()); - workbook.write(fileOut); - fileOut.close(); - workbook.close(); - tempFile.deleteOnExit(); - freeResources(); - } - - /** - * Releases resources associated with ImportSession by nulling field - */ - private void freeResources() { - workbook = null; - sessionData = null; - inFile = null; - outFile = null; + public String closeSession() throws IOException, UnitializedException { + return sessionData.saveData(); } } diff --git a/src/main/java/seedu/carvicim/storage/session/JobEntry.java b/src/main/java/seedu/carvicim/storage/session/JobEntry.java index a0bc52730ace..f909be4302d8 100644 --- a/src/main/java/seedu/carvicim/storage/session/JobEntry.java +++ b/src/main/java/seedu/carvicim/storage/session/JobEntry.java @@ -20,7 +20,7 @@ /** * Represents a job entry in an (@link ImportSession) */ -public class JobEntry extends Job implements ExcelRowReference { +public class JobEntry extends Job { public static final String NEWLINE = "\n"; private final int sheetNumber; @@ -82,11 +82,11 @@ public String getCommentsAsString() { return stringBuilder.toString(); } - @Override public int getSheetNumber() { + public int getSheetNumber() { return sheetNumber; } - @Override public int getRowNumber() { + public int getRowNumber() { return rowNumber; } } diff --git a/src/main/java/seedu/carvicim/storage/session/RowData.java b/src/main/java/seedu/carvicim/storage/session/RowData.java index 44a42d3b6e86..5b0588c97d5e 100644 --- a/src/main/java/seedu/carvicim/storage/session/RowData.java +++ b/src/main/java/seedu/carvicim/storage/session/RowData.java @@ -5,7 +5,6 @@ import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; @@ -13,7 +12,7 @@ /** * Represents a field that spans one or more columns */ -public class RowData implements ExcelColumnSpannable { +public class RowData { private final int startIndex; private final int endIndex; @@ -22,31 +21,19 @@ public RowData(int startIndex, int endIndex) { this.endIndex = endIndex; } - @Override public int getStartIndex() { return startIndex; } - @Override public int getEndIndex() { return endIndex; } - @Override - public ArrayList readData(Workbook workbook, int sheetNumber, int rowNumber) - throws DataIndexOutOfBoundsException { - if (sheetNumber < workbook.getFirstVisibleTab() - || sheetNumber >= workbook.getNumberOfSheets() + workbook.getFirstVisibleTab()) { - throw new DataIndexOutOfBoundsException("Sheets", workbook.getFirstVisibleTab(), - workbook.getNumberOfSheets() + workbook.getFirstVisibleTab(), sheetNumber); - } - Sheet sheet = workbook.getSheetAt(sheetNumber); - return readDataFromSheet(sheet, rowNumber); - } - - @Override + /** + * Reads all the entries between (@code startIndex) and (@code endIndex) from a row in the excel file + */ public ArrayList readDataFromSheet(Sheet sheet, int rowNumber) - throws DataIndexOutOfBoundsException { + throws DataIndexOutOfBoundsException { if (rowNumber < sheet.getFirstRowNum() || rowNumber > sheet.getLastRowNum()) { throw new DataIndexOutOfBoundsException("Rows", sheet.getFirstRowNum(), sheet.getLastRowNum(), rowNumber); } diff --git a/src/main/java/seedu/carvicim/storage/session/SessionData.java b/src/main/java/seedu/carvicim/storage/session/SessionData.java index a2c558cc4b1a..1d5d6a246987 100644 --- a/src/main/java/seedu/carvicim/storage/session/SessionData.java +++ b/src/main/java/seedu/carvicim/storage/session/SessionData.java @@ -1,43 +1,210 @@ package seedu.carvicim.storage.session; +import static java.util.Objects.requireNonNull; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.Iterator; - import java.util.List; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; + +import org.apache.poi.ss.usermodel.WorkbookFactory; + +import seedu.carvicim.model.job.Job; import seedu.carvicim.storage.session.exceptions.DataIndexOutOfBoundsException; +import seedu.carvicim.storage.session.exceptions.FileAccessException; +import seedu.carvicim.storage.session.exceptions.FileFormatException; +import seedu.carvicim.storage.session.exceptions.InvalidDataException; +import seedu.carvicim.storage.session.exceptions.UnitializedException; //@@author yuhongherald /** * A data structure used to keep track of job entries in an (@code ImportSession) */ public class SessionData { + public static final String ERROR_MESSAGE_FILE_OPEN = "An excel file is already open."; + public static final String ERROR_MESSAGE_INVALID_FILEPATH = "Please check the path to your file."; + public static final String ERROR_MESSAGE_READ_PERMISSION = "Please enable file read permission."; + public static final String ERROR_MESSAGE_FILE_FORMAT = "Unable to read the format of file. " + + "Please ensure the file is in .xls or .xlsx format"; + public static final String ERROR_MESSAGE_IO_EXCEPTION = "Unable to read file. Please close the file and try again."; public static final String ERROR_MESSAGE_EMPTY_UNREVIWED_JOB_LIST = "There are no unreviewed job entries left!"; + public static final String FILE_PATH_CHARACTER = "/"; + public static final String TIMESTAMP_FORMAT = "yyyy.MM.dd.HH.mm.ss"; + public static final String SAVEFILE_SUFFIX = ""; + public static final String TEMPFILE_SUFFIX = "temp"; + public static final String ERROR_MESSAGE_UNITIALIZED = "There is no imported file to save!"; + private final ArrayList unreviewedJobEntries; private final ArrayList reviewedJobEntries; private final ArrayList sheets; - // will be using an ObservableList - SessionData() { + private File importFile; + private File tempFile; + private Workbook workbook; // write comments to column after last row, with approval status + private File saveFile; + + + public SessionData() { unreviewedJobEntries = new ArrayList<>(); reviewedJobEntries = new ArrayList<>(); sheets = new ArrayList<>(); } + public boolean isInitialized() { + return (workbook != null); + } + + /*=================================================================== + savefile methods + ===================================================================*/ + + /** + * Creates a file using relative filePath of (@code importFile), then appending a timestamp and + * (@code appendedName) to make it unique + */ + private File generateFile(String appendedName) { + requireNonNull(importFile); + String timeStamp = new SimpleDateFormat(TIMESTAMP_FORMAT).format(new Date()); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(importFile.getParent()); + stringBuilder.append(FILE_PATH_CHARACTER); + stringBuilder.append(timeStamp); + stringBuilder.append(importFile.getName()); + stringBuilder.append(appendedName); + return new File(stringBuilder.toString()); + } + + public String getSaveFilePath() { + if (saveFile != null) { + return saveFile.getPath(); + } + saveFile = generateFile(SAVEFILE_SUFFIX); + return saveFile.getPath(); + } + + /** + * Sets the filePath using relative address from import file + */ + public void setSaveFile(String filePath) { + saveFile = new File(filePath); + } + + /*=================================================================== + Initialization methods + ===================================================================*/ + + /** + * Attempts load file specified at (@code filePath) if there is no currently open file and + * specified file exists, is readable and is an excel file + */ + public void loadFile(String filePath) throws FileAccessException, FileFormatException { + if (isInitialized()) { + throw new FileAccessException(ERROR_MESSAGE_FILE_OPEN); + } + File file = new File(filePath); + if (!file.exists()) { + throw new FileAccessException(ERROR_MESSAGE_INVALID_FILEPATH); + } else if (!file.canRead()) { + throw new FileAccessException(ERROR_MESSAGE_READ_PERMISSION); + } + importFile = file; + + try { + workbook = createWorkBook(file); + } catch (InvalidFormatException e) { + throw new FileFormatException(ERROR_MESSAGE_FILE_FORMAT); + } catch (IOException e) { + throw new FileFormatException(ERROR_MESSAGE_IO_EXCEPTION); + } + + initializeSessionData(); + } + /** - * @return a copy of unreviewed job entries stored in this sheet + * Attempts to create a (@code Workbook) for a given (@code File) */ - public List getUnreviewedJobEntries() { + private Workbook createWorkBook(File file) throws IOException, InvalidFormatException { + tempFile = generateFile(TEMPFILE_SUFFIX); + FileOutputStream fileOutputStream = new FileOutputStream(tempFile); + Workbook workbook = WorkbookFactory.create(file); + workbook.write(fileOutputStream); + workbook.close(); + workbook = WorkbookFactory.create(tempFile); + return workbook; + } + /** + * Attempts to parse the column headers and retrieve job entries + */ + public void initializeSessionData() throws FileFormatException { + SheetWithHeaderFields sheetWithHeaderFields; + SheetParser sheetParser; + Sheet sheet; + + for (int i = 0; i < workbook.getNumberOfSheets(); i++) { + sheet = workbook.getSheetAt(workbook.getFirstVisibleTab() + i); + sheetParser = new SheetParser(sheet); + sheetWithHeaderFields = sheetParser.parseSheetWithHeaderField(); + addSheet(sheetWithHeaderFields); + } + } + + /** + * Saves feedback to specified saveFile path + */ + public String saveData() throws IOException, UnitializedException { + if (!isInitialized()) { + throw new UnitializedException(ERROR_MESSAGE_UNITIALIZED); + } + if (saveFile == null) { // does not check if a file exists + saveFile = generateFile(SAVEFILE_SUFFIX); + } + FileOutputStream fileOut = new FileOutputStream(saveFile); + String path = saveFile.getAbsolutePath(); + workbook.write(fileOut); + fileOut.close(); + workbook.close(); + freeResources(); + return path; + } + /** + * Releases resources associated with ImportSession by nulling field + */ + public void freeResources() { + workbook = null; + importFile = null; + tempFile.delete(); + tempFile = null; + saveFile = null; + unreviewedJobEntries.clear(); + reviewedJobEntries.clear(); + sheets.clear(); + } + + /*=================================================================== + Job review methods + ===================================================================*/ + /** + * @return a copy of unreviewed jobs stored in this sheet + */ + public List getUnreviewedJobEntries() { return Collections.unmodifiableList(unreviewedJobEntries); } /** - * @return a copy of reviewed job entries stored in this sheet + * @return a copy of reviewed jobs stored in this sheet */ - public List getReviewedJobEntries() { + public List getReviewedJobEntries() { return Collections.unmodifiableList(reviewedJobEntries); } @@ -55,19 +222,41 @@ public void addSheet(SheetWithHeaderFields sheetWithHeaderFields) { /** * Reviews all remaining jobs using (@code reviewJobEntry) */ - void reviewAllRemainingJobEntries(boolean approved, String comments) throws DataIndexOutOfBoundsException { + public void reviewAllRemainingJobEntries(boolean approved, String comments) throws DataIndexOutOfBoundsException { while (!getUnreviewedJobEntries().isEmpty()) { reviewJobEntry(0, approved, comments); } } + /** + * Reviews a (@code JobEntry) specified by (@code listIndex) + * @param jobNumber index of (@code JobEntry) in (@code unreviewedJobEntries) + * @param approved whether job entry will be added to Carvicim + * @param comments feedback in string representation + */ + public void reviewJobEntryUsingJobNumber(int jobNumber, boolean approved, String comments) + throws DataIndexOutOfBoundsException, InvalidDataException { + if (unreviewedJobEntries.isEmpty()) { + throw new IllegalStateException(ERROR_MESSAGE_EMPTY_UNREVIWED_JOB_LIST); + } + JobEntry entry; + for (int i = 0; i < unreviewedJobEntries.size(); i++) { + entry = unreviewedJobEntries.get(i); + if (entry.getJobNumber().asInteger() == jobNumber) { + reviewJobEntry(i, approved, comments); + return; + } + } + throw new InvalidDataException("Job number not found!"); + } + /** * Reviews a (@code JobEntry) specified by (@code listIndex) * @param listIndex index of (@code JobEntry) in (@code unreviewedJobEntries) * @param approved whether job entry will be added to Carvicim * @param comments feedback in string representation */ - void reviewJobEntry(int listIndex, boolean approved, String comments) throws DataIndexOutOfBoundsException { + public void reviewJobEntry(int listIndex, boolean approved, String comments) throws DataIndexOutOfBoundsException { if (unreviewedJobEntries.isEmpty()) { throw new IllegalStateException(ERROR_MESSAGE_EMPTY_UNREVIWED_JOB_LIST); } else if (listIndex < 0 || listIndex >= unreviewedJobEntries.size()) { @@ -77,7 +266,9 @@ void reviewJobEntry(int listIndex, boolean approved, String comments) throws Dat JobEntry jobEntry = unreviewedJobEntries.get(listIndex); jobEntry.review(approved, comments); unreviewedJobEntries.remove(jobEntry); - reviewedJobEntries.add(jobEntry); + if (approved) { + reviewedJobEntries.add(jobEntry); + } SheetWithHeaderFields sheet = sheets.get(jobEntry.getSheetNumber()); sheet.commentJobEntry(jobEntry.getRowNumber(), jobEntry.getCommentsAsString()); if (approved) { diff --git a/src/main/java/seedu/carvicim/storage/session/exceptions/UnitializedException.java b/src/main/java/seedu/carvicim/storage/session/exceptions/UnitializedException.java new file mode 100644 index 000000000000..826dac0ae98a --- /dev/null +++ b/src/main/java/seedu/carvicim/storage/session/exceptions/UnitializedException.java @@ -0,0 +1,11 @@ +package seedu.carvicim.storage.session.exceptions; + +//@@author yuhongherald +/** + * Represents an error when {@link seedu.carvicim.storage.session.SessionData} is not initialized. + */ +public class UnitializedException extends Exception { + public UnitializedException(String message) { + super(message); + } +} diff --git a/src/main/java/seedu/carvicim/ui/JobListPanel.java b/src/main/java/seedu/carvicim/ui/JobListPanel.java index 3c1c37ed5beb..0aa505a26555 100644 --- a/src/main/java/seedu/carvicim/ui/JobListPanel.java +++ b/src/main/java/seedu/carvicim/ui/JobListPanel.java @@ -14,6 +14,7 @@ import javafx.scene.control.ListView; import javafx.scene.layout.Region; import seedu.carvicim.commons.core.LogsCenter; +import seedu.carvicim.commons.events.ui.DisplayAllJobsEvent; import seedu.carvicim.commons.events.ui.JobPanelSelectionChangedEvent; import seedu.carvicim.commons.events.ui.JumpToListRequestEvent; import seedu.carvicim.commons.events.ui.PersonPanelSelectionChangedEvent; @@ -99,6 +100,13 @@ private void handlePersonPanelSelectionChangedEvent(PersonPanelSelectionChangedE updateList(event.getNewSelection().employee); } + @Subscribe + private void handleDisplayAllJobsEvent(DisplayAllJobsEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + jobList = event.getJobList(); + setConnections(jobList); + } + private void updateList(Employee employee) { ObservableList filteredList = FXCollections.unmodifiableObservableList( jobList.filtered(JobList.filterByEmployee(jobList, employee))); diff --git a/src/test/java/seedu/carvicim/logic/commands/AddEmployeeCommandTest.java b/src/test/java/seedu/carvicim/logic/commands/AddEmployeeCommandTest.java index 576a62367cfa..ddaf2af965da 100644 --- a/src/test/java/seedu/carvicim/logic/commands/AddEmployeeCommandTest.java +++ b/src/test/java/seedu/carvicim/logic/commands/AddEmployeeCommandTest.java @@ -126,6 +126,15 @@ public void addMissingEmployees(Set employees) { fail("This method should not be called."); } + @Override public boolean isViewingImportedJobs() { + fail("This method should not be called."); + return false; + } + + @Override public void switchJobView() { + fail("This method should not be called."); + } + @Override public void resetData(ReadOnlyCarvicim newData, CommandWords newCommandWords) { fail("This method should not be called."); diff --git a/src/test/java/seedu/carvicim/logic/commands/AddJobCommandTest.java b/src/test/java/seedu/carvicim/logic/commands/AddJobCommandTest.java index 1b692d39f54e..2d433f16c7bd 100644 --- a/src/test/java/seedu/carvicim/logic/commands/AddJobCommandTest.java +++ b/src/test/java/seedu/carvicim/logic/commands/AddJobCommandTest.java @@ -107,6 +107,15 @@ public void addMissingEmployees(Set employees) { fail("This method should not be called."); } + @Override public boolean isViewingImportedJobs() { + fail("This method should not be called."); + return false; + } + + @Override public void switchJobView() { + fail("This method should not be called."); + } + @Override public void resetData(ReadOnlyCarvicim newData, CommandWords newCommandWords) { fail("This method should not be called."); diff --git a/src/test/java/seedu/carvicim/storage/ImportSessionTest.java b/src/test/java/seedu/carvicim/storage/ImportSessionTest.java index 14b98758dce4..9b64930dc638 100644 --- a/src/test/java/seedu/carvicim/storage/ImportSessionTest.java +++ b/src/test/java/seedu/carvicim/storage/ImportSessionTest.java @@ -1,14 +1,38 @@ package seedu.carvicim.storage; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.junit.Test; + +import seedu.carvicim.storage.session.ImportSession; + + +//@@author yuhongherald public class ImportSessionTest { - /* @Test + private static final String TEST_INPUT_FILE = "storage/session/ImportSessionTest/CS2103-testsheet.xlsx"; + private static final String TEST_OUTPUT_FILE = ""; + private static final String OUTFILE_NAME = "outFile"; + + @Test public void importTestFileWithErrorCorrection() throws Exception { ImportSession importSession = ImportSession.getInstance(); - String path; - path = new File(".").getCanonicalPath(); - importSession.initializeSession( - path + "\\src\\test\\resources\\model.session.ImportSessionTest\\CS2103-testsheet.xlsx"); + + ClassLoader classLoader = getClass().getClassLoader(); + String path = classLoader.getResource(TEST_INPUT_FILE) + .getPath(); + importSession.initializeSession(path); importSession.reviewAllRemainingJobEntries(true); importSession.closeSession(); - }*/ + //deleteFile(OUTFILE_NAME); + } + + private void compareExcelFiles() { + ; + } + + private void deleteFile(String filePath) throws IOException { + Files.deleteIfExists(Paths.get(filePath)); + } } diff --git a/src/test/resources/storage/session/ImportSessionTest/CS2103-testsheet.xlsx b/src/test/resources/storage/session/ImportSessionTest/CS2103-testsheet.xlsx new file mode 100644 index 000000000000..46c974c13714 Binary files /dev/null and b/src/test/resources/storage/session/ImportSessionTest/CS2103-testsheet.xlsx differ diff --git a/src/test/resources/model.session.ImportSessionTest/CS2103-testsheet.xlsx2018.03.25.23.24.19CS2103-testsheet.xlsx b/src/test/resources/storage/session/ImportSessionTest/CS2103-testsheet.xlsx-result.xlsx similarity index 100% rename from src/test/resources/model.session.ImportSessionTest/CS2103-testsheet.xlsx2018.03.25.23.24.19CS2103-testsheet.xlsx rename to src/test/resources/storage/session/ImportSessionTest/CS2103-testsheet.xlsx-result.xlsx