Pages

BibCity

import java.util.List;
import java.util.Collection;
import java.util.ArrayList;

public class BibCity
{
    public static void main(String[] args)
    {
        Publisher addisonWesley =
            PublishersTradeAssociation.newPublisher("Addison Wesley");

        Author gbt = new Author("George B. Thomas");
        Book calculus_e1 = gbt.newNonfiction(
            addisonWesley, "Calculus and Analytic Geometry, 1st ed.");
        
        AuthorCollector dek = new AuthorCollector("Donald E. Knuth");
        dek.library().add(calculus_e1.copy());
        dek.signBookDeal(addisonWesley);
        Book taocp_v1 = dek.newNonfiction(
            "The Art of Computer Programming, vol. 1 (Fundamental Algorithms)");
        dek.library().add(taocp_v1.copy());
        Book surreal = dek.newFiction("Surreal Numbers");
        dek.library().add(surreal.copy());
        
        Author[] collaborator = { new Author("Ross L. Finney") };
        gbt.collaborateWith(collaborator);
        Book calculus_e8 = gbt.newNonfiction(
            addisonWesley, "Calculus and Analytic Geometry, 8th ed.");
        
        Collector jps = new Collector("Mr. Spurgeon");
        jps.library().add(calculus_e8.copy());
        jps.library().add(taocp_v1.copy());
        
        System.out.println("DEK's Collection:");
        System.out.println(dek.library());
        System.out.println("JPS's Collection:");
        System.out.println(jps.library());
    }
}
class Publisher
{
    private final String name;
    private final Integer id;
    private Integer currentBookNumber = 0;
    
    public Publisher(String name, int id)
    {
        this.name = name;
        this.id = id;
    }
    public String name() { return name; }
    public Integer id()   { return id; }
    public String nextIsbn()
    {
        currentBookNumber++;
        return id.toString() + "-" + currentBookNumber.toString();
    }
}

class PublishersTradeAssociation
{
    private static int currentPublisherNumber = 0;
    
    public static Publisher newPublisher(String name)
    {
        currentPublisherNumber++;
        return new Publisher(name, currentPublisherNumber);
    }
}
class Library
{
    private Collection<PrintCopy> collection = new ArrayList<PrintCopy>();
    
    public boolean hasBook(Book book)
    {
        for (PrintCopy copy : collection)
        {
            if (copy.isbn().equals(book.isbn()))
                return true;
        }
        return false;
    }
    public void add(PrintCopy copy)
    {
        collection.add(copy);
    }
    public String toString()
    {
        String s = "";
        for (PrintCopy book : collection)
        {
            s += book.toString() + "\n";
        }
        return s;
    }
}
class Author
{
    private String name;
    private Author[] collaborators = {};
    private Publisher myPublisher = null;
    private List<Book> myBooks = new ArrayList<Book>();
    
    public Author(String name)                     { this.name = name; }
    public void collaborateWith(Author[] others)   { collaborators = others; }
    public void stopCollaborating()                { collaborators = new Author[0]; }
    public List<Book> myBooks()                    { return myBooks; }
    public void signBookDeal(Publisher publisher)  { this.myPublisher = publisher; }
    public Book newFiction(String title)
    {
        return this.newFiction(this.myPublisher, title);
    }
    public Book newNonfiction(String title)
    {
        return this.newNonfiction(this.myPublisher, title);
    }
    public Book newFiction(Publisher publisher, String title)
    {
        Book newBook = collaborators.length == 0 ?
            new FictionBook(publisher, title, this) :
            new CollaborativeFictionBook(publisher, title, this, collaborators);
        for (Author collaborator : collaborators)
            collaborator.myBooks().add(newBook);
        this.myBooks.add(newBook);
        return newBook;
    }
    public Book newNonfiction(Publisher publisher, String title)
    {
        Book newBook = collaborators.length == 0 ?
            new NonFictionBook(publisher, title, this) :
            new NonFictionBook(publisher, title, this, collaborators);
        for (Author collaborator : collaborators)
            collaborator.myBooks().add(newBook);
        this.myBooks.add(newBook);
        return newBook;
    }
}
interface Bibliophile
{
    public abstract Library library();
}

class AuthorCollector extends Author implements Bibliophile
{
    private Library myLibrary = new Library();
    
    public AuthorCollector(String name) { super(name); }
    public Library library()            { return myLibrary; }
}

class Collector implements Bibliophile
{
    private String name;
    private Library myLibrary = new Library();
    
    public Collector(String name) { this.name = name; }
    public Library library()      { return myLibrary; }
    
}
interface BookInfo
{
    public abstract String isbn();
    public abstract Publisher publisher();
    public abstract String title();
    public abstract Author author();
    public abstract Author author(int i);
    public abstract int authorCount();
    public abstract String category();
}

class PrintCopy implements BookInfo
{
    private final Book book;
    private final int copyNumber;
    
    public PrintCopy(Book book)
    {
        this.book = book;
        this.copyNumber = book.copiesPrinted();
    }
    public String isbn()                  { return this.book.isbn(); }
    public String title()                 { return this.book.title(); }
    public Author author()                { return this.book.author(); }
    public Author author(int i)           { return this.book.author(i); }
    public int authorCount()              { return this.book.authorCount(); }
    public String category()              { return this.book.category(); }
    public Publisher publisher()          { return this.book.publisher(); }
    public boolean equals(PrintCopy copy) { return this.isbn().equals(copy.isbn()); }
    public String toString()
    {
        return "copy #" + copyNumber + ": " + this.book.toString();
    }
}
abstract class Book implements BookInfo
{
    private int copiesPrinted = 0;
    private final String isbn;
    private final String title;
    private final Author[] authors;
    private final Publisher publisher;
    
    protected Book(Publisher publisher, String title, Author author)
    {
        this.publisher = publisher;
        this.isbn = publisher.nextIsbn();
        this.title = title;
        this.authors = new Author[1];
        authors[0] = author;
    }
    protected Book(Publisher publisher, String title, Author author, Author[] others)
    {
        this.publisher = publisher;
        this.isbn = publisher.nextIsbn();
        this.title = title;
        int n = others.length;
        this.authors = new Author[n + 1];
        this.authors[0] = author;
        for (int i = 0; i < n; i++)
            this.authors[i + 1] = others[i];
    }
    public PrintCopy copy()
    {
        this.copiesPrinted++;
        return new PrintCopy(this);
    }
    public String isbn()               { return this.isbn; }
    public String title()              { return this.title; }
    public int copiesPrinted()         { return this.copiesPrinted; }
    public Author author()             { return this.authors[0]; }
    public Author author(int i)        { return this.authors[i]; }
    public int authorCount()           { return this.authors.length; }
    public Publisher publisher()       { return this.publisher; }
    public String toString()           { return this.title; }
    public abstract String category();
}
class FictionBook extends Book
{
    public FictionBook(Publisher publisher, String title, Author author)
    {
        super(publisher, title, author);
    }
    public String category() { return "fiction"; }
}

class CollaborativeFictionBook extends Book
{
    public CollaborativeFictionBook(
        Publisher publisher, String title, Author author, Author[] others)
    {
        super(publisher, title, author, others);
    }
    public String category() { return "collaborative fiction"; }
}

class NonFictionBook extends Book
{
    public NonFictionBook(
        Publisher publisher, String title, Author author, Author[] others)
    {
        super(publisher, title, author, others);
    }
    public NonFictionBook(Publisher publisher, String title, Author author)
    {
        super(publisher, title, author);
    }
    public String category() { return "nonfiction"; }
}