diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f4b8cf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +/.library.txt +/out/production/Library-Management-System/Admin.class +/out/production/Library-Management-System/Book.class +/out/production/Library-Management-System/Library.class +/out/production/Library-Management-System/Manual.class +/out/production/Library-Management-System/MyApp.class +/out/production/Library-Management-System/NormalUser.class +/out/production/Library-Management-System/Rent.class +/out/production/Library-Management-System/User.class +/out/production/Library-Management-System/Updatable.class diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..0a87188 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..6f29fee --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..d5f086e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Answers/src/Admin.java b/Answers/src/Admin.java new file mode 100644 index 0000000..45d1d35 --- /dev/null +++ b/Answers/src/Admin.java @@ -0,0 +1,21 @@ + +public class Admin extends User { + private final String password; + + public Admin(String name, String phoneNumber, String password) throws IllegalArgumentException { + super(name, phoneNumber); + + // validate password + if (!password.matches(".*\\d.*") && !password.matches(".*[a-z].*") && + !password.matches(".*[A-Z].*") && !password.matches("[^(\"\\s)]*")) + throw new IllegalArgumentException("Password should contain at least one digit," + + "one capital and small letter\nand should not have \" character and white spaces."); + + this.password = password; + } + + // to verify the password + public boolean verify(String password) { + return this.password.equals(password); + } +} diff --git a/Answers/src/Book.java b/Answers/src/Book.java new file mode 100644 index 0000000..0dbb580 --- /dev/null +++ b/Answers/src/Book.java @@ -0,0 +1,105 @@ +import java.sql.*; + +public class Book implements Updatable { + private String title; + private String author; + private String description; + private int uniqueID; // unique id automatically generate in database + private boolean availabilityStatus = true; + + // two arguments constructor + public Book(String title, String author) { + this.title = title; + this.author = author; + } + + // three arguments constructor + public Book(String title, String author, String description) { + this.title = title; + this.author = author; + this.description = description; + } + + public Book(int bookID) throws Exception { + final String SQL_COMMAND = "SELECT * FROM books WHERE BookID = ?;"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, MyApp.DB_USERNAME, + MyApp.DB_PASSWORD); + PreparedStatement selectBook = connection.prepareStatement(SQL_COMMAND)){ + + selectBook.setInt(1, bookID); + + ResultSet resultSet = selectBook.executeQuery(); + + if (resultSet.next()) { + this.uniqueID = bookID; + this.title = resultSet.getString("Title"); + this.author = resultSet.getString("Author"); + this.description = resultSet.getString("Description"); + this.availabilityStatus = resultSet.getBoolean("AvailabilityStatus"); + } else + throw new Exception("Book with ID = " + bookID + " not found."); + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + System.exit(1); + } + } + + @Override + public void update() { + final String SQL_COMMAND = "SELECT BookID, AvailabilityStatus FROM books WHERE Title = ? " + + "AND Author = ?"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, + MyApp.DB_USERNAME, MyApp.DB_PASSWORD); + PreparedStatement selectID = connection.prepareStatement(SQL_COMMAND)) { + + selectID.setString(1, this.title); + selectID.setString(2, this.author); + + ResultSet resultSet = selectID.executeQuery(); + if (resultSet.next()) { + this.uniqueID = resultSet.getInt("BookID"); + this.availabilityStatus = resultSet.getBoolean("AvailabilityStatus"); + } + } catch (SQLException sqlException) { + sqlException.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + System.exit(1); + } + } + + public void setStatus(boolean availabilityStatus) { + final String SQL_COMMAND = "UPDATE books SET AvailabilityStatus = ? WHERE BookID = ?;"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, MyApp.DB_USERNAME, + MyApp.DB_PASSWORD); + PreparedStatement changeStatusCommand = connection.prepareStatement(SQL_COMMAND)){ + + changeStatusCommand.setBoolean(1, availabilityStatus); + changeStatusCommand.setInt(2, this.uniqueID); + changeStatusCommand.executeUpdate(); + + this.availabilityStatus = availabilityStatus; + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + } + } + public String getTitle() { + return title; + } + + public String getAuthor() { + return author; + } + + public String getDescription() { + return description; + } + + public int getUniqueID() { + return uniqueID; + } +} \ No newline at end of file diff --git a/Answers/src/Library.java b/Answers/src/Library.java new file mode 100644 index 0000000..df96f87 --- /dev/null +++ b/Answers/src/Library.java @@ -0,0 +1,304 @@ +import javax.naming.NoPermissionException; +import javax.sql.rowset.JdbcRowSet; +import javax.sql.rowset.RowSetProvider; +import java.io.FileNotFoundException; +import java.sql.*; +import java.util.ArrayList; +import java.util.Formatter; + +public class Library { + private String name; + private int capacity; + private String operatingHours; + private User user; // user that log in now + + public void saveLibrary() throws FileNotFoundException, SecurityException { + Formatter output = new Formatter(MyApp.PATH.toString()); + output.format("%s%n%d%n%s", name, capacity, operatingHours); + output.close(); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setCapacity(int capacity) { + this.capacity = capacity; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public String getOperatingHours() { + return operatingHours; + } + + public void setOperatingHours(String operatingHours) throws IllegalArgumentException { + { + // validate operating hours + if (!operatingHours.matches("\\d{2}-\\d{2}")) + throw new IllegalArgumentException("Invalid format (e.g. 08-20)."); + + String[] hours = operatingHours.split("-"); + if (Integer.parseInt(hours[0]) > 24 || Integer.parseInt(hours[1]) > 24) + throw new IllegalArgumentException("Invalid hours."); + } + this.operatingHours = operatingHours; + } + + // add normal user + // return the unique ID of the user + public int addUser(NormalUser user) { + final String SQL_COMMAND = "INSERT INTO users (Name, PhoneNumber, UserType," + + " RegisterTimestamp) VALUES (?, ?, ?, ?)"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, + MyApp.DB_USERNAME, MyApp.DB_PASSWORD); + PreparedStatement insertUser = connection.prepareStatement(SQL_COMMAND)) { + + insertUser.setString(1, user.getName()); + insertUser.setString(2, user.getPhoneNumber()); + insertUser.setString(3, "normal"); + insertUser.setTimestamp(4, user.getRegisterTimestamp()); + + insertUser.executeUpdate(); + } catch (SQLException sqlException) { + sqlException.printStackTrace(); + System.err.print("Connection to database failed!"); + return 0; + } + + user.update(); + return user.getUniqueID(); + } + + // add admin user + // return the unique ID of the user + public int addUser(User admin, String password) { + final String SQL_COMMAND = "INSERT INTO users (Name, PhoneNumber, UserType, Password) " + + "VALUES (?, ?, ?, ?)"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, + MyApp.DB_USERNAME, MyApp.DB_PASSWORD); + PreparedStatement insertUser = connection.prepareStatement(SQL_COMMAND)) { + + insertUser.setString(1, admin.getName()); + insertUser.setString(2, admin.getPhoneNumber()); + insertUser.setString(3, "admin"); + insertUser.setString(4, password); + + insertUser.executeUpdate(); + } catch (SQLException sqlException) { + sqlException.printStackTrace(); + System.err.print("Connection to database failed!"); + return 0; + } + + // get the unique id from database + admin.update(); + return admin.getUniqueID(); + } + + public int removeUser(int userID) throws NoPermissionException { + if (user == null || user instanceof NormalUser) + throw new NoPermissionException("You don't have permission to remove members!"); + + if (userID < this.user.getUniqueID()) + throw new NoPermissionException("You don't have permission to remove this member!"); + + for (int i = 0;; i++) { + System.out.print("Enter your password: "); + String password = MyApp.input.nextLine(); + if (((Admin) user).verify(password)) + break; + else if (i == 2) + throw new IllegalArgumentException("3 incorrect password attempts..."); + else + System.out.println("Invalid password. Try again."); + } + + final String SQL_COMMAND = "DELETE FROM users WHERE UserID = ?"; + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, + MyApp.DB_USERNAME, MyApp.DB_PASSWORD); + PreparedStatement deleteUser = connection.prepareStatement(SQL_COMMAND)) { + + deleteUser.setInt(1, userID); + return deleteUser.executeUpdate(); + } catch (SQLException sqlException) { + sqlException.printStackTrace(); + System.err.print("Connection to database failed!"); + return 0; + } + } + + // add book + public int addBook(Book book) { + final String SQL_COMMAND = "INSERT INTO books (BookID, Title, Author, Description) " + + "VALUES (?, ?, ?, ?)"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, + MyApp.DB_USERNAME, MyApp.DB_PASSWORD); + PreparedStatement insertBook = connection.prepareStatement(SQL_COMMAND)) { + + insertBook.setInt(1, book.getUniqueID()); + insertBook.setString(2, book.getTitle()); + insertBook.setString(3, book.getAuthor()); + insertBook.setString(4, book.getDescription()); + + insertBook.executeUpdate(); + } catch (SQLException sqlException) { + sqlException.printStackTrace(); + System.err.print("Connection to database failed!"); + return 0; + } + + // get the unique id from database + book.update(); + + return book.getUniqueID(); + } + + // login to library + public User login(String userID) { + User user = null; + final String SQL_COMMAND = "SELECT * FROM users WHERE UserID = ?"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, + MyApp.DB_USERNAME, MyApp.DB_PASSWORD); + PreparedStatement loginUser = connection.prepareStatement(SQL_COMMAND)) { + + loginUser.setString(1, userID); + ResultSet resultSet = loginUser.executeQuery(); + + // If there is no such user + if (!resultSet.isBeforeFirst()) + return null; + resultSet.next(); + + // get name and phone number of the user + String name = resultSet.getString("Name"); + String phoneNumber = resultSet.getString("PhoneNumber"); + + if (resultSet.getString("UserType").equals("admin")) { + String password = resultSet.getString("Password"); + user = new Admin(name, phoneNumber, password); + user.update(); + } else { + Timestamp registerTimestamp = resultSet.getTimestamp("RegisterTimestamp"); + user = new NormalUser(name, phoneNumber, registerTimestamp); + user.update(); + } + } catch (SQLException sqlException) { + sqlException.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + System.exit(1); + } + return user; + } + + public void getAvailableBooks() { + final String SQl_COMMAND = "SELECT BookID, Title, Author, Description " + + "FROM books WHERE AvailabilityStatus = 1"; + + // connect to database books and query database + try (JdbcRowSet rowSet = RowSetProvider.newFactory().createJdbcRowSet()) { + + rowSet.setUrl(MyApp.DB_URL); + rowSet.setUsername(MyApp.DB_USERNAME); + rowSet.setPassword(MyApp.DB_PASSWORD); + rowSet.setCommand(SQl_COMMAND); + rowSet.execute(); + + // process query results + ResultSetMetaData metaData = rowSet.getMetaData(); + int numberOfColumns = metaData.getColumnCount(); + System.out.printf("Available books:%n%n"); + // display rowset header + for (int i = 1; i <= numberOfColumns; i++) { + if (i > 2) + System.out.printf("%-20s\t", metaData.getColumnName(i)); + else + System.out.printf("%-15s\t", metaData.getColumnName(i)); + } + System.out.println(); + // display each row + while (rowSet.next()) + { + for (int i = 1; i <= numberOfColumns; i++) { + if (i > 2) + System.out.printf("%-20s\t", rowSet.getObject(i)); + else + System.out.printf("%-15s\t", rowSet.getObject(i)); + } + System.out.println(); + } + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + System.exit(1); + } + } + + // search books by name + public ArrayList searchBook(String bookName) { + final String SQL_COMMAND = "SELECT * FROM books WHERE Title = ? AND AvailabilityStatus = ?"; + ArrayList resultBooks = new ArrayList<>(); + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, MyApp.DB_USERNAME, + MyApp.DB_PASSWORD); + PreparedStatement searchStatement = connection.prepareStatement(SQL_COMMAND)) { + + searchStatement.setString(1, bookName); + searchStatement.setBoolean(2, true); + + ResultSet resultSet = searchStatement.executeQuery(); + + while (resultSet.next()) { + Book book = new Book(bookName, resultSet.getString("Author"), + resultSet.getString("Description")); + book.update(); + resultBooks.add(book); + } + + return resultBooks; + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed!"); + return null; + } + } + + public void returnBook(int bookID) { + // set rental date in database + final String SQL_COMMAND1 = "UPDATE rents SET ReturnDate = ? WHERE BookID = ?;"; + + // change availability status of the book + final String SQL_COMMAND2 = "UPDATE books SET AvailabilityStatus = 1 WHERE BookID = ?;"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, MyApp.DB_USERNAME, + MyApp.DB_PASSWORD); + PreparedStatement returnCommand = connection.prepareStatement(SQL_COMMAND1); + PreparedStatement changeStatus = connection.prepareStatement(SQL_COMMAND2)) { + // set rental date + returnCommand.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + returnCommand.setInt(2, bookID); + returnCommand.executeUpdate(); + + // change availability status of the book + changeStatus.setInt(1, bookID); + changeStatus.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed!"); + } + } +} diff --git a/Answers/src/Manual.java b/Answers/src/Manual.java new file mode 100644 index 0000000..469de3e --- /dev/null +++ b/Answers/src/Manual.java @@ -0,0 +1,48 @@ +public class Manual { + public static void printNormalUser() { + // command who am I + System.out.println("whoami: show who are you"); + + // command log in + System.out.println("lib login : Log in to your account"); + + // command log out + System.out.println("lib logout : Log out from your account"); + + // command hrs + System.out.println("lib get hrs : Retrieve library operating hours."); + + // command view book + System.out.println("lib get available books : View available books for rental."); + + // command rent from library + System.out.println("lib rent : Rent a book from the library."); + + // command lib get rented books + System.out.println("lib get rented books : shows your rented books"); + + // command exit + System.out.println("lib exit : exit the program"); + + // command return book + System.out.println("lib return : Return a rented book to the library."); + } + + public static void printAdmin() { + // command add book + System.out.println("lib add book : " + + "Add a new book to the library."); + + // command add member + System.out.println("lib add member " + + " : Add a new member to the library (admin privilege required)."); + + // command remove member + System.out.println("lib remove member " + + ": Remove a member from the library (admin privilege required)."); + + // command rent for member + System.out.println("lib rent " + + " : Rent a book for a specific member."); + } +} diff --git a/Answers/src/MyApp.java b/Answers/src/MyApp.java new file mode 100644 index 0000000..a092cd2 --- /dev/null +++ b/Answers/src/MyApp.java @@ -0,0 +1,577 @@ +// main class for handling the CLI + +import javax.naming.NoPermissionException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.InputMismatchException; +import java.util.Scanner; + +public class MyApp { + // database information + public static final String DB_URL = "jdbc:mysql://localhost/library"; + public static final String DB_USERNAME = "LMSjava"; + public static final String DB_PASSWORD = "lmsjava1234"; + + // library information + public static final Library library = new Library(); // our library + public static final Path PATH = Paths.get(".library.txt"); + + // scanner for input from client + public static Scanner input = new Scanner(System.in); + + public static void main(String[] args) { + // check to library is existed or not + if (!Files.exists(PATH)) { + System.out.println("Welcome to LMS(Library Management System)!"); + System.out.println("You should create your own library first\n"); + while (!createLibrary()); // first we should create a library to use it + + System.out.println("Now you should add a new admin to your library!"); + // add a new admin user + while (true) { + System.out.println("\nEnter these information about your admin:"); + try { + // get admin name + System.out.print("Name: "); + String name = input.nextLine(); + + // get admin phone number + System.out.print("Phone number: "); + String phoneNumber = input.nextLine(); + + // get admin password + System.out.print("Password: "); + String password = input.nextLine(); + + Admin admin = new Admin(name, phoneNumber, password); + + if (library.addUser(admin, password) == 0) { + // delete library file + File libraryFile = PATH.toFile(); + libraryFile.delete(); + + System.out.println("Terminating..."); + System.exit(1); + } + + library.setUser(admin); // this is log in now + System.out.printf("You are now logged in! Your ID is %s.%n", + library.getUser().getUniqueID()); + } catch (IllegalArgumentException e) { + System.err.printf("%s%n", e.getMessage()); + System.out.println("Try again."); + continue; + } + + break; + } + } + else { + try (Scanner retrieveLibrary = new Scanner(PATH)) { + library.setName(retrieveLibrary.nextLine()); + library.setCapacity(retrieveLibrary.nextInt()); + library.setOperatingHours(retrieveLibrary.next()); + + } catch (IOException e) { + System.err.printf("%s%n", e.getMessage()); + e.printStackTrace(); + } + } + // welcome to library + System.out.printf("Welcome to %s library.%n", library.getName()); + System.out.println("For more information enter command "); + System.out.println("Enter your command:"); + + while (true) { + String command = null; + + try { + if (library.getUser() == null) + System.out.print(">>> "); + else if (library.getUser() instanceof Admin) + System.out.print("Admin> "); + else + System.out.printf("%s> ", library.getUser().getName()); + command = input.nextLine(); + CLI(command.trim()); + } catch (InvalidParameterException e) { + System.err.println("Invalid username. please try again."); + } catch (IllegalArgumentException e) { + if (e.getMessage() == null) + System.out.printf("command <%s> %s%n", command.trim(), "Not Found."); + else + System.out.printf("%s%n", e.getMessage()); + } catch (ArrayIndexOutOfBoundsException e) { + System.out.printf("command <%s> %s%n", command.trim(), "Not Found."); + } catch (NoPermissionException e) { + System.out.printf("%s%n", e.getMessage()); + } catch (InputMismatchException e) { + System.out.printf("Invalid input. proccess cancled..."); + } + } + } + + private static boolean createLibrary() { + System.out.println("Please enter these information about your library:"); + + try { + System.out.print("name : "); + library.setName(input.nextLine()); + + System.out.print("capacity : "); + library.setCapacity(input.nextInt()); + input.nextLine(); + + System.out.print("operating hours (format : xx-xx): "); + library.setOperatingHours(input.nextLine()); + + library.saveLibrary(); + + System.out.println("Your library was created successfully.\n"); + } catch (InputMismatchException e) { + System.err.printf("%s%n", e.getMessage()); + System.err.println("creation was not successful. Terminating program."); + System.exit(1); // creation was not successful + + } catch (IllegalArgumentException e) { + System.err.printf("%s%n%n", e.getMessage()); + System.out.println("Try again."); + return false; + } catch (SecurityException securityException) { + System.err.println("Write permission denied. Terminating."); + System.exit(1); // terminate the program + + } catch (FileNotFoundException fileNotFoundException) { + System.err.println("Error opening file. Terminating."); + System.exit(1); // terminate the program + } + return true; + } + + public static void CLI(String command) throws IllegalArgumentException, NoPermissionException, + InputMismatchException { + if (command.equals("whoami")) + if (library.getUser() == null) + System.out.println("No one one has logged in yet."); + else + System.out.println(library.getUser()); + // command lib man + else if (command.matches("lib\\sman")) { + System.out.println("You can use these commands :\n"); + if (library.getUser() instanceof Admin) + Manual.printAdmin(); + + Manual.printNormalUser(); + } + else if (command.matches("lib\\sget\\srented\\sbooks")) { + if (library.getUser() == null) + throw new NoPermissionException("You should first login."); + else if (library.getUser() instanceof Admin) + throw new NoPermissionException("You are admin!You can't rent a book:)"); + + ArrayList books = ((NormalUser) library.getUser()).getRentBooks(); + + if (books.size() == 1) + System.out.println("Your rented book is :"); + else + System.out.println("Your rented books are: "); + + int numberOfRows = 1; + for (Book book : books) { + System.out.printf("%d.%s", numberOfRows++, book.getTitle()); + System.out.println(); + } + } + // command lib get hrs + else if (command.matches("lib\\sget\\shrs")) + System.out.print(library.getOperatingHours()); + else if (command.matches("lib\\sget\\savailable\\sbooks")) + library.getAvailableBooks(); + // command lib remove member + else if (command.matches("lib\\slogin\\s\\d+")) { + //command lib login + if (library.getUser() != null) + throw new NoPermissionException("Another account is still logged in! " + + "Log out and try again."); + String[] temp = command.split("\\s"); + library.setUser(library.login(temp[2])); + if (library.getUser() == null) + throw new InvalidParameterException(); + else if (library.getUser() instanceof NormalUser) + System.out.printf("Hello %s!You logged in successfully.%n", library.getUser().getName()); + else { + Admin adminUser = (Admin) library.getUser(); + for (int i = 0; i < 3; i++) { + System.out.printf("Enter password for %s: ", adminUser.getName()); + String password = input.nextLine(); + if (adminUser.verify(password)) { + System.out.printf("Hello %s! You logged in successfully.%n", adminUser.getName()); + return; + } else + System.out.println("Invalid password. Try again."); + } + library.setUser(null); + throw new IllegalArgumentException("3 incorrect password attempts..."); + } + } else if (command.matches("lib\\slogout")) { + if (library.getUser() == null) + System.out.println("No one has logged in yet"); + else { + System.out.printf("%s logged out successfully.%n", library.getUser().getName()); + library.setUser(null); + } + } else if (command.matches("lib\\sreturn\\s.+")) { + // return a book + String bookName = command.substring(11); + ArrayList books = ((NormalUser) library.getUser()).getRentBooks(); + boolean hasBook = false; + int bookID = 0; + for (Book book : books) + if (book.getTitle().equals(bookName)) { + hasBook = true; + bookID = book.getUniqueID(); + } + if (hasBook) { + library.returnBook(bookID); + System.out.printf("Book <%s> returned to library.%n", bookName); + } else + System.out.println("You didn't rent this book:)"); + } else if (command.matches("lib\\srent\\s\"?[^\"]*\"?\\s\"?[^\"]*\"?\\s\\d{7,}")) { + if (library.getUser() == null) + throw new NoPermissionException("You should first login."); + else if (library.getUser() instanceof NormalUser) + throw new NoPermissionException("You don't have permission to rent a book for " + + "another person."); + else + for (int i = 0; i < 3; i++) { + System.out.printf("Enter password for %s: ", library.getUser().getName()); + String password = input.nextLine(); + if (((Admin) library.getUser()).verify(password)) + break; + else if (i == 2) { + System.out.println("3 incorrect password attempts..."); + library.setUser(null); + return; + } else + System.out.println("Invalid password. Try again."); + } + command = command.substring(9); + + String[] temp = new String[2]; + for (int i = 0; i < 2; i++) { + if (command.startsWith("\"")) { + command = command.substring(1); + temp[i] = command.substring(0, command.indexOf("\"")); + command = command.replaceFirst(temp[i] + "\" ", ""); + } else { + temp[i] = command.substring(0, command.indexOf(" ")); + command = command.replaceFirst(temp[i] + " ", ""); + } + } + + String bookName = temp[0], memberName = temp[1]; + int memberID = Integer.parseInt(command); + + // get books with this name + ArrayList books = library.searchBook(bookName); + + if (books.size() == 0) { + System.out.printf("book %s not found or not available!%n", bookName); + return; + } + + Rent rent = null; + NormalUser user = null; + + try { + user = new NormalUser(memberID, memberName); + } catch (Exception e) { + System.out.println(e.getMessage()); + return; + } + + if (user.getRentBooks().size() >= 5) { + System.out.println("You have already rented 5 books and you can no longer " + + "rent a book"); + return; + } if (books.size() == 1) + rent = new Rent(books.get(0), user); + else { + System.out.println("Which book?"); + + // show selections + int numberOfRows = 1; + for (Book book : books) { + System.out.printf("%d. ID = %d, Author = %d", numberOfRows, + book.getUniqueID(), book.getAuthor()); + numberOfRows++; + } + + // select choice + int choice = 1; + for (int i = 0; i < 3; i++) { + if (library.getUser() == null) + System.out.print(">>> "); + else if (library.getUser() instanceof Admin) + System.out.print("Admin> "); + else + System.out.printf("%s> ", library.getUser().getName()); + choice = input.nextInt(); + if (choice > numberOfRows) { + if (i == 2) { + System.out.println("3 invalid choice..."); + return; + } + System.out.print("Invalid choice. please try again."); + } else + break; + } + + // create rent class + rent = new Rent(books.get(choice - 1), user); + + } + int rentalID = user.rentBook(rent); + if (rentalID == 0) + return; + System.out.printf("Book %s was rented for %s successfully.", bookName, user.getName()); + System.out.printf("rental ID = %d%n", rentalID); + } else if (command.matches("lib\\sadd\\smember\\s\"?[^\"]*\"?\\s\\+?[\\d-]+\\s?[^(\"\\s)]*")) { + // commadn lib add member + // if he didn't admin user yet throw exception + if (library.getUser() instanceof Admin) { + for (int i = 0; i < 3; i++) { + System.out.printf("Enter password for %s: ", library.getUser().getName()); + String password = input.nextLine(); + if (((Admin) library.getUser()).verify(password)) + break; + else if (i == 2) { + System.out.println("3 incorrect password attempts..."); + library.setUser(null); + return; + } else + System.out.println("Invalid password. Try again."); + } + + String name, phoneNumber; + int userID; + + String[] temp1 = command.split("\""); + if (temp1.length == 3) { + name = temp1[1].trim(); + + String[] temp2 = temp1[2].trim().split("\\s"); + phoneNumber = temp2[0].trim(); + User user; + if (temp2.length == 2) { + user = new Admin(name, phoneNumber, temp2[1].trim()); + userID = library.addUser(user, temp2[1].trim()); + } else { + user = new NormalUser(name, phoneNumber); + userID = library.addUser((NormalUser) user); + } + } else { + String[] temp = command.split("\\s"); + + if (temp.length > 6) + throw new IllegalArgumentException( + "You should use \" character to split string with space"); + + name = temp[3].trim(); + phoneNumber = temp[4].trim(); + + User user; + if (temp.length == 6) { + user = new Admin(name, phoneNumber, temp[5].trim()); + userID = library.addUser(user, temp[5].trim()); + } else { + user = new NormalUser(name, phoneNumber); + userID = library.addUser((NormalUser) user); + } + } + + // prompt the user + System.out.printf("User %s with ID = %d added to library.%n", name, userID); + } // end if (library.user instanceof Admin) + else + throw new NoPermissionException("You don't have permission to add members!"); + } else if (command.matches("lib\\sremove\\smember\\s\\d{7,}")) { + if (library.getUser() == null) + throw new NoPermissionException("You should first login."); + else if (library.getUser() instanceof NormalUser) + throw new NoPermissionException("You don't have permission to remove members."); + else + for (int i = 0; i < 3; i++) { + System.out.printf("Enter password for %s: ", library.getUser().getName()); + String password = input.nextLine(); + if (((Admin) library.getUser()).verify(password)) + break; + else if (i == 2) { + System.out.println("3 incorrect password attempts..."); + library.setUser(null); + return; + } else + System.out.println("Invalid password. Try again."); + } + + // get user id from command + int userID = Integer.parseInt(command.substring(18)); + + if (library.removeUser(userID) == 0) + throw new IllegalArgumentException("User with " + userID + " not found!"); + + System.out.printf("Account with ID = %d deleted successfully.%n", userID); + } else if (command.matches("lib\\sadd\\sbook\\s\"?[^\"]*\"?\\s\"?[^\"]*\"?\\s?(\"?[^\"]*\"?)?")) { + // command lib add book + // if he didn't admin user yet throw exception + if (library.getUser() instanceof Admin) { + String title, author; + + // delete lib add book from command + command = command.replaceFirst("lib\\sadd\\sbook\\s", ""); + + // find the name of the book + if (command.startsWith("\"")) { + title = command.substring(1, command.indexOf("\"", 1)); + + // delete title of the book from command + command = command.replaceFirst("\"" + title + "\" ", ""); + } else { + title = command.substring(0, command.indexOf(" ")); + + // delete title of the book from command + command = command.replaceFirst(title + " ", ""); + } + + // find the author of the book + if (!command.contains(" ")) { + author = command; + command = ""; + } else if (command.startsWith("\"")) { + author = command.substring(1, command.indexOf("\"", 1)); + + // delete author of the book from command + command = command.replaceFirst("\"" + author + "\" ", ""); + } else { + author = command.substring(0, command.indexOf(" ")); + + // delete author of the book from command + command = command.replaceFirst(author + " ", ""); + } + + // if command doesn't have description + if (command.equals("")) { + Book book = new Book(title.trim(), author.trim()); + int bookID = library.addBook(book); + if (bookID != 0) + System.out.printf("Book %s with ID = %d added to library.%n", book.getTitle(), + bookID); + return; + } + + String description; + + // find the desciption of the book + if (command.startsWith("\"")) { + description = command.substring(1, command.indexOf("\"", 1)); + + // delete description of the book from command + command = command.replaceFirst("\"" + description + "\"", ""); + } else if (command.contains(" ")) + throw new IllegalArgumentException( + "You should use \" character to split string with space"); + else { + description = command; + + // delete description of the book from command + command = ""; + } + + // if command has too many argument + if (!command.equals("")) + throw new IllegalArgumentException( + "You should use \" character to split string with space"); + + Book book = new Book(title.trim(), author.trim(), description.trim()); + int bookID = library.addBook(book); + if (bookID != 0) + System.out.printf("Book %s with ID = %d added to library.%n", book.getTitle(), + bookID); + } else + throw new NoPermissionException("You don't have permission to add books!"); + } else if (command.matches("lib\\srent\\s.+")) { + if (library.getUser() == null) + System.out.println("You should first login to rent a book."); + else if (library.getUser() instanceof Admin) + System.out.println("You are admin!You can't rent a book:)"); + else { + String bookName = command.substring(8).trim(); + if (bookName.startsWith("\"")) + bookName = bookName.substring(1, bookName.length() - 1); + + ArrayList books = library.searchBook(bookName); + Rent rent = null; + + if (books.size() == 0) { + System.out.printf("book %s not found or not available!%n", bookName); + return; + } else if (((NormalUser) library.getUser()).getRentBooks().size() >= 5) { + System.out.println("You have already rented 5 books and you can no longer " + + "rent a book"); + return; + } else if (books.size() == 1) + rent = new Rent(books.get(0), (NormalUser) library.getUser()); + else { + System.out.println("Which book do you want?"); + + // show selections + int numberOfRows = 1; + for (Book book : books) { + System.out.printf("%d. ID = %d, Author = %d", numberOfRows, + book.getUniqueID(), book.getAuthor()); + numberOfRows++; + } + + // select choice + int choice = 1; + for (int i = 0; i < 3; i++) { + if (library.getUser() == null) + System.out.print(">>> "); + else if (library.getUser() instanceof Admin) + System.out.print("Admin> "); + else + System.out.printf("%s> ", library.getUser().getName()); + choice = input.nextInt(); + if (choice > numberOfRows) { + if (i == 2) { + System.out.println("3 invalid choice..."); + return; + } + System.out.print("Invalid choice. please try again."); + } else + break; + } + + // create rent class + rent = new Rent(books.get(choice - 1), (NormalUser) library.getUser()); + } + int rentalID = ((NormalUser) library.getUser()).rentBook(rent); + if (rentalID == 0) + return; + System.out.println("You rented this book successfully."); + System.out.printf("rental ID = %d%n", rentalID); + } + } else if (command.matches("lib\\sexit")) { + //command lib exit + System.out.print("Bye."); + System.exit(0); + } else + throw new IllegalArgumentException(); + } +} diff --git a/Answers/src/NormalUser.java b/Answers/src/NormalUser.java new file mode 100644 index 0000000..558faa2 --- /dev/null +++ b/Answers/src/NormalUser.java @@ -0,0 +1,99 @@ +import java.sql.*; +import java.util.ArrayList; + +public class NormalUser extends User implements Updatable { + private Timestamp registerTimestamp; + private ArrayList rentBooks = new ArrayList<>(); + + public NormalUser(String name, String phoneNumber, Timestamp registerDateTime) { + super(name, phoneNumber); + this.registerTimestamp = registerDateTime; + } + + public NormalUser(String name, String phoneNumber) { + super(name, phoneNumber); + this.registerTimestamp = new Timestamp(System.currentTimeMillis()); + } + + public NormalUser(int userID, String name) throws Exception { + super(userID, name); + final String SQL_COMMAND = "SELECT RegisterTimeStamp FROM users WHERE UserID = ? " + + "AND UserType = 'normal';"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, MyApp.DB_USERNAME, + MyApp.DB_PASSWORD); + PreparedStatement selectUser = connection.prepareStatement(SQL_COMMAND)){ + + selectUser.setInt(1, userID); + ResultSet resultSet = selectUser.executeQuery(); + + if (resultSet.next()) { + registerTimestamp = resultSet.getTimestamp("RegisterTimeStamp"); + } else + throw new Exception("User with ID = " + userID + "is not a normal user."); + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + System.exit(1); + } + } + + public Timestamp getRegisterTimestamp() { + return registerTimestamp; + } + + // rent a book + public int rentBook(Rent rent) { + final String SQL_COMMAND = "INSERT INTO rents (UserID, BookID, RentalDate) VALUES (?, ?, ?);"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, MyApp.DB_USERNAME, + MyApp.DB_PASSWORD); + PreparedStatement addRentCommand = connection.prepareStatement(SQL_COMMAND)){ + + addRentCommand.setInt(1, rent.getPerson().getUniqueID()); + addRentCommand.setInt(2, rent.getBook().getUniqueID()); + addRentCommand.setTimestamp(3, rent.getRentalTimestamp()); + addRentCommand.executeUpdate(); + + rent.update(); + rent.getBook().setStatus(false); + rentBooks.add(rent.getBook()); + return rent.getRentalID(); + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed!"); + return 0; + } + } + + @Override + public void update() { + super.update(); + final String SQL_COMMAND = "SELECT * FROM rents WHERE UserID = ? AND ReturnDate IS NULL;"; + rentBooks.clear(); + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, MyApp.DB_USERNAME, + MyApp.DB_PASSWORD); + PreparedStatement selectRentBooks = connection.prepareStatement(SQL_COMMAND)) { + + selectRentBooks.setInt(1, this.getUniqueID()); + + ResultSet resultSet = selectRentBooks.executeQuery(); + + while (resultSet.next()) { + Book book = new Book(resultSet.getInt("BookID")); + rentBooks.add(book); + } + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed!"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + + public ArrayList getRentBooks() { + update(); + return rentBooks; + } +} \ No newline at end of file diff --git a/Answers/src/Rent.java b/Answers/src/Rent.java new file mode 100644 index 0000000..8d7316d --- /dev/null +++ b/Answers/src/Rent.java @@ -0,0 +1,57 @@ +// this class for simulates renting +import java.sql.*; + +public class Rent implements Updatable { + private Book book; + private NormalUser person; + private int rentalID; + private Timestamp rentalTimestamp; + + public Rent(Book book, NormalUser person) { + this.book = book; + this.person = person; + this.rentalTimestamp = new Timestamp(System.currentTimeMillis()); + } + + public Rent(Book book, NormalUser person, Timestamp rentalTimestamp) { + this.book = book; + this.person = person; + this.rentalTimestamp = rentalTimestamp; + } + + public void update() { + final String SQL_COMMAND = "SELECT RentalID FROM rents WHERE UserID = ? AND BookID = ? " + + "AND ReturnDate IS NULL;"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, + MyApp.DB_USERNAME, MyApp.DB_PASSWORD); + PreparedStatement updateRent = connection.prepareStatement(SQL_COMMAND)) { + + updateRent.setInt(1, this.person.getUniqueID()); + updateRent.setInt(2, this.book.getUniqueID()); + + ResultSet resultSet = updateRent.executeQuery(); + if (resultSet.next()) + this.rentalID = resultSet.getInt("RentalID"); + } catch (SQLException sqlException) { + sqlException.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + System.exit(1); + } + } + public Book getBook() { + return book; + } + + public NormalUser getPerson() { + return person; + } + + public int getRentalID() { + return rentalID; + } + + public Timestamp getRentalTimestamp() { + return rentalTimestamp; + } +} \ No newline at end of file diff --git a/Answers/src/Updatable.java b/Answers/src/Updatable.java new file mode 100644 index 0000000..9d7467f --- /dev/null +++ b/Answers/src/Updatable.java @@ -0,0 +1,3 @@ +public interface Updatable { + void update(); +} diff --git a/Answers/src/User.java b/Answers/src/User.java new file mode 100644 index 0000000..8d34632 --- /dev/null +++ b/Answers/src/User.java @@ -0,0 +1,85 @@ +// this class simulates the users +// and it is superclass for NormalUser and Admin +import java.sql.*; + +public class User implements Updatable { + private String name; + private int uniqueID; // unique id automatically creates in database + private String phoneNumber; + + // constructor + public User(String name, String phoneNumber) throws IllegalArgumentException { + // validate phoneNumber + String regexPhoneNumber = "(\\+989|09|00989)((0[0-5]|1[0-9]|2[0-3]|3[0-9]|9[0-6])-?\\d{3}-?\\d{4})|" + + "(99-?1[0134]{2}-?[0134]{4})|(99-?[09]{3}-?[09]{4})"; + if (phoneNumber != null && !phoneNumber.matches(regexPhoneNumber)) + throw new IllegalArgumentException("Invalid phone number!"); + + this.name = name; + this.phoneNumber = phoneNumber; + } + + protected User(int uniqueID, String name) throws Exception { + final String SQL_COMMAND = "SELECT Name, PhoneNumber FROM users WHERE UserID = ?;"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, MyApp.DB_USERNAME, + MyApp.DB_PASSWORD); + PreparedStatement selectUser = connection.prepareStatement(SQL_COMMAND)) { + + selectUser.setInt(1, uniqueID); + ResultSet resultSet = selectUser.executeQuery(); + + if (resultSet.next()) { + if (name.equals(resultSet.getString("Name"))) + this.name = name; + else + throw new Exception("The username does not match the ID"); + this.uniqueID = uniqueID; + this.phoneNumber = resultSet.getString("PhoneNumber"); + } else + throw new Exception("User with ID = " + uniqueID + "not found."); + } catch (SQLException e) { + e.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + System.exit(1); + } + } + + @Override + public void update() { + final String SQL_COMMAND = "SELECT UserID FROM users WHERE PhoneNumber = ?"; + + try (Connection connection = DriverManager.getConnection(MyApp.DB_URL, + MyApp.DB_USERNAME, MyApp.DB_PASSWORD); + PreparedStatement selectID = connection.prepareStatement(SQL_COMMAND)) { + + selectID.setString(1, this.phoneNumber); + + ResultSet resultSet = selectID.executeQuery(); + if (resultSet.next()) + this.uniqueID = resultSet.getInt("UserID"); + } catch (SQLException sqlException) { + sqlException.printStackTrace(); + System.err.print("Connection to database failed! Terminating..."); + System.exit(1); + } + } + + public String getName() { + return name; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public int getUniqueID() { + return uniqueID; + } + + @Override + // to string method of admins + public String toString() { + return String.format("You are "+ this.getName() + " with id = " + this.getUniqueID()); + } +} diff --git a/Library-Management-System.iml b/Library-Management-System.iml new file mode 100644 index 0000000..b1321ae --- /dev/null +++ b/Library-Management-System.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file