This repository has been archived on 2025-07-20. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
fsad/assignment4/submission/BooksDatabaseClient.java
AKP 73d797e638
Alter 3 files
Add `BooksDatabaseClient.java`
Add `BooksDatabaseServer.java`
Add `BooksDatabaseService.java`
2023-04-29 18:21:50 +01:00

301 lines
9.3 KiB
Java

/*
* Client.java
*
* A client for accessing the books database
* A naive JavaFX for connecting to the database server and interact
* with the database.
*
* author: 2430671
*
*/
import java.io.*;
import java.net.InetAddress;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import java.lang.ClassNotFoundException;
import java.lang.IndexOutOfBoundsException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.*;
import javax.sql.rowset.CachedRowSet;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TextArea;
import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.stage.Stage;
import javafx.geometry.Insets;
import javafx.collections.ObservableList;
import javafx.collections.FXCollections;
import javafx.beans.property.StringProperty;
import javafx.beans.property.SimpleStringProperty;
public class BooksDatabaseClient extends Application {
public static BooksDatabaseClient me; //Get the application instance in javafx
public static Stage thePrimaryStage; //Get the application primary scene in javafx
private Socket clientSocket = null;
private String userCommand = null; //The user command
private CachedRowSet serviceOutcome = null; //The service outcome
//Convenient to populate the TableView
public class MyTableRecord {
private StringProperty title;
private StringProperty publisher;
private StringProperty genre;
private StringProperty rrp;
private StringProperty copyID;
public void setTitle(String value) { titleProperty().set(value); }
public String getTitle() { return titleProperty().get(); }
public void setPublisher(String value) { publisherProperty().set(value); }
public String getPublisher() { return publisherProperty().get(); }
public void setGenre(String value) { genreProperty().set(value); }
public String getGenre() { return genreProperty().get(); }
public void setRrp(String value) { rrpProperty().set(value); }
public String getRrp() { return rrpProperty().get(); }
public void setCopyID(String value) { copyIDProperty().set(value); }
public String getCopyID() { return copyIDProperty().get(); }
public StringProperty titleProperty() {
if (title == null)
title = new SimpleStringProperty(this, "");
return title;
}
public StringProperty publisherProperty() {
if (publisher == null)
publisher = new SimpleStringProperty(this, "");
return publisher;
}
public StringProperty genreProperty() {
if (genre == null)
genre = new SimpleStringProperty(this, "");
return genre;
}
public StringProperty rrpProperty() {
if (rrp == null)
rrp = new SimpleStringProperty(this, "");
return rrp;
}
public StringProperty copyIDProperty() {
if (copyID == null)
copyID = new SimpleStringProperty(this, "");
return copyID;
}
}
//Class Constructor
public BooksDatabaseClient(){
me=this;
}
//Initializes the client socket using the credentials from class Credentials.
public void initializeSocket(){
try {
clientSocket = new Socket(InetAddress.getByName(Credentials.HOST), Credentials.PORT);
} catch (Exception e) {
System.err.println("cannot open socket: " + e);
System.exit(1);
}
}
public void requestService() {
try {
System.out.println("Client: Requesting books database service for user command\n" + this.userCommand +"\n");
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
out.print(userCommand + "#");
out.flush();
}catch(IOException e){
System.out.println("Client: I/O error. " + e);
}
}
public void reportServiceOutcome() {
try {
ObjectInputStream outcomeStreamReader = new ObjectInputStream(clientSocket.getInputStream());
serviceOutcome = (CachedRowSet) outcomeStreamReader.readObject();
LinkedList<MyTableRecord> r = new LinkedList<>();
while (serviceOutcome.next()) {
MyTableRecord tr = new MyTableRecord();
tr.setTitle(serviceOutcome.getString(1));
tr.setPublisher(serviceOutcome.getString(2));
tr.setGenre(serviceOutcome.getString(3));
tr.setRrp(serviceOutcome.getString(4));
tr.setCopyID(serviceOutcome.getString(5));
r.add(tr);
}
TableView<MyTableRecord> view = (TableView<MyTableRecord>) ((GridPane) thePrimaryStage.getScene().getRoot()).getChildren().get(5);
view.setItems(FXCollections.observableList(r));
System.out.println(r +"\n====================================\n");
}catch(IOException e){
System.out.println("Client: I/O error. " + e);
}catch(ClassNotFoundException e){
System.out.println("Client: Unable to cast read object to CachedRowSet. " + e);
}catch(SQLException e){
System.out.println("Client: Can't retrieve requested attribute from result set. " + e);
}
}
//Execute client
public void execute(){
GridPane grid = (GridPane) thePrimaryStage.getScene().getRoot();
ObservableList<Node> childrens = grid.getChildren();
TextField authorInputBox = (TextField) childrens.get(1);
TextField libraryInputBox = (TextField) childrens.get(3);
//Build user message command
userCommand = authorInputBox.getText() + ";" + libraryInputBox.getText();
//Request service
try{
//Initializes the socket
this.initializeSocket();
//Request service
this.requestService();
//Report user outcome of service
this.reportServiceOutcome();
//Close the connection with the server
this.clientSocket.close();
}catch(Exception e)
{// Raised if connection is refused or other technical issue
System.out.println("Client: Exception " + e);
}
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Books Database Client");
//Create a GridPane container
GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10));
grid.setVgap(5);
grid.setHgap(5);
//Add the input boxes
Label authorLabel = new Label("Author's Surname:");
GridPane.setConstraints(authorLabel, 0, 0);
grid.getChildren().add(authorLabel);
TextField authorInputBox = new TextField ();
authorInputBox.setPromptText("Author's Surname:");
authorInputBox.setPrefColumnCount(30);
GridPane.setConstraints(authorInputBox, 1, 0);
grid.getChildren().add(authorInputBox);
Label libraryLabel = new Label("Library's city:");
GridPane.setConstraints(libraryLabel, 0, 1);
grid.getChildren().add(libraryLabel);
TextField libraryInputBox = new TextField ();
libraryInputBox.setPromptText("Library's city:");
libraryInputBox.setPrefColumnCount(30);
GridPane.setConstraints(libraryInputBox, 1, 1);
grid.getChildren().add(libraryInputBox);
//Add the service request button
Button btn = new Button();
btn.setText("Request Books Database Service");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
me.execute();
}
});
GridPane.setConstraints(btn, 0, 2, 2, 1);
grid.getChildren().add(btn);
//Add the output box
TableView<MyTableRecord> outputBox = new TableView<MyTableRecord>();
TableColumn<MyTableRecord,String> titleCol = new TableColumn<MyTableRecord,String>("Title");
TableColumn<MyTableRecord,String> publisherCol = new TableColumn<MyTableRecord,String>("Publisher");
TableColumn<MyTableRecord,String> genreCol = new TableColumn<MyTableRecord,String>("Genre");
TableColumn<MyTableRecord,String> rrpCol = new TableColumn<MyTableRecord,String>("RRP");
TableColumn<MyTableRecord,String> copyIDCol = new TableColumn<MyTableRecord,String>("Num. Copies");
titleCol.setCellValueFactory(new PropertyValueFactory("title"));
publisherCol.setCellValueFactory(new PropertyValueFactory("publisher"));
genreCol.setCellValueFactory(new PropertyValueFactory("genre"));
rrpCol.setCellValueFactory(new PropertyValueFactory("rrp"));
copyIDCol.setCellValueFactory(new PropertyValueFactory("copyID"));
@SuppressWarnings("unchecked") ObservableList<TableColumn<MyTableRecord,?>> tmp = outputBox.getColumns();
tmp.addAll(titleCol, publisherCol, genreCol, rrpCol, copyIDCol);
//Leaving this type unchecked by now... It may be convenient to compile with -Xlint:unchecked for details.
GridPane.setConstraints(outputBox, 0, 3, 2, 1);
grid.getChildren().add(outputBox);
//Adjust gridPane's columns width
ColumnConstraints col1 = new ColumnConstraints();
col1.setPercentWidth(25);
ColumnConstraints col2 = new ColumnConstraints();
col2.setPercentWidth(75);
grid.getColumnConstraints().addAll( col1, col2);
primaryStage.setScene(new Scene(grid, 505, 505));
primaryStage.show();
thePrimaryStage = primaryStage;
}
public static void main (String[] args) {
launch(args);
System.out.println("Client: Finished.");
System.exit(0);
}
}