Skip to content

Commit

Permalink
Merge pull request #224 from LeowWB/export-1.4
Browse files Browse the repository at this point in the history
Export 1.4
  • Loading branch information
LeowWB committed Nov 8, 2019
2 parents f7db35a + 821a9f1 commit 69486c7
Show file tree
Hide file tree
Showing 35 changed files with 477 additions and 126 deletions.
97 changes: 78 additions & 19 deletions docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -245,37 +245,96 @@ prefixes like `t>` and `d>`
** Cons: Difficult to implement.
// end::deadline[]


//@@author LeowWB
// tag::flashcardexport[]
=== Exporting of FlashCards
==== Implementation

// tag::flashcardexportimport[]

=== Exporting/Importing of FlashCards
==== Implementation

The `FlashCard` exporting mechanism is primarily facilitated by the following classes:
Our application currently supports the exporting of `FlashCards` to two file formats (`.docx` and `.json`) and importing of `FlashCards` from one
file format (`.json`). These mechanisms are primarily facilitated by the following classes:

* `ExportUtil` -- Handles the actual exporting of `FlashCards`
* `ExportCommand` -- Embodies an `export` command by the user; carries information about which `FlashCards` are to be exported, and to where
* `ExportCommandParser` -- Parses user input and uses it to construct an `ExportCommand` instance
* `ImportCommand` -- Embodies an `import` command by the user; carries information about where `FlashCards` are to be imported from
* `ImportCommandParser` -- Parses user input and uses it to construct an `ImportCommand` instance
* `ExportPath` -- Represents the path to a specific file - either absolute or relative to the application directory
* `ExportPathFactory` -- Parses the user-provided file path and creates instances of `ExportPath`

NOTE: The "export" in `ExportPath` is to be taken as a noun, not a verb. An `ExportPath`, therefore, is not the path that we export to, but the
path of an export. `ExportPaths` are used in both exporting and importing of files.

`ExportPath` is an abstract class that follows the factory pattern. Each subclass of `ExportPath` represents the path to a specific file of a
specific extension (e.g. an instance of `DocumentPath` represents the path to a specific document). Instances of these subclasses are created by
`ExportPathFactory#getExportPath(String)`, which determines the appropriate subclass to create based on the extension of the provided file path String.
Once created, an `ExportPath` will expose the following relevant methods:

* `getPath()` -- Returns a Java `Path` object that represents this `ExportPath`
* `export(List<FlashCard> list)` -- Exports the given `List` of `FlashCards` to the file path embodied by this `ExportPath`
* `importFrom()` -- Attempts to import `FlashCards` from the file path represented by this `ExportPath`

CAUTION: Not all `ExportPath` subclasses will implement the `importFrom()` method. `DocumentPath`, for example, does not - this is because documents are
relatively unstructured and impractical to import from, and there are other reasons for exporting to a document (e.g. to use as cheat sheet).

Because `ExportPath` follows the factory pattern, any class that deals with `ExportPath` or its subclasses need not know which particular subclass it is
dealing with exactly. Each `ExportPath` subclass will implement its own `export` and `import` methods, which, when called, will perform the required operations
without any further hassle. Of course, due to the Separation of Concerns principle, the `ExportPath` subclasses will not handle these directly.
Instead, they will delegate the work to other utility classes, which, in turn, interface with the external libraries necessary to complete the task.

TIP: The exporting/importing functionality is extremely easy to extend - support for new formats can be added simply through the creation of new subclasses of `ExportPath`.

NOTE: All relevant classes can be found in the `seedu.address.model.export` package. The only exceptions are `ExportCommand`, `ImportCommand`, `ExportCommandParser`, and `ImportCommandParser`, which can be found in the `seedu.address.logic` package.

The following table shows the classes and methods that you may have to deal with when exporting to or importing from each format:

[width="59%",cols="20%,35%,35%",options="header",]
|====

The mechanism is also supported by the package `seedu.address.model.export`, consisting of the following classes:
|**File format** |Document |JSON

* `DocumentPath` -- Represents the path to a specific document - either absolute or relative to the application directory
* `DocumentFilePath` -- Represents the path to a specific document, relative to its immediate parent directory
* `DirectoryPath` -- Represents the path to a specific directory - either absolute or relative to the application directory
|**File extension** |`.docx` |`.json`

Of particular note is `ExportUtil`, as it is arguably the class responsible for doing the most tangible work.
Similar to the other classes in the `util` package, it consists entirely of `static` methods, and does not keep track of any variables.
It exposes a single method, `ExportUtil#exportFlashCards(List<FlashCard>, DocumentPath)`, which prints a `List` of `FlashCards` to a `.docx`
document located at the given `DocumentPath`. This is done by interfacing with the Apache POI library (in particular, the package
`org.apache.poi.xwpf.usermodel`).
|**`ExportPath` subclass** |`DocumentPath` |`JsonExportPath`

The following sequence diagram shows how the export operation works:
a|**Export utility class and method**
a|`DocumentExportUtil#exportFlashCardsToDocument( List<FlashCard>, DocumentPath)`
a|`JsonExportUtil#exportFlashCardsToJson( List<FlashCard>, JsonExportPath)`

a|**Import utility class and method**
a|_None - importing not supported_
a|`JsonImportUtil#importFlashCardsFromJson( JsonExportPath)`

|**External library used** |Apache POI |Jackson
|====

The number of classes supporting the import/export feature is rather large. The following class diagram will help to clarify the associations
between these classes:

image::ExportClassDiagram.png[height=700]

_Figure 1: Class diagram showing the classes directly relevant to importing and exporting_

The following sequence diagram shows how the export operation works when the user tries to export to a document (`.docx`) file:

image::ExportSequenceDiagram.png[]

_Figure 2: Sequence diagram showing the process of exporting to a document file_

NOTE: Due to a limitation of PlantUML, object lifelines in the diagram extend beyond the destroy markers. This, of course, should be ignored.

The following activity diagram summarizes what happens when a user executes an export command:

image::ExportActivityDiagram.png[width=320,height=480]
image::ExportActivityDiagram.png[width=500,height=540]

_Figure 3: Activity diagram of when the user executes an export command_

The following activity diagram summarizes what happens when a user executes an import command:

image::ImportActivityDiagram.png[width=500,height=580]

_Figure 4: Activity diagram of when the user executes an import command_

==== Design Considerations

Expand Down Expand Up @@ -313,9 +372,9 @@ NOTE: The original AddressBook application, from which KeyboardFlashCards was mo
* **Alternative 1:** Read file path as-is, using the existing AddressBook parser
** Pros: Does not require further code changes
** Cons: Means that errors may occur for certain file paths
* **Alternative 2:** Disallow user from selecting file path - instead, always export to a specific directory
* **Alternative 2:** Disallow user from selecting file path - instead, always export to and import from a specific directory
** Pros: Is somewhat easy to implement
** Cons: Requires user to navigate to the specified directory to obtain the file; requires a means of finding alternatives if the default directory does not exist
** Cons: Requires user to navigate to the specified directory; requires a means of finding alternatives if the default directory does not exist
* **Alternative 3:** Ask user to replace slashes in file path with another character
** Pros: Is very easy to implement
** Cons: Greatly inconveniences the user; extra work must be done to restore the input to the original file path
Expand All @@ -325,7 +384,7 @@ NOTE: The original AddressBook application, from which KeyboardFlashCards was mo

NOTE: **Alternative 4** was preferred as it provides users with the greatest overall convenience.

// end::flashcardexport[]
// end::flashcardexportimport[]

//@@author keiteo
// tag::dataencryption[]
Expand Down
40 changes: 30 additions & 10 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ This section contains the features and their respective commands
* Items with `…`​ after them can be inserted zero or more times e.g. `[c>CATEGORY]...` can be used as `{nbsp}` (i.e. 0 times), `c>math`, `c>math c>school` etc.
* Parameters can be in any order e.g. if the command specifies `q>QUESTION a>ANSWER`, `a>ANSWER q>QUESTION` is also acceptable.
* Currently, our application does not support emoji.
Please also note the following icons, which will indicate points of interest throughout this document.
NOTE: A point of information that you may wish to note
TIP: A tip or suggestion
CAUTION: A cautionary word of advice
====

// tag::flashcard[]
Expand Down Expand Up @@ -278,6 +284,9 @@ This command rates the flashcard, depending on how well you answered the questio
You can stop the test any time simply by typing `end`.

//@@author LeowWB

// tag::flashcardexport[]

=== Export flashcards to a file: `export c>CATEGORY p>FILE_PATH`

You can use this command to export all your FlashCards in a particular category, to an external file.
Expand All @@ -290,10 +299,16 @@ Suppose you have a category named `CS2105`, and you wanted to export the FlashCa
(so you can share them with your friend). Here's how you would go about this:

. Type the example command given above into the command box (`export c>CS2105 p>C:\Documents\cs2105.json`), as shown below.
+
image::ExportDemo1.png[width="600"]

. Press **Enter** to execute the command. The results box will display a success message similar to the one shown in the screenshot below.
+
image::ExportDemo2.png[width="600"]

. Navigate to the directory that you specified in the command (in this case, it would be 'C:\Documents'). Sure enough, your exported file is there!
+
image::ExportDemo3.png[width="600"]

NOTE: Only the questions and answers of FlashCards will be exported.

Expand All @@ -305,22 +320,33 @@ CAUTION: Do note that some directories may be protected by your operating system
TIP: Use this to export your flashcards into an easily-printable cheat sheet! Use them for your assessments or
self-learning.

// end::flashcardexport[]

// tag::flashcardimport[]

=== Import flashcards from a JSON file: `import p>FILE_PATH`

You can use this command to import FlashCards from a file that you or someone else had exported to earlier.
We currently only support importing from JSON (.json) files. +
Example: `import p>C:\Downloads\cs2105.json`

Suppose your friend has kindly exported some of his FlashCards for you to use. You've download the `.json` file that he sent you;
now your next step is to get those FlashCards into your copy of KFC. Here's how you'd go about this:
Suppose your friend has kindly exported some of his FlashCards for you to use. You have download the `.json` file that he sent you,
and it's currently located at the following path: `C:\Downloads\cs2105.json`.
Your next step is to get those FlashCards into your copy of KFC. Here's how you'd go about this:

. Type the example command given above into the command box (`import p>C:\Downloads\cs2105.json`), as shown below.
+
image::ImportDemo1.png[width="600"]

. Press **Enter** to execute the command. The results box will display a success message similar to the one shown in the screenshot below.
Furthermore, the category panel on the left will now display the category of the newly-imported FlashCards!
Furthermore, the category list on the left will now display the category of the newly-imported FlashCards!
+
image::ImportDemo2.png[width="600"]

NOTE: Duplicate FlashCards will not be imported. You will be notified when we detect duplicate FlashCards in the file you provide.

// end::flashcardimport[]

=== Get the full list of commands: `help`

This command allows you to view all the commands available in the application. +
Expand Down Expand Up @@ -424,20 +450,14 @@ To exit:
*Q*: Will I be able to resume the test from where I left off after I have stopped? +
*A*: No. The program does not support that.

*Q*: Can I undo the commands that I have entered? +
*A*: No. However, a confirmation will be displayed before any potentially-hard-to-reverse actions are done.

*Q*: Can I change the category of a flashcard? +
*A*: Yes, it will be one of the fields you can change when you edit the flashcard. Do note that after you change the category, you will have to refer to it using its new category and ID.

*Q*: Can I use my mouse to interact with the user interface? +
*A*: Yes, but only to a very small extent, like closing the window. This application is targeted primarily at keyboard users.

*Q*: What if I forget the format of a command’s arguments? +
*A*: Don’t worry! You will be shown the expected format once you have keyed in the whole command.

*Q*: Is there an autocomplete functionality? +
*A*: Yes, you can press Tab to use this feature.
*A*: Don’t worry! Just try your best. If the format you've provided is wrong, you will be prompted with the correct format.

== Command Summary

Expand Down
23 changes: 14 additions & 9 deletions docs/diagrams/ExportActivityDiagram.puml
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
@startuml
start
:User executes export command;
:User executes export command, with a specified category and file path;

'Since the beta syntax does not support placing the condition outside the
'diamond we place it as the true branch instead.

if () then ([file path is valid])
:Obtain the desired FlashCards;
:Create a new document;
if () then ([else])
if () then ([file path is valid and represents\na document or JSON file])
if () then ([Category exists and is non-empty])
:Obtain all FlashCards from category;
if () then ([file path is for document file])
:Create a new document;
else ([file path is for a JSON file])
:Create a new JSON file;
endif
repeat
:Write FlashCard to document;
:Write FlashCard to file;
repeat while () is ([more FlashCards\nto write])
->[all FlashCards written];
else ([no FlashCards to be written])
:Save file to given file path;
:Display success message;
else ([else])
:Display error message;
endif
:Save document to given file path;
:Display success message;
else ([else])
:Display error message;
endif
Expand Down
65 changes: 65 additions & 0 deletions docs/diagrams/ExportClassDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
@startuml
!include style.puml

skinparam arrowThickness 1.1
skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR



Package Logic <<Rectangle>>{
Class ExportCommand LOGIC_COLOR
Class ImportCommand LOGIC_COLOR
Class ExportCommandParser LOGIC_COLOR
Class ImportCommandParser LOGIC_COLOR
Abstract Class Command LOGIC_COLOR
Class Parser <<interface>> LOGIC_COLOR
}

Command <|- ExportCommand LOGIC_COLOR
Command <|- ImportCommand LOGIC_COLOR
Parser <|.. ExportCommandParser LOGIC_COLOR
Parser <|.. ImportCommandParser LOGIC_COLOR

Parser .. Command LOGIC_COLOR
ExportCommandParser .. ExportCommand LOGIC_COLOR
ImportCommandParser .. ImportCommand LOGIC_COLOR



Package seedu.address.model.export <<Rectangle>>{
Class DirectoryPath
Class DocumentExportUtil
Class DocumentFilePath
Class DocumentPath
Abstract Class ExportPath
Class ExportPathFactory
Class JsonExportFilePath
Class JsonExportPath
Class JsonExportUtil
Class JsonImportUtil
}

ExportPath <|- DocumentPath
ExportPath <|- JsonExportPath

DocumentPath *-- DocumentFilePath
DocumentPath *-- DirectoryPath

JsonExportPath *-- JsonExportFilePath
JsonExportPath *-- DirectoryPath

ExportPathFactory .up. ExportPath

DocumentExportUtil .. DocumentPath
JsonExportUtil .. JsonExportPath
JsonImportUtil .. JsonExportPath



ExportCommand "0..1" ------> "1" ExportPath LOGIC_COLOR
ImportCommand "0..1" --> "1" ExportPath LOGIC_COLOR

ExportCommandParser .. ExportPath LOGIC_COLOR
ImportCommandParser .. ExportPath LOGIC_COLOR
@enduml
Loading

0 comments on commit 69486c7

Please sign in to comment.