diff --git a/src/me/teridax/jcash/Main.java b/src/me/teridax/jcash/Main.java index 8a392c0..784241c 100644 --- a/src/me/teridax/jcash/Main.java +++ b/src/me/teridax/jcash/Main.java @@ -1,11 +1,9 @@ package me.teridax.jcash; -import me.teridax.jcash.banking.management.BankingManagementSystem; import me.teridax.jcash.gui.IconProvider; import me.teridax.jcash.gui.Loader; +import me.teridax.jcash.gui.MainFrame; import me.teridax.jcash.gui.Utils; -import me.teridax.jcash.gui.account.AccountController; -import me.teridax.jcash.gui.login.LoginController; import me.teridax.jcash.lang.Locales; import javax.swing.*; @@ -16,82 +14,30 @@ import java.util.logging.Level; import static me.teridax.jcash.Logging.LOGGER; import static me.teridax.jcash.Logging.initializeSystemLogger; -import static me.teridax.jcash.lang.Translator.translate; public final class Main { - private static final String LOGIN_SCREEN_STRING_IDENT = "LoginScreen"; - private static final String PROFILE_SCREEN_STRING_IDENT = "ProfileScreen"; - private static final String VERSION = "v2.0.0"; - /** * Main instance of this program. Contains the primary window. */ private static Main instance; - /** - * Primary window of this program - */ - private final JFrame window; - private final CardLayout layout; - - private BankingManagementSystem bms; - - private LoginController loginMask; - private AccountController accountController; + private final MainFrame window; private Main() { - // create main window and set defaults - this.window = new JFrame(); - this.window.setTitle(translate("Cashmachine") + getInfoString()); - this.window.setLocationByPlatform(true); - this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - this.window.setIconImage(IconProvider.getWindowIcon()); - - this.layout = new CardLayout(); - this.window.getContentPane().setLayout(this.layout); - - initialize(); - } - - private String getInfoString() { - return " locale: [" + Locales.getDefaultLocale().toString() + "] " + VERSION; - } - - private void initialize() { - // create the login mask - - this.loginMask = new LoginController(); - - // when we have logged in set the account viewer as window content - this.loginMask.addAccountSelectionListener(account -> { - LOGGER.finer("account selected: " + Objects.toString(account, "null")); - accountController.setProfile(account, bms); - layout.show(window.getContentPane(), PROFILE_SCREEN_STRING_IDENT); - }); - - this.window.getContentPane().add(loginMask.getView(), LOGIN_SCREEN_STRING_IDENT); - - // create the account viewer - - this.accountController = new AccountController(); - this.window.getContentPane().add(accountController.getView(), PROFILE_SCREEN_STRING_IDENT); + this.window = new MainFrame(); } public void loadDatabase() { try { - this.bms = Loader.load(); + var bms = Loader.load(); + this.window.setBms(bms); + } catch (Exception e) { LOGGER.severe("Failed to load database: " + e.getMessage()); Utils.error("Failed to load database"); System.exit(1); } - this.loginMask.setBankingManagementSystem(bms); - showLoginScreen(); - this.window.pack(); - this.window.setResizable(false); - this.window.setLocationRelativeTo(null); - this.window.setVisible(true); } public static void main(String[] args) { @@ -181,24 +127,11 @@ public final class Main { Main.instance = new Main(); } - /** - * Shows the open dialog for selecting a database file. After selection, it then proceeds to prompt login. - * Afterward the selected account can be managed. - * This method is non-blocking and all work described is performed asynchronously on the AWT Event dispatcher. - */ - public void showLoginScreen() { - this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT); - } - - /** - * Logs the user out of the database, hiding the main window. - */ - public void logout() { - this.loginMask.logout(); - this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT); - } - public JFrame getWindow() { - return this.window; + return this.window.getWindow(); + } + + public void logout() { + this.window.logout(); } } \ No newline at end of file diff --git a/src/me/teridax/jcash/gui/MainFrame.java b/src/me/teridax/jcash/gui/MainFrame.java new file mode 100644 index 0000000..7cdc26f --- /dev/null +++ b/src/me/teridax/jcash/gui/MainFrame.java @@ -0,0 +1,101 @@ +package me.teridax.jcash.gui; + +import me.teridax.jcash.banking.management.BankingManagementSystem; +import me.teridax.jcash.gui.account.AccountController; +import me.teridax.jcash.gui.login.LoginController; +import me.teridax.jcash.lang.Locales; + +import javax.swing.*; +import java.awt.*; +import java.util.Objects; + +import static me.teridax.jcash.Logging.LOGGER; +import static me.teridax.jcash.lang.Translator.translate; + +public class MainFrame { + + private static final String LOGIN_SCREEN_STRING_IDENT = "LoginScreen"; + private static final String PROFILE_SCREEN_STRING_IDENT = "ProfileScreen"; + private static final String VERSION = "v2.0.0"; + + /** + * Primary window of this program + */ + private final JFrame window; + private final CardLayout layout; + + private BankingManagementSystem bms; + + private LoginController loginMask; + private AccountController accountController; + + public MainFrame() { + // create main window and set defaults + this.window = new JFrame(); + this.window.setTitle(translate("Cashmachine") + getInfoString()); + this.window.setLocationByPlatform(true); + this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.window.setIconImage(IconProvider.getWindowIcon()); + + this.layout = new CardLayout(); + this.window.getContentPane().setLayout(this.layout); + + initialize(); + } + + + private String getInfoString() { + return " locale: [" + Locales.getDefaultLocale().toString() + "] " + VERSION; + } + + private void initialize() { + // create the login mask + + this.loginMask = new LoginController(); + + // when we have logged in set the account viewer as window content + this.loginMask.addAccountSelectionListener(account -> { + LOGGER.finer("account selected: " + Objects.toString(account, "null")); + accountController.setProfile(account, bms); + layout.show(window.getContentPane(), PROFILE_SCREEN_STRING_IDENT); + }); + + this.window.getContentPane().add(loginMask.getView(), LOGIN_SCREEN_STRING_IDENT); + + // create the account viewer + + this.accountController = new AccountController(); + this.window.getContentPane().add(accountController.getView(), PROFILE_SCREEN_STRING_IDENT); + } + + public void setBms(BankingManagementSystem bms) { + this.bms = bms; + this.loginMask.setBankingManagementSystem(bms); + this.showLoginScreen(); + this.window.pack(); + this.window.setResizable(false); + this.window.setLocationRelativeTo(null); + this.window.setVisible(true); + } + + /** + * Shows the open dialog for selecting a database file. After selection, it then proceeds to prompt login. + * Afterward the selected account can be managed. + * This method is non-blocking and all work described is performed asynchronously on the AWT Event dispatcher. + */ + private void showLoginScreen() { + this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT); + } + + /** + * Logs the user out of the database, hiding the main window. + */ + public void logout() { + this.loginMask.logout(); + this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT); + } + + public JFrame getWindow() { + return this.window; + } +} diff --git a/src/me/teridax/jcash/gui/account/AccountController.java b/src/me/teridax/jcash/gui/account/AccountController.java index 2a629f3..49b8c37 100644 --- a/src/me/teridax/jcash/gui/account/AccountController.java +++ b/src/me/teridax/jcash/gui/account/AccountController.java @@ -58,7 +58,6 @@ public class AccountController { private void logout() { Logging.LOGGER.fine("Logging out of account"); Main.getInstance().logout(); - Main.getInstance().showLoginScreen(); } private void changeAccount() { diff --git a/src/me/teridax/jcash/gui/transfer/TransferController.java b/src/me/teridax/jcash/gui/transfer/TransferController.java index 593e6d0..351d6ae 100644 --- a/src/me/teridax/jcash/gui/transfer/TransferController.java +++ b/src/me/teridax/jcash/gui/transfer/TransferController.java @@ -33,20 +33,8 @@ public class TransferController { this.transferData = new TransferData(bms); this.view.getTransfer().addActionListener(e -> transfer()); this.view.getCancel().addActionListener(e -> view.dispose()); - this.view.getValue().getDocument().addDocumentListener(new DocumentListener() { - private void validateInputState() { - var balance = account.getBalance(); - try { - view.getValue().commitEdit(); - var amount = view.getAmount(); - view.setCommittedValue(amount, balance - amount); - view.getTransfer().setEnabled(true); - } catch (InvalidInputException | ParseException ex) { - view.setCommittedValue(0, balance); - view.getTransfer().setEnabled(false); - } - } + var validator = new DocumentListener() { @Override public void insertUpdate(DocumentEvent documentEvent) { validateInputState(); @@ -61,10 +49,40 @@ public class TransferController { public void changedUpdate(DocumentEvent documentEvent) { validateInputState(); } - }); + }; + + this.view.getValue().getDocument().addDocumentListener(validator); + this.view.getIbanTextField().getDocument().addDocumentListener(validator); + this.view.getBlzTextField().getDocument().addDocumentListener(validator); + this.view.showDialog(); } + private boolean validateTargetAccount() { + if (transferData.validateBLZ(this.view.getBlz())) { + return transferData.validateIBAN(this.view.getBlz(), view.getIban()); + } + return false; + } + + private boolean validateTransferValue() { + var balance = account.getBalance(); + try { + view.getValue().commitEdit(); + var amount = view.getAmount(); + view.setCommittedValue(amount, balance - amount); + return true; + } catch (InvalidInputException | ParseException ex) { + view.setCommittedValue(0, balance); + return false; + } + } + + private void validateInputState() { + var valid = validateTargetAccount() && validateTransferValue(); + view.getTransfer().setEnabled(valid); + } + private void transfer() { try { var amount = view.getAmount(); diff --git a/src/me/teridax/jcash/gui/transfer/TransferData.java b/src/me/teridax/jcash/gui/transfer/TransferData.java index bdcc756..03b68ce 100644 --- a/src/me/teridax/jcash/gui/transfer/TransferData.java +++ b/src/me/teridax/jcash/gui/transfer/TransferData.java @@ -46,4 +46,18 @@ public class TransferData { account.get().getPrimaryAccount().deposit(amount); } + + public boolean validateBLZ(String blz) { + return bms.getBank(blz).isPresent(); + } + + public boolean validateIBAN(String blz, String ibanString) { + var bank = bms.getBank(blz); + try { + var iban = StringDecoder.decodeUniqueIdentificationNumber(ibanString); + return bank.map(value -> value.getAccount(iban).isPresent()).orElse(false); + } catch (Exception e) { + return false; + } + } } diff --git a/src/me/teridax/jcash/gui/transfer/TransferView.java b/src/me/teridax/jcash/gui/transfer/TransferView.java index 99316a2..c8af6f2 100644 --- a/src/me/teridax/jcash/gui/transfer/TransferView.java +++ b/src/me/teridax/jcash/gui/transfer/TransferView.java @@ -179,6 +179,14 @@ public class TransferView { return blz.getText(); } + public JFormattedTextField getIbanTextField() { + return iban; + } + + public JFormattedTextField getBlzTextField() { + return blz; + } + public void dispose() { this.dialog.dispose(); }