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.csvlibrary. 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’sAnnotationfeature. 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.0andv1.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.csvwill 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
CsvMapperis responsible for managing custom configurations for the conversions. For instance, it can toggle headers withwithHeader()and skip unknown fields with theIGNORE_UNKNOWNfeature, both of which are used in the feature implementation. -
The
CsvSchemaobject is created by a configuredCsvMapperobject 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 ofPatientobjects into a .csv file to the path at the specifiedpathString. -
CstUtil#readPatientsFromCsv(String)— Read a .csv file at the specified path indicated bypathStringand return a corresponding list ofPatientobjects. -
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.csvlibrary.-
Pros: Well integrated with the existing
JacksonJSON 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
Jacksonlibraries 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 ofPatientobjects corresponding to the provided indexes from thePatientBook, if the indexes are valid. -
PatientBook#GetPatientByIndex(Index)— Returns thePatientobject 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 newPatientBookobject containing thePatientobjects in the provided list. The oldPatientBookstored in theModelis then replaced with the newPatientBookby 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 anyPatientin the given list ofPatientobjects. -
Model#addPatients(List<Patient>)— Adds allPatientobjects 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
Patientdata will not be accidentally overridden. No need to deal with potential merge conflicts. -
Cons: User may have intended to use
app-import-mergeto update old data. More hassle for the user to delete oldPatientdata that they want to replace.
-
-
Alternative 2: In case of duplicates, replace old
Patientdata.-
Pros: Conveniently update old
Patientdata. -
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.
-