import java.util.ArrayList;
import java.util.List;
// Genre interface defining standard book categories
interface Genre {
int UNCLASSIFIED = 0, ACTION = 1, COMEDY = 2, HORROR = 3;
void setGenre(int genre);
int getGenre();
}
// Interface for objects that support password-based locking
interface PasswordLockable {
void setPassword(String password);
void lock(String password);
void unlock(String password);
boolean isLocked();
}
// Book class implementation with security and comparison features
class Book implements Genre, PasswordLockable, Comparable<Book> {
private String bookCode;
private String title;
private double price;
private int genre;
private String password;
private boolean booksLocked;
public Book(String bookCode, String title, double price, int genre) {
this.bookCode = bookCode;
this.title = title;
this.price = price;
this.genre = genre;
this.password = "";
this.booksLocked = false;
}
// Unified guard method to handle lock state checks
private boolean isUpdateAllowed() {
if (booksLocked) {
System.out.println("Book is locked, cannot update.");
return false;
}
return true;
}
// Encapsulated setters with lock validation
public void setBookCode(String bookCode) {
if (isUpdateAllowed())
this.bookCode = bookCode;
}
public String getBookCode() {
return bookCode;
}
public void setTitle(String title) {
if (isUpdateAllowed())
this.title = title;
}
public String getTitle() {
return title;
}
public void setPrice(double price) {
if (isUpdateAllowed())
this.price = price;
}
public double getPrice() {
return price;
}
public void setGenre(int genre) {
if (isUpdateAllowed())
this.genre = genre;
}
public int getGenre() {
return genre;
}
// Security management methods
public void setPassword(String password) {
this.password = password;
}
public void lock(String password) {
if (this.password.equals(password)) {
this.booksLocked = true;
System.out.println("Book is locked now.");
} else {
System.out.println("Invalid password. Book is still unlocked.");
}
}
public void unlock(String password) {
if (this.password.equals(password)) {
this.booksLocked = false;
System.out.println("Book is unlocked now.");
} else {
System.out.println("Book is still locked.");
}
}
public boolean isLocked() {
return booksLocked;
}
// Map integer constant to human-readable genre name
public String getGenreText() {
return switch (genre) {
case ACTION -> "Action";
case COMEDY -> "Comedy";
case HORROR -> "Horror";
default -> "Unclassified";
};
}
// Price-based comparison for sorting and searching
@Override
public int compareTo(Book other) {
return Double.compare(this.price, other.price);
}
// Formatted string representation of the book record
@Override
public String toString() {
return String.format("Book code: %-6s Title: %-20s Price: %10.2f Genre: %s",
bookCode, title, price, getGenreText());
}
}
// Application entry point for record processing
public class BookApp {
public static void main(String[] args) {
System.out.println("Creating 4 book records:");
Book[] books = {
new Book("A001", "Unknown Title", 0.00, Genre.UNCLASSIFIED),
new Book("B002", "Ocean Heart", 150.75, Genre.COMEDY),
new Book("C003", "Cave", 180.59, Genre.HORROR),
new Book("D004", "Master", 211.39, Genre.ACTION)
};
for (Book b : books)
System.out.println(b);
// Security feature test sequence
System.out.println("\nSet up a password. The password is PASS123");
books[0].setPassword("PASS123");
System.out.println("A password has been set up.");
System.out.println("\nFirst book record is: " + books[0]);
System.out.println("\nLock the first book record using PASS123");
books[0].lock("PASS123");
System.out.println("\nAttempt to change the price of the 1st book.");
books[0].setPrice(211.39);
System.out.println("\nTry to unlock it with a wrong password.");
books[0].unlock("WRONG");
System.out.println("\nNow use PASS123 to unlock it.");
books[0].unlock("PASS123");
// Record update sequence
System.out.println("\nThe first book's title, price, and genre have been updated:");
books[0].setTitle("A movie.");
books[0].setPrice(211.39);
books[0].setGenre(Genre.ACTION);
System.out.println(books[0]);
// Efficient single-pass search for all records sharing the maximum price
System.out.println("\nList of books that have the highest price:");
List<Book> topPricedBooks = new ArrayList<>();
double maxPrice = -1.0;
for (Book b : books) {
if (b.getPrice() > maxPrice) {
maxPrice = b.getPrice();
topPricedBooks.clear();
topPricedBooks.add(b);
} else if (Math.abs(b.getPrice() - maxPrice) < 0.001) {
topPricedBooks.add(b);
}
}
topPricedBooks.forEach(System.out::println);
}
}