diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..cbab909
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,82 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/)
+and this project adheres to [Semantic Versioning](http://semver.org/).
+
+## [Unreleased]
+
+### Added
+
+### Changed
+
+### Fixed
+
+## [6.0.0] - 2024-01-14
+
+### Added
+
+- Added PostgreSQL support.
+- Added tools-scripts (bat/sh).
+- Added license.
+
+### Changed
+
+- Removed datastore selection on startup.
+- Removed editing date addition and added sorting of parameters by key in properties file.
+- Made refactoring.
+
+### Fixed
+
+- Fixed several bugs.
+
+## [5.0.0] - around 2022-08-22
+
+### Added
+
+- Added import data from file and export data to file for different formats : xml, yaml, json, csv, bser, ser.
+
+### Changed
+
+- Made refactoring using features from java 17.
+
+### Fixed
+
+- Fixed several bugs.
+
+## [4.0.0] - around 2022-04-10
+
+### Changed
+
+- Made clean up, improved and refactored code.
+
+### Fixed
+
+- Fixed several bugs.
+
+## [3.0.0] - around 2021-07-24
+
+### Changed
+
+- The operation logic of saving data has been changed: now saving data to database occurs after pressing the save button.
+
+### Fixed
+
+- Fixed several bugs.
+
+## [2.0.0] - around 2021-07-21
+
+### Added
+
+- Added SQLite database file chooser.
+
+### Fixed
+
+- Fixed several bugs.
+
+## [1.0.0] - 2021-07-11
+
+### Added
+
+- Added base version that works with one internal SQLite database file.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index e0d0d38..be55458 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,48 @@
-# Vehicle_accounting
+[![Apache 2.0](https://img.shields.io/github/license/m1ra9e/gui-swing.svg)](http://www.apache.org/licenses/LICENSE-2.0)
-## Version description
+# Gui-swing
+
+GUI application for working with the vehicle database and the ability to import and export data to files.
+
+* Supported databases: SQLite, PostgreSQL.
+
+* Supported import and export formats: xml, yaml, jsom, csv, bser, ser.
+
+## Build
+
+Build requires Java (JDK) 17+ and Apache Maven 3.8+.
+
+```sh
+git clone https://github.com/m1ra9e/gui-swing.git gui-swing
+cd gui-swing
+mvn clean package
+```
+
+## Run
+
+For run the application, execute [run.bat](tools/run.bat) on Windows or [run.sh](tools/run.sh) on Linux.
+
+## Test
+
+For test with local PostgreSQL fill [pg_test_settings.properties](src/test/resources/home/db/pg_test_settings.properties) by own data.
+
+For run tests, execute [test.bat](tools/test.bat) on Windows or [test.sh](tools/test.sh) on Linux.
+
+## Changelog
+
+[Changelog information](CHANGELOG.md)
+
+
+### Short version description
| version | description |
| ------- | ----------- |
-| 1.0.0 | work with one internal db |
-| 2.0.0 | db chooser |
-| 3.0.0 | save data after push button |
-| 4.0.0 | improve and refactoring |
+| 6.0.0 | added PostgreSQL, removed choose data store on start, date and sorting in properties-file, added tools-scripts, refactoring, added license |
| 5.0.0 | java_17, import and export |
+| 4.0.0 | improve and refactoring |
+| 3.0.0 | save data after push button |
+| 2.0.0 | db chooser |
+| 1.0.0 | work with one internal db |
## Plans
diff --git a/pom.xml b/pom.xml
index b10e990..67d7452 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
homevehicle
- 5.0.0
+ 6.0.0jar
@@ -30,6 +30,11 @@
sqlite-jdbc3.34.0
+
+ org.postgresql
+ postgresql
+ 42.3.4
+ org.yamlsnakeyaml
@@ -58,7 +63,7 @@
org.junit.jupiterjunit-jupiter
- 5.8.1
+ 5.9.3test
diff --git a/src/main/java/home/Const.java b/src/main/java/home/Const.java
new file mode 100644
index 0000000..fec94f3
--- /dev/null
+++ b/src/main/java/home/Const.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home;
+
+public final class Const {
+
+ public static final String EMPTY_STRING = "";
+
+ private Const() {
+ }
+}
diff --git a/src/main/java/home/Data.java b/src/main/java/home/Data.java
index e89b56e..564b37d 100644
--- a/src/main/java/home/Data.java
+++ b/src/main/java/home/Data.java
@@ -1,36 +1,63 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home;
import java.io.IOException;
import java.sql.SQLException;
+import javax.swing.JOptionPane;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import home.db.DbInitializer;
-import home.db.dao.DaoSQLite;
+import home.db.conn.Connector;
+import home.db.dao.Dao;
+import home.db.init.DbInitializer;
import home.gui.DataActionInGui;
import home.gui.Gui;
-import home.gui.component.CustomJFileChooserDb;
-import home.gui.component.CustomJFileChooserDb.ChooserDbOperation;
-import home.utils.ThreadUtil;
+import home.gui.GuiConst;
import home.utils.LogUtils;
+import home.utils.ThreadUtil;
+import home.utils.Utils;
final class Data {
private static final Logger LOG = LoggerFactory.getLogger(Data.class);
static void initDb() {
- if (Settings.hasPathToDbFile()) {
+ if (!Settings.hasDatabase()) {
+ return;
+ }
+
+ int dialogContinuePreviousDbResult = JOptionPane.showConfirmDialog(null,
+ GuiConst.PREVIOUS_DATABASE_TEXT.formatted(Utils.generateDbDescription()),
+ GuiConst.PREVIOUS_DATABASE_TITLE, JOptionPane.YES_NO_OPTION);
+ if (dialogContinuePreviousDbResult == JOptionPane.YES_OPTION) {
readDataFromDb();
- } else {
- try {
- CustomJFileChooserDb.createAndShowChooser(null,
- ChooserDbOperation.CREATE_OR_OPEN);
- readDataFromDb();
- Gui.INSTANCE.setDbLabel(Settings.getDbFilePath());
- } catch (IOException e) {
- throw new IllegalStateException("Error while create/open DB file.", e);
- }
+ return;
+ }
+
+ try {
+ Connector.resetConnectionDataAndSettings();
+ Gui.INSTANCE.setDbLabel(GuiConst.DATABASE_NOT_SELECTED);
+ JOptionPane.showMessageDialog(null, GuiConst.REMOVED_PREVIOUS_CONNECTION_TEXT,
+ GuiConst.REMOVED_PREVIOUS_CONNECTION_TITLE, JOptionPane.INFORMATION_MESSAGE);
+ } catch (IOException e) {
+ throw LogUtils.logAndCreateIllegalStateException(
+ "Error while removing connection to previous database.", LOG, e);
}
}
@@ -39,7 +66,7 @@ private static void readDataFromDb() {
Thread.currentThread().setName("-> read data from database");
try {
DbInitializer.createTableIfNotExists();
- DataActionInGui.init(DaoSQLite.getInstance().readAll());
+ DataActionInGui.init(Dao.readAll());
} catch (SQLException e) {
String errorMsg = "Error while read data from database: " + e.getMessage();
LogUtils.logAndShowError(LOG, null, errorMsg, "Data reading error", e);
diff --git a/src/main/java/home/IConsts.java b/src/main/java/home/IConsts.java
deleted file mode 100644
index 8136e3e..0000000
--- a/src/main/java/home/IConsts.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package home;
-
-public interface IConsts {
-
- String EMPTY_STRING = "";
-}
diff --git a/src/main/java/home/Main.java b/src/main/java/home/Main.java
index 6bb4327..5390c34 100644
--- a/src/main/java/home/Main.java
+++ b/src/main/java/home/Main.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home;
import java.lang.Thread.UncaughtExceptionHandler;
@@ -45,7 +60,7 @@ private static void startApplication() {
}
private static void setUncaughtExceptionProcessing() {
- UncaughtExceptionHandler handler = new UncaughtExceptionHandler() {
+ var handler = new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
LogUtils.logAndShowError(LOG, null, e.getMessage(), "Error", e);
diff --git a/src/main/java/home/Settings.java b/src/main/java/home/Settings.java
index 529bea7..c744fa0 100644
--- a/src/main/java/home/Settings.java
+++ b/src/main/java/home/Settings.java
@@ -1,21 +1,46 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
+import java.sql.SQLException;
import java.util.Locale;
-import java.util.Properties;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Function;
+import home.db.DbType;
import home.gui.ColorSchema;
+import home.utils.CustomProperties;
public final class Settings {
public enum Setting {
- STYLE("style", ColorSchema.CROSSPLATFORM.name().toLowerCase(Locale.ROOT)),
- DB_FILE_PATH("db_file_path", IConsts.EMPTY_STRING);
+ AUTO_RESIZE_TABLE_WIDTH("gui.auto_resize_table_width", "false"),
+ DATABASE("db.database", Const.EMPTY_STRING),
+ DATABASE_TYPE("db.type", Const.EMPTY_STRING),
+ HOST("db.host", Const.EMPTY_STRING),
+ PASSWORD("db.password", Const.EMPTY_STRING),
+ PORT("db.port", Const.EMPTY_STRING),
+ USER("db.user", Const.EMPTY_STRING),
+ STYLE("gui.style", ColorSchema.CROSSPLATFORM.name().toLowerCase(Locale.ROOT));
private final String name;
private final String defaultValue;
@@ -34,49 +59,127 @@ public String getDefaultValue() {
}
}
+ public enum ResetType {
+ SET_DEFAULT, CLEAR;
+ }
+
private static final String SETTINGS_FILE_NAME = "settings.properties";
- private static final Properties SETTINGS = new Properties();
+ private static final CustomProperties SETTINGS = new CustomProperties();
public static String getStyle() {
return get(Setting.STYLE);
}
- public static String getDbFilePath() {
- return get(Setting.DB_FILE_PATH);
+ public static boolean isAutoResizeTableWidth() {
+ return Boolean.parseBoolean(get(Setting.AUTO_RESIZE_TABLE_WIDTH));
+ }
+
+ public static DbType getDatabaseType() throws SQLException {
+ String databaseTypeStr = get(Setting.DATABASE_TYPE);
+ return DbType.getDbType(databaseTypeStr);
}
- public static boolean hasPathToDbFile() {
- String dbFilePath = get(Setting.DB_FILE_PATH);
- return dbFilePath != null && !dbFilePath.isBlank();
+ public static String getHost() {
+ return get(Setting.HOST);
+ }
+
+ public static int getPort() throws SQLException {
+ String port = get(Setting.PORT);
+ try {
+ return Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ throw new SQLException("Incorrect value of parameter %s: %s"
+ .formatted(Setting.PORT, port));
+ }
+ }
+
+ public static String getDatabase() {
+ return get(Setting.DATABASE);
+ }
+
+ public static String getUser() {
+ return get(Setting.USER);
+ }
+
+ public static String getPassword() {
+ return get(Setting.PASSWORD);
+ }
+
+ public static boolean hasDatabase() {
+ String database = get(Setting.DATABASE);
+ return database != null && !database.isBlank();
}
private static String get(Setting setting) {
return SETTINGS.getProperty(setting.getName());
}
- public static void writeSetting(Setting setting, String value) throws IOException {
+ public static void saveStyle(String style) throws IOException {
+ saveSetting(Setting.STYLE, style);
+ }
+
+ public static void saveAutoResizeTableWidth(boolean isAutoResizeTableWidth) throws IOException {
+ saveSetting(Setting.AUTO_RESIZE_TABLE_WIDTH, String.valueOf(isAutoResizeTableWidth));
+ }
+
+ public static void saveDatabaseType(String databaseType) throws IOException {
+ saveSetting(Setting.DATABASE_TYPE, databaseType);
+ }
+
+ public static void saveDatabase(String database) throws IOException {
+ saveSetting(Setting.DATABASE, database);
+ }
+
+ private static void saveSetting(Setting setting, String value) throws IOException {
SETTINGS.setProperty(setting.getName(), value);
- try (OutputStream outputStream = new FileOutputStream(SETTINGS_FILE_NAME)) {
- SETTINGS.store(outputStream, null);
+ writeSettings();
+ readSettings();
+ }
+
+ public static void saveDbConnSettings(String host, String port,
+ String dbName, String user, String pass, String dbType) throws IOException {
+ saveSettings(Map.ofEntries(
+ Map.entry(Setting.HOST, host),
+ Map.entry(Setting.PORT, port),
+ Map.entry(Setting.DATABASE, dbName),
+ Map.entry(Setting.USER, user),
+ Map.entry(Setting.PASSWORD, pass),
+ Map.entry(Setting.DATABASE_TYPE, dbType)));
+ }
+
+ public static void saveSettings(Map settingsMap) throws IOException {
+ for (Entry settingEntry : settingsMap.entrySet()) {
+ SETTINGS.setProperty(settingEntry.getKey().getName(), settingEntry.getValue());
+ }
+ writeSettings();
+ readSettings();
+ }
+
+ private static void writeSettings() {
+ try (var outputStream = new FileOutputStream(SETTINGS_FILE_NAME)) {
+ SETTINGS.store(outputStream);
} catch (IOException e) {
throw new IllegalStateException("Error while filling the settings file: "
+ SETTINGS_FILE_NAME, e);
}
- readSettings();
}
public static void readSettings() {
- try (var inputStream = new FileInputStream(getSettingsPath())) {
+ readSettings(SETTINGS_FILE_NAME);
+ }
+
+ public static void readSettings(String settingsFileName) {
+ try (var inputStream = new FileInputStream(getSettingsPath(settingsFileName))) {
SETTINGS.load(inputStream);
} catch (IOException e) {
throw new IllegalStateException("Error while reading settings from file: "
- + SETTINGS_FILE_NAME, e);
+ + settingsFileName, e);
}
}
- private static String getSettingsPath() {
+ private static String getSettingsPath(String settingsFileName) {
try {
- File file = new File(SETTINGS_FILE_NAME);
+ var file = new File(settingsFileName);
if (!file.exists()) {
file.createNewFile();
fillWithDefaultSettings();
@@ -84,19 +187,40 @@ private static String getSettingsPath() {
return file.getAbsolutePath();
} catch (IOException e) {
throw new IllegalStateException("Error while creating the settings file: "
- + SETTINGS_FILE_NAME, e);
+ + settingsFileName, e);
}
}
private static void fillWithDefaultSettings() {
- try (OutputStream outputStream = new FileOutputStream(SETTINGS_FILE_NAME)) {
- SETTINGS.setProperty(Setting.STYLE.getName(), Setting.STYLE.getDefaultValue());
- SETTINGS.setProperty(Setting.DB_FILE_PATH.getName(), Setting.DB_FILE_PATH.getDefaultValue());
- SETTINGS.store(outputStream, null);
- } catch (IOException e) {
- throw new IllegalStateException("Error while filling the settings file: "
- + SETTINGS_FILE_NAME, e);
+ for (Setting setting : Setting.values()) {
+ SETTINGS.setProperty(setting.getName(), setting.getDefaultValue());
+ }
+ writeSettings();
+ }
+
+ // clearing DB settings is used only if the user wants to work
+ // with a new DB when the application starts
+ public static void resetDbSettings(ResetType resetType) throws IOException {
+ String styleValue = getStyle();
+ String isAutoResizeTableWidthValue = get(Setting.AUTO_RESIZE_TABLE_WIDTH);
+
+ Function getValueFnc = getSettingValueFunction(resetType);
+ for (Setting setting : Setting.values()) {
+ SETTINGS.setProperty(setting.getName(), getValueFnc.apply(setting));
}
+
+ SETTINGS.setProperty(Setting.STYLE.getName(), styleValue);
+ SETTINGS.setProperty(Setting.AUTO_RESIZE_TABLE_WIDTH.getName(), isAutoResizeTableWidthValue);
+
+ writeSettings();
+ readSettings();
+ }
+
+ private static Function getSettingValueFunction(ResetType resetType) {
+ return switch (resetType) {
+ case SET_DEFAULT -> setting -> setting.getDefaultValue();
+ case CLEAR -> setting -> Const.EMPTY_STRING;
+ };
}
private Settings() {
diff --git a/src/main/java/home/Storage.java b/src/main/java/home/Storage.java
index aab320b..b649fbc 100644
--- a/src/main/java/home/Storage.java
+++ b/src/main/java/home/Storage.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home;
import java.util.HashSet;
diff --git a/src/main/java/home/db/Connector.java b/src/main/java/home/db/Connector.java
deleted file mode 100644
index 9ed2779..0000000
--- a/src/main/java/home/db/Connector.java
+++ /dev/null
@@ -1,81 +0,0 @@
-
-package home.db;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Properties;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import home.Settings;
-import home.utils.LogUtils;
-
-public final class Connector {
-
- private static final Logger LOG = LoggerFactory.getLogger(Connector.class);
-
- private static final String QUERY_TIMEOUT = "30";
-
- private static final String JDBC_DRIVER_POSTGRESQL = "org.postgresql.Driver";
- private static final String URL_POSTGRESQL = "jdbc:postgresql://%s:%s/%s";
-
- private static final String JDBC_DRIVER_SQLITE = "org.sqlite.JDBC";
- private static final String URL_SQLITE = "jdbc:sqlite:%s";
-
- // TODO add PostgreSQL
- public static Connection getConnectionToPostgreSQL(String host, String port,
- String dbName, String user, String password) throws SQLException {
- String url = generatePostgreSqlURL(host, port, dbName);
-
- Properties props = new Properties();
- props.setProperty("user", user);
- props.setProperty("password", password);
- props.setProperty("reWriteBatchedInserts", "true");
- props.setProperty("loginTimeout", QUERY_TIMEOUT);
- props.setProperty("connectTimeout", QUERY_TIMEOUT);
- props.setProperty("cancelSignalTimeout", QUERY_TIMEOUT);
- props.setProperty("socketTimeout", QUERY_TIMEOUT);
-
- return getConnection(url, props, JDBC_DRIVER_POSTGRESQL);
- }
-
- private static String generatePostgreSqlURL(String host, String port, String dbName) {
- String db;
- try {
- db = URLEncoder.encode(dbName, "UTF-8");
- } catch (UnsupportedEncodingException ex) {
- LOG.error("Encoding error of database name.", ex);
- db = dbName;
- }
- return String.format(URL_POSTGRESQL, host, port, db);
- }
-
- public static Connection getConnectionToSQLite() throws SQLException {
- return getConnection(String.format(URL_SQLITE, Settings.getDbFilePath()),
- new Properties(), JDBC_DRIVER_SQLITE);
- }
-
- private static Connection getConnection(String url, Properties props, String jdbcDriver)
- throws SQLException {
- try {
- Class.forName(jdbcDriver);
-
- // Driver driver = (Driver)
- // Class.forName(jdbcDriver).newInstance();
- // DriverManager.registerDriver(driver);
-
- return DriverManager.getConnection(url, props);
- } catch (ClassNotFoundException e) {
- throw LogUtils.logAndCreateSqlException("Database driver class not found.", LOG, e);
- } catch (SQLException e) {
- throw LogUtils.logAndCreateSqlException("Error while connecting to the database.", LOG, e);
- }
- }
-
- private Connector() {
- }
-}
diff --git a/src/main/java/home/db/DbInitializer.java b/src/main/java/home/db/DbInitializer.java
deleted file mode 100644
index 6da5858..0000000
--- a/src/main/java/home/db/DbInitializer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package home.db;
-
-import java.io.File;
-import java.io.IOException;
-import java.sql.SQLException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import home.Settings;
-import home.Settings.Setting;
-
-public final class DbInitializer {
-
- private static final Logger LOG = LoggerFactory.getLogger(DbInitializer.class);
-
- private static final String CREATE_TBL_QUERY = """
- CREATE TABLE IF NOT EXISTS vehicle (
- 'id' INTEGER PRIMARY KEY AUTOINCREMENT,
- 'type' TEXT,
- 'color' TEXT,
- 'number' TEXT,
- 'is_transports_cargo' INTEGER,
- 'is_transports_passengers' INTEGER,
- 'has_trailer' INTEGER,
- 'has_cradle' INTEGER,
- 'date_time' INTEGER);""";
-
- public static void createDbFileIfNotExists(File file) throws IOException {
- try {
- if (!file.exists()) {
- file.createNewFile();
- }
- Settings.writeSetting(Setting.DB_FILE_PATH, file.getAbsolutePath());
- } catch (IOException e) {
- LOG.error("Error while creating the database file.", e);
- throw new IOException("Error while creating the database file.", e);
- }
- }
-
- public static void createTableIfNotExists() throws SQLException {
- try (var conn = Connector.getConnectionToSQLite();
- var stmt = conn.createStatement()) {
- stmt.execute(CREATE_TBL_QUERY);
- }
- }
-
- private DbInitializer() {
- }
-}
diff --git a/src/main/java/home/db/DbType.java b/src/main/java/home/db/DbType.java
new file mode 100644
index 0000000..580f283
--- /dev/null
+++ b/src/main/java/home/db/DbType.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db;
+
+import java.sql.SQLException;
+
+public enum DbType {
+
+ // TODO add support for MS SQL Server
+ // MS_SQL_Server("com.microsoft.sqlserver.jdbc.SQLServerDriver",
+ // "jdbc:sqlserver://%s:%d;DatabaseName=%s"),
+ PostgreSQL("org.postgresql.Driver", "jdbc:postgresql://%s:%d/%s"),
+ SQLite("org.sqlite.JDBC", "jdbc:sqlite:%s");
+
+ private final String jdbcDriver;
+ private final String url;
+
+ private DbType(String jdbcDriver, String url) {
+ this.jdbcDriver = jdbcDriver;
+ this.url = url;
+ }
+
+ public String getJdbcDriver() {
+ return jdbcDriver;
+ }
+
+ /**
+ * Gets the URL of the database
+ *
+ *
+ *
+ * @param args database url parameters
+ * @return database url
+ */
+ public String getUrl(Object... args) {
+ return url.formatted(args);
+ }
+
+ public boolean in(DbType... dbTypes) {
+ for (var dbType : dbTypes) {
+ if (this == dbType) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static DbType getDbType(String type) throws SQLException {
+ String typeFormatted = type.strip();
+ for (DbType dbType : DbType.values()) {
+ if (typeFormatted.equalsIgnoreCase(dbType.name())) {
+ return dbType;
+ }
+ }
+
+ throw new SQLException("Unsupported database type : " + type);
+ }
+}
diff --git a/src/main/java/home/db/conn/AbstractConnectionDataHelper.java b/src/main/java/home/db/conn/AbstractConnectionDataHelper.java
new file mode 100644
index 0000000..3b3eb23
--- /dev/null
+++ b/src/main/java/home/db/conn/AbstractConnectionDataHelper.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.conn;
+
+import java.util.Properties;
+
+import home.db.DbType;
+
+abstract sealed class AbstractConnectionDataHelper permits PgConnectionDataHelper, SQLiteConnectionDataHelper {
+
+ ConnectionData getConnectionData() {
+ String url = getUrl();
+ Properties connProps = getConnectionProps();
+ DbType dbType = getDbType();
+ return new ConnectionData(url, connProps, dbType.getJdbcDriver());
+ }
+
+ protected abstract DbType getDbType();
+
+ protected abstract String getUrl();
+
+ protected abstract Properties getConnectionProps();
+}
diff --git a/src/main/java/home/db/conn/ConnectionData.java b/src/main/java/home/db/conn/ConnectionData.java
new file mode 100644
index 0000000..a8469cd
--- /dev/null
+++ b/src/main/java/home/db/conn/ConnectionData.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.conn;
+
+import java.util.Properties;
+
+record ConnectionData(String url, Properties connProps, String jdbcDriver) {
+}
diff --git a/src/main/java/home/db/conn/Connector.java b/src/main/java/home/db/conn/Connector.java
new file mode 100644
index 0000000..694f92b
--- /dev/null
+++ b/src/main/java/home/db/conn/Connector.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.conn;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import home.Settings;
+import home.Settings.ResetType;
+import home.db.DbType;
+import home.gui.GuiConst;
+import home.utils.LogUtils;
+
+public final class Connector {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Connector.class);
+
+ private static ConnectionData connectionData;
+
+ // resetting the connection settings cache is used only when changing the DB
+ public static void resetConnectionDataAndSettings() throws IOException {
+ Settings.resetDbSettings(ResetType.CLEAR);
+ connectionData = null;
+ }
+
+ public static boolean testConnection(String host, int port, String dbName,
+ String user, String pass, DbType dbType) throws SQLException {
+ if (dbType == DbType.PostgreSQL) {
+ ConnectionData connectionData = new PgConnectionDataHelper(host, port, dbName, user, pass)
+ .getConnectionData();
+ return testConnection(connectionData);
+ }
+
+ throw new SQLException(GuiConst.CONNECTION_TEST_SUPPORT_ERROR_TEXT.formatted(dbType));
+ }
+
+ public static boolean testCurrentConnection() throws SQLException {
+ ConnectionData connData = getConnectionData();
+ return testConnection(connData);
+ }
+
+ private static boolean testConnection(ConnectionData connData) throws SQLException {
+ try (Connection conn = getConnection(connData)) {
+ return true;
+ } catch (SQLException e) {
+ throw new SQLException(GuiConst.CONNECTION_TEST_ERROR_TEXT.formatted(e.getMessage()), e);
+ }
+ }
+
+ public static Connection getConnection() throws SQLException {
+ ConnectionData connData = getConnectionData();
+ return getConnection(connData);
+ }
+
+ private static ConnectionData getConnectionData() throws SQLException {
+ if (connectionData != null) {
+ return connectionData;
+ }
+
+ DbType dbType = Settings.getDatabaseType();
+
+ AbstractConnectionDataHelper connectionDataHelper = switch (dbType) {
+ case PostgreSQL -> new PgConnectionDataHelper(Settings.getHost(),
+ Settings.getPort(), Settings.getDatabase(),
+ Settings.getUser(), Settings.getPassword());
+ case SQLite -> new SQLiteConnectionDataHelper(Settings.getDatabase());
+ };
+
+ connectionData = connectionDataHelper.getConnectionData();
+
+ return connectionData;
+ }
+
+ private static Connection getConnection(ConnectionData connData) throws SQLException {
+ return getConnection(connData.url(), connData.connProps(), connData.jdbcDriver());
+ }
+
+ private static Connection getConnection(String url, Properties props, String jdbcDriver)
+ throws SQLException {
+ try {
+ Class.forName(jdbcDriver);
+
+ // Driver driver = (Driver) Class.forName(jdbcDriver).newInstance();
+ // DriverManager.registerDriver(driver);
+
+ return DriverManager.getConnection(url, props);
+ } catch (ClassNotFoundException e) {
+ throw LogUtils.logAndCreateSqlException("Database driver class not found.", LOG, e);
+ } catch (SQLException e) {
+ throw LogUtils.logAndCreateSqlException("Error while connecting to the database. %s"
+ .formatted(e.getMessage()), LOG, e);
+ }
+ }
+
+ private Connector() {
+ }
+}
diff --git a/src/main/java/home/db/conn/MsConnectionDataHelper.java b/src/main/java/home/db/conn/MsConnectionDataHelper.java
new file mode 100644
index 0000000..5a0c1b9
--- /dev/null
+++ b/src/main/java/home/db/conn/MsConnectionDataHelper.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.conn;
+
+import java.util.Properties;
+
+import home.db.DbType;
+
+// TODO add support for MS SQL Server
+final class MsConnectionDataHelper { // extends AbstractConnectionDataHelper
+
+ private static String QUERY_TIMEOUT = "15"; // sec
+ private static String LOCK_TIMEOUT = "10000"; // ms
+
+ private final String host;
+ private final int port; // default port usually is 1433
+ private final String dbName;
+ private final String user;
+ private final String pass;
+
+ MsConnectionDataHelper(String host, int port, String dbName,
+ String user, String pass) {
+ this.host = host;
+ this.port = port;
+ this.dbName = dbName;
+ this.user = user;
+ this.pass = pass;
+ }
+
+ // @Override
+ protected DbType getDbType() {
+ // DbType.MS_SQL_Server
+ return null;
+ }
+
+ // @Override
+ protected String getUrl() {
+ return getDbType().getUrl(host, port, dbName);
+ }
+
+ // @Override
+ protected Properties getConnectionProps() {
+ var props = new Properties();
+ props.setProperty("user", user);
+ props.setProperty("password", pass);
+ props.setProperty("trustServerCertificate", "true");
+ props.setProperty("queryTimeout", QUERY_TIMEOUT);
+ props.setProperty("lockTimeout", LOCK_TIMEOUT);
+ return props;
+ }
+}
diff --git a/src/main/java/home/db/conn/PgConnectionDataHelper.java b/src/main/java/home/db/conn/PgConnectionDataHelper.java
new file mode 100644
index 0000000..5efc7af
--- /dev/null
+++ b/src/main/java/home/db/conn/PgConnectionDataHelper.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.conn;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import home.db.DbType;
+
+final class PgConnectionDataHelper extends AbstractConnectionDataHelper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PgConnectionDataHelper.class);
+
+ private static final String TIMEOUT = "30"; // sec
+ private static String QUERY_TIMEOUT = "15000"; // ms // without final-modifier because of test
+ private static String LOCK_TIMEOUT = "10000"; // ms // without final-modifier because of test
+
+ private final String host;
+ private final int port; // default port usually is 5432
+ private final String dbName;
+ private final String user;
+ private final String pass;
+
+ PgConnectionDataHelper(String host, int port, String dbName,
+ String user, String pass) {
+ this.host = host;
+ this.port = port;
+ this.dbName = dbName;
+ this.user = user;
+ this.pass = pass;
+ }
+
+ @Override
+ protected DbType getDbType() {
+ return DbType.PostgreSQL;
+ }
+
+ @Override
+ protected String getUrl() {
+ String db;
+ try {
+ db = URLEncoder.encode(dbName, StandardCharsets.UTF_8.toString());
+ } catch (UnsupportedEncodingException ex) {
+ LOG.error("Encoding error of database name.", ex);
+ db = dbName;
+ }
+ return getDbType().getUrl(host, port, db);
+ }
+
+ @Override
+ protected Properties getConnectionProps() {
+ var props = new Properties();
+ props.setProperty("user", user);
+ props.setProperty("password", pass);
+ props.setProperty("reWriteBatchedInserts", "true");
+ props.setProperty("loginTimeout", TIMEOUT);
+ props.setProperty("connectTimeout", TIMEOUT);
+ props.setProperty("cancelSignalTimeout", TIMEOUT);
+ props.setProperty("socketTimeout", TIMEOUT);
+ props.setProperty("options", "-c statement_timeout=%s -c lock_timeout=%s"
+ .formatted(QUERY_TIMEOUT, LOCK_TIMEOUT));
+ return props;
+ }
+}
diff --git a/src/main/java/home/db/conn/SQLiteConnectionDataHelper.java b/src/main/java/home/db/conn/SQLiteConnectionDataHelper.java
new file mode 100644
index 0000000..98b97e2
--- /dev/null
+++ b/src/main/java/home/db/conn/SQLiteConnectionDataHelper.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.conn;
+
+import java.util.Properties;
+
+import home.db.DbType;
+
+final class SQLiteConnectionDataHelper extends AbstractConnectionDataHelper {
+
+ private final String dbName;
+
+ SQLiteConnectionDataHelper(String dbName) {
+ this.dbName = dbName;
+ }
+
+ @Override
+ protected DbType getDbType() {
+ return DbType.SQLite;
+ }
+
+ @Override
+ protected String getUrl() {
+ return getDbType().getUrl(dbName);
+ }
+
+ @Override
+ protected Properties getConnectionProps() {
+ return new Properties();
+ }
+}
diff --git a/src/main/java/home/db/dao/AbstractDao.java b/src/main/java/home/db/dao/AbstractDao.java
index 3f0f51e..9f3d140 100644
--- a/src/main/java/home/db/dao/AbstractDao.java
+++ b/src/main/java/home/db/dao/AbstractDao.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.db.dao;
import java.sql.Connection;
@@ -14,50 +29,69 @@
import java.util.stream.Stream;
import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import home.IConsts;
+import home.Const;
import home.Storage;
+import home.db.conn.Connector;
import home.model.AbstractVehicle;
import home.model.Car;
import home.model.Motorcycle;
import home.model.Truck;
import home.model.VehicleType;
import home.utils.LogUtils;
-
-abstract sealed class AbstractDao implements IDao permits DaoSQLite {
-
- private static final String SELECT_ALL = "SELECT * FROM vehicle;";
-
- private static final String SELECT_ONE = "SELECT * FROM vehicle WHERE id = ?;";
-
- private static final String INSERT = """
- INSERT INTO vehicle
- ('type', 'color', 'number', 'date_time', 'is_transports_cargo',
- 'is_transports_passengers', 'has_trailer', 'has_cradle')
- VALUES (?, ?, ?, ?, ?, ?, ?, ?);""";
-
- private static final String UPDATE = """
- UPDATE vehicle SET
- type = ?, color = ?, number = ?, date_time = ?, is_transports_cargo = ?,
- is_transports_passengers = ?, has_trailer = ?, has_cradle = ?
- WHERE id = ?;""";
-
- private static final String DELETE = "DELETE FROM vehicle WHERE id in (%s);";
-
+import home.utils.NamedFormatter;
+
+abstract sealed class AbstractDao implements IDao permits PgDao, SQLiteDao {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractDao.class);
+
+ private static final String SELECT_ALL = NamedFormatter
+ .format("SELECT * FROM ${table_name}",
+ DaoConst.PLACEHOLDER_VALUES);
+
+ private static final String SELECT_ONE = NamedFormatter
+ .format("SELECT * FROM ${table_name} WHERE ${col_id} = ?",
+ DaoConst.PLACEHOLDER_VALUES);
+
+ // !!! the order of the columns in the INSERT query must be the same as in the
+ // UPDATE query because they both use the fillStmtByDataFromObj method.
+ private static final String INSERT = NamedFormatter.format("""
+ INSERT INTO ${table_name}
+ (${col_type}, ${col_color}, ${col_number}, ${col_date_time},
+ ${col_is_transports_cargo}, ${col_is_transports_passengers},
+ ${col_has_trailer}, ${col_has_cradle})
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+ """, DaoConst.PLACEHOLDER_VALUES);
+
+ // !!! the order of the columns in the UPDATE query must be the same as in the
+ // INSERT query because they both use the fillStmtByDataFromObj method.
+ private static final String UPDATE = NamedFormatter.format("""
+ UPDATE ${table_name} SET
+ ${col_type} = ?, ${col_color} = ?, ${col_number} = ?, ${col_date_time} = ?,
+ ${col_is_transports_cargo} = ?, ${col_is_transports_passengers} = ?,
+ ${col_has_trailer} = ?, ${col_has_cradle} = ?
+ WHERE ${col_id} = ?
+ """, DaoConst.PLACEHOLDER_VALUES);
+
+ private static final String DELETE = NamedFormatter
+ .format("DELETE FROM ${table_name} WHERE ${col_id} ",
+ DaoConst.PLACEHOLDER_VALUES)
+ + "IN (%s)";
+
+ private static final int BATCH_SIZE = 1_000;
+
+ // https://www.ibm.com/docs/en/db2woc?topic=messages-sqlstate
+ // 08 - Connection Exception
private static final String CONNECTION_ERROR_CODE = "08";
- protected AbstractDao() {
- }
-
- protected abstract Connection getConnection() throws SQLException;
+ private static final int FALSE_VALUE_FOR_DB = 0;
protected abstract int getTransactionIsolation();
- protected abstract Logger getLogger();
-
@Override
public AbstractVehicle readOne(long id) throws SQLException {
- try (var conn = getConnection()) {
+ try (var conn = Connector.getConnection()) {
conn.setTransactionIsolation(getTransactionIsolation());
try (var pstmt = conn.prepareStatement(SELECT_ONE)) {
@@ -82,7 +116,7 @@ public AbstractVehicle readOne(long id) throws SQLException {
@Override
public List readAll() throws SQLException {
- try (var conn = getConnection()) {
+ try (var conn = Connector.getConnection()) {
conn.setTransactionIsolation(getTransactionIsolation());
try (var stmt = conn.createStatement();
var res = stmt.executeQuery(SELECT_ALL)) {
@@ -96,40 +130,46 @@ public List readAll() throws SQLException {
}
private AbstractVehicle convertResultToDataObj(ResultSet res) throws SQLException {
- String type = res.getString(IDaoConsts.TYPE);
- VehicleType vehicleType = VehicleType.getVehicleType(type);
- if (vehicleType == null) {
- throw new SQLException("Wrong vehicle type received : " + type);
- }
+ String type = res.getString(DaoConst.TYPE);
+
+ VehicleType vehicleType = getVehicleTypeOrThrowSqlException(type);
AbstractVehicle vehicle = switch (vehicleType) {
case CAR -> {
var car = new Car();
- car.setTransportsPassengers(convertToBoolean(res.getInt(IDaoConsts.IS_TRANSPORTS_PASSENGERS)));
- car.setHasTrailer(convertToBoolean(res.getInt(IDaoConsts.HAS_TRAILER)));
+ car.setTransportsPassengers(convertToBoolean(res.getInt(DaoConst.IS_TRANSPORTS_PASSENGERS)));
+ car.setHasTrailer(convertToBoolean(res.getInt(DaoConst.HAS_TRAILER)));
yield car;
}
case TRUCK -> {
var truck = new Truck();
- truck.setTransportsCargo(convertToBoolean(res.getInt(IDaoConsts.IS_TRANSPORTS_CARGO)));
- truck.setHasTrailer(convertToBoolean(res.getInt(IDaoConsts.HAS_TRAILER)));
+ truck.setTransportsCargo(convertToBoolean(res.getInt(DaoConst.IS_TRANSPORTS_CARGO)));
+ truck.setHasTrailer(convertToBoolean(res.getInt(DaoConst.HAS_TRAILER)));
yield truck;
}
case MOTORCYCLE -> {
var motorcycle = new Motorcycle();
- motorcycle.setHasCradle(convertToBoolean(res.getInt(IDaoConsts.HAS_CRADLE)));
+ motorcycle.setHasCradle(convertToBoolean(res.getInt(DaoConst.HAS_CRADLE)));
yield motorcycle;
}
};
- vehicle.setId(res.getLong(IDaoConsts.ID));
- vehicle.setColor(res.getString(IDaoConsts.COLOR));
- vehicle.setNumber(res.getString(IDaoConsts.NUMBER));
- vehicle.setDateTime(res.getLong(IDaoConsts.DATE_TIME));
+ vehicle.setId(res.getLong(DaoConst.ID));
+ vehicle.setColor(res.getString(DaoConst.COLOR));
+ vehicle.setNumber(res.getString(DaoConst.NUMBER));
+ vehicle.setDateTime(res.getLong(DaoConst.DATE_TIME));
return vehicle;
}
+ private VehicleType getVehicleTypeOrThrowSqlException(String type) throws SQLException {
+ try {
+ return VehicleType.getVehicleType(type);
+ } catch (IllegalArgumentException e) {
+ throw new SQLException(e.getMessage(), e);
+ }
+ }
+
private boolean convertToBoolean(int intBoolean) throws SQLException {
return switch (intBoolean) {
case 0 -> false;
@@ -143,6 +183,7 @@ private boolean convertToBoolean(int intBoolean) throws SQLException {
public void saveAllChanges() throws SQLException {
var exceptions = new ArrayList();
+ // delete operations
try {
Long[] idsForDel = Storage.INSTANCE.getIdsForDelete();
if (idsForDel.length > 0) {
@@ -152,6 +193,7 @@ public void saveAllChanges() throws SQLException {
exceptions.add(new SQLException("DELETE operation error.", e));
}
+ // update operations
try {
Set idsForUpdate = Storage.INSTANCE.getIdsForUpdate();
operation(this::update, dataObj -> dataObj.getId() > 0
@@ -160,6 +202,7 @@ public void saveAllChanges() throws SQLException {
exceptions.add(new SQLException("UPDATE operation error.", e));
}
+ // insert operations
try {
operation(this::insert, dataObj -> dataObj.getId() == 0);
} catch (IllegalStateException e) {
@@ -203,7 +246,7 @@ private void sqlOperationBatch(boolean isUpdateOperation,
List dataObjs, String errorMsg) {
String sql = isUpdateOperation ? UPDATE : INSERT;
- try (var conn = getConnection()) {
+ try (var conn = Connector.getConnection()) {
conn.setAutoCommit(false);
conn.setTransactionIsolation(getTransactionIsolation());
try (var pstmt = conn.prepareStatement(sql)) {
@@ -214,21 +257,22 @@ private void sqlOperationBatch(boolean isUpdateOperation,
pstmt.addBatch();
operationsCount++;
- // Execute every 1_000 items.
- if (operationsCount % 1_000 == 0 || operationsCount == dataObjs.size()) {
+ // Execute every BATCH_SIZE items.
+ if (operationsCount % BATCH_SIZE == 0 || operationsCount == dataObjs.size()) {
checkBatchExecution(pstmt.executeBatch(),
- String.format(errorMsg, dataObj), getLogger());
+ errorMsg.formatted(dataObj), LOG);
conn.commit();
}
}
- conn.setAutoCommit(true);
} catch (SQLException e) {
- String error = String.format(errorMsg, IConsts.EMPTY_STRING);
+ String error = errorMsg.formatted(Const.EMPTY_STRING);
checkConnectionState(e, error);
rollbackAndLog(conn, e, error);
sqlOperationOneByOne(conn, sql, dataObjs, isUpdateOperation, error);
+ } finally {
+ conn.setAutoCommit(true);
}
} catch (SQLException e) {
String operationType = isUpdateOperation ? "UPDATE" : "INSERT";
@@ -265,12 +309,12 @@ void checkBatchExecution(int[] batchResults, String errorMsg, Logger log)
}
private void rollbackAndLog(Connection conn, Exception e, String errorMsg) {
- getLogger().error(errorMsg, e);
+ LOG.error(errorMsg, e);
try {
conn.rollback();
} catch (SQLException ex) {
throw LogUtils.logAndCreateIllegalStateException(
- errorMsg + " Sql rollback error.", getLogger(), e);
+ errorMsg + " Sql rollback error.", LOG, e);
}
}
@@ -278,7 +322,7 @@ private void checkConnectionState(SQLException e, String errorMsg) throws SQLExc
String sqlState = e.getSQLState();
if (sqlState.startsWith(CONNECTION_ERROR_CODE)) {
throw LogUtils.logAndCreateSqlException(
- "%s:\nConnection error (code %s)".formatted(errorMsg, sqlState), getLogger(), e);
+ "%s:\nConnection error (code %s)".formatted(errorMsg, sqlState), LOG, e);
}
}
@@ -307,7 +351,7 @@ private void sqlOperationOneByOne(Connection conn, String sql,
sb.append(errorMsg).append(" Can't ").append(operationType)
.append(":\n").append(String.join("\n", errorsWithDataObjs));
- throw LogUtils.logAndCreateSqlException(sb.toString(), getLogger(), mainExeption);
+ throw LogUtils.logAndCreateSqlException(sb.toString(), LOG, mainExeption);
}
}
@@ -323,17 +367,24 @@ private void fillStmtByDataFromObj(PreparedStatement pstmt, AbstractVehicle data
switch (dataObjType) {
case CAR:
Car car = (Car) dataObj;
+ pstmt.setInt(5, FALSE_VALUE_FOR_DB);
pstmt.setInt(6, convertToInt(car.isTransportsPassengers()));
pstmt.setInt(7, convertToInt(car.hasTrailer()));
+ pstmt.setInt(8, FALSE_VALUE_FOR_DB);
break;
case TRUCK:
Truck truck = (Truck) dataObj;
pstmt.setInt(5, convertToInt(truck.isTransportsCargo()));
+ pstmt.setInt(6, FALSE_VALUE_FOR_DB);
pstmt.setInt(7, convertToInt(truck.hasTrailer()));
+ pstmt.setInt(8, FALSE_VALUE_FOR_DB);
break;
case MOTORCYCLE:
+ pstmt.setInt(5, FALSE_VALUE_FOR_DB);
+ pstmt.setInt(6, FALSE_VALUE_FOR_DB);
+ pstmt.setInt(7, FALSE_VALUE_FOR_DB);
pstmt.setInt(8, convertToInt(((Motorcycle) dataObj).hasCradle()));
break;
}
@@ -349,8 +400,8 @@ private int convertToInt(boolean booleaVal) {
private void delete(Long[] ids) {
String idsStr = Stream.of(ids).map(String::valueOf).collect(Collectors.joining(","));
- String sql = String.format(DELETE, idsStr);
- try (var conn = getConnection()) {
+ String sql = DELETE.formatted(idsStr);
+ try (var conn = Connector.getConnection()) {
conn.setAutoCommit(false);
conn.setTransactionIsolation(getTransactionIsolation());
try (var pstmt = conn.prepareStatement(sql)) {
@@ -359,7 +410,6 @@ private void delete(Long[] ids) {
+ "\n Id list for delete: " + idsStr);
}
conn.commit();
- conn.setAutoCommit(true);
} catch (SQLException e) {
String errorMsg = "Error while removal several rows in one query";
@@ -367,6 +417,8 @@ private void delete(Long[] ids) {
rollbackAndLog(conn, e, errorMsg);
deleteOneByOne(conn, ids);
+ } finally {
+ conn.setAutoCommit(true);
}
} catch (SQLException e) {
throw new IllegalStateException("Sql DELETE operation error : ", e);
@@ -378,13 +430,13 @@ private void deleteOneByOne(Connection conn, Long[] ids) throws SQLException {
var errorsWithIds = new ArrayList();
conn.setAutoCommit(true);
- String sql = String.format(DELETE, "?");
+ String sql = DELETE.formatted("?");
for (Long id : ids) {
try (var pstmt = conn.prepareStatement(sql)) {
pstmt.setLong(1, id);
if (pstmt.executeUpdate() <= 0) {
- errorsWithIds.add(id + IConsts.EMPTY_STRING);
+ errorsWithIds.add(id + Const.EMPTY_STRING);
}
} catch (SQLException e) {
mainExeption = addException(mainExeption, e,
@@ -399,7 +451,7 @@ private void deleteOneByOne(Connection conn, Long[] ids) throws SQLException {
.append("\nCan't delete objects with ids:\n")
.append(String.join("\n", errorsWithIds));
- throw LogUtils.logAndCreateSqlException(sb.toString(), getLogger(), mainExeption);
+ throw LogUtils.logAndCreateSqlException(sb.toString(), LOG, mainExeption);
}
}
diff --git a/src/main/java/home/db/dao/Dao.java b/src/main/java/home/db/dao/Dao.java
new file mode 100644
index 0000000..f7360a3
--- /dev/null
+++ b/src/main/java/home/db/dao/Dao.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.dao;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import home.Settings;
+import home.db.DbType;
+import home.model.AbstractVehicle;
+
+public final class Dao {
+
+ private static IDao dao;
+ private static DbType previousDbType;
+
+ public static List readAll() throws SQLException {
+ return getDao().readAll();
+ }
+
+ @Deprecated(forRemoval = true) // because it uses only in test
+ public static AbstractVehicle readOne(long id) throws SQLException {
+ return getDao().readOne(id);
+ }
+
+ public static void saveAllChanges() throws SQLException {
+ getDao().saveAllChanges();
+ }
+
+ public static void saveAs() throws SQLException {
+ getDao().saveAs();
+ }
+
+ private static IDao getDao() throws SQLException {
+ DbType currentDbType = Settings.getDatabaseType();
+
+ if (dao != null && previousDbType == currentDbType) {
+ return dao;
+ }
+
+ dao = switch (currentDbType) {
+ case SQLite -> new SQLiteDao();
+ case PostgreSQL -> new PgDao();
+ };
+ previousDbType = currentDbType;
+
+ return dao;
+ }
+
+ private Dao() {
+ }
+}
diff --git a/src/main/java/home/db/dao/DaoConst.java b/src/main/java/home/db/dao/DaoConst.java
new file mode 100644
index 0000000..39b20c9
--- /dev/null
+++ b/src/main/java/home/db/dao/DaoConst.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.dao;
+
+import java.util.Map;
+
+final class DaoConst {
+
+ // Table name
+ private static final String DATA_TABLE = "vehicle";
+
+ // The names of the columns in the table
+ static final String ID = "id";
+ static final String TYPE = "type";
+ static final String COLOR = "color";
+ static final String NUMBER = "number";
+ static final String DATE_TIME = "date_time";
+ static final String IS_TRANSPORTS_CARGO = "is_transports_cargo";
+ static final String IS_TRANSPORTS_PASSENGERS = "is_transports_passengers";
+ static final String HAS_TRAILER = "has_trailer";
+ static final String HAS_CRADLE = "has_cradle";
+
+ // Map with values of placeholders for using in NamedFormatter
+ // (key - is placeholder, value - is value for placeholder)
+ static final Map PLACEHOLDER_VALUES = Map.ofEntries(
+ // Table name
+ Map.entry("table_name", DATA_TABLE),
+ // The names of the columns in the table
+ Map.entry("col_id", ID),
+ Map.entry("col_type", TYPE),
+ Map.entry("col_color", COLOR),
+ Map.entry("col_number", NUMBER),
+ Map.entry("col_date_time", DATE_TIME),
+ Map.entry("col_is_transports_cargo", IS_TRANSPORTS_CARGO),
+ Map.entry("col_is_transports_passengers", IS_TRANSPORTS_PASSENGERS),
+ Map.entry("col_has_trailer", HAS_TRAILER),
+ Map.entry("col_has_cradle", HAS_CRADLE));
+
+ private DaoConst() {
+ }
+}
diff --git a/src/main/java/home/db/dao/DaoSQLite.java b/src/main/java/home/db/dao/DaoSQLite.java
deleted file mode 100644
index e544d6b..0000000
--- a/src/main/java/home/db/dao/DaoSQLite.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package home.db.dao;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import home.db.Connector;
-
-public final class DaoSQLite extends AbstractDao {
-
- private static final Logger LOG = LoggerFactory.getLogger(DaoSQLite.class);
-
- private static IDao instance;
-
- private DaoSQLite() {
- }
-
- public static IDao getInstance() {
- if (instance == null) {
- instance = new DaoSQLite();
- }
- return instance;
- }
-
- @Override
- protected Connection getConnection() throws SQLException {
- return Connector.getConnectionToSQLite();
- }
-
- @Override
- protected int getTransactionIsolation() {
- return Connection.TRANSACTION_SERIALIZABLE;
- }
-
- @Override
- protected Logger getLogger() {
- return LOG;
- }
-}
diff --git a/src/main/java/home/db/dao/IDao.java b/src/main/java/home/db/dao/IDao.java
index 587d0ea..9e16214 100644
--- a/src/main/java/home/db/dao/IDao.java
+++ b/src/main/java/home/db/dao/IDao.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.db.dao;
import java.sql.SQLException;
@@ -5,7 +20,7 @@
import home.model.AbstractVehicle;
-public sealed interface IDao permits AbstractDao {
+sealed interface IDao permits AbstractDao {
List readAll() throws SQLException;
diff --git a/src/main/java/home/db/dao/IDaoConsts.java b/src/main/java/home/db/dao/IDaoConsts.java
deleted file mode 100644
index 3fba12b..0000000
--- a/src/main/java/home/db/dao/IDaoConsts.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package home.db.dao;
-
-interface IDaoConsts {
-
- // Table name
- String VEHICLE = "vehicle";
-
- // The names of the columns in the table
- String ID = "id";
- String TYPE = "type";
- String COLOR = "color";
- String NUMBER = "number";
- String IS_TRANSPORTS_CARGO = "is_transports_cargo";
- String IS_TRANSPORTS_PASSENGERS = "is_transports_passengers";
- String HAS_TRAILER = "has_trailer";
- String HAS_CRADLE = "has_cradle";
- String DATE_TIME = "date_time";
-
- // Data types
- String INTEGER = "INTEGER";
- String TEXT = "TEXT";
-}
diff --git a/src/main/java/home/db/dao/PgDao.java b/src/main/java/home/db/dao/PgDao.java
new file mode 100644
index 0000000..512a894
--- /dev/null
+++ b/src/main/java/home/db/dao/PgDao.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.dao;
+
+import java.sql.Connection;
+
+final class PgDao extends AbstractDao {
+
+ @Override
+ protected int getTransactionIsolation() {
+ return Connection.TRANSACTION_READ_COMMITTED;
+ }
+}
diff --git a/src/main/java/home/db/dao/SQLiteDao.java b/src/main/java/home/db/dao/SQLiteDao.java
new file mode 100644
index 0000000..a8c4112
--- /dev/null
+++ b/src/main/java/home/db/dao/SQLiteDao.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.dao;
+
+import java.sql.Connection;
+
+final class SQLiteDao extends AbstractDao {
+
+ @Override
+ protected int getTransactionIsolation() {
+ return Connection.TRANSACTION_SERIALIZABLE;
+ }
+}
diff --git a/src/main/java/home/db/init/AbstractDbInitializer.java b/src/main/java/home/db/init/AbstractDbInitializer.java
new file mode 100644
index 0000000..752b9d1
--- /dev/null
+++ b/src/main/java/home/db/init/AbstractDbInitializer.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.init;
+
+import java.sql.SQLException;
+
+import home.db.conn.Connector;
+
+abstract sealed class AbstractDbInitializer permits PgDbInitializer, SQLiteDbInitializer {
+
+ protected void createTableIfNotExists() throws SQLException {
+ try (var conn = Connector.getConnection();
+ var stmt = conn.createStatement()) {
+ stmt.execute(getTableCreationQuery());
+ }
+ }
+
+ protected abstract String getTableCreationQuery();
+}
diff --git a/src/main/java/home/db/init/DbInitializer.java b/src/main/java/home/db/init/DbInitializer.java
new file mode 100644
index 0000000..bd25db2
--- /dev/null
+++ b/src/main/java/home/db/init/DbInitializer.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.init;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+
+import home.Settings;
+import home.db.DbType;
+
+public final class DbInitializer {
+
+ private static AbstractDbInitializer initializer;
+ private static DbType previousDbType;
+
+ public static void createDbFileIfNotExists(File file) throws IOException, SQLException {
+ Settings.saveDatabaseType(DbType.SQLite.name());
+ ((SQLiteDbInitializer) getInitializer()).createDbFileIfNotExists(file);
+ }
+
+ public static void createTableIfNotExists() throws SQLException {
+ getInitializer().createTableIfNotExists();
+ }
+
+ private static AbstractDbInitializer getInitializer() throws SQLException {
+ DbType currentDbType = Settings.getDatabaseType();
+
+ if (initializer != null && previousDbType == currentDbType) {
+ return initializer;
+ }
+
+ initializer = switch (currentDbType) {
+ case SQLite -> new SQLiteDbInitializer();
+ case PostgreSQL -> new PgDbInitializer();
+ };
+ previousDbType = currentDbType;
+
+ return initializer;
+ }
+
+ private DbInitializer() {
+ }
+}
diff --git a/src/main/java/home/db/init/PgDbInitializer.java b/src/main/java/home/db/init/PgDbInitializer.java
new file mode 100644
index 0000000..af70826
--- /dev/null
+++ b/src/main/java/home/db/init/PgDbInitializer.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.init;
+
+final class PgDbInitializer extends AbstractDbInitializer {
+
+ private static final String CREATE_TABLE_QUERY = """
+ CREATE SEQUENCE IF NOT EXISTS public.vehicle_id_seq
+ AS bigint
+ START WITH 1
+ INCREMENT BY 1
+ NO MAXVALUE
+ NO MINVALUE
+ CACHE 1;
+
+ CREATE TABLE IF NOT EXISTS public.vehicle (
+ id bigint DEFAULT nextval('public.vehicle_id_seq'::regclass) NOT NULL,
+ type character varying(50),
+ color text,
+ number character varying(50),
+ is_transports_cargo integer,
+ is_transports_passengers integer,
+ has_trailer integer,
+ has_cradle integer,
+ date_time bigint,
+ CONSTRAINT vehicle_pkey PRIMARY KEY (id)
+ );
+ """;
+
+ @Override
+ protected String getTableCreationQuery() {
+ return CREATE_TABLE_QUERY;
+ }
+}
diff --git a/src/main/java/home/db/init/SQLiteDbInitializer.java b/src/main/java/home/db/init/SQLiteDbInitializer.java
new file mode 100644
index 0000000..8ad4a43
--- /dev/null
+++ b/src/main/java/home/db/init/SQLiteDbInitializer.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.db.init;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import home.Settings;
+
+final class SQLiteDbInitializer extends AbstractDbInitializer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SQLiteDbInitializer.class);
+
+ private static final String CREATE_TABLE_QUERY = """
+ CREATE TABLE IF NOT EXISTS vehicle (
+ 'id' INTEGER PRIMARY KEY AUTOINCREMENT,
+ 'type' TEXT,
+ 'color' TEXT,
+ 'number' TEXT,
+ 'is_transports_cargo' INTEGER,
+ 'is_transports_passengers' INTEGER,
+ 'has_trailer' INTEGER,
+ 'has_cradle' INTEGER,
+ 'date_time' INTEGER)
+ """;
+
+ @Override
+ protected String getTableCreationQuery() {
+ return CREATE_TABLE_QUERY;
+ }
+
+ void createDbFileIfNotExists(File file) throws IOException {
+ try {
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+ Settings.saveDatabase(file.getAbsolutePath());
+ } catch (IOException e) {
+ LOG.error("Error while creating the database file.", e);
+ throw new IOException("Error while creating the database file.", e);
+ }
+ }
+}
diff --git a/src/main/java/home/file/FileHandler.java b/src/main/java/home/file/FileHandler.java
index 9650e99..752bbeb 100644
--- a/src/main/java/home/file/FileHandler.java
+++ b/src/main/java/home/file/FileHandler.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file;
import java.io.BufferedReader;
diff --git a/src/main/java/home/file/IExporter.java b/src/main/java/home/file/IExporter.java
index fa483b3..fcf19cc 100644
--- a/src/main/java/home/file/IExporter.java
+++ b/src/main/java/home/file/IExporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file;
public interface IExporter {
diff --git a/src/main/java/home/file/IImporter.java b/src/main/java/home/file/IImporter.java
index fc15d1c..668c135 100644
--- a/src/main/java/home/file/IImporter.java
+++ b/src/main/java/home/file/IImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file;
import java.io.File;
diff --git a/src/main/java/home/file/Tag.java b/src/main/java/home/file/Tag.java
index 0d0e08b..af7d0ab 100644
--- a/src/main/java/home/file/Tag.java
+++ b/src/main/java/home/file/Tag.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file;
public enum Tag {
@@ -23,13 +38,14 @@ public String getTagName() {
return tagName;
}
- public static Tag getTag(String tagName) {
+ public static Tag getTag(String tagName, String errorMsg) {
String tagFormatted = tagName.strip();
for (Tag tag : Tag.values()) {
if (tagFormatted.equals(tag.getTagName())) {
return tag;
}
}
- return null;
+
+ throw new IllegalArgumentException(errorMsg.formatted(tagName));
}
}
diff --git a/src/main/java/home/file/csv/CsvConst.java b/src/main/java/home/file/csv/CsvConst.java
new file mode 100644
index 0000000..d742476
--- /dev/null
+++ b/src/main/java/home/file/csv/CsvConst.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.file.csv;
+
+import home.file.Tag;
+
+final class CsvConst {
+
+ static final int TYPE_IDX = 0;
+ static final int COLOR_IDX = 1;
+ static final int NUMBER_IDX = 2;
+ static final int DATE_IDX = 3;
+ static final int HAS_TRAILER_IDX = 4;
+ static final int IS_TRANSPORTS_PASSENGERS_IDX = 5;
+ static final int IS_TRANSPORTS_CARGO_IDX = 6;
+ static final int HAS_CRADLE_IDX = 7;
+
+ static final String[] CSV_HEADER = {
+ Tag.TYPE.getTagName(),
+ Tag.COLOR.getTagName(),
+ Tag.NUMBER.getTagName(),
+ Tag.DATE.getTagName(),
+ Tag.HAS_TRAILER.getTagName(),
+ Tag.IS_TRANSPORTS_PASSENGERS.getTagName(),
+ Tag.IS_TRANSPORTS_CARGO.getTagName(),
+ Tag.HAS_CRADLE.getTagName()
+ };
+
+ static final int CSV_ROW_SIZE = CSV_HEADER.length;
+
+ private CsvConst() {
+ }
+}
diff --git a/src/main/java/home/file/csv/CsvExporter.java b/src/main/java/home/file/csv/CsvExporter.java
index 812dd10..efddbe9 100644
--- a/src/main/java/home/file/csv/CsvExporter.java
+++ b/src/main/java/home/file/csv/CsvExporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.csv;
import java.io.IOException;
@@ -36,7 +51,7 @@ public String exportAllDataObjsToString() {
List dataObjStorage = Storage.INSTANCE.getAll();
var convertedDataObjs = new ArrayList(dataObjStorage.size() + 1);
- convertedDataObjs.add(ICsvConsts.CSV_HEADER);
+ convertedDataObjs.add(CsvConst.CSV_HEADER);
for (AbstractVehicle dataObj : dataObjStorage) {
convertedDataObjs.add(convertDataObjToArray(dataObj));
}
@@ -54,38 +69,38 @@ public String exportAllDataObjsToString() {
}
private String[] convertDataObjToArray(AbstractVehicle dataObj) {
- var array = new String[ICsvConsts.CSV_ROW_SIZE];
+ var array = new String[CsvConst.CSV_ROW_SIZE];
VehicleType type = dataObj.getType();
- array[ICsvConsts.TYPE_IDX] = type.getType();
- array[ICsvConsts.COLOR_IDX] = dataObj.getColor();
- array[ICsvConsts.NUMBER_IDX] = dataObj.getNumber();
- array[ICsvConsts.DATE_IDX] = Utils.getFormattedDate(dataObj.getDateTime());
+ array[CsvConst.TYPE_IDX] = type.getType();
+ array[CsvConst.COLOR_IDX] = dataObj.getColor();
+ array[CsvConst.NUMBER_IDX] = dataObj.getNumber();
+ array[CsvConst.DATE_IDX] = Utils.getFormattedDate(dataObj.getDateTime());
String hasTrailerStr = FALSE;
if (type.in(VehicleType.CAR, VehicleType.TRUCK)) {
hasTrailerStr = Boolean.toString(((AbstractVehicleWithTrailer) dataObj).hasTrailer());
}
- array[ICsvConsts.HAS_TRAILER_IDX] = hasTrailerStr;
+ array[CsvConst.HAS_TRAILER_IDX] = hasTrailerStr;
String isTransportsPassengersStr = FALSE;
if (VehicleType.CAR == type) {
isTransportsPassengersStr = Boolean.toString(((Car) dataObj).isTransportsPassengers());
}
- array[ICsvConsts.IS_TRANSPORTS_PASSENGERS_IDX] = isTransportsPassengersStr;
+ array[CsvConst.IS_TRANSPORTS_PASSENGERS_IDX] = isTransportsPassengersStr;
String isTransportsCargoStr = FALSE;
if (VehicleType.TRUCK == type) {
isTransportsCargoStr = Boolean.toString(((Truck) dataObj).isTransportsCargo());
}
- array[ICsvConsts.IS_TRANSPORTS_CARGO_IDX] = isTransportsCargoStr;
+ array[CsvConst.IS_TRANSPORTS_CARGO_IDX] = isTransportsCargoStr;
String hasCradle = FALSE;
if (VehicleType.MOTORCYCLE == type) {
hasCradle = Boolean.toString(((Motorcycle) dataObj).hasCradle());
}
- array[ICsvConsts.HAS_CRADLE_IDX] = hasCradle;
+ array[CsvConst.HAS_CRADLE_IDX] = hasCradle;
return array;
}
diff --git a/src/main/java/home/file/csv/CsvImporter.java b/src/main/java/home/file/csv/CsvImporter.java
index 744633f..6dcaa05 100644
--- a/src/main/java/home/file/csv/CsvImporter.java
+++ b/src/main/java/home/file/csv/CsvImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.csv;
import java.io.File;
@@ -61,7 +76,7 @@ private List parse(List rawDataObjs) {
private void checkElementsCountInRawDataObjs(List rawDataObjs) {
for (String[] rawDataObj : rawDataObjs) {
- if (ICsvConsts.CSV_ROW_SIZE != rawDataObj.length) {
+ if (CsvConst.CSV_ROW_SIZE != rawDataObj.length) {
throw new IllegalArgumentException("Incorrect count of elements in : [%s]"
.formatted(String.join(", ", rawDataObj)));
}
@@ -70,17 +85,14 @@ private void checkElementsCountInRawDataObjs(List rawDataObjs) {
private List getRawDataObjsWithoutHeader(List rawDataObjs) {
String[] header = rawDataObjs.get(0);
- return Arrays.equals(header, ICsvConsts.CSV_HEADER)
+ return Arrays.equals(header, CsvConst.CSV_HEADER)
? rawDataObjs.subList(1, rawDataObjs.size())
: rawDataObjs;
}
private AbstractVehicle convertToDataObj(String[] rawDataObj) {
- String type = rawDataObj[ICsvConsts.TYPE_IDX];
+ String type = rawDataObj[CsvConst.TYPE_IDX];
VehicleType vehicleType = VehicleType.getVehicleType(type);
- if (vehicleType == null) {
- throw new IllegalArgumentException("Wrong vehicle type received : " + type);
- }
AbstractVehicle dataObj = switch (vehicleType) {
case CAR -> new Car();
@@ -88,31 +100,31 @@ private AbstractVehicle convertToDataObj(String[] rawDataObj) {
case MOTORCYCLE -> new Motorcycle();
};
- for (int tagIdx = ICsvConsts.COLOR_IDX; ICsvConsts.HAS_CRADLE_IDX >= tagIdx; tagIdx++) {
+ for (int tagIdx = CsvConst.COLOR_IDX; CsvConst.HAS_CRADLE_IDX >= tagIdx; tagIdx++) {
String value = rawDataObj[tagIdx];
switch (tagIdx) {
- case ICsvConsts.COLOR_IDX -> dataObj.setColor(value);
- case ICsvConsts.NUMBER_IDX -> dataObj.setNumber(value);
- case ICsvConsts.DATE_IDX -> dataObj.setDateTime(Utils.getLongFromFormattedDate(value));
- case ICsvConsts.HAS_TRAILER_IDX -> {
+ case CsvConst.COLOR_IDX -> dataObj.setColor(value);
+ case CsvConst.NUMBER_IDX -> dataObj.setNumber(value);
+ case CsvConst.DATE_IDX -> dataObj.setDateTime(Utils.getLongFromFormattedDate(value));
+ case CsvConst.HAS_TRAILER_IDX -> {
if (vehicleType.in(VehicleType.CAR, VehicleType.TRUCK)) {
boolean hasTrailer = Boolean.parseBoolean(value);
((AbstractVehicleWithTrailer) dataObj).setHasTrailer(hasTrailer);
}
}
- case ICsvConsts.IS_TRANSPORTS_PASSENGERS_IDX -> {
+ case CsvConst.IS_TRANSPORTS_PASSENGERS_IDX -> {
if (VehicleType.CAR == vehicleType) {
boolean isTransportsPassengers = Boolean.parseBoolean(value);
((Car) dataObj).setTransportsPassengers(isTransportsPassengers);
}
}
- case ICsvConsts.IS_TRANSPORTS_CARGO_IDX -> {
+ case CsvConst.IS_TRANSPORTS_CARGO_IDX -> {
if (VehicleType.TRUCK == vehicleType) {
boolean isTransportsCargo = Boolean.parseBoolean(value);
((Truck) dataObj).setTransportsCargo(isTransportsCargo);
}
}
- case ICsvConsts.HAS_CRADLE_IDX -> {
+ case CsvConst.HAS_CRADLE_IDX -> {
if (VehicleType.MOTORCYCLE == vehicleType) {
boolean hasCradle = Boolean.parseBoolean(value);
((Motorcycle) dataObj).setHasCradle(hasCradle);
diff --git a/src/main/java/home/file/csv/ICsvConsts.java b/src/main/java/home/file/csv/ICsvConsts.java
deleted file mode 100644
index 6202e61..0000000
--- a/src/main/java/home/file/csv/ICsvConsts.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package home.file.csv;
-
-import home.file.Tag;
-
-interface ICsvConsts {
-
- int TYPE_IDX = 0;
- int COLOR_IDX = 1;
- int NUMBER_IDX = 2;
- int DATE_IDX = 3;
- int HAS_TRAILER_IDX = 4;
- int IS_TRANSPORTS_PASSENGERS_IDX = 5;
- int IS_TRANSPORTS_CARGO_IDX = 6;
- int HAS_CRADLE_IDX = 7;
-
- String[] CSV_HEADER = {
- Tag.TYPE.getTagName(),
- Tag.COLOR.getTagName(),
- Tag.NUMBER.getTagName(),
- Tag.DATE.getTagName(),
- Tag.HAS_TRAILER.getTagName(),
- Tag.IS_TRANSPORTS_PASSENGERS.getTagName(),
- Tag.IS_TRANSPORTS_CARGO.getTagName(),
- Tag.HAS_CRADLE.getTagName()
- };
-
- int CSV_ROW_SIZE = CSV_HEADER.length;
-}
diff --git a/src/main/java/home/file/json_yaml/AbstractJsonYamlExporter.java b/src/main/java/home/file/json_yaml/AbstractJsonYamlExporter.java
index 12b6a6d..49db0dd 100644
--- a/src/main/java/home/file/json_yaml/AbstractJsonYamlExporter.java
+++ b/src/main/java/home/file/json_yaml/AbstractJsonYamlExporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.json_yaml;
import java.util.LinkedHashMap;
diff --git a/src/main/java/home/file/json_yaml/AbstractJsonYamlImporter.java b/src/main/java/home/file/json_yaml/AbstractJsonYamlImporter.java
index 334f48c..0e62baa 100644
--- a/src/main/java/home/file/json_yaml/AbstractJsonYamlImporter.java
+++ b/src/main/java/home/file/json_yaml/AbstractJsonYamlImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.json_yaml;
import java.util.Map;
@@ -31,9 +46,6 @@ protected void checkRootTagName(String rootTagName) {
protected AbstractVehicle convertToDataObj(Map rawDataStringMap) {
String type = removeRequiredParam(Tag.TYPE, rawDataStringMap);
VehicleType vehicleType = VehicleType.getVehicleType(type);
- if (vehicleType == null) {
- throw new IllegalArgumentException("Wrong vehicle type received : " + type);
- }
AbstractVehicle dataObj = switch (vehicleType) {
case CAR -> new Car();
@@ -45,10 +57,7 @@ protected AbstractVehicle convertToDataObj(Map rawDataStringMap)
String tagName = tagData.getKey();
String tagValue = tagData.getValue();
- Tag tag = Tag.getTag(tagName);
- if (tag == null) {
- throw new IllegalArgumentException("Incorrect tag name : " + tagName);
- }
+ Tag tag = Tag.getTag(tagName, "Incorrect tag name : %s");
switch (tag) {
case COLOR -> dataObj.setColor(tagValue);
diff --git a/src/main/java/home/file/json_yaml/JsonExporter.java b/src/main/java/home/file/json_yaml/JsonExporter.java
index 541cf8b..b7a71ae 100644
--- a/src/main/java/home/file/json_yaml/JsonExporter.java
+++ b/src/main/java/home/file/json_yaml/JsonExporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.json_yaml;
import java.util.ArrayList;
diff --git a/src/main/java/home/file/json_yaml/JsonImporter.java b/src/main/java/home/file/json_yaml/JsonImporter.java
index 3c9c0b6..e4deedc 100644
--- a/src/main/java/home/file/json_yaml/JsonImporter.java
+++ b/src/main/java/home/file/json_yaml/JsonImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.json_yaml;
import java.io.File;
diff --git a/src/main/java/home/file/json_yaml/YamlExporter.java b/src/main/java/home/file/json_yaml/YamlExporter.java
index 46e357e..f85f23b 100644
--- a/src/main/java/home/file/json_yaml/YamlExporter.java
+++ b/src/main/java/home/file/json_yaml/YamlExporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.json_yaml;
import java.util.ArrayList;
diff --git a/src/main/java/home/file/json_yaml/YamlImporter.java b/src/main/java/home/file/json_yaml/YamlImporter.java
index 42bc788..8d01faa 100644
--- a/src/main/java/home/file/json_yaml/YamlImporter.java
+++ b/src/main/java/home/file/json_yaml/YamlImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.json_yaml;
import java.io.File;
@@ -25,7 +40,7 @@ public final class YamlImporter extends AbstractJsonYamlImporter {
@Override
public List importDataObjsFromFile(File file) {
try (InputStream inputStream = new FileInputStream(file)) {
- Yaml yaml = new Yaml();
+ var yaml = new Yaml();
Map allData = yaml.load(inputStream);
List dataObjs = parse(allData);
return dataObjs;
diff --git a/src/main/java/home/file/ser/AbstractSerImporter.java b/src/main/java/home/file/ser/AbstractSerImporter.java
index 50467a6..bcb0d94 100644
--- a/src/main/java/home/file/ser/AbstractSerImporter.java
+++ b/src/main/java/home/file/ser/AbstractSerImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.ser;
import java.io.IOException;
diff --git a/src/main/java/home/file/ser/BserExporter.java b/src/main/java/home/file/ser/BserExporter.java
index 2b5fcf1..236ac01 100644
--- a/src/main/java/home/file/ser/BserExporter.java
+++ b/src/main/java/home/file/ser/BserExporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.ser;
import java.io.ByteArrayOutputStream;
diff --git a/src/main/java/home/file/ser/BserImporter.java b/src/main/java/home/file/ser/BserImporter.java
index c91411e..a99de3b 100644
--- a/src/main/java/home/file/ser/BserImporter.java
+++ b/src/main/java/home/file/ser/BserImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.ser;
import java.io.ByteArrayInputStream;
diff --git a/src/main/java/home/file/ser/SerExporter.java b/src/main/java/home/file/ser/SerExporter.java
index 4ad5b9c..18c5766 100644
--- a/src/main/java/home/file/ser/SerExporter.java
+++ b/src/main/java/home/file/ser/SerExporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.ser;
import java.io.BufferedOutputStream;
diff --git a/src/main/java/home/file/ser/SerImporter.java b/src/main/java/home/file/ser/SerImporter.java
index 125feac..94ca652 100644
--- a/src/main/java/home/file/ser/SerImporter.java
+++ b/src/main/java/home/file/ser/SerImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.ser;
import java.io.BufferedInputStream;
diff --git a/src/main/java/home/file/xml/XmlExporter.java b/src/main/java/home/file/xml/XmlExporter.java
index 70625b0..6b98c10 100644
--- a/src/main/java/home/file/xml/XmlExporter.java
+++ b/src/main/java/home/file/xml/XmlExporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.xml;
import java.io.ByteArrayOutputStream;
diff --git a/src/main/java/home/file/xml/XmlImporter.java b/src/main/java/home/file/xml/XmlImporter.java
index 67d37f5..b10f9e3 100644
--- a/src/main/java/home/file/xml/XmlImporter.java
+++ b/src/main/java/home/file/xml/XmlImporter.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.file.xml;
import java.io.File;
@@ -47,10 +62,7 @@ public List importDataObjsFromFile(File file) {
String tagName = reader.getName().getLocalPart();
- Tag tag = Tag.getTag(tagName);
- if (tag == null) {
- throw new IllegalArgumentException("Wrong start of tag name : " + tagName);
- }
+ Tag tag = Tag.getTag(tagName, "Wrong start of tag name : %s");
switch (tag) {
case VEHICLES:
@@ -127,10 +139,7 @@ public List importDataObjsFromFile(File file) {
String tagName = reader.getName().getLocalPart();
- Tag tag = Tag.getTag(tagName);
- if (tag == null) {
- throw new IllegalArgumentException("Wrong end of tag name : " + tagName);
- }
+ Tag tag = Tag.getTag(tagName, "Wrong end of tag name : %s");
if (Tag.VEHICLE == tag) {
dataObjs.add(dataObj);
@@ -170,11 +179,7 @@ private void chcekAttribute(XMLStreamReader reader) {
private AbstractVehicle createDataObj(XMLStreamReader reader) {
String type = reader.getAttributeValue(0);
-
VehicleType vehicleType = VehicleType.getVehicleType(type);
- if (vehicleType == null) {
- throw new IllegalArgumentException("Wrong vehicle type received : " + type);
- }
return switch (vehicleType) {
case CAR -> new Car();
diff --git a/src/main/java/home/gui/ColorSchema.java b/src/main/java/home/gui/ColorSchema.java
index e6e6617..de940d3 100644
--- a/src/main/java/home/gui/ColorSchema.java
+++ b/src/main/java/home/gui/ColorSchema.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui;
import javax.swing.UIManager;
@@ -36,6 +51,7 @@ public static ColorSchema getColorSchema(String colorSchemaName) {
return colorSchema;
}
}
- return null;
+
+ throw new IllegalArgumentException("Incorrect style name : " + colorSchemaName);
}
}
diff --git a/src/main/java/home/gui/DataActionInGui.java b/src/main/java/home/gui/DataActionInGui.java
index b310352..9e34689 100644
--- a/src/main/java/home/gui/DataActionInGui.java
+++ b/src/main/java/home/gui/DataActionInGui.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui;
import java.util.List;
@@ -5,7 +20,7 @@
import home.Storage;
import home.model.AbstractVehicle;
-public class DataActionInGui {
+public final class DataActionInGui {
public static void init(List dataObjs) {
Storage.INSTANCE.initDataObjs(dataObjs);
diff --git a/src/main/java/home/gui/DbOperation.java b/src/main/java/home/gui/DbOperation.java
new file mode 100644
index 0000000..e5e866d
--- /dev/null
+++ b/src/main/java/home/gui/DbOperation.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui;
+
+public enum DbOperation {
+
+ CREATE_OR_OPEN_FILE_DATABASE(GuiConst.CREATE_OR_OPEN_FILE_DATABASE),
+ CONNECT_TO_SERVER_DATABASE(GuiConst.CONNECT_TO_SERVER_DATABASE),
+ SAVE(GuiConst.SAVE),
+ SAVE_AS(GuiConst.SAVE_AS);
+
+ private String operationText;
+
+ private DbOperation(String operationText) {
+ this.operationText = operationText;
+ }
+
+ public String getOperatioText() {
+ return operationText;
+ }
+}
diff --git a/src/main/java/home/gui/DialogCaller.java b/src/main/java/home/gui/DialogCaller.java
index 0d9107b..66cd244 100644
--- a/src/main/java/home/gui/DialogCaller.java
+++ b/src/main/java/home/gui/DialogCaller.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui;
import java.lang.reflect.Constructor;
@@ -8,7 +23,7 @@
import org.slf4j.LoggerFactory;
import home.Storage;
-import home.gui.component.dialog.AbstractDialog;
+import home.gui.component.dialog.AbstractDialogVehicle;
import home.gui.component.dialog.DialogCar;
import home.gui.component.dialog.DialogMotorcycle;
import home.gui.component.dialog.DialogTruck;
@@ -16,7 +31,7 @@
import home.model.VehicleType;
import home.utils.LogUtils;
-public final class DialogCaller {
+final class DialogCaller {
private static final Logger LOG = LoggerFactory.getLogger(DialogCaller.class);
@@ -24,7 +39,7 @@ public final class DialogCaller {
private static final int OBJ_DIALOG_HEIGHT = 350;
@SuppressWarnings("unchecked")
- static void showObjDialog(JFrame frame,
+ static void showObjDialog(JFrame frame,
AbstractVehicle dataObj, int tblRowOfSelectedDataObj) {
Class dialogClass = null;
VehicleType objType = dataObj.getType();
@@ -38,12 +53,12 @@ static void showObjDialog(JFrame frame,
showObjDialog(frame, dialogClass, dataObj, tblRowOfSelectedDataObj);
}
- static void showObjDialog(JFrame frame,
+ static void showObjDialog(JFrame frame,
Class dialogClass) {
showObjDialog(frame, dialogClass, null, Storage.NO_ROW_IS_SELECTED);
}
- private static void showObjDialog(JFrame frame,
+ private static void showObjDialog(JFrame frame,
Class dialogClass, AbstractVehicle dataObj, int tblRowOfSelectedDataObj) {
Constructor constructor;
try {
diff --git a/src/main/java/home/gui/Gui.java b/src/main/java/home/gui/Gui.java
index 40b963f..c650e40 100644
--- a/src/main/java/home/gui/Gui.java
+++ b/src/main/java/home/gui/Gui.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui;
import java.awt.BorderLayout;
@@ -31,23 +46,26 @@
import home.Main;
import home.Settings;
-import home.Settings.Setting;
import home.Storage;
import home.gui.component.CustomJButton;
import home.gui.component.CustomJFileChooserImpExp.DataFormat;
import home.gui.component.CustomJFrame;
+import home.gui.component.CustomJLabel;
import home.gui.component.CustomJPanel;
import home.gui.component.CustomJPanel.PanelType;
import home.gui.component.CustomJTable;
+import home.gui.component.CustomJTableDataModel;
import home.gui.component.dialog.DialogCar;
import home.gui.component.dialog.DialogMotorcycle;
import home.gui.component.dialog.DialogTruck;
-import home.gui.listener.CreateOrOpenActionListener;
+import home.gui.listener.ConnectToServerDatabaseActionListener;
+import home.gui.listener.CreateOrOpenFileDatabaseActionListener;
import home.gui.listener.ExportImportActionListener;
import home.gui.listener.SaveActionListener;
import home.model.AbstractVehicle;
-import home.utils.ThreadUtil;
import home.utils.LogUtils;
+import home.utils.ThreadUtil;
+import home.utils.Utils;
public enum Gui {
@@ -59,8 +77,8 @@ public enum Gui {
private JLabel dbLabel;
- private JTable table;
- private AbstractTableModel tableModel;
+ private CustomJTable table;
+ private AbstractTableModel tableDataModel;
private JScrollPane tableScrollPane;
private JButton btnCar;
@@ -71,10 +89,10 @@ public enum Gui {
private JPanel panelTable;
private JPanel panelButton;
private JMenuBar menuBar;
- private JFrame frame;
+ private CustomJFrame frame;
public void refreshTable() {
- tableModel.fireTableDataChanged();
+ tableDataModel.fireTableDataChanged();
}
public void setDbLabel(String label) {
@@ -94,20 +112,16 @@ public void buildGui() {
private void setStyle(String style) {
try {
ColorSchema colorSchema = ColorSchema.getColorSchema(style);
- if (colorSchema == null) {
- throw new IllegalArgumentException("Incorrect style name : " + style);
- }
UIManager.setLookAndFeel(colorSchema.getLookAndFeelClassName());
} catch (Exception e) {
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
- Settings.writeSetting(Setting.STYLE,
- ColorSchema.CROSSPLATFORM.name().toLowerCase(Locale.ROOT));
- LogUtils.logAndShowError(LOG, frame,
- "Error while set the system color scheme.\n"
- + ColorSchema.CROSSPLATFORM.getNameForGui()
- + " color scheme will be used.\nError: "
- + e.getMessage(),
+ Settings.saveStyle(ColorSchema.CROSSPLATFORM.name().toLowerCase(Locale.ROOT));
+ LogUtils.logAndShowError(LOG, frame, """
+ Error while set the system color scheme.
+ %s color scheme will be used.
+ Error: %s"""
+ .formatted(ColorSchema.CROSSPLATFORM.getNameForGui(), e.getMessage()),
"System color scheme error", e);
} catch (Exception ex) {
JFrame.setDefaultLookAndFeelDecorated(true);
@@ -119,10 +133,11 @@ private void setStyle(String style) {
}
private void createTable() {
- dbLabel = new JLabel(Settings.hasPathToDbFile() ? Settings.getDbFilePath()
- : IGuiConsts.CHOOSE_DB_FILE);
+ dbLabel = CustomJLabel.createSmall(Utils.generateDbDescription());
+
+ tableDataModel = new CustomJTableDataModel(Storage.INSTANCE.getAll());
- table = CustomJTable.create();
+ table = CustomJTable.create(tableDataModel, Settings.isAutoResizeTableWidth());
table.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent mouseEvent) {
@@ -136,24 +151,22 @@ public void mousePressed(MouseEvent mouseEvent) {
});
tableScrollPane = new JScrollPane(table);
-
- tableModel = (AbstractTableModel) table.getModel();
}
private void createButtons() {
- btnCar = CustomJButton.create(IGuiConsts.CAR);
+ btnCar = CustomJButton.create(GuiConst.CAR);
btnCar.addActionListener(actionEvent -> DialogCaller
.showObjDialog(frame, DialogCar.class));
- btnTruck = CustomJButton.create(IGuiConsts.TRUCK);
+ btnTruck = CustomJButton.create(GuiConst.TRUCK);
btnTruck.addActionListener(actionEvent -> DialogCaller
.showObjDialog(frame, DialogTruck.class));
- btnMotorcycle = CustomJButton.create(IGuiConsts.MOTORCYCLE);
+ btnMotorcycle = CustomJButton.create(GuiConst.MOTORCYCLE);
btnMotorcycle.addActionListener(actionEvent -> DialogCaller
.showObjDialog(frame, DialogMotorcycle.class));
- btnDelete = CustomJButton.create(IGuiConsts.DELETE);
+ btnDelete = CustomJButton.create(GuiConst.DELETE);
btnDelete.addActionListener(actionEvent -> {
ThreadUtil.runInThread(() -> {
Thread.currentThread().setName("-> delete from storage");
@@ -169,11 +182,11 @@ private void createButtons() {
}
private void createPanels() {
- panelTable = CustomJPanel.create(PanelType.FRAME_TABLE_PANEL);
+ panelTable = CustomJPanel.create(PanelType.MAIN_FRAME_TABLE_PANEL);
panelTable.add(dbLabel, BorderLayout.NORTH);
panelTable.add(tableScrollPane, BorderLayout.CENTER);
- panelButton = CustomJPanel.create(PanelType.FRAME_BUTTON_PANEL);
+ panelButton = CustomJPanel.create(PanelType.MAIN_FRAME_BUTTON_PANEL);
panelButton.add(btnCar);
panelButton.add(btnTruck);
panelButton.add(btnMotorcycle);
@@ -183,16 +196,24 @@ private void createPanels() {
private void createMenu() {
menuBar = new JMenuBar();
- JMenuItem createOrOpenItem = createMenuItem(IGuiConsts.CREATE_OR_OPEN,
- new CreateOrOpenActionListener(frame, dbLabel, LOG));
- JMenuItem saveItem = createMenuItem(IGuiConsts.SAVE,
+ JMenuItem createOrOpenFileDatabaseItem = createMenuItem(
+ DbOperation.CREATE_OR_OPEN_FILE_DATABASE.getOperatioText(),
+ new CreateOrOpenFileDatabaseActionListener(frame, dbLabel, LOG));
+ JMenuItem connectToServerDatabaseItem = createMenuItem(
+ DbOperation.CONNECT_TO_SERVER_DATABASE.getOperatioText(),
+ new ConnectToServerDatabaseActionListener(frame, dbLabel, LOG));
+ JMenuItem saveItem = createMenuItem(
+ DbOperation.SAVE.getOperatioText(),
new SaveActionListener(frame, dbLabel, false, LOG));
- JMenuItem saveAsItem = createMenuItem(IGuiConsts.SAVE_AS,
+ JMenuItem saveAsItem = createMenuItem(
+ DbOperation.SAVE_AS.getOperatioText(),
new SaveActionListener(frame, dbLabel, true, LOG));
JMenu importItem = createImportExportDropdownMenu(true);
JMenu exportItem = createImportExportDropdownMenu(false);
- var fileMenu = new JMenu(IGuiConsts.FILE);
- fileMenu.add(createOrOpenItem);
+ var fileMenu = new JMenu(GuiConst.FILE);
+ fileMenu.add(createOrOpenFileDatabaseItem);
+ fileMenu.add(new JSeparator());
+ fileMenu.add(connectToServerDatabaseItem);
fileMenu.add(new JSeparator());
fileMenu.add(saveItem);
fileMenu.add(saveAsItem);
@@ -203,11 +224,11 @@ private void createMenu() {
menuBar.add(creatStyleMenu());
- JMenuItem aboutItem = createMenuItem(IGuiConsts.ABOUT,
+ JMenuItem aboutItem = createMenuItem(GuiConst.ABOUT,
actionEvent -> JOptionPane.showMessageDialog(
- frame, IGuiConsts.ABOUT_TEXT.formatted(Main.appVersion),
- IGuiConsts.ABOUT_TITLE, JOptionPane.INFORMATION_MESSAGE));
- var helpMenu = new JMenu(IGuiConsts.HELP);
+ frame, GuiConst.ABOUT_TEXT.formatted(Main.appVersion),
+ GuiConst.ABOUT_TITLE, JOptionPane.INFORMATION_MESSAGE));
+ var helpMenu = new JMenu(GuiConst.HELP);
helpMenu.add(aboutItem);
menuBar.add(helpMenu);
}
@@ -219,7 +240,7 @@ private JMenuItem createMenuItem(String name, ActionListener actionListener) {
}
private JMenu createImportExportDropdownMenu(boolean isImport) {
- var dropdownMenu = new JMenu(isImport ? IGuiConsts.IMPORT_FROM : IGuiConsts.EXPORT_TO);
+ var dropdownMenu = new JMenu(isImport ? GuiConst.IMPORT_FROM : GuiConst.EXPORT_TO);
for (DataFormat dataFormat : DataFormat.values()) {
dropdownMenu.add(createMenuItem(dataFormat.getExtension(),
new ExportImportActionListener(dataFormat, isImport, frame, LOG)));
@@ -228,15 +249,20 @@ private JMenu createImportExportDropdownMenu(boolean isImport) {
}
private JMenu creatStyleMenu() {
- var styleMenu = new JMenu(IGuiConsts.STYLE);
+ var styleMenu = new JMenu(GuiConst.STYLE);
+
+ styleMenu.add(createCheckBoxResizeTblMenuItem());
+ styleMenu.add(new JSeparator());
+
var checkBoxItems = new ArrayList();
for (ColorSchema colorSchema : ColorSchema.values()) {
- styleMenu.add(createCheckBoxMenuItem(colorSchema, checkBoxItems));
+ styleMenu.add(createCheckBoxColorSchemaMenuItem(colorSchema, checkBoxItems));
}
+
return styleMenu;
}
- private JCheckBoxMenuItem createCheckBoxMenuItem(ColorSchema colorSchema,
+ private JCheckBoxMenuItem createCheckBoxColorSchemaMenuItem(ColorSchema colorSchema,
List checkBoxItems) {
var checkBoxMenuItem = new JCheckBoxMenuItem(colorSchema.getNameForGui());
checkBoxMenuItem.setSelected(
@@ -258,7 +284,7 @@ private void styleSelectAction(ActionEvent actionEvent,
var selectedItem = (JCheckBoxMenuItem) actionEvent.getSource();
selectedItem.setSelected(true);
- Settings.writeSetting(Setting.STYLE, selectedItem.getText().toLowerCase(Locale.ROOT));
+ Settings.saveStyle(selectedItem.getText().toLowerCase(Locale.ROOT));
setStyle(Settings.getStyle());
SwingUtilities.updateComponentTreeUI(frame);
@@ -268,24 +294,35 @@ private void styleSelectAction(ActionEvent actionEvent,
}
}
+ private JCheckBoxMenuItem createCheckBoxResizeTblMenuItem() {
+ var checkBoxMenuItem = new JCheckBoxMenuItem(GuiConst.AUTO_RESIZE_TABLE_WIDTH);
+ checkBoxMenuItem.setSelected(Settings.isAutoResizeTableWidth());
+
+ checkBoxMenuItem.addActionListener(actionEvent -> {
+ try {
+ boolean isAutoResizeTableWidthCurrent = Settings.isAutoResizeTableWidth();
+ boolean isAutoResizeTableWidthNew = !isAutoResizeTableWidthCurrent;
+
+ Settings.saveAutoResizeTableWidth(isAutoResizeTableWidthNew);
+
+ checkBoxMenuItem.setSelected(isAutoResizeTableWidthNew);
+ table.setAutoResize(isAutoResizeTableWidthNew);
+
+ SwingUtilities.updateComponentTreeUI(frame);
+ } catch (Exception e) {
+ LogUtils.logAndShowError(LOG, frame,
+ "Error while changing auto resizing mode of table.", "Style error", e);
+ }
+ });
+
+ return checkBoxMenuItem;
+ }
+
private void createFrame() {
frame = CustomJFrame.create(Main.appName);
frame.setJMenuBar(menuBar);
frame.getContentPane().add(panelTable, BorderLayout.CENTER);
frame.getContentPane().add(panelButton, BorderLayout.EAST);
- makeFrameVisible();
- }
-
- /**
- * Creating and displaying a form. When launched via
- * "SwingUtilities.invokeLater(new Runnable(){...}" the frame will be created
- * and displayed after all expected events have been processed, i.e. the frame
- * will be created and displayed when all resources are ready. This is
- * necessary, so that all elements are guaranteed to be displayed in the window
- * (if you do "frame.setVisible(true)" from the main thread, then there is a
- * chance that some element will not be displayed in the window).
- */
- private void makeFrameVisible() {
- SwingUtilities.invokeLater(() -> frame.setVisible(true));
+ frame.makeFrameVisible();
}
}
diff --git a/src/main/java/home/gui/GuiConst.java b/src/main/java/home/gui/GuiConst.java
new file mode 100644
index 0000000..ddbccc9
--- /dev/null
+++ b/src/main/java/home/gui/GuiConst.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui;
+
+public final class GuiConst {
+
+ public static final String DATE_FORMAT = "yyyy.MM.dd | HH:mm:ss";
+
+ // label format "postgresql://127.0.0.1:5432/database_name"
+ public static final String DB_LABEL_FORMAT = "%s://%s:%d/%s";
+
+ // Table column names
+ public static final String TYPE = "Type";
+ public static final String COLOR = "Color";
+ public static final String NUMBER = "Number";
+ public static final String DATE = "Date";
+ public static final String DELETION_MARK = "Deletion mark";
+
+ // Button names
+ static final String CAR = "Car";
+ static final String TRUCK = "Truck";
+ static final String MOTORCYCLE = "Motorcycle";
+ static final String DELETE = "Delete";
+ public static final String OK = "Ok";
+ public static final String TEST_CONNECTION = "Test connection";
+ public static final String SAVE_AND_CONNECT = "Save and connect";
+ public static final String CANCEL = "Cancel";
+ public static final String HAS_TRAILER = "has trailer";
+ public static final String TRANSPORTS_PASSENGERS = "transports passengers";
+ public static final String TRANSPORTS_CARGO = "transports cargo";
+ public static final String HAS_CRADLE = "has cradle";
+
+ // Menu names
+ static final String FILE = "File";
+ static final String IMPORT_FROM = "Import from ...";
+ static final String EXPORT_TO = "Export to ...";
+ static final String STYLE = "Style";
+ static final String HELP = "Help";
+ static final String ABOUT = "About";
+ public static final String CREATE_OR_OPEN_FILE_DATABASE = "Create/Open file database";
+ public static final String CONNECT_TO_SERVER_DATABASE = "Connect to server database";
+ public static final String SAVE = "Save";
+ public static final String SAVE_AS = "Save as ... (to file)";
+ public static final String AUTO_RESIZE_TABLE_WIDTH = "Auto resize table width";
+
+ // DB label
+ public static final String DATABASE_NOT_SELECTED = "Database not selected";
+
+ // DB Connection dialog labels
+ public static final String HOST = "host";
+ public static final String PORT = "port";
+ public static final String DB_NAME = "database name";
+ public static final String USER = "user";
+ public static final String PASS = "password";
+ public static final String SHOW_PASS = "show password";
+ public static final String DB_TYPE = "database type";
+
+ // About dialog text
+ static final String ABOUT_TITLE = "About";
+ static final String ABOUT_TEXT = "Test application.\nVersion: %s";
+
+ // Save dialog text
+ public static final String SAVE_TITLE = "Saving";
+ public static final String SAVE_TEXT = "Saved successfully";
+
+ // Save to already exists dialog text
+ public static final String ALREADY_EXISTS_TITLE = "Such file already exists";
+ public static final String ALREADY_EXISTS_TEXT = "File with such name already exists, text another name.";
+
+ // Continue previous database dialog text
+ public static final String PREVIOUS_DATABASE_TITLE = "Previous database";
+ public static final String PREVIOUS_DATABASE_TEXT = "Continue with previous database?\n\nPrevious database:\n%s";
+
+ // Removed previous connection dialog text
+ public static final String REMOVED_PREVIOUS_CONNECTION_TITLE = "Removed previous connection";
+ public static final String REMOVED_PREVIOUS_CONNECTION_TEXT = "Connection to previous database was removed.";
+
+ // Operation confirm dialog text
+ public static final String OPERATION_CONFIRM_TITLE = "Operation confirm";
+ public static final String OPERATION_CONFIRM_TEXT = "Do you want to %s ?";
+
+ // Connection test successful dialog text
+ public static final String CONNECTION_TEST_SUCCESSFUL_TITLE = "Connection test";
+ public static final String CONNECTION_TEST_SUCCESSFUL_TEXT = "Connection successful!";
+
+ // Connection test error message
+ public static final String CONNECTION_TEST_ERROR_TEXT = "Connection test error:\n%s";
+
+ // Connection test supported error message
+ public static final String CONNECTION_TEST_SUPPORT_ERROR_TEXT = "Connection test for db %s is not supported";
+
+ private GuiConst() {
+ }
+}
diff --git a/src/main/java/home/gui/IGuiConsts.java b/src/main/java/home/gui/IGuiConsts.java
deleted file mode 100644
index 2d1e2d9..0000000
--- a/src/main/java/home/gui/IGuiConsts.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package home.gui;
-
-public interface IGuiConsts {
-
- String DATE_FORMAT = "yyyy.MM.dd | HH:mm:ss";
-
- // Table column names
- String TYPE = "Type";
- String COLOR = "Color";
- String NUMBER = "Number";
- String DATE = "Date";
- String DELETION_MARK = "Deletion mark";
-
- // Button names
- String CAR = "Car";
- String TRUCK = "Truck";
- String MOTORCYCLE = "Motorcycle";
- String DELETE = "Delete";
- String OK = "Ok";
- String CANCEL = "Cancel";
- String HAS_TRAILER = "has trailer";
- String TRANSPORTS_PASSENGERS = "transports passengers";
- String TRANSPORTS_CARGO = "transports cargo";
- String HAS_CRADLE = "has cradle";
-
- // Menu names
- String FILE = "File";
- String CREATE_OR_OPEN = "Create / Open";
- String SAVE = "Save";
- String SAVE_AS = "Save as ...";
- String IMPORT_FROM = "Import from ...";
- String EXPORT_TO = "Export to ...";
- String STYLE = "Style";
- String HELP = "Help";
- String ABOUT = "About";
-
- // About dialog text
- String ABOUT_TITLE = "About";
- String ABOUT_TEXT = "Test application.\nVersion: %s";
-
- // Save dialog text
- String SAVE_TITLE = "Saving";
- String SAVE_TEXT = "Saved successfully";
-
- // Export/Import dialog text
- String EXPORT_TITLE = "Exporting";
- String EXPORT_TEXT = "Exported successfully";
- String IMPORT_TITLE = "Importing";
- String IMPORT_TEXT = "Imported successfully";
-
- // DB label
- String CHOOSE_DB_FILE = "Choose SQLite DB file via [File] -> [Open]";
-}
diff --git a/src/main/java/home/gui/component/CustomJButton.java b/src/main/java/home/gui/component/CustomJButton.java
index c7d43fe..4eb3f4b 100644
--- a/src/main/java/home/gui/component/CustomJButton.java
+++ b/src/main/java/home/gui/component/CustomJButton.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import javax.swing.JButton;
diff --git a/src/main/java/home/gui/component/CustomJCheckBox.java b/src/main/java/home/gui/component/CustomJCheckBox.java
new file mode 100644
index 0000000..048143a
--- /dev/null
+++ b/src/main/java/home/gui/component/CustomJCheckBox.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui.component;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.event.ItemListener;
+
+import javax.swing.JCheckBox;
+
+@SuppressWarnings("serial")
+public final class CustomJCheckBox extends JCheckBox {
+
+ private static final String FONT_NAME = "Courier";
+ private static final int FONT_SIZE = 14;
+ private static final boolean IS_SELECTED = false;
+
+ private CustomJCheckBox() {
+ }
+
+ public static CustomJCheckBox create(String text, ItemListener itemListener) {
+ var checkBox = new CustomJCheckBox();
+ checkBox.setText(text);
+ checkBox.setSelected(IS_SELECTED);
+ checkBox.setFont(new Font(FONT_NAME, Font.PLAIN, FONT_SIZE));
+ checkBox.setForeground(Color.BLACK);
+ checkBox.addItemListener(itemListener);
+ return checkBox;
+ }
+}
diff --git a/src/main/java/home/gui/component/CustomJComboBox.java b/src/main/java/home/gui/component/CustomJComboBox.java
new file mode 100644
index 0000000..80eadba
--- /dev/null
+++ b/src/main/java/home/gui/component/CustomJComboBox.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui.component;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.util.EnumSet;
+
+import javax.swing.JComboBox;
+
+import home.db.DbType;
+
+@SuppressWarnings("serial")
+public final class CustomJComboBox extends JComboBox {
+
+ private static final String FONT_NAME = "Courier";
+ private static final int FONT_SIZE = 14;
+
+ private CustomJComboBox(String[] items) {
+ super(items);
+ }
+
+ public static CustomJComboBox create(EnumSet dbTypes) {
+ var comboBox = new CustomJComboBox(dbTypes.stream()
+ .map(type -> type.name()).toArray(String[]::new));
+ comboBox.setFont(new Font(FONT_NAME, Font.PLAIN, FONT_SIZE));
+ comboBox.setForeground(Color.BLACK);
+ return comboBox;
+ }
+}
diff --git a/src/main/java/home/gui/component/CustomJFileChooserDb.java b/src/main/java/home/gui/component/CustomJFileChooserDb.java
index c7f23b8..582cee3 100644
--- a/src/main/java/home/gui/component/CustomJFileChooserDb.java
+++ b/src/main/java/home/gui/component/CustomJFileChooserDb.java
@@ -1,8 +1,24 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import java.awt.Component;
import java.io.File;
import java.io.IOException;
+import java.sql.SQLException;
import java.util.Arrays;
import javax.swing.JFileChooser;
@@ -10,30 +26,17 @@
import javax.swing.filechooser.FileNameExtensionFilter;
import home.Settings;
-import home.db.DbInitializer;
-import home.gui.IGuiConsts;
+import home.db.conn.Connector;
+import home.db.init.DbInitializer;
+import home.gui.DbOperation;
+import home.gui.GuiConst;
+import home.gui.exception.CreateOpenSaveCancelException;
import home.gui.exception.SaveAsCancelException;
-import home.gui.exception.SaveAsToSameFileException;
+import home.gui.exception.SaveToAlreadyExistsFileException;
@SuppressWarnings("serial")
public final class CustomJFileChooserDb extends JFileChooser {
- public static enum ChooserDbOperation {
-
- CREATE_OR_OPEN(IGuiConsts.CREATE_OR_OPEN),
- SAVE_AS(IGuiConsts.SAVE_AS);
-
- private String operationText;
-
- private ChooserDbOperation(String operationText) {
- this.operationText = operationText;
- }
-
- public String getOperatioText() {
- return operationText;
- }
- }
-
private static final File APPLICATION_DIR = new File(".");
private static final String EXTENSION_DESCRIPTIONS = "SQLite DB (*.db, *.sqlite, *.sqlite3)";
private static final String[] EXTENSIONS = { "db", "sqlite", "sqlite3" };
@@ -55,35 +58,42 @@ private CustomJFileChooserDb() {
super(APPLICATION_DIR);
}
- public static void createAndShowChooser(Component parent, ChooserDbOperation operation)
- throws IOException {
+ public static void createAndShowChooser(Component parent, DbOperation operation)
+ throws IOException, SQLException {
var fileChooser = new CustomJFileChooserDb();
fileChooser.setFileFilter(new FileNameExtensionFilter(
EXTENSION_DESCRIPTIONS, EXTENSIONS));
fileChooser.showChooser(parent, operation);
}
- private void showChooser(Component parent, ChooserDbOperation operation) throws IOException {
+ private void showChooser(Component parent, DbOperation operation)
+ throws IOException, SQLException {
int chooserState = showDialog(parent, operation.getOperatioText());
if (JFileChooser.APPROVE_OPTION == chooserState) {
//// [Create / Open] button pressed
counterBeforeCreateDefaultFile = 0;
File file = getSelectedFile();
file = addExtensionToFileIfNotExists(file);
- if (ChooserDbOperation.SAVE_AS == operation) {
- checkSaveAsFileLocation(file);
+ if (DbOperation.CREATE_OR_OPEN_FILE_DATABASE != operation) {
+ checkSaveToAlreadyExistsFile(file);
}
+ Connector.resetConnectionDataAndSettings();
DbInitializer.createDbFileIfNotExists(file);
- } else if (JFileChooser.APPROVE_OPTION != chooserState && ChooserDbOperation.SAVE_AS == operation) {
+ } else if (JFileChooser.APPROVE_OPTION != chooserState && DbOperation.SAVE_AS == operation) {
//// [Cancel] button pressed while [Save as...]
throw new SaveAsCancelException("Cancel SaveAs action.");
- } else if (JFileChooser.APPROVE_OPTION != chooserState && !Settings.hasPathToDbFile()) {
- //// [Cancel] button pressed during the action [Create / Open],
+ } else if (JFileChooser.APPROVE_OPTION != chooserState && !Settings.hasDatabase()) {
+ //// [Cancel] button pressed during the action [Create / Open] or [Save],
//// while no database was selected before
////
//// Condition of this block is necessary so that when entering the
- //// [Create / Open] menu, you don't need to select database file,
- //// if it already opened.
+ //// [Create / Open] or [Save] menu, you don't need to select database file,
+ //// if it already opened or if you don't want to do it.
+
+ if (!isNeedToDoOperation(parent, operation)) {
+ //// If user don't want to do Create/Open/Save operation.
+ throw new CreateOpenSaveCancelException("Cancel %s action.".formatted(operation));
+ }
if (MAX_TRY_COUNT_BEFORE_CREATE_DEFAULT_FILE == counterBeforeCreateDefaultFile) {
generateDefaultDbFile(parent);
@@ -105,19 +115,26 @@ private File addExtensionToFileIfNotExists(File file) {
return new File(file.getAbsolutePath() + DEFAULT_EXTENSION);
}
- private void checkSaveAsFileLocation(File file) {
+ private void checkSaveToAlreadyExistsFile(File file) {
if (file.exists()) {
- throw new SaveAsToSameFileException("File '"
+ throw new SaveToAlreadyExistsFileException("File '"
+ file.getAbsolutePath() + "' already exists.");
}
}
- private void generateDefaultDbFile(Component parent) throws IOException {
+ private static boolean isNeedToDoOperation(Component parent, DbOperation operation) {
+ int dialogResult = JOptionPane.showConfirmDialog(parent,
+ GuiConst.OPERATION_CONFIRM_TEXT.formatted(operation.getOperatioText()),
+ GuiConst.OPERATION_CONFIRM_TITLE, JOptionPane.YES_NO_OPTION);
+ return dialogResult == JOptionPane.YES_OPTION;
+ }
+
+ private void generateDefaultDbFile(Component parent) throws IOException, SQLException {
String defaultFilePath = getCurrentDirectory().getAbsolutePath()
+ File.separator + DEFAULT_PREFIX
+ System.currentTimeMillis() + DEFAULT_EXTENSION;
JOptionPane.showMessageDialog(parent,
- String.format(WILL_CREATE_DEFAULT_STORAGE, defaultFilePath),
+ WILL_CREATE_DEFAULT_STORAGE.formatted(defaultFilePath),
DEFAULT_STORAGE, JOptionPane.WARNING_MESSAGE);
DbInitializer.createDbFileIfNotExists(new File(defaultFilePath));
}
diff --git a/src/main/java/home/gui/component/CustomJFileChooserImpExp.java b/src/main/java/home/gui/component/CustomJFileChooserImpExp.java
index 682c945..f5e1449 100644
--- a/src/main/java/home/gui/component/CustomJFileChooserImpExp.java
+++ b/src/main/java/home/gui/component/CustomJFileChooserImpExp.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import java.awt.Component;
@@ -26,11 +41,12 @@
import home.file.xml.XmlImporter;
import home.gui.DataActionInGui;
import home.model.AbstractVehicle;
+import home.utils.ThreadUtil;
@SuppressWarnings("serial")
public final class CustomJFileChooserImpExp extends JFileChooser {
- public static enum DataFormat {
+ public enum DataFormat {
XML("xml", "XML (*.xml)"),
YAML("yaml", "YAML (*.yaml)"),
@@ -79,40 +95,44 @@ private void showChooser(Component parent, DataFormat dataFormat,
return;
}
- File file = getSelectedFile();
- file = addExtensionToFileIfNotExists(file, dataFormat.getExtension());
-
- if (isImport) {
- IImporter importer = switch (dataFormat) {
- case XML -> new XmlImporter();
- case YAML -> new YamlImporter();
- case JSON -> new JsonImporter();
- case CSV -> new CsvImporter();
- case BSER -> new BserImporter();
- case SER -> new SerImporter();
- };
- List dataObjs = importer.importDataObjsFromFile(file);
- DataActionInGui.add(dataObjs);
- } else {
- IExporter exporter = switch (dataFormat) {
- case XML -> new XmlExporter();
- case YAML -> new YamlExporter();
- case JSON -> new JsonExporter();
- case CSV -> new CsvExporter();
- case BSER -> new BserExporter();
- case SER -> new SerExporter();
- };
-
- if (DataFormat.SER == dataFormat) {
- ((SerExporter) exporter).exportAllDataObjsToFile(file);
+ ThreadUtil.runInThread(() -> {
+ Thread.currentThread().setName("-> export/import operation");
+
+ File file = getSelectedFile();
+ file = addExtensionToFileIfNotExists(file, dataFormat.getExtension());
+
+ if (isImport) {
+ IImporter importer = switch (dataFormat) {
+ case XML -> new XmlImporter();
+ case YAML -> new YamlImporter();
+ case JSON -> new JsonImporter();
+ case CSV -> new CsvImporter();
+ case BSER -> new BserImporter();
+ case SER -> new SerImporter();
+ };
+ List dataObjs = importer.importDataObjsFromFile(file);
+ DataActionInGui.add(dataObjs);
} else {
- String text = exporter.exportAllDataObjsToString();
- FileHandler.writeStringToFile(file, text);
+ IExporter exporter = switch (dataFormat) {
+ case XML -> new XmlExporter();
+ case YAML -> new YamlExporter();
+ case JSON -> new JsonExporter();
+ case CSV -> new CsvExporter();
+ case BSER -> new BserExporter();
+ case SER -> new SerExporter();
+ };
+
+ if (DataFormat.SER == dataFormat) {
+ ((SerExporter) exporter).exportAllDataObjsToFile(file);
+ } else {
+ String text = exporter.exportAllDataObjsToString();
+ FileHandler.writeStringToFile(file, text);
+ }
}
- }
- JOptionPane.showMessageDialog(parent, direction + " successfully",
- direction, JOptionPane.INFORMATION_MESSAGE);
+ JOptionPane.showMessageDialog(parent, direction + " successfully",
+ direction, JOptionPane.INFORMATION_MESSAGE);
+ });
}
private File addExtensionToFileIfNotExists(File file, String extension) {
diff --git a/src/main/java/home/gui/component/CustomJFrame.java b/src/main/java/home/gui/component/CustomJFrame.java
index 3b92fc2..fbf0bdf 100644
--- a/src/main/java/home/gui/component/CustomJFrame.java
+++ b/src/main/java/home/gui/component/CustomJFrame.java
@@ -1,9 +1,25 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
@SuppressWarnings("serial")
public final class CustomJFrame extends JFrame {
@@ -30,4 +46,17 @@ public static CustomJFrame create(String title) {
frame.setLayout(new BorderLayout(GAP, GAP));
return frame;
}
+
+ /**
+ * Creating and displaying a frame. When launched via
+ * "SwingUtilities.invokeLater(new Runnable(){...}" the frame will be created
+ * and displayed after all expected events have been processed, i.e. the frame
+ * will be created and displayed when all resources are ready. This is
+ * necessary, so that all elements are guaranteed to be displayed in the window
+ * (if you do "frame.setVisible(true)" from the main thread, then there is a
+ * chance that some element will not be displayed in the window).
+ */
+ public void makeFrameVisible() {
+ SwingUtilities.invokeLater(() -> setVisible(true));
+ }
}
\ No newline at end of file
diff --git a/src/main/java/home/gui/component/CustomJLabel.java b/src/main/java/home/gui/component/CustomJLabel.java
index 559000a..a9b7ba7 100644
--- a/src/main/java/home/gui/component/CustomJLabel.java
+++ b/src/main/java/home/gui/component/CustomJLabel.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import java.awt.Color;
@@ -9,15 +24,24 @@
public final class CustomJLabel extends JLabel {
private static final String FONT_NAME = "Courier";
- private static final int FONT_SIZE = 14;
+ private static final int FONT_SIZE_NORMAL = 14;
+ private static final int FONT_SIZE_SMALL = 12;
private CustomJLabel(String text) {
super(text);
}
public static CustomJLabel create(String text) {
+ return create(text, FONT_SIZE_NORMAL);
+ }
+
+ public static CustomJLabel createSmall(String text) {
+ return create(text, FONT_SIZE_SMALL);
+ }
+
+ private static CustomJLabel create(String text, int fontSize) {
var label = new CustomJLabel(text);
- label.setFont(new Font(FONT_NAME, Font.BOLD, FONT_SIZE));
+ label.setFont(new Font(FONT_NAME, Font.BOLD, fontSize));
label.setForeground(Color.BLACK);
return label;
}
diff --git a/src/main/java/home/gui/component/CustomJPanel.java b/src/main/java/home/gui/component/CustomJPanel.java
index a114799..676bc15 100644
--- a/src/main/java/home/gui/component/CustomJPanel.java
+++ b/src/main/java/home/gui/component/CustomJPanel.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import java.awt.BorderLayout;
@@ -9,91 +24,56 @@
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
-@SuppressWarnings("serial")
-public final class CustomJPanel extends JPanel {
+import home.gui.component.CustomJPanel.PanelType;
+
+public final class CustomJPanel {
public enum PanelType {
- FRAME_TABLE_PANEL,
- FRAME_BUTTON_PANEL,
- DIALOG_TEXT_FIELDS_PANEL,
- DIALOG_BUTTON_PANEL
- }
+ // main window panels
+ MAIN_FRAME_TABLE_PANEL,
+ MAIN_FRAME_BUTTON_PANEL,
- // main table panel sizes
- public static final int FRAME_TBL_PANEL_PREF_WIDTH = 302;
- public static final int FRAME_TBL_PANEL_PREF_HEIGHT = 402;
- public static final int FRAME_TBL_PANEL_MIN_WIDTH = 202;
- public static final int FRAME_TBL_PANEL_MIN_HEIGHT = 102;
- public static final int FRAME_TBL_PANEL_BORDER_LAYOUT_GAP = 2;
+ // vehicle dialog panels
+ VEHICLE_DIALOG_TEXT_FIELDS_PANEL,
+ VEHICLE_DIALOG_BUTTON_PANEL,
- // main button panel sizes
- public static final int FRAME_BTN_PANEL_PREF_WIDTH = 152;
- public static final int FRAME_BTN_PANEL_PREF_HEIGHT = 402;
- public static final int FRAME_BTN_PANEL_MIN_WIDTH = 102;
- public static final int FRAME_BTN_PANEL_MIN_HEIGHT = 102;
- public static final int FRAME_BTN_PANEL_GRID_LAYOUT_ROWS = 8;
- public static final int FRAME_BTN_PANEL_GRID_LAYOUT_COLUMNS = 1;
- public static final int FRAME_BTN_PANEL_GRID_LAYOUT_GAP = 10;
-
- // dialog text fields panel sizes
- public static final int DIALOG_TXT_FIELDS_PANEL_WIDTH = 450;
- public static final int DIALOG_TXT_FIELDS_PANEL_HEIGHT = 300;
- public static final int DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_ROWS = 8;
- public static final int DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_COLUMNS = 1;
- public static final int DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP = 10;
-
- // dialog button panel sizes
- public static final int DIALOG_BTN_PANEL_WIDTH = 450;
- public static final int DIALOG_BTN_PANEL_HEIGHT = 50;
- public static final int DIALOG_BTN_PANEL_FLOW_LAYOUT_H_GAP = 10;
- public static final int DIALOG_BTN_PANEL_FLOW_LAYOUT_V_GAP = 2;
+ // connection dialog panels
+ CONNECTION_DIALOG_TEXT_FIELDS_PANEL,
+ CONNECTION_DIALOG_BUTTON_PANEL;
+ }
- public static final int EMPTY_BORDER_SIZE = 10;
+ public static AbstractCustomJPanel create(PanelType panelType) {
+ AbstractCustomJPanel panel = switch (panelType) {
+ case MAIN_FRAME_TABLE_PANEL -> new MainFrameTableJPanel();
+ case MAIN_FRAME_BUTTON_PANEL -> new MainFrameButtonJPanel();
+ case VEHICLE_DIALOG_TEXT_FIELDS_PANEL -> new VehicleDialogTextFieldsJPanel();
+ case VEHICLE_DIALOG_BUTTON_PANEL -> new VehicleDialogButtonJPanel();
+ case CONNECTION_DIALOG_TEXT_FIELDS_PANEL -> new ConnectionDialogTextFieldsJPanel();
+ case CONNECTION_DIALOG_BUTTON_PANEL -> new ConnectionDialogButtonJPanel();
+ };
+ panel.fillPanelParams();
+ return panel;
+ }
private CustomJPanel() {
}
+}
- public static CustomJPanel create(PanelType panelType) {
- var panel = new CustomJPanel();
- panel.setPanelParams(panelType);
- return panel;
- }
+@SuppressWarnings("serial")
+abstract sealed class AbstractCustomJPanel extends
+ JPanel permits MainFrameTableJPanel, MainFrameButtonJPanel,
+ VehicleDialogTextFieldsJPanel, VehicleDialogButtonJPanel,
+ ConnectionDialogTextFieldsJPanel, ConnectionDialogButtonJPanel {
+
+ private static final int EMPTY_BORDER_SIZE = 10;
- private void setPanelParams(PanelType panelType) {
- String panelName = panelType.name();
- switch (panelType) {
- case FRAME_TABLE_PANEL -> setPanelParams(panelName,
- FRAME_TBL_PANEL_PREF_WIDTH, FRAME_TBL_PANEL_PREF_HEIGHT,
- FRAME_TBL_PANEL_MIN_WIDTH, FRAME_TBL_PANEL_MIN_HEIGHT,
- new BorderLayout(FRAME_TBL_PANEL_BORDER_LAYOUT_GAP,
- FRAME_TBL_PANEL_BORDER_LAYOUT_GAP));
-
- case FRAME_BUTTON_PANEL -> setPanelParams(panelName,
- FRAME_BTN_PANEL_PREF_WIDTH, FRAME_BTN_PANEL_PREF_HEIGHT,
- FRAME_BTN_PANEL_MIN_WIDTH, FRAME_BTN_PANEL_MIN_HEIGHT,
- new GridLayout(FRAME_BTN_PANEL_GRID_LAYOUT_ROWS,
- FRAME_BTN_PANEL_GRID_LAYOUT_COLUMNS,
- FRAME_BTN_PANEL_GRID_LAYOUT_GAP,
- FRAME_BTN_PANEL_GRID_LAYOUT_GAP));
-
- case DIALOG_TEXT_FIELDS_PANEL -> setPanelParams(panelName,
- DIALOG_TXT_FIELDS_PANEL_WIDTH, DIALOG_TXT_FIELDS_PANEL_HEIGHT,
- new GridLayout(DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_ROWS,
- DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_COLUMNS,
- DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP,
- DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP));
-
- case DIALOG_BUTTON_PANEL -> setPanelParams(panelName,
- DIALOG_BTN_PANEL_WIDTH, DIALOG_BTN_PANEL_HEIGHT,
- new FlowLayout(FlowLayout.CENTER,
- DIALOG_BTN_PANEL_FLOW_LAYOUT_H_GAP,
- DIALOG_BTN_PANEL_FLOW_LAYOUT_V_GAP));
- }
- }
-
- private void setPanelParams(String name, int width, int height,
+ protected abstract void fillPanelParams();
+
+ protected abstract PanelType getPanelType();
+
+ protected void setPanelParams(int width, int height,
int minWidth, int minHeight, LayoutManager layout) {
- setName(name);
+ setName(getPanelType().name());
setSize(width, height);
setPreferredSize(new Dimension(width, height));
setMinimumSize(new Dimension(minWidth, minHeight));
@@ -102,7 +82,155 @@ private void setPanelParams(String name, int width, int height,
EMPTY_BORDER_SIZE, EMPTY_BORDER_SIZE));
}
- private void setPanelParams(String name, int width, int height, LayoutManager layout) {
- setPanelParams(name, width, height, width, height, layout);
+ protected void setPanelParams(int width, int height, LayoutManager layout) {
+ setPanelParams(width, height, width, height, layout);
+ }
+}
+
+@SuppressWarnings("serial")
+final class MainFrameTableJPanel extends AbstractCustomJPanel {
+
+ // main table panel sizes
+ private static final int FRAME_TBL_PANEL_PREF_WIDTH = 300;
+ private static final int FRAME_TBL_PANEL_PREF_HEIGHT = 400;
+ private static final int FRAME_TBL_PANEL_MIN_WIDTH = 200;
+ private static final int FRAME_TBL_PANEL_MIN_HEIGHT = 100;
+ private static final int FRAME_TBL_PANEL_BORDER_LAYOUT_GAP = 2;
+
+ @Override
+ protected PanelType getPanelType() {
+ return PanelType.MAIN_FRAME_TABLE_PANEL;
+ }
+
+ @Override
+ protected void fillPanelParams() {
+ setPanelParams(FRAME_TBL_PANEL_PREF_WIDTH, FRAME_TBL_PANEL_PREF_HEIGHT,
+ FRAME_TBL_PANEL_MIN_WIDTH, FRAME_TBL_PANEL_MIN_HEIGHT,
+ new BorderLayout(FRAME_TBL_PANEL_BORDER_LAYOUT_GAP,
+ FRAME_TBL_PANEL_BORDER_LAYOUT_GAP));
+ }
+}
+
+@SuppressWarnings("serial")
+final class MainFrameButtonJPanel extends AbstractCustomJPanel {
+
+ // main button panel sizes
+ private static final int FRAME_BTN_PANEL_PREF_WIDTH = 150;
+ private static final int FRAME_BTN_PANEL_PREF_HEIGHT = 400;
+ private static final int FRAME_BTN_PANEL_MIN_WIDTH = 100;
+ private static final int FRAME_BTN_PANEL_MIN_HEIGHT = 100;
+ private static final int FRAME_BTN_PANEL_GRID_LAYOUT_ROWS = 8;
+ private static final int FRAME_BTN_PANEL_GRID_LAYOUT_COLUMNS = 1;
+ private static final int FRAME_BTN_PANEL_GRID_LAYOUT_GAP = 10;
+
+ @Override
+ protected PanelType getPanelType() {
+ return PanelType.MAIN_FRAME_BUTTON_PANEL;
+ }
+
+ @Override
+ protected void fillPanelParams() {
+ setPanelParams(FRAME_BTN_PANEL_PREF_WIDTH, FRAME_BTN_PANEL_PREF_HEIGHT,
+ FRAME_BTN_PANEL_MIN_WIDTH, FRAME_BTN_PANEL_MIN_HEIGHT,
+ new GridLayout(FRAME_BTN_PANEL_GRID_LAYOUT_ROWS,
+ FRAME_BTN_PANEL_GRID_LAYOUT_COLUMNS,
+ FRAME_BTN_PANEL_GRID_LAYOUT_GAP,
+ FRAME_BTN_PANEL_GRID_LAYOUT_GAP));
}
}
+
+@SuppressWarnings("serial")
+final class VehicleDialogTextFieldsJPanel extends AbstractCustomJPanel {
+
+ // vehicle dialog text fields panel sizes
+ private static final int DIALOG_TXT_FIELDS_PANEL_WIDTH = 450;
+ private static final int DIALOG_TXT_FIELDS_PANEL_HEIGHT = 300;
+ private static final int DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_ROWS = 8;
+ private static final int DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_COLUMNS = 1;
+ private static final int DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP = 10;
+
+ @Override
+ protected PanelType getPanelType() {
+ return PanelType.VEHICLE_DIALOG_TEXT_FIELDS_PANEL;
+ }
+
+ @Override
+ protected void fillPanelParams() {
+ setPanelParams(DIALOG_TXT_FIELDS_PANEL_WIDTH, DIALOG_TXT_FIELDS_PANEL_HEIGHT,
+ new GridLayout(DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_ROWS,
+ DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_COLUMNS,
+ DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP,
+ DIALOG_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP));
+ }
+}
+
+@SuppressWarnings("serial")
+final class VehicleDialogButtonJPanel extends AbstractCustomJPanel {
+
+ // vehicle dialog button panel sizes
+ public static final int DIALOG_BTN_PANEL_WIDTH = 450;
+ public static final int DIALOG_BTN_PANEL_HEIGHT = 50;
+ public static final int DIALOG_BTN_PANEL_FLOW_LAYOUT_H_GAP = 10;
+ public static final int DIALOG_BTN_PANEL_FLOW_LAYOUT_V_GAP = 2;
+
+ @Override
+ protected PanelType getPanelType() {
+ return PanelType.VEHICLE_DIALOG_BUTTON_PANEL;
+ }
+
+ @Override
+ protected void fillPanelParams() {
+ setPanelParams(DIALOG_BTN_PANEL_WIDTH, DIALOG_BTN_PANEL_HEIGHT,
+ new FlowLayout(FlowLayout.CENTER,
+ DIALOG_BTN_PANEL_FLOW_LAYOUT_H_GAP,
+ DIALOG_BTN_PANEL_FLOW_LAYOUT_V_GAP));
+ }
+}
+
+@SuppressWarnings("serial")
+final class ConnectionDialogTextFieldsJPanel extends AbstractCustomJPanel {
+
+ // connection dialog text fields panel sizes
+ private static final int CONNECTION_TXT_FIELDS_PANEL_WIDTH = 450;
+ private static final int CONNECTION_TXT_FIELDS_PANEL_HEIGHT = 600;
+ private static final int CONNECTION_TXT_FIELDS_PANEL_GRID_LAYOUT_ROWS = 13;
+ private static final int CONNECTION_TXT_FIELDS_PANEL_GRID_LAYOUT_COLUMNS = 2;
+ private static final int CONNECTION_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP = 10;
+
+ @Override
+ protected PanelType getPanelType() {
+ return PanelType.CONNECTION_DIALOG_TEXT_FIELDS_PANEL;
+ }
+
+ @Override
+ protected void fillPanelParams() {
+ setPanelParams(CONNECTION_TXT_FIELDS_PANEL_WIDTH, CONNECTION_TXT_FIELDS_PANEL_HEIGHT,
+ new GridLayout(CONNECTION_TXT_FIELDS_PANEL_GRID_LAYOUT_ROWS,
+ CONNECTION_TXT_FIELDS_PANEL_GRID_LAYOUT_COLUMNS,
+ CONNECTION_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP,
+ CONNECTION_TXT_FIELDS_PANEL_GRID_LAYOUT_GAP));
+ }
+}
+
+@SuppressWarnings("serial")
+final class ConnectionDialogButtonJPanel extends AbstractCustomJPanel {
+
+ // connection dialog button panel sizes
+ private static final int CONNECTION_BTN_PANEL_WIDTH = 450;
+ private static final int CONNECTION_BTN_PANEL_HEIGHT = 50;
+ private static final int CONNECTION_BTN_PANEL_FLOW_LAYOUT_H_GAP = 10;
+ private static final int CONNECTION_BTN_PANEL_FLOW_LAYOUT_V_GAP = 2;
+
+ @Override
+ protected PanelType getPanelType() {
+ return PanelType.CONNECTION_DIALOG_BUTTON_PANEL;
+ }
+
+ @Override
+ protected void fillPanelParams() {
+ setPanelParams(CONNECTION_BTN_PANEL_WIDTH, CONNECTION_BTN_PANEL_HEIGHT,
+ new FlowLayout(FlowLayout.CENTER,
+ CONNECTION_BTN_PANEL_FLOW_LAYOUT_H_GAP,
+ CONNECTION_BTN_PANEL_FLOW_LAYOUT_V_GAP));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/home/gui/component/CustomJPasswordField.java b/src/main/java/home/gui/component/CustomJPasswordField.java
new file mode 100644
index 0000000..223ce16
--- /dev/null
+++ b/src/main/java/home/gui/component/CustomJPasswordField.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui.component;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import javax.swing.JPasswordField;
+
+@SuppressWarnings("serial")
+public final class CustomJPasswordField extends JPasswordField {
+
+ private static final String FONT_NAME = "Courier";
+ private static final int FONT_SIZE = 14;
+ private static final char ECHO_CHARACTER_TO_DISPLAY = '*';
+
+ private CustomJPasswordField() {
+ }
+
+ public static CustomJPasswordField create(int columns) {
+ var passwordFiled = new CustomJPasswordField();
+ passwordFiled.setColumns(columns);
+ passwordFiled.setFont(new Font(FONT_NAME, Font.PLAIN, FONT_SIZE));
+ passwordFiled.setForeground(Color.BLACK);
+ passwordFiled.setEchoChar(ECHO_CHARACTER_TO_DISPLAY);
+ return passwordFiled;
+ }
+
+ public void showPassword(boolean showPass) {
+ if (showPass) {
+ setEchoChar((char) 0);
+ } else {
+ setEchoChar(ECHO_CHARACTER_TO_DISPLAY);
+ }
+ }
+}
diff --git a/src/main/java/home/gui/component/CustomJTable.java b/src/main/java/home/gui/component/CustomJTable.java
index 66f8e74..21409dd 100644
--- a/src/main/java/home/gui/component/CustomJTable.java
+++ b/src/main/java/home/gui/component/CustomJTable.java
@@ -1,11 +1,25 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
+import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
-import home.Storage;
-
@SuppressWarnings("serial")
public final class CustomJTable extends JTable {
@@ -21,12 +35,13 @@ public final class CustomJTable extends JTable {
private CustomJTable() {
}
- public static CustomJTable create() {
+ public static CustomJTable create(AbstractTableModel tableDataModel,
+ boolean isAutoResizeTableWidth) {
var table = new CustomJTable();
- table.setModel(new CustomJTableDataModel(Storage.INSTANCE.getAll()));
+ table.setModel(tableDataModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
- // table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+ table.setAutoResize(isAutoResizeTableWidth);
table.setColMinWidth(CustomJTableDataModel.TYPE_COL_IDX, TYPE_MIN_WIDTH);
table.setColMinWidth(CustomJTableDataModel.COLOR_COL_IDX, COLOR_MIN_WIDTH);
@@ -50,4 +65,12 @@ private void setColWidths(int colPosition, int minWidth, int maxWidth, int prefW
tblCol.setMaxWidth(maxWidth);
tblCol.setPreferredWidth(prefWidth);
}
+
+ public void setAutoResize(boolean isAutoResizeTableWidth) {
+ if (isAutoResizeTableWidth) {
+ setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+ } else {
+ setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+ }
+ }
}
diff --git a/src/main/java/home/gui/component/CustomJTableDataModel.java b/src/main/java/home/gui/component/CustomJTableDataModel.java
index 2b17db8..831ce37 100644
--- a/src/main/java/home/gui/component/CustomJTableDataModel.java
+++ b/src/main/java/home/gui/component/CustomJTableDataModel.java
@@ -1,16 +1,31 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import java.util.List;
import javax.swing.table.AbstractTableModel;
-import home.IConsts;
-import home.gui.IGuiConsts;
+import home.Const;
+import home.gui.GuiConst;
import home.model.AbstractVehicle;
import home.utils.Utils;
@SuppressWarnings("serial")
-final class CustomJTableDataModel extends AbstractTableModel {
+public final class CustomJTableDataModel extends AbstractTableModel {
private static final int COLUMNS_COUNT = 5;
@@ -22,7 +37,7 @@ final class CustomJTableDataModel extends AbstractTableModel {
private final List dataObjs;
- CustomJTableDataModel(List dataObjs) {
+ public CustomJTableDataModel(List dataObjs) {
this.dataObjs = dataObjs;
}
@@ -46,12 +61,12 @@ public int getColumnCount() {
@Override
public String getColumnName(int columnIndex) {
String columnName = switch (columnIndex) {
- case TYPE_COL_IDX -> IGuiConsts.TYPE;
- case COLOR_COL_IDX -> IGuiConsts.COLOR;
- case NUMBER_COL_IDX -> IGuiConsts.NUMBER;
- case DATE_COL_IDX -> IGuiConsts.DATE;
- case DEL_MARK_COL_IDX -> IGuiConsts.DELETION_MARK;
- default -> IConsts.EMPTY_STRING;
+ case TYPE_COL_IDX -> GuiConst.TYPE;
+ case COLOR_COL_IDX -> GuiConst.COLOR;
+ case NUMBER_COL_IDX -> GuiConst.NUMBER;
+ case DATE_COL_IDX -> GuiConst.DATE;
+ case DEL_MARK_COL_IDX -> GuiConst.DELETION_MARK;
+ default -> Const.EMPTY_STRING;
};
return columnName;
}
@@ -71,7 +86,7 @@ public Object getValueAt(int rowIndex, int columnIndex) {
case NUMBER_COL_IDX -> dataObj.getNumber();
case DATE_COL_IDX -> Utils.getFormattedDate(dataObj.getDateTime());
case DEL_MARK_COL_IDX -> dataObj.isMarkedForDelete();
- default -> IConsts.EMPTY_STRING;
+ default -> Const.EMPTY_STRING;
};
return cellValue;
diff --git a/src/main/java/home/gui/component/CustomJTextField.java b/src/main/java/home/gui/component/CustomJTextField.java
index ca39b55..fbac371 100644
--- a/src/main/java/home/gui/component/CustomJTextField.java
+++ b/src/main/java/home/gui/component/CustomJTextField.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component;
import java.awt.Color;
diff --git a/src/main/java/home/gui/component/CustomJXDatePicker.java b/src/main/java/home/gui/component/CustomJXDatePicker.java
index fb0d88a..0b80db4 100644
--- a/src/main/java/home/gui/component/CustomJXDatePicker.java
+++ b/src/main/java/home/gui/component/CustomJXDatePicker.java
@@ -1,3 +1,25 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright 2012 Charlie Hubbard
+ *
+ * Distributed under LGPLv3. License can be found here:
+ * http://www.gnu.org/licenses/lgpl-3.0.txt
+ * This is provided as is. If you have questions please direct them to
+ * charlie.hubbard at gmail dot you know what.
+ *******************************************************************************/
package home.gui.component;
import java.awt.Color;
@@ -19,15 +41,8 @@
import org.jdesktop.swingx.JXDatePicker;
import org.jdesktop.swingx.calendar.SingleDaySelectionModel;
-import home.gui.IGuiConsts;
+import home.gui.GuiConst;
-/**
- * This is licensed under LGPL. License can be found here:
- * http://www.gnu.org/licenses/lgpl-3.0.txt
- *
- * This is provided as is. If you have questions please direct them to
- * charlie.hubbard at gmail dot you know what.
- */
@SuppressWarnings("serial")
public final class CustomJXDatePicker extends JXDatePicker {
@@ -41,7 +56,7 @@ private CustomJXDatePicker() {
public static CustomJXDatePicker creat(Date date) {
var datePicker = new CustomJXDatePicker();
datePicker.getMonthView().setSelectionModel(new SingleDaySelectionModel());
- datePicker.setFormats(IGuiConsts.DATE_FORMAT);
+ datePicker.setFormats(GuiConst.DATE_FORMAT);
datePicker.setTimeFormat(DateFormat.getTimeInstance(DateFormat.MEDIUM));
datePicker.setDate(date);
return datePicker;
diff --git a/src/main/java/home/gui/component/dialog/AbstractCustomJDialog.java b/src/main/java/home/gui/component/dialog/AbstractCustomJDialog.java
index 7b7a349..77a0b4a 100644
--- a/src/main/java/home/gui/component/dialog/AbstractCustomJDialog.java
+++ b/src/main/java/home/gui/component/dialog/AbstractCustomJDialog.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component.dialog;
import java.awt.BorderLayout;
@@ -9,11 +24,12 @@
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
@SuppressWarnings("serial")
abstract sealed class AbstractCustomJDialog
- extends JDialog permits AbstractDialog {
+ extends JDialog permits AbstractDialogVehicle, DialogDbConnection {
private static final int GAP_BETWEEN_COMPONENTS = 2;
@@ -52,8 +68,25 @@ private void addHotKeyForClose() {
@Override
public void actionPerformed(ActionEvent e) {
- dispose();
+ actionOnHotKeyForClose();
}
});
}
+
+ protected void actionOnHotKeyForClose() {
+ dispose();
+ }
+
+ /**
+ * Creating and displaying a dialog. When launched via
+ * "SwingUtilities.invokeLater(new Runnable(){...}" the dialog will be created
+ * and displayed after all expected events have been processed, i.e. the dialog
+ * will be created and displayed when all resources are ready. This is
+ * necessary, so that all elements are guaranteed to be displayed in the window
+ * (if you do "setVisible(true)" from the main thread, then there is a chance
+ * that some element will not be displayed in the window).
+ */
+ protected void makeDialogVisible() {
+ SwingUtilities.invokeLater(() -> setVisible(true));
+ }
}
diff --git a/src/main/java/home/gui/component/dialog/AbstractDialogTrailer.java b/src/main/java/home/gui/component/dialog/AbstractDialogTrailer.java
index 113e3cd..52eacde 100644
--- a/src/main/java/home/gui/component/dialog/AbstractDialogTrailer.java
+++ b/src/main/java/home/gui/component/dialog/AbstractDialogTrailer.java
@@ -1,14 +1,29 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component.dialog;
import javax.swing.JCheckBox;
-import home.gui.IGuiConsts;
+import home.gui.GuiConst;
import home.model.AbstractVehicle;
import home.model.AbstractVehicleWithTrailer;
@SuppressWarnings("serial")
abstract sealed class AbstractDialogTrailer
- extends AbstractDialog permits DialogCar,DialogTruck {
+ extends AbstractDialogVehicle permits DialogCar, DialogTruck {
private JCheckBox chkHasTrailer;
@@ -20,7 +35,7 @@ protected AbstractDialogTrailer(String title, int width, int height,
@Override
protected void createDataComponents() {
super.createDataComponents();
- chkHasTrailer = new JCheckBox(IGuiConsts.HAS_TRAILER);
+ chkHasTrailer = new JCheckBox(GuiConst.HAS_TRAILER);
if (!isNewDataObj) {
chkHasTrailer.setSelected(((AbstractVehicleWithTrailer) dataObj).hasTrailer());
diff --git a/src/main/java/home/gui/component/dialog/AbstractDialog.java b/src/main/java/home/gui/component/dialog/AbstractDialogVehicle.java
similarity index 72%
rename from src/main/java/home/gui/component/dialog/AbstractDialog.java
rename to src/main/java/home/gui/component/dialog/AbstractDialogVehicle.java
index 3db5946..d6efa2a 100644
--- a/src/main/java/home/gui/component/dialog/AbstractDialog.java
+++ b/src/main/java/home/gui/component/dialog/AbstractDialogVehicle.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component.dialog;
import java.awt.BorderLayout;
@@ -8,12 +23,11 @@
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
-import javax.swing.SwingUtilities;
import org.jdesktop.swingx.JXDatePicker;
import home.gui.DataActionInGui;
-import home.gui.IGuiConsts;
+import home.gui.GuiConst;
import home.gui.component.CustomJButton;
import home.gui.component.CustomJLabel;
import home.gui.component.CustomJPanel;
@@ -23,8 +37,8 @@
import home.model.AbstractVehicle;
@SuppressWarnings("serial")
-public abstract sealed class AbstractDialog
- extends AbstractCustomJDialog permits AbstractDialogTrailer,DialogMotorcycle {
+public abstract sealed class AbstractDialogVehicle
+ extends AbstractCustomJDialog permits AbstractDialogTrailer, DialogMotorcycle {
private static final int TEXT_FIELD_COLUMN_NUMBERS = 9;
@@ -46,7 +60,7 @@ public abstract sealed class AbstractDialog
protected JPanel panelTextFields;
private JPanel panelButtons;
- public AbstractDialog(String title, int width, int height,
+ public AbstractDialogVehicle(String title, int width, int height,
AbstractVehicle dataObj, int tblRowOfSelectedDataObj) {
super(title, width, height);
this.tblRowOfSelectedDataObj = tblRowOfSelectedDataObj;
@@ -72,9 +86,9 @@ public void buildDialog() {
}
protected void createDataComponents() {
- lblColor = CustomJLabel.create(IGuiConsts.COLOR);
- lblNumber = CustomJLabel.create(IGuiConsts.NUMBER);
- lblDate = CustomJLabel.create(IGuiConsts.DATE);
+ lblColor = CustomJLabel.create(GuiConst.COLOR);
+ lblNumber = CustomJLabel.create(GuiConst.NUMBER);
+ lblDate = CustomJLabel.create(GuiConst.DATE);
tfColor = CustomJTextField.create(TEXT_FIELD_COLUMN_NUMBERS);
tfNumber = CustomJTextField.create(TEXT_FIELD_COLUMN_NUMBERS);
@@ -89,7 +103,7 @@ protected void createDataComponents() {
}
private void createButtons() {
- btnSave = CustomJButton.create(IGuiConsts.OK);
+ btnSave = CustomJButton.create(GuiConst.OK);
btnSave.addActionListener(actionEvent -> {
fillDataObj();
if (checkObjFilling()) {
@@ -97,12 +111,12 @@ private void createButtons() {
dispose();
}
});
- btnCancel = CustomJButton.create(IGuiConsts.CANCEL);
+ btnCancel = CustomJButton.create(GuiConst.CANCEL);
btnCancel.addActionListener(actionEvent -> dispose());
}
protected void createPanels() {
- panelTextFields = CustomJPanel.create(PanelType.DIALOG_TEXT_FIELDS_PANEL);
+ panelTextFields = CustomJPanel.create(PanelType.VEHICLE_DIALOG_TEXT_FIELDS_PANEL);
panelTextFields.add(lblColor);
panelTextFields.add(tfColor);
panelTextFields.add(lblNumber);
@@ -110,7 +124,7 @@ protected void createPanels() {
panelTextFields.add(lblDate);
panelTextFields.add(tfDate);
- panelButtons = CustomJPanel.create(PanelType.DIALOG_BUTTON_PANEL);
+ panelButtons = CustomJPanel.create(PanelType.VEHICLE_DIALOG_BUTTON_PANEL);
panelButtons.add(btnSave);
panelButtons.add(btnCancel);
}
@@ -121,19 +135,6 @@ private void createDialog() {
makeDialogVisible();
}
- /**
- * Creating and displaying a form. When launched via
- * "SwingUtilities.invokeLater(new Runnable(){...}" the dialog will be created
- * and displayed after all expected events have been processed, i.e. the dialog
- * will be created and displayed when all resources are ready. This is
- * necessary, so that all elements are guaranteed to be displayed in the window
- * (if you do "setVisible(true)" from the main thread, then there is a chance
- * that some element will not be displayed in the window).
- */
- private void makeDialogVisible() {
- SwingUtilities.invokeLater(() -> setVisible(true));
- }
-
protected void fillDataObj() {
dataObj.setColor(tfColor.getText());
dataObj.setNumber(tfNumber.getText());
diff --git a/src/main/java/home/gui/component/dialog/DialogCar.java b/src/main/java/home/gui/component/dialog/DialogCar.java
index 20446f1..2f7d45e 100644
--- a/src/main/java/home/gui/component/dialog/DialogCar.java
+++ b/src/main/java/home/gui/component/dialog/DialogCar.java
@@ -1,8 +1,23 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component.dialog;
import javax.swing.JCheckBox;
-import home.gui.IGuiConsts;
+import home.gui.GuiConst;
import home.model.AbstractVehicle;
import home.model.Car;
import home.model.VehicleType;
@@ -19,7 +34,7 @@ public DialogCar(int width, int height, AbstractVehicle dataObj, int tblRowOfSel
@Override
protected void createDataComponents() {
super.createDataComponents();
- chkPassengers = new JCheckBox(IGuiConsts.TRANSPORTS_PASSENGERS);
+ chkPassengers = new JCheckBox(GuiConst.TRANSPORTS_PASSENGERS);
if (!isNewDataObj) {
chkPassengers.setSelected(((Car) dataObj).isTransportsPassengers());
diff --git a/src/main/java/home/gui/component/dialog/DialogDbConnection.java b/src/main/java/home/gui/component/dialog/DialogDbConnection.java
new file mode 100644
index 0000000..f18de2c
--- /dev/null
+++ b/src/main/java/home/gui/component/dialog/DialogDbConnection.java
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui.component.dialog;
+
+import java.awt.BorderLayout;
+import java.awt.event.ItemEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.EnumSet;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import home.Const;
+import home.Settings;
+import home.Settings.Setting;
+import home.db.DbType;
+import home.db.conn.Connector;
+import home.gui.GuiConst;
+import home.gui.component.CustomJButton;
+import home.gui.component.CustomJCheckBox;
+import home.gui.component.CustomJComboBox;
+import home.gui.component.CustomJLabel;
+import home.gui.component.CustomJPanel;
+import home.gui.component.CustomJPanel.PanelType;
+import home.gui.component.CustomJPasswordField;
+import home.gui.component.CustomJTextField;
+import home.utils.ThreadUtil;
+
+@SuppressWarnings("serial")
+public final class DialogDbConnection extends AbstractCustomJDialog {
+
+ private enum ProcessingType {
+
+ SAVE_AND_CONNECT(GuiConst.SAVE_AND_CONNECT),
+ TEST(GuiConst.TEST_CONNECTION);
+
+ private final String title;
+
+ private ProcessingType(String title) {
+ this.title = title;
+ }
+
+ private String getTitle() {
+ return title;
+ }
+ }
+
+ private static final int OBJ_DIALOG_WIDTH = 450;
+ private static final int OBJ_DIALOG_HEIGHT = 600;
+
+ private static final int TEXT_FIELD_COLUMN_NUMBERS = 9;
+
+ private static final String DEFAULT_HOST = "127.0.0.1";
+ private static final String DEFAULT_POST = "5432";
+
+ private JLabel lblHost;
+ private JLabel lblPort;
+ private JLabel lblDbName;
+ private JLabel lblUser;
+ private JLabel lblPass;
+ private JLabel lblDbType;
+
+ private JTextField tfHost;
+ private JTextField tfPort;
+ private JTextField tfDbName;
+ private JTextField tfUser;
+ private CustomJPasswordField tfPass;
+ private JCheckBox cbShowPass;
+ private JComboBox cbDbType;
+
+ private JButton btnTestConnection;
+ private JButton btnSaveConnection;
+ private JButton btnCancel;
+
+ protected JPanel panelTextFields;
+ private JPanel panelButtons;
+
+ private final Runnable additionalActionsOnSave;
+ private WindowAdapter additionalActionsOnSaveListener;
+
+ public DialogDbConnection(String title, Runnable additionalActionsOnSave) {
+ super(title, OBJ_DIALOG_WIDTH, OBJ_DIALOG_HEIGHT);
+ this.additionalActionsOnSave = additionalActionsOnSave;
+ }
+
+ public void buildDialog() {
+ init();
+
+ createDataComponents();
+ createButtons();
+ createPanels();
+ createDialog();
+
+ fillDataComponents();
+ addListeners();
+ }
+
+ private void createDataComponents() {
+ lblHost = CustomJLabel.create(GuiConst.HOST);
+ lblPort = CustomJLabel.create(GuiConst.PORT);
+ lblDbName = CustomJLabel.create(GuiConst.DB_NAME);
+ lblUser = CustomJLabel.create(GuiConst.USER);
+ lblPass = CustomJLabel.create(GuiConst.PASS);
+ lblDbType = CustomJLabel.create(GuiConst.DB_TYPE);
+
+ tfHost = CustomJTextField.create(TEXT_FIELD_COLUMN_NUMBERS);
+ tfPort = CustomJTextField.create(TEXT_FIELD_COLUMN_NUMBERS);
+ tfDbName = CustomJTextField.create(TEXT_FIELD_COLUMN_NUMBERS);
+ tfUser = CustomJTextField.create(TEXT_FIELD_COLUMN_NUMBERS);
+ tfPass = CustomJPasswordField.create(TEXT_FIELD_COLUMN_NUMBERS);
+ cbShowPass = CustomJCheckBox.create(GuiConst.SHOW_PASS,
+ itemEvent -> tfPass.showPassword(itemEvent.getStateChange() == ItemEvent.SELECTED));
+ cbDbType = CustomJComboBox.create(EnumSet.of(DbType.PostgreSQL));
+ }
+
+ private void createButtons() {
+ btnTestConnection = CustomJButton.create(ProcessingType.TEST.getTitle());
+ btnTestConnection.addActionListener(actionEvent -> processConnSettings(ProcessingType.TEST));
+ btnSaveConnection = CustomJButton.create(ProcessingType.SAVE_AND_CONNECT.getTitle());
+ btnSaveConnection.addActionListener(actionEvent -> {
+ if (processConnSettings(ProcessingType.SAVE_AND_CONNECT)) {
+ dispose();
+ }
+ });
+ btnCancel = CustomJButton.create(GuiConst.CANCEL);
+ btnCancel.addActionListener(actionEvent -> closeDialogWithoutAdditionalActions());
+ }
+
+ private boolean processConnSettings(ProcessingType settingsProcessingType) {
+ try {
+ String host = tfHost.getText().strip();
+ String port = tfPort.getText().strip();
+ String dbName = tfDbName.getText().strip();
+ String user = tfUser.getText().strip();
+ String pass = new String(tfPass.getPassword());
+ String dbTypeStr = cbDbType.getItemAt(cbDbType.getSelectedIndex());
+
+ checkFields(host, port, dbName, user, pass, dbTypeStr);
+
+ DbType dbType = DbType.getDbType(dbTypeStr);
+
+ switch (settingsProcessingType) {
+ case SAVE_AND_CONNECT -> {
+ Connector.resetConnectionDataAndSettings();
+ Settings.saveDbConnSettings(host, port, dbName, user, pass, dbType.name());
+ }
+ case TEST -> {
+ if (Connector.testConnection(host, Integer.parseInt(port), dbName, user, pass, dbType)) {
+ JOptionPane.showMessageDialog(null, GuiConst.CONNECTION_TEST_SUCCESSFUL_TEXT,
+ GuiConst.CONNECTION_TEST_SUCCESSFUL_TITLE, JOptionPane.INFORMATION_MESSAGE);
+ }
+ }
+ }
+
+ return true;
+ } catch (SQLException | IOException e) {
+ JOptionPane.showMessageDialog(this,
+ "Connection error:\n%s".formatted(e.getMessage()),
+ "Error", JOptionPane.ERROR_MESSAGE);
+ return false;
+ }
+ }
+
+ private void checkFields(String host, String port, String dbName, String user,
+ String pass, String dbType) throws SQLException {
+ if (hasEmptyFields(host, port, dbName, user, pass, dbType)) {
+ throw new SQLException("Not all fields are filled.");
+ }
+
+ try {
+ Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ throw new SQLException("Incorrect value of parameter %s: %s"
+ .formatted(Setting.PORT, port));
+ }
+ }
+
+ public boolean hasEmptyFields() {
+ return hasEmptyFields(tfHost.getText().strip(), tfPort.getText().strip(),
+ tfDbName.getText().strip(), tfUser.getText().strip(),
+ new String(tfPass.getPassword()).strip(),
+ cbDbType.getItemAt(cbDbType.getSelectedIndex()));
+ }
+
+ private boolean hasEmptyFields(String host, String port, String dbName,
+ String user, String pass, String dbType) {
+ return host.isBlank() || port.isBlank() || dbName.isBlank()
+ || user.isBlank() || pass.isBlank() || dbType.isBlank();
+ }
+
+ private void closeDialogWithoutAdditionalActions() {
+ removeWindowListener(additionalActionsOnSaveListener);
+ dispose();
+ }
+
+ private void createPanels() {
+ panelTextFields = CustomJPanel.create(PanelType.CONNECTION_DIALOG_TEXT_FIELDS_PANEL);
+ panelTextFields.add(lblHost);
+ panelTextFields.add(tfHost);
+ panelTextFields.add(lblPort);
+ panelTextFields.add(tfPort);
+ panelTextFields.add(lblDbName);
+ panelTextFields.add(tfDbName);
+ panelTextFields.add(lblUser);
+ panelTextFields.add(tfUser);
+ panelTextFields.add(lblPass);
+ panelTextFields.add(tfPass);
+ panelTextFields.add(cbShowPass);
+ panelTextFields.add(lblDbType);
+ panelTextFields.add(cbDbType);
+
+ panelButtons = CustomJPanel.create(PanelType.CONNECTION_DIALOG_BUTTON_PANEL);
+ panelButtons.add(btnTestConnection);
+ panelButtons.add(btnSaveConnection);
+ panelButtons.add(btnCancel);
+ }
+
+ private void createDialog() {
+ getContentPane().add(panelTextFields, BorderLayout.CENTER);
+ getContentPane().add(panelButtons, BorderLayout.SOUTH);
+ makeDialogVisible();
+ }
+
+ private void fillDataComponents() {
+ try {
+ DbType dbType = Settings.getDatabaseType();
+ if (dbType == DbType.PostgreSQL) {
+ String host = Settings.getHost();
+ String dbName = Settings.getDatabase();
+ String user = Settings.getUser();
+ String pass = Settings.getPassword();
+ if (!host.isBlank() && !dbName.isBlank() && !user.isBlank() && !pass.isBlank()) {
+ tfHost.setText(host.strip());
+ tfDbName.setText(dbName.strip());
+ tfUser.setText(user.strip());
+ tfPass.setText(pass.strip());
+ cbDbType.setSelectedItem(dbType.name());
+
+ String port;
+ try {
+ port = Integer.toString(Settings.getPort());
+ } catch (Exception e) {
+ port = Const.EMPTY_STRING;
+ }
+ tfPort.setText(port);
+ }
+ } else {
+ fillDataComponentsWithDefaultValues();
+ }
+ } catch (SQLException e) {
+ fillDataComponentsWithDefaultValues();
+ }
+ }
+
+ private void fillDataComponentsWithDefaultValues() {
+ tfHost.setText(DEFAULT_HOST);
+ tfPort.setText(DEFAULT_POST);
+ cbDbType.setSelectedItem(DbType.PostgreSQL.name());
+ }
+
+ private void addListeners() {
+ additionalActionsOnSaveListener = new AdditionalActionsOnSaveListener(additionalActionsOnSave);
+ addWindowListener(additionalActionsOnSaveListener);
+ addWindowListener(new NoAdditinalActionsOnEscapeListener());
+ }
+
+ @Override
+ protected void actionOnHotKeyForClose() {
+ closeDialogWithoutAdditionalActions();
+ }
+
+ private static final class AdditionalActionsOnSaveListener extends WindowAdapter {
+
+ private final Runnable additionalActionsOnSave;
+
+ private AdditionalActionsOnSaveListener(Runnable additionalActionsOnSave) {
+ this.additionalActionsOnSave = additionalActionsOnSave;
+ }
+
+ @Override
+ public void windowClosed(WindowEvent event) {
+ ThreadUtil.runInThread(additionalActionsOnSave);
+ super.windowClosed(event);
+ }
+ }
+
+ private static final class NoAdditinalActionsOnEscapeListener extends WindowAdapter {
+
+ @Override
+ public void windowClosing(WindowEvent event) {
+ ((DialogDbConnection) event.getWindow()).closeDialogWithoutAdditionalActions();
+ }
+ }
+}
diff --git a/src/main/java/home/gui/component/dialog/DialogMotorcycle.java b/src/main/java/home/gui/component/dialog/DialogMotorcycle.java
index 0dfe33e..ef67c6e 100644
--- a/src/main/java/home/gui/component/dialog/DialogMotorcycle.java
+++ b/src/main/java/home/gui/component/dialog/DialogMotorcycle.java
@@ -1,14 +1,29 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component.dialog;
import javax.swing.JCheckBox;
-import home.gui.IGuiConsts;
+import home.gui.GuiConst;
import home.model.AbstractVehicle;
import home.model.Motorcycle;
import home.model.VehicleType;
@SuppressWarnings("serial")
-public final class DialogMotorcycle extends AbstractDialog {
+public final class DialogMotorcycle extends AbstractDialogVehicle {
private JCheckBox chkCradle;
@@ -19,7 +34,7 @@ public DialogMotorcycle(int width, int height, AbstractVehicle dataObj, int tblR
@Override
protected void createDataComponents() {
super.createDataComponents();
- chkCradle = new JCheckBox(IGuiConsts.HAS_CRADLE);
+ chkCradle = new JCheckBox(GuiConst.HAS_CRADLE);
if (!isNewDataObj) {
chkCradle.setSelected(((Motorcycle) dataObj).hasCradle());
diff --git a/src/main/java/home/gui/component/dialog/DialogTruck.java b/src/main/java/home/gui/component/dialog/DialogTruck.java
index d7f55dd..7c05f6e 100644
--- a/src/main/java/home/gui/component/dialog/DialogTruck.java
+++ b/src/main/java/home/gui/component/dialog/DialogTruck.java
@@ -1,8 +1,23 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.component.dialog;
import javax.swing.JCheckBox;
-import home.gui.IGuiConsts;
+import home.gui.GuiConst;
import home.model.AbstractVehicle;
import home.model.Truck;
import home.model.VehicleType;
@@ -19,7 +34,7 @@ public DialogTruck(int width, int height, AbstractVehicle dataObj, int tblRowOfS
@Override
protected void createDataComponents() {
super.createDataComponents();
- chkCargo = new JCheckBox(IGuiConsts.TRANSPORTS_CARGO);
+ chkCargo = new JCheckBox(GuiConst.TRANSPORTS_CARGO);
if (!isNewDataObj) {
chkCargo.setSelected(((Truck) dataObj).isTransportsCargo());
diff --git a/src/main/java/home/gui/exception/CreateOpenSaveCancelException.java b/src/main/java/home/gui/exception/CreateOpenSaveCancelException.java
new file mode 100644
index 0000000..68e1fc9
--- /dev/null
+++ b/src/main/java/home/gui/exception/CreateOpenSaveCancelException.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui.exception;
+
+public final class CreateOpenSaveCancelException extends RuntimeException {
+
+ private static final long serialVersionUID = 3561574118447534122L;
+
+ public CreateOpenSaveCancelException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/home/gui/exception/SaveAsCancelException.java b/src/main/java/home/gui/exception/SaveAsCancelException.java
index 7d7fa2a..efc2f3c 100644
--- a/src/main/java/home/gui/exception/SaveAsCancelException.java
+++ b/src/main/java/home/gui/exception/SaveAsCancelException.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.exception;
public final class SaveAsCancelException extends RuntimeException {
diff --git a/src/main/java/home/gui/exception/SaveAsToSameFileException.java b/src/main/java/home/gui/exception/SaveAsToSameFileException.java
deleted file mode 100644
index 7372357..0000000
--- a/src/main/java/home/gui/exception/SaveAsToSameFileException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package home.gui.exception;
-
-public final class SaveAsToSameFileException extends RuntimeException {
-
- private static final long serialVersionUID = -4526765533335630589L;
-
- public SaveAsToSameFileException(String message) {
- super(message);
- }
-}
diff --git a/src/main/java/home/gui/exception/SaveToAlreadyExistsFileException.java b/src/main/java/home/gui/exception/SaveToAlreadyExistsFileException.java
new file mode 100644
index 0000000..050f872
--- /dev/null
+++ b/src/main/java/home/gui/exception/SaveToAlreadyExistsFileException.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui.exception;
+
+public final class SaveToAlreadyExistsFileException extends RuntimeException {
+
+ private static final long serialVersionUID = -4526765533335630589L;
+
+ public SaveToAlreadyExistsFileException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/home/gui/listener/ConnectToServerDatabaseActionListener.java b/src/main/java/home/gui/listener/ConnectToServerDatabaseActionListener.java
new file mode 100644
index 0000000..b5b32b3
--- /dev/null
+++ b/src/main/java/home/gui/listener/ConnectToServerDatabaseActionListener.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui.listener;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.sql.SQLException;
+
+import javax.swing.JLabel;
+
+import org.slf4j.Logger;
+
+import home.Settings;
+import home.db.conn.Connector;
+import home.db.dao.Dao;
+import home.db.init.DbInitializer;
+import home.gui.DataActionInGui;
+import home.gui.component.dialog.DialogDbConnection;
+import home.utils.LogUtils;
+import home.utils.Utils;
+
+/**
+ * Action listener for working with server databases.
+ *
+ * Supported: PostgreSql.
+ *
+ */
+public final class ConnectToServerDatabaseActionListener implements ActionListener {
+
+ private final Component parent;
+ private final JLabel dbLabel;
+ private final Logger log;
+
+ public ConnectToServerDatabaseActionListener(Component parent, JLabel dbLabel, Logger log) {
+ this.parent = parent;
+ this.dbLabel = dbLabel;
+ this.log = log;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ Thread.currentThread().setName("-> connect to server database");
+
+ var dialogDbConnction = new DialogDbConnection("Connect to server database", () -> {
+ try {
+ String dbTypeStr = Settings.getDatabaseType().name();
+ Thread.currentThread().setName("-> connect to %s database".formatted(dbTypeStr));
+ if (Connector.testCurrentConnection()) {
+ DbInitializer.createTableIfNotExists();
+ DataActionInGui.init(Dao.readAll());
+ dbLabel.setText(Utils.generateDbDescription());
+ }
+ } catch (SQLException e) {
+ LogUtils.logAndShowError(log, parent,
+ "Error while read selected DB.\n" + e.getLocalizedMessage(),
+ "Read selected DB error", e);
+ }
+ });
+
+ dialogDbConnction.buildDialog();
+ }
+}
diff --git a/src/main/java/home/gui/listener/CreateOrOpenActionListener.java b/src/main/java/home/gui/listener/CreateOrOpenActionListener.java
deleted file mode 100644
index 14bd9a0..0000000
--- a/src/main/java/home/gui/listener/CreateOrOpenActionListener.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package home.gui.listener;
-
-import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.IOException;
-import java.sql.SQLException;
-
-import javax.swing.JLabel;
-
-import org.slf4j.Logger;
-
-import home.Settings;
-import home.db.DbInitializer;
-import home.db.dao.DaoSQLite;
-import home.gui.DataActionInGui;
-import home.gui.component.CustomJFileChooserDb;
-import home.gui.component.CustomJFileChooserDb.ChooserDbOperation;
-import home.utils.ThreadUtil;
-import home.utils.LogUtils;
-
-public final class CreateOrOpenActionListener implements ActionListener {
-
- private final Component parent;
- private final JLabel dbLabel;
- private final Logger log;
-
- public CreateOrOpenActionListener(Component parent, JLabel dbLabel, Logger log) {
- this.parent = parent;
- this.dbLabel = dbLabel;
- this.log = log;
- }
-
- @Override
- public void actionPerformed(ActionEvent event) {
- ThreadUtil.runInThread(() -> {
- Thread.currentThread().setName("-> create or open database");
- try {
- CustomJFileChooserDb.createAndShowChooser(parent,
- ChooserDbOperation.CREATE_OR_OPEN);
- DbInitializer.createTableIfNotExists();
- DataActionInGui.init(DaoSQLite.getInstance().readAll());
- dbLabel.setText(Settings.getDbFilePath());
- } catch (IOException e) {
- LogUtils.logAndShowError(log, parent, "Error while create/open DB file.",
- "Create/Open file error.", e);
- } catch (SQLException e) {
- LogUtils.logAndShowError(log, parent,
- "Error while read selected DB file.\n" + e.getLocalizedMessage(),
- "Read selected DB error", e);
- }
- });
- }
-}
diff --git a/src/main/java/home/gui/listener/CreateOrOpenFileDatabaseActionListener.java b/src/main/java/home/gui/listener/CreateOrOpenFileDatabaseActionListener.java
new file mode 100644
index 0000000..9beb171
--- /dev/null
+++ b/src/main/java/home/gui/listener/CreateOrOpenFileDatabaseActionListener.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.gui.listener;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.sql.SQLException;
+
+import javax.swing.JLabel;
+
+import org.slf4j.Logger;
+
+import home.Settings;
+import home.db.dao.Dao;
+import home.db.init.DbInitializer;
+import home.gui.DataActionInGui;
+import home.gui.DbOperation;
+import home.gui.component.CustomJFileChooserDb;
+import home.gui.exception.CreateOpenSaveCancelException;
+import home.utils.LogUtils;
+import home.utils.ThreadUtil;
+
+/**
+ * Action listener for working with databases contained in a file.
+ *
+ * Supported: SQLite.
+ */
+public final class CreateOrOpenFileDatabaseActionListener implements ActionListener {
+
+ private final Component parent;
+ private final JLabel dbLabel;
+ private final Logger log;
+
+ public CreateOrOpenFileDatabaseActionListener(Component parent, JLabel dbLabel, Logger log) {
+ this.parent = parent;
+ this.dbLabel = dbLabel;
+ this.log = log;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ try {
+ CustomJFileChooserDb.createAndShowChooser(parent,
+ DbOperation.CREATE_OR_OPEN_FILE_DATABASE);
+ createReadDataTable();
+ } catch (CreateOpenSaveCancelException e) {
+ // to do nothing
+ return;
+ } catch (IOException e) {
+ LogUtils.logAndShowError(log, parent, "Error while create/open DB file.",
+ "Create/Open file error.", e);
+ } catch (SQLException e) {
+ LogUtils.logAndShowError(log, parent,
+ "Error while read selected DB.\n" + e.getLocalizedMessage(),
+ "Read selected DB error", e);
+ }
+ }
+
+ private void createReadDataTable() {
+ ThreadUtil.runInThread(() -> {
+ Thread.currentThread().setName("-> create/read data table");
+ try {
+ DbInitializer.createTableIfNotExists();
+ DataActionInGui.init(Dao.readAll());
+ dbLabel.setText(Settings.getDatabase());
+ } catch (SQLException e) {
+ LogUtils.logAndShowError(log, parent,
+ "Error while create/read data table.\n" + e.getLocalizedMessage(),
+ "Create/read data table error", e);
+ }
+ });
+ }
+}
diff --git a/src/main/java/home/gui/listener/ExportImportActionListener.java b/src/main/java/home/gui/listener/ExportImportActionListener.java
index 1739e4b..d469103 100644
--- a/src/main/java/home/gui/listener/ExportImportActionListener.java
+++ b/src/main/java/home/gui/listener/ExportImportActionListener.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.listener;
import java.awt.Component;
@@ -8,7 +23,6 @@
import home.gui.component.CustomJFileChooserImpExp;
import home.gui.component.CustomJFileChooserImpExp.DataFormat;
-import home.utils.ThreadUtil;
import home.utils.LogUtils;
public final class ExportImportActionListener implements ActionListener {
@@ -28,13 +42,10 @@ public ExportImportActionListener(DataFormat dataFormat,
@Override
public void actionPerformed(ActionEvent event) {
- ThreadUtil.runInThread(() -> {
- Thread.currentThread().setName("-> export/import operation");
- try {
- CustomJFileChooserImpExp.createAndShowChooser(parent, dataFomat, isImport);
- } catch (Exception e) {
- LogUtils.logAndShowError(log, parent, e.getMessage(), "Export/Import error", e);
- }
- });
+ try {
+ CustomJFileChooserImpExp.createAndShowChooser(parent, dataFomat, isImport);
+ } catch (Exception e) {
+ LogUtils.logAndShowError(log, parent, e.getMessage(), "Export/Import error", e);
+ }
}
}
\ No newline at end of file
diff --git a/src/main/java/home/gui/listener/SaveActionListener.java b/src/main/java/home/gui/listener/SaveActionListener.java
index 7c0544d..a256a56 100644
--- a/src/main/java/home/gui/listener/SaveActionListener.java
+++ b/src/main/java/home/gui/listener/SaveActionListener.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.gui.listener;
import java.awt.Component;
@@ -12,16 +27,18 @@
import org.slf4j.Logger;
import home.Settings;
-import home.db.DbInitializer;
-import home.db.dao.DaoSQLite;
+import home.db.dao.Dao;
+import home.db.init.DbInitializer;
import home.gui.DataActionInGui;
-import home.gui.IGuiConsts;
+import home.gui.DbOperation;
+import home.gui.GuiConst;
import home.gui.component.CustomJFileChooserDb;
-import home.gui.component.CustomJFileChooserDb.ChooserDbOperation;
+import home.gui.exception.CreateOpenSaveCancelException;
import home.gui.exception.SaveAsCancelException;
-import home.gui.exception.SaveAsToSameFileException;
+import home.gui.exception.SaveToAlreadyExistsFileException;
import home.utils.LogUtils;
import home.utils.ThreadUtil;
+import home.utils.Utils;
public final class SaveActionListener implements ActionListener {
@@ -40,35 +57,65 @@ public SaveActionListener(Component parent, JLabel dbLabel,
@Override
public void actionPerformed(ActionEvent event) {
+ try {
+ if (isSaveAs) {
+ try {
+ CustomJFileChooserDb.createAndShowChooser(parent, DbOperation.SAVE_AS);
+ } catch (SaveToAlreadyExistsFileException e) {
+ JOptionPane.showMessageDialog(parent, GuiConst.ALREADY_EXISTS_TEXT,
+ GuiConst.ALREADY_EXISTS_TITLE, JOptionPane.ERROR_MESSAGE);
+ return;
+ } catch (SaveAsCancelException e) {
+ // to do nothing
+ return;
+ }
+ } else {
+ try {
+ if (!Settings.hasDatabase()) {
+ CustomJFileChooserDb.createAndShowChooser(parent, DbOperation.SAVE);
+ DbInitializer.createTableIfNotExists();
+ }
+ } catch (SaveToAlreadyExistsFileException e) {
+ JOptionPane.showMessageDialog(parent, GuiConst.ALREADY_EXISTS_TEXT,
+ GuiConst.ALREADY_EXISTS_TITLE, JOptionPane.ERROR_MESSAGE);
+ return;
+ } catch (CreateOpenSaveCancelException e) {
+ // to do nothing
+ return;
+ }
+ }
+
+ saveChangesToDb();
+ } catch (IOException e) {
+ LogUtils.logAndShowError(log, parent, "Error while create/open DB file.",
+ "Create/Open file error.", e);
+ } catch (SQLException e) {
+ LogUtils.logAndShowError(log, parent,
+ "Error while work with DB.\n" + e.getMessage(),
+ "Work with DB error", e);
+ }
+ }
+
+ private void saveChangesToDb() {
ThreadUtil.runInThread(() -> {
Thread.currentThread().setName("-> save changes to database");
+
try {
if (isSaveAs) {
- try {
- CustomJFileChooserDb.createAndShowChooser(parent,
- ChooserDbOperation.SAVE_AS);
- DbInitializer.createTableIfNotExists();
- DaoSQLite.getInstance().saveAs();
- } catch (SaveAsToSameFileException e) {
- DaoSQLite.getInstance().saveAllChanges();
- } catch (SaveAsCancelException e) {
- // to do nothing
- return;
- }
+ DbInitializer.createTableIfNotExists();
+ Dao.saveAs();
} else {
- DaoSQLite.getInstance().saveAllChanges();
+ Dao.saveAllChanges();
}
- DataActionInGui.init(DaoSQLite.getInstance().readAll());
- dbLabel.setText(Settings.getDbFilePath());
- JOptionPane.showMessageDialog(parent, IGuiConsts.SAVE_TEXT,
- IGuiConsts.SAVE_TITLE, JOptionPane.INFORMATION_MESSAGE);
- } catch (IOException e) {
- LogUtils.logAndShowError(log, parent, "Error while create/open DB file.",
- "Create/Open file error.", e);
+ DataActionInGui.init(Dao.readAll());
+ dbLabel.setText(Utils.generateDbDescription());
+
+ JOptionPane.showMessageDialog(parent, GuiConst.SAVE_TEXT,
+ GuiConst.SAVE_TITLE, JOptionPane.INFORMATION_MESSAGE);
} catch (SQLException e) {
LogUtils.logAndShowError(log, parent,
- "Error while work with DB file.\n" + e.getMessage(),
+ "Error while work with DB.\n" + e.getMessage(),
"Work with DB error", e);
}
});
diff --git a/src/main/java/home/model/AbstractVehicle.java b/src/main/java/home/model/AbstractVehicle.java
index 0b36b3b..2e15eb7 100644
--- a/src/main/java/home/model/AbstractVehicle.java
+++ b/src/main/java/home/model/AbstractVehicle.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.model;
import java.io.Serializable;
@@ -7,7 +22,7 @@
import java.util.TimeZone;
public abstract sealed class AbstractVehicle
- implements Serializable permits AbstractVehicleWithTrailer,Motorcycle {
+ implements Serializable permits AbstractVehicleWithTrailer, Motorcycle {
private static final long serialVersionUID = 4228103618146673801L;
diff --git a/src/main/java/home/model/AbstractVehicleWithTrailer.java b/src/main/java/home/model/AbstractVehicleWithTrailer.java
index 8549c17..e985228 100644
--- a/src/main/java/home/model/AbstractVehicleWithTrailer.java
+++ b/src/main/java/home/model/AbstractVehicleWithTrailer.java
@@ -1,9 +1,24 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.model;
import java.util.Objects;
public abstract sealed class AbstractVehicleWithTrailer
- extends AbstractVehicle permits Car,Truck {
+ extends AbstractVehicle permits Car, Truck {
private static final long serialVersionUID = 5771617467340614253L;
diff --git a/src/main/java/home/model/Car.java b/src/main/java/home/model/Car.java
index abe077a..e544019 100644
--- a/src/main/java/home/model/Car.java
+++ b/src/main/java/home/model/Car.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.model;
import java.util.Objects;
diff --git a/src/main/java/home/model/Motorcycle.java b/src/main/java/home/model/Motorcycle.java
index ed121b9..b5c2935 100644
--- a/src/main/java/home/model/Motorcycle.java
+++ b/src/main/java/home/model/Motorcycle.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.model;
import java.util.Objects;
diff --git a/src/main/java/home/model/Truck.java b/src/main/java/home/model/Truck.java
index f0a69e9..5fa01ac 100644
--- a/src/main/java/home/model/Truck.java
+++ b/src/main/java/home/model/Truck.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.model;
import java.util.Objects;
diff --git a/src/main/java/home/model/VehicleType.java b/src/main/java/home/model/VehicleType.java
index c1564a4..0c01aaf 100644
--- a/src/main/java/home/model/VehicleType.java
+++ b/src/main/java/home/model/VehicleType.java
@@ -1,3 +1,18 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
package home.model;
public enum VehicleType {
@@ -23,7 +38,8 @@ public static VehicleType getVehicleType(String type) {
return vehicleType;
}
}
- return null;
+
+ throw new IllegalArgumentException("Wrong vehicle type received : " + type);
}
public boolean in(VehicleType... vehicleTypes) {
diff --git a/src/main/java/home/utils/CustomProperties.java b/src/main/java/home/utils/CustomProperties.java
new file mode 100644
index 0000000..1f1ee9e
--- /dev/null
+++ b/src/main/java/home/utils/CustomProperties.java
@@ -0,0 +1,242 @@
+/*******************************************************************************
+ * Copyright 2021-2024 Lenar Shamsutdinov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package home.utils;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HexFormat;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Properties without date comment for
+ * {@link java.util.Properties#store(OutputStream, String) store} method and
+ * with sorting of keys
+ */
+public final class CustomProperties extends Properties {
+
+ private static final long serialVersionUID = 693357491710031108L;
+
+ //// code for deleting a comment
+
+ @Override
+ public void store(OutputStream out, String comments)
+ throws IOException {
+ throw new UnsupportedOperationException("This method will not be implemented "
+ + "for this class. Please use 'CustomProperties.store(OutputStream out)' instead.");
+ }
+
+ public void store(OutputStream out) throws IOException {
+ store0(new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8.toString())),
+ null, false, true);
+ }
+
+ /**
+ * Modification of parent method:
+ * {@link java.util.Properties#store0(BufferedWriter, String, boolean) store0}
+ */
+ private void store0(BufferedWriter bw, String comments, boolean addDate, boolean escUnicode)
+ throws IOException {
+ if (comments != null) {
+ writeComments(bw, comments);
+ }
+ if (addDate) {
+ bw.write("#" + new Date().toString());
+ bw.newLine();
+ }
+ synchronized (this) {
+ for (Entry