From 688da711317cffdda7826db5ecc04811aa26d6fe Mon Sep 17 00:00:00 2001 From: AKP Date: Mon, 1 May 2023 02:31:54 +0100 Subject: [PATCH] Fix small bug (ignore if book is on loan or not) Signed-off-by: AKP --- .../java/net/akpain/BooksDatabaseService.java | 4 +- .../submission/BooksDatabaseClient.java | 301 ------------------ .../submission/BooksDatabaseServer.java | 85 ----- .../submission/BooksDatabaseService.java | 165 ---------- assignment4/submission/generate.sh | 13 + 5 files changed, 15 insertions(+), 553 deletions(-) delete mode 100644 assignment4/submission/BooksDatabaseClient.java delete mode 100644 assignment4/submission/BooksDatabaseServer.java delete mode 100644 assignment4/submission/BooksDatabaseService.java create mode 100644 assignment4/submission/generate.sh diff --git a/assignment4/src/main/java/net/akpain/BooksDatabaseService.java b/assignment4/src/main/java/net/akpain/BooksDatabaseService.java index 05e3538..fa559fa 100644 --- a/assignment4/src/main/java/net/akpain/BooksDatabaseService.java +++ b/assignment4/src/main/java/net/akpain/BooksDatabaseService.java @@ -82,8 +82,8 @@ public class BooksDatabaseService extends Thread{ String sql = "select book.title, book.publisher, book.genre, book.rrp, count(*) as \"number_available\" from bookcopy join book on bookcopy.bookid = book.bookid where\n" + "\tlibraryid = (select libraryid from \"library\" where city = ?) and\n" + - "\tbookcopy.bookid in (select bookid from book where authorid = (select authorid from author where familyname = ?)) and\n" + - "\t(onloan = false or onloan is null)\n" + + "\tbookcopy.bookid in (select bookid from book where authorid = (select authorid from author where familyname = ?))" + + // "\t and (onloan = false or onloan is null)\n" + "group by book.title, book.publisher, book.genre, book.rrp;"; // city then author name diff --git a/assignment4/submission/BooksDatabaseClient.java b/assignment4/submission/BooksDatabaseClient.java deleted file mode 100644 index 076549d..0000000 --- a/assignment4/submission/BooksDatabaseClient.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * 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 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 view = (TableView) ((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 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() { - - @Override - public void handle(ActionEvent event) { - me.execute(); - } - }); - GridPane.setConstraints(btn, 0, 2, 2, 1); - grid.getChildren().add(btn); - - //Add the output box - TableView outputBox = new TableView(); - TableColumn titleCol = new TableColumn("Title"); - TableColumn publisherCol = new TableColumn("Publisher"); - TableColumn genreCol = new TableColumn("Genre"); - TableColumn rrpCol = new TableColumn("RRP"); - TableColumn copyIDCol = new TableColumn("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> 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); - } -} diff --git a/assignment4/submission/BooksDatabaseServer.java b/assignment4/submission/BooksDatabaseServer.java deleted file mode 100644 index 482a225..0000000 --- a/assignment4/submission/BooksDatabaseServer.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * BooksDatabaseServer.java - * - * The server main class. - * This server provides a service to access the Books database. - * - * author: 2430671 - * - */ - -import java.net.Socket; -import java.net.ServerSocket; -import java.net.InetAddress; - - - -public class BooksDatabaseServer { - - private int thePort = 0; - private String theIPAddress = null; - private ServerSocket serverSocket = null; - - //Support for closing the server - //private boolean keypressedFlag = false; - - - //Class constructor - public BooksDatabaseServer(){ - //Initialize the TCP socket - thePort = Credentials.PORT; - theIPAddress = Credentials.HOST; - - //Initialize the socket and runs the service loop - System.out.println("Server: Initializing server socket at " + theIPAddress + " with listening port " + thePort); - System.out.println("Server: Exit server application by pressing Ctrl+C (Windows or Linux) or Opt-Cmd-Shift-Esc (Mac OSX)." ); - try { - //Initialize the socket - serverSocket = new ServerSocket(thePort, 1, InetAddress.getByName(theIPAddress)); - System.out.println("Server: Server at " + theIPAddress + " is listening on port : " + thePort); - } catch (Exception e){ - //The creation of the server socket can cause several exceptions; - //See https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html - System.out.println(e); - System.exit(1); - } - } - - //Runs the service loop - public void executeServiceLoop() - { - System.out.println("Server: Start service loop."); - try { - //Service loop - while (true) { - Socket sock = serverSocket.accept(); - new BooksDatabaseService(sock); - } - } catch (Exception e){ - //The creation of the server socket can cause several exceptions; - //See https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html - System.out.println(e); - } - System.out.println("Server: Finished service loop."); - } - - -/* - @Override - protected void finalize() { - //If this server has to be killed by the launcher with destroyForcibly - //make sure we also kill the service threads. - System.exit(0); - } -*/ - - public static void main(String[] args){ - //Run the server - BooksDatabaseServer server=new BooksDatabaseServer(); //inc. Initializing the socket - server.executeServiceLoop(); - System.out.println("Server: Finished."); - System.exit(0); - } - - -} diff --git a/assignment4/submission/BooksDatabaseService.java b/assignment4/submission/BooksDatabaseService.java deleted file mode 100644 index d045c18..0000000 --- a/assignment4/submission/BooksDatabaseService.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * BooksDatabaseService.java - * - * The service threads for the books database server. - * This class implements the database access service, i.e. opens a JDBC connection - * to the database, makes and retrieves the query, and sends back the result. - * - * author: 2430671 - * - */ - -import java.io.*; -//import java.io.OutputStreamWriter; - -import java.net.Socket; - -import java.util.Arrays; -import java.util.Properties; -import java.util.StringTokenizer; - -import java.sql.*; -import javax.sql.rowset.*; - //Direct import of the classes CachedRowSet and CachedRowSetImpl will fail becuase - //these clasess are not exported by the module. Instead, one needs to impor - //javax.sql.rowset.* as above. - - - -public class BooksDatabaseService extends Thread{ - - private Socket serviceSocket = null; - private String[] requestStr = new String[2]; //One slot for author's name and one for library's name. - private ResultSet outcome = null; - - //JDBC connection - private String USERNAME = Credentials.USERNAME; - private String PASSWORD = Credentials.PASSWORD; - private String URL = Credentials.URL; - - - - //Class constructor - public BooksDatabaseService(Socket aSocket){ - serviceSocket = aSocket; - this.start(); - } - - - //Retrieve the request from the socket - public String[] retrieveRequest() - { - StringBuilder sb = new StringBuilder(); - try { - BufferedReader in = new BufferedReader(new InputStreamReader(serviceSocket.getInputStream())); - int c = 0; - while (c != '#') { - c = in.read(); - if (c == 0) { - System.out.println("reading null bytes"); - System.exit(1); - } - sb.append((char) c); - } - }catch(IOException e){ - System.out.println("Service thread " + this.getId() + ": " + e); - } - - String inp = sb.toString(); - this.requestStr = inp.substring(0, inp.length() - 1).split(";"); - - // returns [0]: author, [1]: city - return this.requestStr; - } - - - //Parse the request command and execute the query - public boolean attendRequest() - { - boolean flagRequestAttended = true; - - this.outcome = null; - - String sql = "select book.title, book.publisher, book.genre, book.rrp, count(*) as \"number_available\" from bookcopy join book on bookcopy.bookid = book.bookid where\n" + - "\tlibraryid = (select libraryid from \"library\" where city = ?) and\n" + - "\tbookcopy.bookid in (select bookid from book where authorid = (select authorid from author where familyname = ?)) and\n" + - "\t(onloan = false or onloan is null)\n" + - "group by book.title, book.publisher, book.genre, book.rrp;"; - // city then author name - - try { - //Connet to the database - Properties connectionProps = new Properties(); - connectionProps.put("user", USERNAME); - connectionProps.put("password", PASSWORD); - Connection conn = DriverManager.getConnection(URL, connectionProps); - - //Make the query - PreparedStatement q = conn.prepareStatement(sql); - q.setString(1, this.requestStr[1]); // city - q.setString(2, this.requestStr[0]); // author surname - - //Process query - ResultSet res = q.executeQuery(); - RowSetFactory aFactory = RowSetProvider.newFactory() ; - CachedRowSet crs = aFactory.createCachedRowSet(); - crs.populate(res); - outcome = crs; - - //Clean up - res.close(); - q.close(); - conn.close(); - - } catch (Exception e) - { System.out.println(e); } - - return flagRequestAttended; - } - - - - //Wrap and return service outcome - public void returnServiceOutcome(){ - try { - //Return outcome - ObjectOutputStream output = new ObjectOutputStream(serviceSocket.getOutputStream()); - output.writeObject(outcome); - - System.out.println("Service thread " + this.getId() + ": Service outcome returned; " + this.outcome); - - //Terminating connection of the service socket - output.close(); - serviceSocket.close(); - }catch (IOException e){ - System.out.println("Service thread " + this.getId() + ": " + e); - } - } - - - //The service thread run() method - public void run() - { - try { - System.out.println("\n============================================\n"); - //Retrieve the service request from the socket - this.retrieveRequest(); - System.out.println("Service thread " + this.getId() + ": Request retrieved: " - + "author->" + this.requestStr[0] + "; library->" + this.requestStr[1]); - - //Attend the request - boolean tmp = this.attendRequest(); - - //Send back the outcome of the request - if (!tmp) - System.out.println("Service thread " + this.getId() + ": Unable to provide service."); - this.returnServiceOutcome(); - - }catch (Exception e){ - System.out.println("Service thread " + this.getId() + ": " + e); - } - //Terminate service thread (by exiting run() method) - System.out.println("Service thread " + this.getId() + ": Finished service."); - } - -} diff --git a/assignment4/submission/generate.sh b/assignment4/submission/generate.sh new file mode 100644 index 0000000..a98e3cb --- /dev/null +++ b/assignment4/submission/generate.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -ex + +OUTPUT_FILENAME="fsad-assignment4-2430671.zip" +TEMP_DIR=$(mktemp --directory --tmpdir=.) + +cp ../src/main/java/net/akpain/BooksDatabase*.java $TEMP_DIR +sed -i -- 's/package net.akpain;//g' $TEMP_DIR/* + +zip -j0 fsad-assignment4-2430671.zip $TEMP_DIR/* + +rm -rf $TEMP_DIR \ No newline at end of file