public class BibCity2
{
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 CircularList<PrintCopy>();
public boolean hasBook(Book book)
{
Iterator<PrintCopy> i = collection.iterator();
while (i.hasNext())
{
PrintCopy copy = i.next();
if (copy.isbn().equals(book.isbn()))
return true;
}
return false;
}
public void add(PrintCopy copy)
{
collection.add(copy);
}
public String toString()
{
String s = "";
Iterator<PrintCopy> i = collection.iterator();
while (i.hasNext())
{
PrintCopy copy = i.next();
s += copy.toString() + "\n";
}
return s;
}
}
class Author
{
private String name;
private Author[] collaborators = {};
private Publisher myPublisher = null;
private List<Book> myBooks = new CircularList<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"; }
}
interface Iterator<T>
{
public abstract T next();
public abstract boolean hasNext();
}
interface Iterable<T>
{
public abstract Iterator<T> iterator();
}
interface Collection<T> extends Iterable<T>
{
public abstract boolean contains(T object);
public abstract boolean add(T object);
}
interface List<T> extends Collection<T>
{
}
class ListIterator<T> implements Iterator<T>
{
private ListNode<T> current;
private final ListNode<T> stop;
public ListIterator(ListNode<T> start, ListNode<T> stop)
{
this.current = start;
this.stop = stop;
}
public T next()
{
current = this.current.getNext();
return this.current.getValue();
}
public boolean hasNext()
{
return this.current.getNext() != this.stop;
}
}
class CircularList<T> implements List<T>
{
private ListNode<T> head, tail;
public CircularList()
{
head = new ListNode<T>();
tail = head.setNext(head);
}
public ListIterator<T> iterator()
{
return new ListIterator<T>(head, head);
}
public boolean contains(T object)
{
ListIterator<T> i = this.iterator();
while (i.hasNext())
{
if (i.next().equals(object))
return true;
}
return false;
}
public boolean add(T object)
{
tail.setNext(new ListNode<T>(object, tail.getNext()));
return true;
}
}
class ListNode<T>
{
private T value;
private ListNode<T> nextNode;
public ListNode()
{
this(null, null);
}
public ListNode(T value)
{
this(value, null);
}
public ListNode(T value, ListNode<T> node)
{
this.value = value;
this.nextNode = node;
}
public ListNode<T> getNext()
{
return nextNode;
}
public ListNode<T> setNext(ListNode<T> node)
{
return this.nextNode = node;
}
public T getValue()
{
return this.value;
}
}