Clean initial

This commit is contained in:
Imbus 2024-02-06 03:28:24 +01:00
commit a2035a8486
21 changed files with 1193 additions and 0 deletions

View file

@ -0,0 +1,63 @@
package datamodel;
/**
* CurrentUser represents the current user that has logged on to
* the movie booking system. It is a singleton class.
*/
public class CurrentUser {
/**
* The single instance of this class
*/
private static CurrentUser instance;
/**
* The name of the current user.
*/
private String currentUserId;
/**
* Create a CurrentUser object.
*/
private CurrentUser() {
currentUserId = null;
}
/**
* Returns the single instance of this class.
*
* @return The single instance of the class.
*/
public static CurrentUser instance() {
if (instance == null)
instance = new CurrentUser();
return instance;
}
/**
* Check if a user has logged in.
*
* @return true if a user has logged in, false otherwise.
*/
public boolean isLoggedIn() {
return currentUserId != null;
}
/**
* Get the user id of the current user. Should only be called if
* a user has logged in.
*
* @return The user id of the current user.
*/
public String getCurrentUserId() {
return currentUserId == null ? "<none>" : currentUserId;
}
/**
* A new user logs in.
*
* @param userId The user id of the new user.
*/
public void loginAs(String userId) {
currentUserId = userId;
}
}

View file

@ -0,0 +1,88 @@
package datamodel;
import java.sql.*;
/**
* Database is a class that specifies the interface to the
* movie database. Uses JDBC and the MySQL Connector/J driver.
*/
public class Database {
/**
* The database connection.
*/
private Connection conn;
/**
* Create the database interface object. Connection to the database
* is performed later.
*/
public Database() {
conn = null;
}
/* --- TODO: Change this method to fit your choice of DBMS --- */
/**
* Open a connection to the database, using the specified user name
* and password.
*
* @param userName The user name.
* @param password The user's password.
* @return true if the connection succeeded, false if the supplied
* user name and password were not recognized. Returns false also
* if the JDBC driver isn't found.
*/
public boolean openConnection(String userName, String password) {
try {
// Connection strings for included DBMS clients:
// [MySQL] jdbc:mysql://[host]/[database]
// [PostgreSQL] jdbc:postgresql://[host]/[database]
// [SQLite] jdbc:sqlite://[filepath]
// Use "jdbc:mysql://puccini.cs.lth.se/" + userName if you using our shared server
// If outside, this statement will hang until timeout.
conn = DriverManager.getConnection
("jdbc:sqlite:movieBookings.db3", userName, password);
}
catch (SQLException e) {
System.err.println(e);
e.printStackTrace();
return false;
}
return true;
}
/**
* Close the connection to the database.
*/
public void closeConnection() {
try {
if (conn != null)
conn.close();
}
catch (SQLException e) {
e.printStackTrace();
}
conn = null;
System.err.println("Database connection closed.");
}
/**
* Check if the connection to the database has been established
*
* @return true if the connection has been established
*/
public boolean isConnected() {
return conn != null;
}
public Show getShowData(String mTitle, String mDate) {
Integer mFreeSeats = 42;
String mVenue = "Kino 2";
/* --- TODO: add code for database query --- */
return new Show(mTitle, mDate, mVenue, mFreeSeats);
}
/* --- TODO: insert more own code here --- */
}

View file

@ -0,0 +1,38 @@
package datamodel;
// Container for the booking data
public class Reservation {
private int bookingId;
private String movieTitle;
private String performanceDate;
private String theatreName;
public Reservation() {
this(-1, "N/A", "N/A", "N/A");
}
// constructor
public Reservation(int bookingId, String movieTitle, String performanceDate, String theatreName) {
this.bookingId = bookingId;
this.movieTitle = movieTitle;
this.performanceDate = performanceDate;
this.theatreName = theatreName;
}
// getters
public int getBookingId() {
return bookingId;
}
public String getMovieTitle() {
return movieTitle;
}
public String getPerformanceDate() {
return performanceDate;
}
public String getTheatreName() {
return theatreName;
}
}

View file

@ -0,0 +1,39 @@
package datamodel;
// Container for the database data
/* --- TODO: Modify as needed --- */
public class Show {
// attributes associated with database columns
private String title;
private String date;
private String venue;
private Integer freeSeats;
// constructor for "no show"
public Show() {
init("","","",-1);
}
// constructor defining all content
public Show(String t, String d, String v, Integer fs) {
init(t,d,v,fs);
}
// constructor defining only the title
public Show(String t) {
init(t,"","",-1);
}
// all constructors use this
private void init(String t, String d, String v, Integer fs) {
title = t; date = d; venue = v; freeSeats = fs;
}
// getters
public String getTitle() { return title; }
public String getDate() { return date; }
public String getVenue() { return venue; }
public Integer getSeats() { return freeSeats; }
}

View file

@ -0,0 +1,12 @@
package gui;
import javafx.application.Application;
/**
* The application entry-point, the location of the primary main function.
*/
public class App {
public static void main(String[] args) {
Application.launch(MainApplication.class, args);
}
}

146
src/main/java/gui/BookingTab.java Executable file
View file

@ -0,0 +1,146 @@
package gui;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Button;
import javafx.scene.text.Text;
import java.util.List;
import datamodel.CurrentUser;
import datamodel.Database;
import datamodel.Show;
import java.util.ArrayList;
public class BookingTab {
// top context message
@FXML private Text topContext;
// bottom message
@FXML private Text bookMsg;
// table references
@FXML private ListView<String> moviesList;
@FXML private ListView<String> datesList;
// show info references
@FXML private Label showTitle;
@FXML private Label showDate;
@FXML private Label showVenue;
@FXML private Label showFreeSeats;
// booking button
@FXML private Button bookTicket;
private Database db;
private Show crtShow = new Show();
public void initialize() {
System.out.println("Initializing BookingTab");
// set up listeners for the movie list selection
moviesList.getSelectionModel().selectedItemProperty().addListener(
(obs, oldV, newV) -> {
// need to update the date list according to the selected movie
// update also the details on the right panel
String movie = newV;
fillDatesList(newV);
fillShow(movie,null);
});
// set up listeners for the date list selection
datesList.getSelectionModel().selectedItemProperty().addListener(
(obs, oldV, newV) -> {
// need to update the details according to the selected date
String movie = moviesList.getSelectionModel().getSelectedItem();
String date = newV;
fillShow(movie, date);
});
// set up booking button listener
// one can either use this method (setup a handler in initialize)
// or directly give a handler name in the fxml, as in the LoginTab class
bookTicket.setOnAction(
(event) -> {
String movie = moviesList.getSelectionModel().getSelectedItem();
String date = datesList.getSelectionModel().getSelectedItem();
/* --- TODO: should attempt to book a ticket via the database --- */
/* --- do not forget to report booking number! --- */
/* --- update the displayed details (free seats) --- */
report("Booked one ticket to "+movie+" on "+date);
});
report("Ready.");
}
// helpers
// updates user display
private void fillStatus(String usr) {
if(usr.isEmpty()) topContext.setText("You must log in as a known user!");
else topContext.setText("Currently logged in as " + usr);
}
private void report(String msg) {
bookMsg.setText(msg);
}
public void setDatabase(Database db) {
this.db = db;
}
private void fillNamesList() {
List<String> allmovies = new ArrayList<String>();
// query the database via db
/* --- TODO: replace with own code --- */
allmovies.add("Pulp Fiction");
allmovies.add("The Big Lebowski");
allmovies.add("Whiplash");
/* --- END TODO --- */
moviesList.setItems(FXCollections.observableList(allmovies));
// remove any selection
moviesList.getSelectionModel().clearSelection();
}
private void fillDatesList(String m) {
List<String> alldates = new ArrayList<String>();
if(m!=null) {
// query the database via db
/* --- TODO: replace with own code --- */
alldates.add("2016-02-01");
alldates.add("2016-01-15");
/* --- END TODO --- */
}
datesList.setItems(FXCollections.observableList(alldates));
// remove any selection
datesList.getSelectionModel().clearSelection();
}
private void fillShow(String movie, String date) {
if(movie==null) // no movie selected
crtShow = new Show();
else if(date==null) // no date selected yet
crtShow = new Show(movie);
else // query the database via db
crtShow = db.getShowData(movie, date);
showTitle.setText(crtShow.getTitle());
showDate.setText(crtShow.getDate());
showVenue.setText(crtShow.getVenue());
if(crtShow.getSeats() >= 0) showFreeSeats.setText(crtShow.getSeats().toString());
else showFreeSeats.setText("-");
}
// called in case the user logged in changed
public void userChanged() {
fillStatus(CurrentUser.instance().getCurrentUserId());
fillNamesList();
fillDatesList(null);
fillShow(null,null);
}
}

71
src/main/java/gui/LoginTab.java Executable file
View file

@ -0,0 +1,71 @@
package gui;
import datamodel.CurrentUser;
import datamodel.Database;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.text.Text;
import javafx.scene.control.TextField;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.*;
// controller for both the top tabs and login tab!
public class LoginTab {
@FXML private Text actiontarget;
@FXML private TextField username;
private BookingTab bookingTabCtrl;
private Database db;
@FXML protected void handleSubmitButtonAction(ActionEvent event) {
if(!db.isConnected()) {
// inform the user that there is no check against the database
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Login fail");
alert.setHeaderText(null);
alert.setContentText("No database connection! Cannot check user credentials.");
alert.showAndWait();
} else {
String uname = username.getText();
/* --- TODO: add code to query the database credentials --- */
// could be if(!db.login(uname)) alert...
// inform the user that there is no check against the database
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Login fail");
alert.setHeaderText(null);
alert.setContentText("No user check implemented yet!");
alert.showAndWait();
/* --- END TODO --- */
// setting the user name
CurrentUser.instance().loginAs(uname);
// inform the user about logging in
actiontarget.setText("Sign in user "+uname);
// inform booking tab of user change
bookingTabCtrl.userChanged();
}
}
public void initialize() {
System.out.println("Initializing LoginTab.");
}
// helpers
// use this pattern to send data down to controllers at initialization
public void setBookingTab(BookingTab bookingTabCtrl) {
System.out.println("LoginTab sets bookingTab:"+bookingTabCtrl);
this.bookingTabCtrl = bookingTabCtrl;
}
public void setDatabase(Database db) {
this.db = db;
}
}

View file

@ -0,0 +1,65 @@
package gui;
import datamodel.Database;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.stage.Stage;
/**
* The Main JavaFX Application class
*
* Use the main method in App to start it all.
*/
public class MainApplication extends Application {
private Database db = new Database();
@Override
public void start(Stage primaryStage) {
try {
// BorderPane root = new BorderPane();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/TopTab.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root,600,440);
scene.getStylesheets().add(getClass().getResource("/application.css").toExternalForm());
// obtain main controller
TopTabView wc = (TopTabView) loader.getController();
// make the database object visible to the controller
wc.setDatabase(db);
primaryStage.setTitle("Movie Booking System");
primaryStage.setScene(scene);
primaryStage.show();
// opening database connection
/* --- TODO: change xxx to your user name, yyy to your password --- */
if(!db.openConnection("xxx", "yyy")) {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Database error");
alert.setHeaderText(null);
alert.setContentText("Could not connect to the database! Check console for details.");
alert.showAndWait();
}
} catch(Exception e) {
e.printStackTrace();
}
}
public void stop() {
// close the database here
db.closeConnection();
try {
super.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,64 @@
package gui;
import java.util.Arrays;
import java.util.List;
import datamodel.Reservation;
import datamodel.Database;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
public class ReservationsTab {
@FXML private TableView<Reservation> tableReservations = new TableView<>();
private Database db;
public void setDatabase(Database db) {
this.db = db;
}
@SuppressWarnings("unchecked")
public void initialize() {
System.out.println("Initializing BookingListTab");
// Create Column ID
TableColumn<Reservation, Integer> bookingIdColumn = new TableColumn<>("ID");
bookingIdColumn.setPrefWidth(75);
bookingIdColumn.setCellValueFactory(new PropertyValueFactory<Reservation, Integer>("bookingId"));
// Create Column MovieTitle
TableColumn<Reservation, String> movieTitleColumn = new TableColumn<>("Movie Title");
movieTitleColumn.setPrefWidth(150);
movieTitleColumn.setCellValueFactory(new PropertyValueFactory<Reservation, String>("movieTitle"));
// Create Column Date
TableColumn<Reservation, String> performanceDateColumn = new TableColumn<>("Date");
performanceDateColumn.setPrefWidth(120);
performanceDateColumn.setCellValueFactory(new PropertyValueFactory<Reservation, String>("performanceDate"));
// Create Column Theatre Name
TableColumn<Reservation, String> theatreNameColumn = new TableColumn<>("Theatre Name");
theatreNameColumn.setPrefWidth(150);
theatreNameColumn.setCellValueFactory(new PropertyValueFactory<Reservation, String>("theatreName"));
//Insert all columns
tableReservations.getColumns()
.addAll(bookingIdColumn,
movieTitleColumn,
performanceDateColumn,
theatreNameColumn);
}
/**
* Refresh the table view, by getting and replacing the tables content.
*/
public void updateList() {
/* --- TODO: replace with own code using the database object instead --- */
System.out.println("Update booking list called.");
List<Reservation> bookings = Arrays.asList(new Reservation(1, "Star Wars", "2019-12-30", "Bio Söder"));
tableReservations.getItems().setAll(bookings);
}
}

View file

@ -0,0 +1,40 @@
package gui;
import javafx.scene.Parent;
import javafx.scene.control.Tab;
import datamodel.Database;
import javafx.fxml.FXML;
public class TopTabView {
@FXML private Parent aLoginTab;
@FXML private LoginTab aLoginTabController;
@FXML private Parent aBookingTab;
@FXML private BookingTab aBookingTabController;
@FXML private Tab reservationTab;
@FXML private ReservationsTab aReservationTabController;
public void initialize() {
System.out.println("Initializing TopTabView");
// send the booking controller reference to the login controller
// in order to pass data between the two
aLoginTabController.setBookingTab(aBookingTabController);
// When selection is changed, update the list
reservationTab.setOnSelectionChanged(e -> {
if(reservationTab.isSelected()) {
// Initiate an update
aReservationTabController.updateList();
}
});
}
public void setDatabase(Database db) {
aLoginTabController.setDatabase(db);
aBookingTabController.setDatabase(db);
aReservationTabController.setDatabase(db);
}
}