diff --git a/src/main/java/billgates/Main.java b/src/main/java/billgates/Main.java index 30f9fc4..895d164 100644 --- a/src/main/java/billgates/Main.java +++ b/src/main/java/billgates/Main.java @@ -1,9 +1,9 @@ package billgates; import billgates.database.MySQLDatabaseGateway; -import billgates.entities.User; import billgates.interface_adapters.BillPanelUpdatable; import billgates.interface_adapters.DatabaseGateway; +import billgates.interface_adapters.UserJoinUpdatable; import billgates.use_cases.bill_update.BillUpdateController; import billgates.use_cases.bill_update.BillUpdateOutputPort; import billgates.use_cases.bill_update.BillUpdatePresenter; @@ -11,6 +11,7 @@ import billgates.use_cases.delete_entry.DeleteEntryController; import billgates.use_cases.delete_entry.DeleteEntryInputPort; import billgates.use_cases.delete_entry.DeleteEntryUseCase; +import billgates.use_cases.user_join.*; import billgates.view.gui.MainFrame; import javax.swing.*; @@ -29,18 +30,14 @@ public static void main(String[] args){ } catch (UnsupportedLookAndFeelException ignored) { } - // TODO: remove this: this is for debugging purposes - User.getInstance(0, "Scott", "12345678", 0); - // init database gateway DatabaseGateway databaseGateway = new MySQLDatabaseGateway(); - databaseGateway.setUserId(User.getInstance().getBillId()); - // init the main frame MainFrame mainFrame = new MainFrame(); mainFrame.setBillUpdateController(initBillUpdateUseCase(databaseGateway, mainFrame.getBillPanel())); mainFrame.setDeleteEntryController(initDeleteEntryUseCase(databaseGateway)); + mainFrame.setUserJoinController(initUserJoinUseCase(databaseGateway, mainFrame.getActionPanel())); mainFrame.setVisible(true); // init column widths @@ -60,6 +57,13 @@ private static DeleteEntryController initDeleteEntryUseCase(DatabaseGateway data return new DeleteEntryController(useCase); } + private static UserJoinController initUserJoinUseCase(DatabaseGateway databaseGateway, + UserJoinUpdatable updatable) { + UserJoinOutputPort userJoinPresenter = new UserJoinPresenter(updatable); + UserJoinInputPort userJoinUseCase = new UserJoinUseCase(databaseGateway, userJoinPresenter); + return new UserJoinController(userJoinUseCase); + } + // add new functions to init all other use cases } diff --git a/src/main/java/billgates/entities/User.java b/src/main/java/billgates/entities/User.java index c4d83d8..572c51b 100644 --- a/src/main/java/billgates/entities/User.java +++ b/src/main/java/billgates/entities/User.java @@ -61,7 +61,7 @@ private User(int id, String name, String password, int billId) { } /** - * Get or create an instance of a user. + * Create the instance of User. * * @param id the id of this user * @param name the name of this user @@ -69,9 +69,8 @@ private User(int id, String name, String password, int billId) { * @param billID the main bill id of this user * @return a new user instance */ - public static User getInstance(int id, String name, String password, int billID) { - if (instance == null) - instance = new User(id, name, password, billID); + public static User createInstance(int id, String name, String password, int billID) { + instance = new User(id, name, password, billID); return instance; } diff --git a/src/main/java/billgates/use_cases/user_join/UserJoinUseCase.java b/src/main/java/billgates/use_cases/user_join/UserJoinUseCase.java index 461071c..1d4506a 100644 --- a/src/main/java/billgates/use_cases/user_join/UserJoinUseCase.java +++ b/src/main/java/billgates/use_cases/user_join/UserJoinUseCase.java @@ -1,7 +1,11 @@ package billgates.use_cases.user_join; +import billgates.database.QueryUserData; +import billgates.entities.User; import billgates.interface_adapters.DatabaseGateway; +import java.util.List; + public class UserJoinUseCase implements UserJoinInputPort { private final DatabaseGateway gateway; private final UserJoinOutputPort outputPort; @@ -13,23 +17,44 @@ public UserJoinUseCase(DatabaseGateway gateway, UserJoinOutputPort outputPort) { @Override public void join(UserJoinRequestModel model) { -// QueryUserData userData = gateway.getUserData(); -// if (!userData.getUsers().contains(model.getUsername())) { -// // TODO add the user in the database. -// -// // TODO log the user in -// outputPort.display(new UserJoinResponseModel(true, "Registered successfully")); -// } -// else { -// int userIndex = userData.getUsers().indexOf(model.getUsername()); -// if (userData.getPasswords().get(userIndex).equals(model.getPassword())) { -// // TODO log the user in -// outputPort.display(new UserJoinResponseModel(true, "Logged in successfully")); -// } else { -// outputPort.display(new UserJoinResponseModel(false, "Incorrect password " + -// "or the username already exists.")); -// } -// // TODOs above depends on the implementation of DatabaseGateway -// } + List usersData = this.gateway.getUserData(); + boolean exist = usersData.stream().anyMatch(d -> d.getUsername().equals(model.getUsername())); + // if the user does not exist + if (!exist) { + // register + // Create a QueryUserData in the database + QueryUserData tempUser = new QueryUserData(model.getUsername(), model.getPassword()); + this.gateway.insertUser(tempUser); + QueryUserData actualUser = this.gateway.getUserData(model.getUsername()); + // create a new bill + this.gateway.createBillTable(actualUser.getBillID()); + // set the database user id + this.gateway.setUserId(actualUser.getUserID()); + // Create a local User + User.createInstance(actualUser.getUserID(), actualUser.getUsername(), + actualUser.getPassword(), actualUser.getBillID()); + // Notify the user that they have successfully registered + this.outputPort.display(new UserJoinResponseModel(true, "Registered successfully")); + } + // if the user exists + else { + QueryUserData actualUser = this.gateway.getUserData(model.getUsername()); + // if the password matches + if (actualUser.getPassword().equals(model.getPassword())) { + // Create a local User + User.createInstance(actualUser.getUserID(), actualUser.getUsername(), + actualUser.getPassword(), actualUser.getBillID()); + // set the database user id + this.gateway.setUserId(actualUser.getUserID()); + // Notify the user that they have successfully login + this.outputPort.display(new UserJoinResponseModel(true, "Logged in successfully")); + } + // incorrect password + else { + // Notify the user that they couldn't log in + this.outputPort.display(new UserJoinResponseModel(false, "Incorrect password " + + "or the username already exists.")); + } + } } } diff --git a/src/main/java/billgates/view/gui/ActionPanel.java b/src/main/java/billgates/view/gui/ActionPanel.java index a6d21db..cffe684 100644 --- a/src/main/java/billgates/view/gui/ActionPanel.java +++ b/src/main/java/billgates/view/gui/ActionPanel.java @@ -1,9 +1,11 @@ package billgates.view.gui; +import billgates.interface_adapters.UserJoinUpdatable; +import billgates.use_cases.user_join.UserJoinViewModel; + import javax.swing.*; import javax.swing.border.TitledBorder; import java.awt.*; -import java.util.Arrays; import java.util.Objects; /** @@ -11,7 +13,7 @@ * * @author Charlotte, Scott */ -public class ActionPanel extends JPanel { +public class ActionPanel extends JPanel implements UserJoinUpdatable { public static final int DEFAULT_WIDTH = (int) (MainFrame.DEFAULT_WIDTH / 3.5); public static final int DEFAULT_HEIGHT = MainFrame.DEFAULT_HEIGHT; @@ -56,6 +58,9 @@ private void initSignInPanel() { // Set the size of signInPanel this.signInPanel.setMaximumSize(new Dimension(DEFAULT_SIGN_IN_PANEL_WIDTH, DEFAULT_SIGN_IN_PANEL_HEIGHT)); + // Restrict the input of usernameField (user cannot input whitespace for their username) + this.usernameField.setDocument(new RegexDocument("\\S*")); + // add and layout components // username label this.signInPanel.add(this.usernameLabel); @@ -142,46 +147,40 @@ private void initBorder() { } private void signIn() { - // Get the username and password from user + // Get the username and password from the user String userName = this.usernameField.getText(); - String userPassword = Arrays.toString(this.passwordField.getPassword()); - System.out.println("Name: " + userName); - System.out.println("Password: " + userPassword); - - // TODO: Call the controller of UserJoinUseCase - - // If the user has successfully signed in, - if (this.checkUsername() & this.checkPassword()) { - // disable the signInButton, and enable the signOutButton and addEntryButton - this.signInButton.setEnabled(false); - this.signOutButton.setEnabled(true); - this.addEntryButton.setEnabled(true); - - // the usernameField and passwordField shouldn't be editable - this.usernameField.setEditable(false); - this.passwordField.setEditable(false); - - // enable importMenu - TopMenuBar menuBar = (TopMenuBar) this.getRootPane().getJMenuBar(); - menuBar.getImportMenu().setEnabled(true); + String userPassword = String.valueOf(this.passwordField.getPassword()); - // enable billTable - BillTable billTable = this.mainFrame.getBillPanel().getBillTable(); - billTable.setVisible(true); - billTable.setEnabled(true); - - // if the user had successfully signed in, then we update the bill - SwingUtilities.invokeLater(() -> this.mainFrame.getBillUpdateController().update(-1)); + // If the username and password are legal, we should then call the controller of UserJoinUseCase + if (this.checkUsername() && this.checkPassword()) { + // Call the UserJoinController + SwingUtilities.invokeLater(() -> this.mainFrame.getUserJoinController().userJoin(userName, userPassword)); } } private boolean checkUsername() { - // Will be implemented further + int usernameLength = this.usernameField.getText().length(); + if (usernameLength == 0) { + JOptionPane.showMessageDialog(this.mainFrame, "Username cannot be empty!"); + return false; + } + else if (usernameLength > 10) { + JOptionPane.showMessageDialog(this.mainFrame, "Username exceeds the maximum length!"); + return false; + } return true; } private boolean checkPassword() { - // Will be implemented further + int passwordLength = String.valueOf(this.passwordField.getPassword()).length(); + if (passwordLength == 0) { + JOptionPane.showMessageDialog(this.mainFrame, "Password cannot be empty!"); + return false; + } + else if (passwordLength > 16) { + JOptionPane.showMessageDialog(this.mainFrame, "Password exceeds the maximum length!"); + return false; + } return true; } @@ -201,11 +200,11 @@ private void signOut() { this.passwordField.setText(""); // Disable the importMenu - TopMenuBar menuBar = (TopMenuBar) this.getRootPane().getJMenuBar(); - menuBar.getImportMenu().setEnabled(false); + TopMenuBar topMenuBar = (TopMenuBar) this.mainFrame.getJMenuBar(); + topMenuBar.getImportMenu().setEnabled(false); // Disable the billTable - BillTable billTable = this.mainFrame.getBillPanel().getBillTable(); + BillTable billTable = (BillTable) this.mainFrame.getBillPanel().getBillTable(); billTable.setEnabled(false); billTable.setVisible(false); } @@ -236,4 +235,33 @@ private void deleteEntry() { public JButton getDeleteEntryButton() { return this.deleteEntryButton; } + + @Override + public void view(UserJoinViewModel viewModel) { + // If the user join successfully, + if (viewModel.isJoined()) { + // disable the signInButton, and enable the signOutButton and addEntryButton + this.signInButton.setEnabled(false); + this.signOutButton.setEnabled(true); + this.addEntryButton.setEnabled(true); + + // the usernameField and passwordField shouldn't be editable + this.usernameField.setEditable(false); + this.passwordField.setEditable(false); + + // enable importMenu + TopMenuBar topMenuBar = (TopMenuBar) this.mainFrame.getJMenuBar(); + topMenuBar.getImportMenu().setEnabled(true); + + SwingUtilities.invokeLater(() -> this.mainFrame.getBillUpdateController().update(-2)); + + // enable billTable + BillTable billTable = this.mainFrame.getBillPanel().getBillTable(); + billTable.setVisible(true); + billTable.setEnabled(true); + } + + // Show a message dialog with whatever the text from the viewModel + JOptionPane.showMessageDialog(this.mainFrame, viewModel.getReasonRejected()); + } } diff --git a/src/main/java/billgates/view/gui/BillDemo.java b/src/main/java/billgates/view/gui/BillDemo.java deleted file mode 100644 index 2c71a0b..0000000 --- a/src/main/java/billgates/view/gui/BillDemo.java +++ /dev/null @@ -1,97 +0,0 @@ -package billgates.view.gui; - -import billgates.database.MySQLDatabaseGateway; -import billgates.entities.User; -import billgates.interface_adapters.BillPanelUpdatable; -import billgates.use_cases.bill_update.*; -import billgates.view.BillTableModel; - -import javax.swing.*; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.util.Arrays; - -/** - * Clean Architecture Layer: Frameworks & Drivers - * A demo class for demonstrating the UpdateBillUseCase. - * - * @author Scott - */ -public class BillDemo extends JFrame implements BillPanelUpdatable { - - private final JPanel contentPane = new JPanel(new BorderLayout()); - private final JTable table = new JTable(); - private final JScrollPane scrollPane = new JScrollPane(this.table); - - public BillDemo() throws HeadlessException { - super("Bill Demo"); - this.setDefaultCloseOperation(EXIT_ON_CLOSE); - this.setSize(1000, 618); - this.setResizable(false); - this.setLocation(200, 200); - this.setContentPane(this.contentPane); - - this.initTable(); - - JButton testButton = new JButton("Test"); - this.add(testButton, BorderLayout.NORTH); - testButton.addActionListener(new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - User.getInstance(0, "Scott", "12345678", 0); - MySQLDatabaseGateway gateway = new MySQLDatabaseGateway(); - gateway.initializeConnection(); - BillUpdateOutputPort presenter = new BillUpdatePresenter(BillDemo.this); - BillUpdateInputPort interactor = new BillUpdateUseCase(presenter, gateway); - interactor.updateBill(User.getInstance().getCurrentBillID()); - } - }); - } - - public static void main(String[] args) { - BillDemo frame = new BillDemo(); - frame.setVisible(true); - - // a simulation - User.getInstance(0, "Scott", "12345678", 0); - MySQLDatabaseGateway gateway = new MySQLDatabaseGateway(); - gateway.initializeConnection(); - BillUpdateOutputPort presenter = new BillUpdatePresenter(frame); - BillUpdateInputPort useCase = new BillUpdateUseCase(presenter, gateway); - BillUpdateController controller = new BillUpdateController(useCase); -// controller.update(); - } - - private void initTable() { - this.add(this.scrollPane, BorderLayout.CENTER); - this.table.setModel(new BillTableModel()); - this.table.setRowHeight(40); -// this.table.setModel(new DefaultTableModel(new Object[][]{{"1"}}, new Object[] {"1"})); - this.table.getModel().addTableModelListener(new TableModelListener() { - @Override - public void tableChanged(TableModelEvent e) { - System.out.println(e.getType()); - } - }); - } - - public JTable getTable() { - return this.table; - } - - public JScrollPane getScrollPane() { - return this.scrollPane; - } - - @Override - public void update(BillUpdateViewModel viewModel) { - BillTableModel model = (BillTableModel) this.table.getModel(); - model.setColumnNames(viewModel.getColumns()); - model.setData(viewModel.getEntries()); - System.out.println(model.getData()); - System.out.println(Arrays.toString(model.getColumnNames())); - this.table.updateUI(); - } -} diff --git a/src/main/java/billgates/view/gui/MainFrame.java b/src/main/java/billgates/view/gui/MainFrame.java index 093b3fa..b2f26ad 100644 --- a/src/main/java/billgates/view/gui/MainFrame.java +++ b/src/main/java/billgates/view/gui/MainFrame.java @@ -2,6 +2,7 @@ import billgates.use_cases.bill_update.BillUpdateController; import billgates.use_cases.delete_entry.DeleteEntryController; +import billgates.use_cases.user_join.UserJoinController; import javax.swing.*; import java.awt.*; @@ -23,6 +24,7 @@ public class MainFrame extends JFrame { private final ActionPanel actionPanel = new ActionPanel(this); private final BillPanel billPanel = new BillPanel(this); private final JMenuBar menu = new TopMenuBar(); + private UserJoinController userJoinController; // controllers will be set after constructing the view objects private BillUpdateController billUpdateController; @@ -74,4 +76,12 @@ public DeleteEntryController getDeleteEntryController() { public void setDeleteEntryController(DeleteEntryController deleteEntryController) { this.deleteEntryController = deleteEntryController; } + + public UserJoinController getUserJoinController() { + return userJoinController; + } + + public void setUserJoinController(UserJoinController userJoinController) { + this.userJoinController = userJoinController; + } } \ No newline at end of file diff --git a/src/main/java/billgates/view/gui/RegexDocument.java b/src/main/java/billgates/view/gui/RegexDocument.java new file mode 100644 index 0000000..6199608 --- /dev/null +++ b/src/main/java/billgates/view/gui/RegexDocument.java @@ -0,0 +1,29 @@ +package billgates.view.gui; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RegexDocument extends PlainDocument { + private final Pattern pattern; + + public RegexDocument(String regex) { + super(); + this.pattern = Pattern.compile(regex); + } + + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (str == null) { + return; + } + String text = this.getText(0, offs).concat(str); + Matcher matcher = this.pattern.matcher(text); + + if (matcher.matches()) { + super.insertString(offs, str, a); + } + } +}