Loyola College in Maryland

CS 201 - Computer Science I
Fall 2003


Loyola College > Department of Computer Science > CS 201 > Examples and Lecture Notes > Library Book class

Class implementation (LibraryBook.java)

import java.util.*; // for GregorianCalendar and Date
import java.text.*; // for DateFormat

/**
 * A library book.  In this simple model of a book, a book has a title and
 * an author, a due date, and a borrower.
 *
 * @author Jim Glenn
 * @version 0.1 9/26/2003
 */

public class LibraryBook
{
    // declarations of the fields

    /**
     * The title of this book.
     */

    private String title;

    /**
     * The author of this book.
     */

    private String author;

    /**
     * The name of the person who has borrowed this book, or null
     * if this book is not checked out.
     */

    private String borrower;

    /**
     * The date this book is due, or null if this book is not
     * checked out.
     */

    private GregorianCalendar dueDate;

    // Definition of the constructor

    /**
     * Creates a new book with the given title and author.  The book will
     * not be checked out, so there is no borrower and date due.
     *
     * @param t the title of the book
     * @param a the author of the book
     */

    public LibraryBook(String t, String a)
    {
	title = t;
	author = a;
	borrower = null; // not really needed; object fields default to null
	dueDate = null;
    }

    // Definitions of the methods

    /**
     * Returns the title of this book.
     *
     * @return the title of this book.
     */

    public String getTitle()
    {
	return title;
    }

    /**
     * Returns the author of this book.
     *
     * @return the author of this book.
     */

    public String getAuthor()
    {
	return author;
    }

    /**
     * Returns the borrower of this book.  If this book is not checked out,
     * returns null.
     *
     * @return the name of the borrower of this book
     */

    public String getBorrower()
    {
	return borrower;
    }

    /**
     * Returns the date this book is due.  If this book is not checked out,
     * returns null.
     *
     * @return the date this book is due
     */

    public GregorianCalendar getDueDate()
    {
	return dueDate;
    }

    /**
     * Checks this book out to the given borrower and records the given due
     * date.
     *
     * @param n the name of the person borrowing this book
     * @param due the date this book is due
     */

    public void checkout(String n, GregorianCalendar due)
    {
	borrower = n;
	dueDate = (GregorianCalendar)(due.clone());
    }

    /**
     * Returns this book.
     */

    public void checkin()
    {
	borrower = null;
	dueDate = null;
    }

    /**
     * Renews this book for the given time.
     *
     * @param days the number of days by which to extend the due date of this
     * book
     */

    public void renew(int days)
    {
	dueDate.add(GregorianCalendar.DAY_OF_MONTH, days);
    }

    /**
     * Determines the number of days until this book is due.  The return
     * value will be negative if this book is overdue.
     *
     * @return the number of days until this book is due
     * @throws NullPointerException if this book is not checked out
     */

    public int getDaysUntilDue()
    {
	// get today's date, as milliseconds since 1/1/1970

	Date today = new Date();

	// convert the due date to milliseconds since 1/1/1970

	Date due = dueDate.getTime();

	// compute difference between dates (in milliseconds)

	long diff = due.getTime() - today.getTime();

	// convert from milliseconds to days

	diff = diff / 1000 / 60 / 60 / 24;

	// report that result

	return (int)diff;
    }

    /**
     * Calculates the overdue fine for this book.  If this book is not overdue,
     * returns zero.
     *
     * @param rate the daily fine
     * @return the total fine for this book
     * @throws NullPointerException if this book is not checked out
     */

    public double calculateOverdueFine(double rate)
    {
	return -Math.min(0, getDaysUntilDue()) * rate;
    }
}

Test driver (BookTest.java)

import java.util.*;

/**
 * Test driver for the LibraryBook class.
 *
 * @author Jim Glenn
 * @version 0.1 9/26/2003
 */

public class BookTest
{
    public static void main(String[] args)
    {
	LibraryBook one = new LibraryBook("A Lost Lady", "Willa Cather");
	LibraryBook two = new LibraryBook("Hyperion", "Dan Simmons");

	System.out.println("Book 1's title: " + one.getTitle());
	System.out.println("Book 2's title: " + two.getTitle());

	// no borrower -- prints null

	System.out.println("Book 1 checked out by: " + one.getBorrower());

	GregorianCalendar past = new GregorianCalendar(2003, Calendar.MAY, 1);

	one.checkout("Crawford Hightower", past);
	two.checkout("Bryant Stith", past);

	System.out.println("Book 1 checked out by: " + one.getBorrower());

	GregorianCalendar due = one.getDueDate();
	System.out.println("Book 1 due on: " + due.get(Calendar.DAY_OF_MONTH));

	System.out.println("Book 1 due in: " + one.getDaysUntilDue());
	System.out.println("Book 1 fine: " + one.calculateOverdueFine(0.25));

	one.renew(365);
	
	due = one.getDueDate(); // due is not automatically updated

	System.out.println("Book 1 due in year: " + due.get(Calendar.YEAR));
	System.out.println("Book 1 due in: " + one.getDaysUntilDue());
	System.out.println("Book 1 fine: " + one.calculateOverdueFine(0.25));

	// without the .clone() in checkout we'd get unexpected results here!

	System.out.println("Book 2 due in: " + two.getDaysUntilDue());
	System.out.println("Book 2 fine: " + two.calculateOverdueFine(0.25));

	two.checkin();
	System.out.println("Book 2 checked out by: " + two.getBorrower());
    }
}

The test driver outputs

Book 1's title: A Lost Lady
Book 2's title: Hyperion
Book 2 checked out by: null
Book 2 checked out by: Crawford Hightower
Book 1 due on: 1
Book 1 due in: -148
Book 1 fine: 37.0
Book 1 due in year: 2004
Book 1 due in: 216
Book 1 fine: 0.0
Book 2 due in: -148
Book 2 fine: 37.0
Book 2 checked out by: null

This code can also be downloaded from the files LibraryBook.java and BookTest.java.