Overview
NurseTraverse is a desktop application designed to help community nurses manage all the data they may need, including visit management, appointment scheduling, and importing and exporting of patient data. The user interacts with the app using a CLI (Command Line Interface) enhanced with an autocomplete functionality and ability to undo and redo commands. The app has a GUI created with JavaFX and is written in Java. NurseTraverse is built by me and 4 other students.
Summary of contributions
-
Major enhancement: added the function to export and import patient data.
-
What it does:
-
Exporting features: allows the user to export patient data into a comma separated values (CSV) file. Patient data can be exported all at once, or selectively by index.
-
Importing features: allows the user to import patient data from a CSV file. Imported patient data can either be used to replace all existing patient data or be merged with existing patient data.
-
-
Justification: This feature improves the functionality of the product by facilitating convenient data sharing. To add data for a few patients, there is no longer a need to use the add command multiple times, which can be a hassle. Example use cases:
-
A freshly trained nurse has been assigned her first set of patients. The patients' data can be passed to the nurse in the CSV format and imported in one go.
-
A (few) patient(s) has been transferred from the care of one nurse to another. The relevant patient data can be exported, passed to the other nurse, and imported.
-
An archive of patient data has to be kept for records purposes. The export feature allows for a "snapshot" of all patient data to be saved easily.
-
-
Highlights: This feature was implementation with Jackson’s
dataformat.csv
library. The library is full of functions but is not exactly well documented, and thus the implementation took significant research and experimentation. The final implementation with this library is such that the export and import functionality can easily be extended to include additional data fields in the future, using Jackson’sAnnotation
feature. Apart the CSV parsing aspect, coding the data interaction for reading and writing patients to the address book had its challenges as well, due to the potential (buggy) interactions with the data from other features. -
Credits: Jackson Dataformat CSV, along with the existing Jackson annotations in AB3 used for JSON processing.
-
-
Code contributed: My contributed code can be found here. Use the filters to sort functional and test code as needed.
-
Other contributions:
-
Project management:
-
Opened milestones and user stories issues.
-
Managed milestones
v1.0
andv1.1
.
-
-
Documentation:
-
Created the product README
-
Sanitized irrelevant aspects of the User Guide and Developer Guide : #200
-
-
Community:
-
Tools:
-
Integrated coveralls to the project.
-
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
Importing and Exporting of Patient Data
Importing and Exporting of Patient Data
As a community nurse, you may be assigned new patients, or some of your patients may be assigned to other community nurses. To facilitate the transferring of patient information from one device to another, you can import and export the data of your patients. This section describes the features that will allow you to import and export patient information.
CSV Compatibility You may encounter issues when trying to import a CSV file written by another machine with a different operating system. As of v1.4, CSV files written by Windows and Unix machines are not cross-compatible. This means that the app, running on Windows, can only import CSV files written by a Windows machine. The same goes for Unix systems. This issue can be circumvented by using text file format converters to convert a Windows written CSV to a Unix one, and vice versa.
The recommended converters are |
Importing Patients from a CSV file: app-import-replace
, app-import-merge
You can import patient data from a .csv file into the application using
app-import-replace
or app-import-merge
.
CSV files used for importing must adhere to the following format requirements.
|
Examples of valid CSV files can be seen here
Import and Replace: app-import-replace
Reads patient data from a specified .csv file.
".csv"
will be auto-appended to the specified FILENAME
,
so there is no need to type in the file extension.
All existing patient data will be deleted and replaced with this new data. All existing appointment data will be deleted. |
Format: app-import-replace n/FILENAME
Examples:
-
app-import-replace n/my_assigned_patients
-
Patient data will be entirely replaced with new data from
./imports/my_assigned_patients.csv
.
-
Import and Merge: app-import-merge
Patient data will be read from a specified .csv file and merged without affecting existing data.
".csv"
will be auto-appended to the specified FILENAME
,
so there is no need to type in the file extension.
Format: app-import-merge n/FILENAME
Examples:
-
app-import-replace n/my_new_patients
-
Patient data from
./imports/my_new_patients.csv
will be added into the app.
-
Exporting patients into a CSV file: app-export
You can export patient data from the application into a .csv file using app-export
.
A new .csv file will be created and data will be written into it.
Indexes can be provided to selectively export data of specific persons.
".csv"
will be auto-appended to the specified FILENAME
,
so there is no need to type in the file extension.
Format: app-export n/FILENAME [i/INDEX…]
Examples:
-
app-export n/patients
-
All patient data will be exported to
./exports/patients.csv
.
-
-
app-export n/alex i/1
-
The data of the patient at index 1 will be exported to
./exports/alex.csv
.
-
-
app-export n/tomorrow i/2 i/4 i/6
-
The data of the patients at indexes 2, 4 and 6 will be exported to
./exports/tomorrow.csv
.
-
|
Exporting Appointments [coming in v2.0]
You can export your appointment data into a .csv file using app-export-appt
.
A new .csv file will be created and data will be written into it.
Format: app-export-appt n/FILENAME
Examples:
-
app-export-appt n/appointments
-
All appointment data will be exported to
./exports/appointments.csv
.
-
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
Import and export functionality are split into three commands:
-
app-export
-
app-import-replace
-
app-import-merge
Jackson Library
The current import and export features are built upon the the existing Jackson
libraries,
in particular the dataformat
, databind
and datatype
modules. Technical knowledge of the
Jackson
library will be helpful for maintenance of feature, but is not necessary.
However, understanding Jackson
's annotations
will be needed in order to extend export and import
functionality to cover new data fields or classes implemented in the future. They are explained
here.
Csv Processing
All of the data processing needed for this feature can be found in the CsvUtil
file;
it is responsible for converting the data of Patient
objects into a .csv friendly String
format
and vice versa. The actual reading and writing of .csv files is then done with existing
FileUtil
functionality.
The conversion of Patient
objects to and from .csv formatted Strings
are handled by
the CsvMapper
and CsvSchema
classes implemented in dataformat
.
-
The
CsvMapper
is responsible for managing custom configurations for the conversions. For instance, it can toggle headers withwithHeader()
and skip unknown fields with theIGNORE_UNKNOWN
feature, both of which are used in the feature implementation. -
The
CsvSchema
object is created by a configuredCsvMapper
object and anObject.class
, in this case,Patient.class
. It dictates the scheme for how data in each column of the .csv corresponds with the fields in the Object class. This schema can then be used to instantiate a reader or a writer object.
The following functions are implemented:
-
CsvUtil#writePatientsToCsv(List<Patient>, String)
— Write a list ofPatient
objects into a .csv file to the path at the specifiedpathString
. -
CstUtil#readPatientsFromCsv(String)
— Read a .csv file at the specified path indicated bypathString
and return a corresponding list ofPatient
objects. -
importsContainDupes(List<Patient>)
— Check if the given list contains duplicate patients, i.e. the list is not unique.
Csv Processing Design Considerations
-
Alternative 1 (current choice): Use
Jackson
'sdataformat.csv
library.-
Pros: Well integrated with the existing
Jackson
JSON parsing libraries. Tons of functions for CSV parsing. -
Cons: Does not support Excel formats. Comprehensive library, recently updated but not well-documented. Hard to understand.
-
-
Alternative 2: Use other libraries, like Apache Commons CSV.
-
Pros: More features like Excel format parsing. Well documented.
-
Cons: Does not integrate well with the existing
Jackson
libraries used.
-
-
Alternative 3: Build your own parser!
-
Pros: Lightweight, implement only what is needed. Can be white box tested.
-
Cons: Lots of developer work to reinvent the wheel. Likely to be buggy as there are tons of edge cases to consider, due to many special characters.
-
Command Implementation
Command: app-export
The app-export
command works by retrieving a list of Patient
objects from the Model
and
passing it to CsvUtil
to process and write into a .csv file. If provided with indexes, the
app-export
feature can selectively export the Patient
objects that correspond to the
specified indexes.
To facilitate the selective export functionality, the following methods were implemented in
Model
and PatientBook
.
-
Model#GetPatientsByIndexes(Set<Indexes>)
— Retrieves and returns a list ofPatient
objects corresponding to the provided indexes from thePatientBook
, if the indexes are valid. -
PatientBook#GetPatientByIndex(Index)
— Returns thePatient
object corresponding to the specified index, if the index is valid.
If indexes are not specified in the command arguments, a list of all currently existing Patient
objects will be retrieved with Model#getStagedPatientList()
.
The app-export
command MUST be provided with a desired file name for the .csv file. The .csv
file will be written to /exports/[FILENAME].csv
. Existing files will NOT be overridden and
thus the provided file name cannot already exist in /exports
.
The following diagrams show how an export command works:
ExportCommand Design Considerations
Aspect: File Overriding
-
Alternative 1 (current choice): Disallow overriding, file name provided must be new
-
Pros: Existing .csv files will not be accidentally overridden. Prevents potential loss of data.
-
Cons: Additional hassle for the user to delete files that they want to replace.
-
-
Alternative 2: Allow overriding
-
Pros: Conveniently replace existing, unused files.
-
Cons: May accidentally override and lose important data.
-
Aspect: Illegal Characters in Data Fields
-
Alternative 1 (current choice): Allow forbidden characters
-
Pros: Certain fields may be more accurately represented, i.e. addresses.
-
Cons: The exported csv file may be bugged in edge cases, i.e. have data in the wrong columns. Exported fields with forbidden characters may not be properly handled and escaped all of the time. More developer work to test around edge cases.
-
-
Alternative 2: Disallow forbidden characters
-
Pros: Exported .csv files are guaranteed to be in the correct format.
-
Cons: Data fields are restricted and cannot have commas, semi-colons, etc.
-
Import
The import commands work by reading a .csv file and converting it into a list of Patient
objects by using CsvUtil
. The list is then passed to Model
. What happens next depends
on which variant of import is called.
For both variants of the command, the imported list of patients CANNOT have any duplicates.
This is ensured with CsvUtil#importsContainDupes(List<Patient>)
.
Command: app-import-replace
The Model
will replace all existing Patient
data in the PatientBook
with the data
of the new list of Patient
objects. To do this, the following was implemented:
-
Model#replaceStagedPatientBook(List<Patient>)
— Creates a newPatientBook
object containing thePatient
objects in the provided list. The oldPatientBook
stored in theModel
is then replaced with the newPatientBook
by callingModel#setStagedPatientBook(PatientBook)
.
Command app-import-merge
The Model
will add all Patient
data in the new list of Patient
objects into the
PatientBook
. To do this, the following was implemented:
-
Model#hasAnyPatientInGivenList(List<Patient>)
— Checks if the model contains anyPatient
in the given list ofPatient
objects. -
Model#addPatients(List<Patient>)
— Adds allPatient
objects in the given list into theModel
.
If the operation will result in duplicate Patient
objects in the PatientBook
,
it will not be executed. This is checked by the function stated above,
Model#hasAnyPatientInGivenList(List<Patient>)
.
Import Design Considerations
Aspect: Allowing Patient Overriding for app-import-merge
-
Alternative 1 (current choice): Disallow overriding.
-
Pros: Existing
Patient
data will not be accidentally overridden. No need to deal with potential merge conflicts. -
Cons: User may have intended to use
app-import-merge
to update old data. More hassle for the user to delete oldPatient
data that they want to replace.
-
-
Alternative 2: In case of duplicates, replace old
Patient
data.-
Pros: Conveniently update old
Patient
data. -
Cons: May accidentally override and lose important data, though not a big deal with
app-undo
.
-
-
Alternative 3: Implement a flag to toggle overriding.
-
Pros: Best of both worlds.
-
Cons: More coding and debugging work.
-