brainfrz icon

Untitled

brainfrz | PRO | 10/21/15 11:01:42 AM UTC | 0 ⭐ | 819 👁️ | Never ⏰ | []
Java |

19.52 KB

|

None

|

0 👍

/

0 👎

/**************************************************************************************************
 *  Program Name:     Programming Project 5.7: Bookshelf
 *  Class Name:       pp5_7.Bookshelf
 *  Author:           Terry Weiss
 *  Date Written:     October 15, 2015
 *  Program Description:
 *     This class contains instance data for a bookshelf that is full of `Book`s. It allows the
 *  User to store a book, browse the list of books, view the details of a particular book and
 *  take a book off the shelf.
 **************************************************************************************************/
package pp5_7;
 
//import pp5_7.Book;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
 
 
/**
 * Contains instance data for a bookshelf that is full of {@link pp5_7.Book}s. It allows the User to
 * store a book, browse the list of books, view the details of a particular book and take a book off
 * the Bookshelf.
 *
 * @author Terry Weiss
 * @see    pp5_7.Book
 * @see    pp5_7.Librarian
*/
public class Bookshelf {
    private final String DEFAULT_NAME = "Bookshelf";
 
    /*
     *  Holds all {@link pp5_7.Book}s, genres and authors. Genres and authors are saved here to be
     *  quickly referenced when browsing by category.
     */
    private List<Book> bookList;
    private List<String> genreList = new ArrayList<>();
    private List<String> authorList = new ArrayList<>();
    private final String name;
 
 
    /**
     * Constructs a new Bookshelf instance using the default name.
     */
    public Bookshelf() {
        name = DEFAULT_NAME;
        bookList = new ArrayList<>();
    }
 
    /**
     * Constructs a new Bookshelf instance using the name provided.
     *
     * @param name Name of the bookshelf
     */
    public Bookshelf( String name ) {
        this.name = name;
        bookList = new ArrayList<>();
    }
 
    /**
     * Constructs a new Bookshelf instance, using the default name, populated by a list of
     * {@link pp5_7.Book}s. Bookshelf's size will be originally allocated to 150% the size of the
     * loaded list.
     *
     * @param loadedList Bookshelf to be loaded
     */
    public Bookshelf( List<Book> loadedList ) {
        name = DEFAULT_NAME;
        // Initialize with more space following default +10 rule
        bookList = new ArrayList<>(loadedList.size() + 10);
 
        // Add each book "manually" instead of copying everything, in case handling changes later.
        for ( Book book : loadedList ) {
            addBook(book);
        }
    }
 
    /**
     * Constructs a new Bookshelf instance, using the specified name, populated by a list of
     * {@link pp5_7.Book}s. Bookshelf's size will be originally allocated to 150% the size of the
     * loaded list.
     *
     * @param loadedList Bookshelf to be loaded
     * @param name Name of the bookshelf
     */
    public Bookshelf( List<Book> loadedList, String name ) {
        this.name = name;
        bookList = new ArrayList<>(loadedList.size() + 10);
 
        for (Book book : loadedList) {
            addBook(book);
        }
    }
 
 
    /**
     * Gives current number of {@link pp5_7.Book}s on the shelf.
     *
     * @return Number of Books
     */
    public int getNumberOfBooks() {
        return bookList.size();
    }
 
    /**
     * Provides the current list of {@link pp5_7.Book}s on the shelf as a
     * {@link java.util.List}.
     *
     * @return All Book objects in a List
     */
    public List<Book> getBookList() {
        return bookList;
    }
 
    /**
     * Provides a {@link pp5_7.Book} object from the shelf, retrieved by its location.
     *
     * @param location Location of the desired book
     * @return Book object retrieved
     */
    public Book getBook( int location ) {
        return bookList.get(location);
    }
 
    /**
     * Provides a {@link pp5_7.Book} object from the shelf, retrieved by its title.
     *
     * @param title Title of the desired book
     * @return Book object retrieved
     */
    public Book getBook( String title ) {
        return bookList.get(findBook(title));
    }
 
    /**
     * Gives the name of the bookshelf.
     *
     * @return Bookshelf's name
     */
    public String getName() {
        return name;
    }
 
 
    /**
     * Adds a pre-created {@link pp5_7.Book} to the shelf.
     *
     * @param book Book instance to be added
     * @return Book instance that was added
     */
    public final Book addBook( Book book ) {
        bookList.add(book);
 
        String genre = book.getGenre();
        if (!genreList.contains(genre)) {
            genreList.add(genre);
        }
 
        String author = book.getAuthor();
        if (!authorList.contains(author)) {
            authorList.add(author);
        }
 
        return book;
    }
 
    /**
     * Removes a specific {@link pp5_7.Book} object from the Bookshelf.
     *
     * @param book Book instance to be removed
     * @return <tt>true</tt> if the Book was successfully removed
     */
    public boolean removeBook( Book book ) {
        // If it's the only book of that genre or author, remove the genre/author from its list
        String genre = book.getGenre();
        if (numBooksWithGenre(genre) == 1) {
            genreList.remove(genre);
        }
 
        String author = book.getAuthor();
        if (numBooksWithAuthor(author) == 1) {
            authorList.remove(author);
        }
 
        return bookList.remove(book);
    }
 
    /**
     * Removes {@link pp5_7.Book} from the Bookshelf. Replaced by
     * {@link #removeBook(java.lang.String)}. Only use if the book being removed must be saved,
     * since the positions change with each sort.
     *
     * @param position Position of the Book in the list
     * @return Book instance being removed
     */
    public Book removeBook( int position ) {
        Book book = bookList.get(position);
 
        String genre = book.getGenre();
        if (numBooksWithGenre(genre) == 1) {
            genreList.remove(genre);
        }
 
        String author = book.getAuthor();
        if (numBooksWithGenre(genre) == 1) {
            authorList.remove(author);
        }
 
        return bookList.remove(position);
    }
 
    /**
     * Removes {@link pp5_7.Book} from the Bookshelf.
     *
     * @param title Title of the Book to be removed
     * @return <tt>true</tt> if the Book was successfully removed
     */
    public boolean removeBook( String title ) {
        if (numBooksWithTitle(title) == 1) {
            removeBook(findBook(title));
            return true;
        }
        else {
            return false;
        }
    }
 
    /**
     * Removes all {@link pp5_7.Book}s from the Bookshelf.
     *
     * @return List of Books prior to deletion
     */
    public List<Book> emptyBookshelf() {
        List<Book> list = bookList;
 
        for (int i = 0; i < bookList.size(); i++) {
            removeBook(i);
        }
 
        return list;
    }
 
 
    /**
     * Provides details of a specific {@link pp5_7.Book} from the Bookshelf, or if the Book doesn't
     * exist. Only use in cases where you want only one version of a Book that has a non-unique
     * title, since the positions change with each sort.
     *
     * @param position Position of Book to be viewed
     * @deprecated Replaced by {@link #viewBook(java.lang.String)}
     * @return String holding the details of the book if it exists
     */
    public String viewBook( int position ) {
        String ret;
 
        if (position < 0 || position >= bookList.size()) {
            ret = "That book isn't on the shelf.";
        }
        else {
            ret = bookList.get(position).displayDetails();
        }
 
        return ret;
    }
 
    /**
     * Provides details of a specific {@link pp5_7.Book} from the Bookshelf, or if the Book doesn't
     * exist. In cases where the title isn't unique, all Books by this title are shown and separated
     * by an empty line.
     *
     * @param title Title of the Book
     * @return String holding the details of the Books by that title
     */
    public String viewBook( String title ) {
        String details = "";
 
        for (Book currentBook : bookList) {
            if (currentBook.getTitle().equalsIgnoreCase(title)) {
                if (details.length() > 0) {  // Separate each entry by a blank line in cases
                    details += "\n\n";       // of duplicate titles
                }
 
                details += currentBook.displayDetails();
            }
        }
 
        if (details.length() == 0) {
            details = title + " isn't on the shelf.";
        }
 
        return details;
    }
 
 
    /**
     * Sorts all {@link pp5_7.Book}s in ascending alphabetical order by title.
     *
     * @see pp5_7.Book#sortByTitle
     */
    public void sortBooksByTitle() {
        Collections.sort(bookList, Book.sortByTitle);
    }
 
    /**
     * Sorts all {@link pp5_7.Book}s in ascending alphabetical by Author first and then by Title.
     *
     * @see pp5_7.Book#sortByAuthor
     */
    public void sortBooksByAuthor() {
        // Sorts must be done in reverse order to get benefit of sorting by Title while not
        // overriding the sort by author.
        sortBooksByTitle();
        Collections.sort(bookList, Book.sortByAuthor);
    }
 
    /**
     * Sorts all {@link pp5_7.Book}s in ascending alphabetical by Genre first and then by Title.
     *
     * @see pp5_7.Book#sortByGenre
     */
    public void sortBooksByGenre() {
        sortBooksByTitle();
        Collections.sort(bookList, Book.sortByGenre);
    }
 
    /**
     * Sorts all {@link pp5_7.Book}s in ascending numerical order by size first and then by Title
     * in cases where two books are the same size.
     */
    public void sortBooksBySize() {
        sortBooksByTitle();
        Collections.sort(bookList);
    }
 
 
    /**
     * Returns the index of the first occurrence of the {@link pp5_7.Book} in this list, or -1 if
     * this list does not contain the Book.
     *
     * @param book Book object to search for
     * @return Index of the first Book, or <tt>-1</tt> if it's not there
     */
    public int findBook( Book book ) {
        return bookList.indexOf(book);
    }
 
    /**
     * Returns the index of the first occurrence of the {@link pp5_7.Book} of the same title in this
     * list, or -1 if this list does not contain the Book.
     *
     * @param title Title of the book to search for
     * @return Index of the first Book, or <tt>-1</tt> if it's not there
     */
    public int findBook( String title ) {
        for (int currentBook = 0; currentBook < bookList.size(); currentBook++) {
            String currentTitle = bookList.get(currentBook).getTitle();
            if (currentTitle.equalsIgnoreCase(title)) {
                return currentBook;
            }
        }
 
        return -1;
    }
 
 
    /**
     * Provides the number of {@link pp5_7.Book}s of a certain genre.
     *
     * @param genre Name of the genre
     * @return Number of Books of the provided genre
     */
    public int numBooksWithGenre( String genre ) {
        int books = 0;
 
        for (Book book : bookList ) {
            if (book.getGenre().equalsIgnoreCase(genre)) {
                books++;
            }
        }
 
        return books;
    }
 
    /**
     * Provides the number of {@link pp5_7.Book}s of a certain author.
     *
     * @param author Name of the author
     * @return Number of Books by the provided author
     */
    public int numBooksWithAuthor( String author ) {
        int books = 0;
 
        for (Book book : bookList ) {
            if (book.getAuthor().equalsIgnoreCase(author)) {
                books++;
            }
        }
 
        return books;
    }
 
    /**
     * Provides the number of {@link pp5_7.Book}s of a certain title.
     *
     * @param title Title to be searched for
     * @return Number of Books of the same title
     */
    public int numBooksWithTitle( String title ) {
        int books = 0;
 
        for (Book book : bookList ) {
            if (book.getTitle().equalsIgnoreCase(title)) {
                books++;
            }
        }
 
        return books;
    }
 
 
    /**
     * Provides a String of all {@link pp5_7.Book}s on the Bookshelf using their String
     * representation.
     *
     * @return List of all Books on the Bookshelf
     */
    public String browse() {
        String list = "";
 
        for (Book currentBook : bookList) {
            list += currentBook + "\n";
        }
 
        return list;
    }
 
    /**
     * Provides a String of all {@link pp5_7.Book}s on the Bookshelf using their String
     * representation. Books are resorted by title.
     *
     * @return List of all Books on the Bookshelf, sorted by title
     * @see #sortBooksByTitle
     */
    public String browseByTitle() {
        sortBooksByTitle();
        return browse();
    }
 
    /**
     * Provides a String of all {@link pp5_7.Book}s on the Bookshelf using their String
     * representation. Books are resorted by author's last name.
     *
     * @return List of all Books on the Bookshelf, sorted by author
     * @see #sortBooksByAuthor
     */
    public String browseByAuthor() {
        sortBooksByAuthor();
        String list = "";
 
        for (Book currentBook : bookList ) {
            list += String.format("%-20s    %s\n", currentBook, currentBook.getAuthor());
        }
 
        return list;
    }
 
    /**
     * Provides a String of all {@link pp5_7.Book}s on the Bookshelf using their String
     * representation. Books are resorted by genre.
     *
     * @return List of all Books on the Bookshelf, sorted by genre
     * @see #sortBooksByGenre
     */
    public String browseByGenre() {
        sortBooksByGenre();
        String list = "";
 
        for (Book currentBook : bookList ) {
            list += String.format("%-20s    %s\n", currentBook, currentBook.getGenre());
        }
 
        return list;
    }
 
    /**
     * Provides a String of all {@link pp5_7.Book}s on the Bookshelf using their String
     * representation. Books are resorted by size.
     *
     * @return List of all Books on the Bookshelf, sorted by size
     * @see #sortBooksBySize
     */
    public String browseBySize() {
        sortBooksBySize();
        String list = "";
 
        for (Book currentBook : bookList ) {
            list += String.format("%-20s    %s\n", currentBook, currentBook.getPages());
        }
 
        return list;
    }
 
    /**
     * Provides a String of all {@link pp5_7.Book}s on the Bookshelf in a specific genre, or if
     * no books in that genre exist. Books are sorted by title.
     *
     * @param genre Genre to be listed
     * @return List of Books in the given genre
     */
    public String browseBooksOfGenre( String genre ) {
        String list = "";
 
        // Make the genre Capitalized to match format of genres and be case-insensitive
        genre = genre.substring(0, 1).toUpperCase() + genre.substring(1).toLowerCase();
 
        if (genreList.indexOf(genre) == -1) {
            list = "There are no books of that genre.\n";
        }
        else {
            sortBooksByGenre();
            int i = 0;
 
            // Find first book with the genre
            while (!bookList.get(i).getGenre().equalsIgnoreCase(genre)) {
                i++;
            }
 
            // Display all books until the genre changes or until it's the last book of the shelf
            while (i < bookList.size() && bookList.get(i).getGenre().equalsIgnoreCase(genre)) {
                list += bookList.get(i) + "\n";
                i++;
            }
        }
 
        return list;
    }
 
    /**
     * Provides a String of all {@link pp5_7.Book}s on the Bookshelf by a specific author, or if
     * no books by that author exist. Books are sorted by title.
     *
     * @param author Author to be listed
     * @return List of Books by the given author
     */
    public String browseBooksOfAuthor( String author ) {
        String list = "";
 
        // Make the genre Capitalized to match format of genres and be case-insensitive
        String capitalizedAuthor = "";
        for (String authorName : author.split(" ")) {
            capitalizedAuthor += authorName.substring(0, 1).toUpperCase()
                                    + authorName.substring(1).toLowerCase() + " ";
        }
        capitalizedAuthor = capitalizedAuthor.trim();
 
        if (authorList.indexOf(capitalizedAuthor) == -1) {
            list = "There are no books by that author.\n";
        }
        else {
            sortBooksByAuthor();
            int i = 0;
 
            // Find first book with the genre
            while (!bookList.get(i).getAuthor().equalsIgnoreCase(capitalizedAuthor)) {
                i++;
            }
 
            // Display all books until the genre changes or until it's the last book of the shelf
            while (i < bookList.size() && bookList.get(i).getAuthor()
                                                            .equalsIgnoreCase(capitalizedAuthor)) {
                list += bookList.get(i) + "\n";
                i++;
            }
        }
 
        return list;
    }
 
    /**
     * Provides a String of all {@link pp5_7.Book}s on the Bookshelf in a specific category, or if
     * no books in that category exist. Books are sorted by title. Currently, the only supported
     * categories are <tt>"author"</tt> and <tt>"genre"</tt>.
     *
     * @param category Category to be used
     * @return List of Books in the given category
     */
    public String browseByCategory( String category ) {
        String list = "";
 
        if (category.equalsIgnoreCase("author") || category.equalsIgnoreCase("authors")) {
            for (String author : authorList) {
                list += author + ":\n"
                      + browseBooksOfAuthor(author) + "\n";
            }
        }
        else if (category.equalsIgnoreCase("genre") || category.equalsIgnoreCase("genres")) {
            for (String genre : genreList) {
                list += genre + ":\n"
                      + browseBooksOfGenre(genre) + "\n";
            }
        }
        else {
            list = "No such category.\n";
        }
 
        return list;
    }
 
 
 
    /**
     * String representation of the Bookshelf
     *
     * @return Bookshelf's name
     */
    @Override
    public String toString() {
        return getName();
    }
 
 
 
 
    /**
     * Used only for debugging purposes
     *
     * @param args Command line input isn't supported
     */
    public static void main( String[] args ) {
        Scanner user_input = new Scanner(System.in);
 
        Bookshelf myShelf = new Bookshelf();
        myShelf.addBook(new Book("book1", 321, "martin", "fiction"));
        myShelf.addBook(new Book("book2", 123, "Martin", "non-fiction"));
        myShelf.addBook(new Book("book3", 852, "Peter", "sci-fi"));
        myShelf.addBook(new Book("book4", 753, "Martin", "fiction"));
        myShelf.addBook(new Book("book5", 159, "Ralph", "non-fiction"));
        myShelf.addBook(new Book("book6", 349, "MartIn", "fiction"));
 
        myShelf.removeBook("book2");
 
        System.out.print(myShelf.browseByCategory("author"));
 
        System.out.println(myShelf.viewBook("book1"));
    }
}

Comments