📄 book.java
字号:
package library;
import java.sql.*;
import java.text.*;
/**
* A class representing a book
*
* @author dms
*
*/
public class Book extends LibraryObject {
private int bookID;
private String callNumber;
private Member borrower;
private Librarian librarian;
private String dueDate;
/**
* class Book constructor
*
*/
public Book(){}
/**
* class Book constructor that runs query
* to load a set of books. Use inherited
* method <code>getNext()</code> to iterate
* through the returned Book objects.
* @param sSQL String containing SQL statement
* @throws SQLException
*/
public Book(String sSQL) throws SQLException {
ensureconnection();
mr = db.runQuery(sSQL);
}
/**
* Sets the object to a specific book based on book id
*
* @param id book id
* @return true if success, false if otherwise
*/
public boolean getBook(int id) {
ensureconnection();
String sSQL = "";
sSQL = "SELECT * FROM Book WHERE bookID = " + id;
try {
ResultSet r = db.runQuery(sSQL);
if (r.next()) {
setVariables(r);
return true;
} else
return false;
}
catch (SQLException e) {
System.err.println(e.toString());
return false;
}
}
/**
* Sets the object to first book in db
*
* @return true if success, false if otherwise
*/
public boolean getBooks() {
ensureconnection();
String sSQL = "";
sSQL = "SELECT * FROM Book ORDER BY BookID ASC";
try {
mr = db.runQuery(sSQL);
return true;
}
catch (SQLException e) {
System.err.println(e.toString());
return false;
}
}
protected void setVariables(ResultSet r) throws SQLException {
bookID = r.getInt("bookid");
callNumber = r.getString("callnumber");
if (r.getString("dueDate") == null)
dueDate = "";
else
dueDate = r.getString("dueDate");
borrower = new Member();
borrower.setConnection(db);
borrower.getMember(r.getInt("borrowerssn"));
librarian = new Librarian();
librarian.setConnection(db);
librarian.getLibrarian(r.getInt("librarianssn"));
}
/**
* Method used to determine if a book
* is currently checked out.
*
* @return boolean true if checked out, false if not checked out
*/
public boolean isCheckedOut() {
if (dueDate.equals(""))
return false;
else
return true;
}
/**
* <p>This method checks out the book to the
* specified member. The appropriate due date
* must be set, and a hold removed if it was held by
* this member.</p>
*
* @param member member who wants to check out the book
* @param librarian librarian who is checking this book out
* @return boolean true if check out succeeds, false if otherwise.
* Fills error hashtable with why the checkout failed.
*/
public boolean checkOut(Librarian librarian, Member member) throws SQLException {
if (checkOutApproved(member)) {
// Create a date three weeks from today.
final int MILLISECONDS_IN_THREE_WEEKS = 1000 * 60 * 60 * 24 * 21;
Date d = new Date(System.currentTimeMillis() + MILLISECONDS_IN_THREE_WEEKS);
// Format it nicely into a String.
SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy");
String dd = f.format(d);
// Build the SQL statement required to check out the book.
String sSQL = "UPDATE Book SET borrowerssn = " + member.getSSN() +
", librarianssn = " + librarian.getSSN() +
", duedate = '" + dd + "' " +
"WHERE bookid = " + this.getBookID();
// See if this book is being held by this member.
boolean heldByMember = false;
Hold hold = member.getHolds();
while (hold.getNext()) {
if (hold.getCallNumber().equals(this.getCallNumber())) {
heldByMember = true;
break;
}
}
if (heldByMember) {
// Since this book title is being held by this member,
// we have to use an explicit transaction to ensure
// that the UPDATE query we run to check out the book
// and the DELETE query we run to remove the hold
// both succeed or both fail.
int retry = 0;
while (retry++ < TRANSACTION_RETRIES) {
System.err.println("RETRY " + retry);
try {
db.executeQuery("BEGIN");
db.executeQuery(sSQL);
hold.releaseHold();
db.executeQuery("COMMIT");
return true;
} catch (SQLException se) {
try {
db.executeQuery("ROLLBACK");
} catch (SQLException se1) {
System.err.println(se1.toString());
}
}
}
setErrors("checkoutbook","There was an unknown exception encountered.");
return false;
} else {
// No hold is being removed, so we
// simply execute the UPDATE query.
try {
db.executeQuery(sSQL);
return true;
} catch (SQLException se2) {
System.err.println(se2.toString());
setErrors("checkoutbook","There was an unknown exception encountered.");
return false;
}
}
} else
return false;
}
/**
*
* Method checkOutApproved has
* to check the following conditions before
* allowing a book to be checked out
* <ol>
* <li>Make sure the book isn't already checked out</li>
* <li>Make sure the book title doesn't have a higher
* priority hold by another member</li>
* <li>Make sure the member doesn't have the maximum
* allowable number of books already checked out</li>
* </ol>
* If all of these conditions are met, then the
* book can be checked out.
*
* @param member member who wished to check out book
* @return boolean true if approved, false if otherwise
* @throws SQLException
*/
private boolean checkOutApproved(Member member) throws SQLException {
clearErrors();
boolean approved = true;
// See if checked out (and by who)
if (this.isCheckedOut()) {
if (this.getBorrower().equals(member))
setErrors("checkoutbook", "This book is currently checked out by this member");
else
setErrors("checkoutbook", "This book is currently checked out by another member");
approved = false;
}
// See if another member has a higher priority hold on this title
BookTitle bookTitle = new BookTitle();
bookTitle.setConnection(db);
bookTitle.getBookTitle(this.getCallNumber());
// We have to check the holds, if the number of
// holds on this title exceeds the number of
// available copies.
int available = bookTitle.getAvailableBookCount();
int holds = bookTitle.getHoldCount();
System.err.println("available: " + available + " holds: " + holds);
if (holds >= available && available > 0) {
// We must make sure that this member has a high enough
// priority hold to checkout this book. For example,
// if a title has 2 available copies, and 3 members have
// holds on this title, this member (in order to check out)
// must have either the oldest, or second oldest hold.
// This can be basically thought of as a queue, so if
// one copy is available, and multiple holds exist, the
// person at the front of the queue (the one with who
// placed their hold first) gets to check it out. But if
// the number of available copies is greater than 1, say n,
// then not just the first person in the queue can check out the book,
// but anyone from 1 to n in the queue can also.
Hold hold = bookTitle.getHolds();
int i = 0;
boolean highEnoughPriority = false;
while (i < holds && i < available) {
hold.getNext();
if (hold.getHolder().equals(member)) {
highEnoughPriority = true;
break;
}
i++;
}
if (!highEnoughPriority) {
setErrors("checkoutbook", "This title is currently held for another member");
approved = false;
}
}
// Make sure this member does not already have the maximum
// allowed number of books checked out.
if (member.getCheckedOutBookCount() == member.MAXIMUM_ALLOWED_CHECKOUT) {
setErrors("checkoutmember", "This member already has the maximum allowed number of checked out books");
approved = false;
}
return approved;
}
/**
* <p>This method checks in a book. Method checkIn
* must check to make sure that the book is currently
* checked out before it can check in.</p>
*
* @return boolean true if check in succeeds, false if otherwise.
* Fills error hashtable with why the checkin failed.
* @throws SQLException
*/
public boolean checkIn() throws SQLException {
clearErrors();
if (this.isCheckedOut()) {
String sql = "UPDATE Book SET borrowerssn = null, librarianssn = null, duedate = null " +
"WHERE BookID = " + this.getBookID();
db.executeQuery(sql);
return true;
} else {
setErrors("checkinbook", "This book is not checked out");
return false;
}
}
/**
* Accessor for book id
* @return int
*/
public int getBookID() {return bookID;}
/**
* Accessor for Call Number
* @return String
*/
public String getCallNumber() {return callNumber;}
/**
* Accessor for due date
* @return String
*/
public String getDueDate() {return dueDate;}
/**
* Accessor for borrower
* @return Member
*/
public Member getBorrower() {
return borrower;
}
/**
* Accessor for librarian
* @return Librarian
*/
public Librarian getLibrarian() {return librarian;}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -