From 792d293dd40f44da86b721a16b51bce56ffb04e4 Mon Sep 17 00:00:00 2001 From: Mehul Ahal <112100480+MehulAhal@users.noreply.github.com> Date: Thu, 12 Jan 2023 23:50:28 +0100 Subject: [PATCH] added docs --- README.md | 42 ++++++++++++++++++ docs/ClassUML.png | Bin 0 -> 850030 bytes src/Main.java | 21 ++++++++- src/apis/DatabaseApi.java | 16 ++++++- src/data/dtos/QueryDTO.java | 8 +++- .../enums/CustomPreparedStatementsRead.java | 1 - src/data/models/PersistentResultSetModel.java | 24 ++++++++++ src/data/repos/QueryResultsRepository.java | 11 ++++- src/services/AppConfigService.java | 8 +++- src/services/DatabaseService.java | 6 ++- src/services/ReportGenerationService.java | 14 +++++- .../constants => utils}/ConstFormatters.java | 2 +- .../constants => utils}/ConstValues.java | 2 +- 13 files changed, 139 insertions(+), 16 deletions(-) create mode 100644 docs/ClassUML.png rename src/{data/constants => utils}/ConstFormatters.java (87%) rename src/{data/constants => utils}/ConstValues.java (87%) diff --git a/README.md b/README.md index 8fcc6af..34609f8 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,45 @@ Please use this readme as your projects readme. You can find instructions for the assignment in the [`INSTRUCTIONS.md`](INSTRUCTIONS.md) file. + +Overview +======== + +This project is a simple command-line application that communicates with a PostgreSQL database to retrieve data and generate reports based on that data. It's composed of several classes and packages that work together to accomplish this task. + +Classes and packages +-------------------- + +The application's main class is `Main` class, it runs the entire application. It's composed of three services: `AppConfigService`, `DatabaseService`, and `ReportGenerationService`. + +### AppConfigService + +`AppConfigService` is a service class that prompts and stores the configuration that the app needs to be run with. It prompts the user for input for the country name and date, and stores them as class members. + +### DatabaseService + +`DatabaseService` class is responsible for maintaining the active connection between the app and the SQL Server. It also communicates with the `DatabaseApi` class to perform final CRUD operations and return any results. + +### ReportGenerationService + +`ReportGenerationService` generates a report from results. Since only a std-out is the only strategy, composition is preferred. It provides a single method `reportBaseResults(QueryResultsRepository queryResultsRepository)` that takes a `QueryResultsRepository` object as input and prints the results to the console. The method prints the `toString()` representation of the `QueryResultsRepository` object. It provides a basic printer and more members can be added in the future to use different strategies for printing out the received results. + +### data.dtos + +`data.dtos` package contains the `QueryDTO` class. This class serves as a container for storing SQL statements to be executed, along with their arguments. + +### data.enums + +`data.enums` package contains the `CustomPreparedStatementsRead` enum. This enum contains all the read-only prepared statements that are used throughout the application. + +### data.repos + +`data.repos` package contains the `QueryResultsRepository` class. This class stores the results of the executed queries, and can be used to generate a report. + +### data.models + +`data.models` package contains the `PersistentResultSetModel` class. This class adapts a given `ResultSet` to a `PersistentResultModel`. + +### apis + +`apis` package contains the `DatabaseApi` class. This class communicates with the database to perform final CRUD operations, returning any results. This class is responsible for executing SQL statements, which are passed to it in the form of a QueryDTO class. It receives a QueryDTO object and a JDBC connection, then it processes the query and returns a PreparedStatement object. This class is designed to handle any exception that may occur during the execution of the query and it can be extended in the future to handle other types of queries if needed. diff --git a/docs/ClassUML.png b/docs/ClassUML.png new file mode 100644 index 0000000000000000000000000000000000000000..3535f4b8a241bd70e6b4398c9543623c4073a4c6 GIT binary patch literal 850030 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