import tester.*; // to represent a book class Book{ String title; ILoA authors; Book(String title, ILoA authors){ this.title = title; this.authors = authors; this.authors.addBook(this); } /* TEMPLATE ... this.title ... -- String ... this.authors ... -- ILoA METHODS: ... this.sameBook(Book) ... -- boolean METHODS FOR FIELDS: ... this.authors.sameAuthorNames(ILoA) ... -- boolean */ // is this the same book as the given book? boolean sameBook(Book that){ return this.title.equals(that.title) && this.authors.sameAuthorNames(that.authors); } } // to represent an author class Author{ String name; ILoB books; Author(String name){ this.name = name; this.books = new MtLoB(); } /* TEMPLATE ... this.name ... -- String ... this.books ... -- ILoB METHODS: ... this.addBook(Book) ... -- void ... this.sameAuthor(Author) ... -- boolean METHODS FOR FIELDS: ... this.books.addBook(Book) ... -- void */ // is this author the same as the given one? boolean sameAuthor(Author that){ return this.name.equals(that.name) && this.books.sameBooks(that.books); } // EFFECT: add the given book to this author's list of books void addBook(Book book){ this.books = new ConsLoB(book, this.books); } } // to represent a list of authors interface ILoA{ // EFFECT: add the given book to every author's list of books (in this list) void addBook(Book book); // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameAuthorNames(ILoA that); // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameMtAuthorNames(MtLoA that); // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameConsAuthorNames(ConsLoA that); } //to represent an empty list of authors class MtLoA implements ILoA{ MtLoA(){} // EFFECT: add the given book to every author's list of books (in this list) public void addBook(Book book){} // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameAuthorNames(ILoA that){ return that.sameMtAuthorNames(this); } // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameMtAuthorNames(MtLoA that){ return true; } // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameConsAuthorNames(ConsLoA that){ return false; } } //to represent a nonempty list of authors class ConsLoA implements ILoA{ Author first; ILoA rest; ConsLoA(Author first, ILoA rest){ this.first = first; this.rest = rest; } /* TEMPLATE ... this.first ... -- Author ... this.rest ... -- ILoA METHODS: ... this.addBook(Book) ... -- void ... this.sameAuthorNames(ILoA that) ... -- boolean ... this.sameMtAuthorNames(MtLoA that) ... -- boolean ... this.sameConsAuthorNames(ConsLoA that) ... -- boolean METHODS FOR FIELDS: ... this.first.addBook(Book) ... -- void ... this.rest.addBook(Book) ... -- void ... this.rest.sameAuthorNames(ILoA that) ... -- boolean ... this.rest.sameMtAuthorNames(MtLoA that) ... -- boolean ... this.rest.sameConsAuthorNames(ConsLoA that) ... -- boolean */ // EFFECT: add the given book to every author's list of books (in this list) public void addBook(Book book){ this.first.addBook(book); this.rest.addBook(book); } // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameAuthorNames(ILoA that){ return that.sameConsAuthorNames(this); } // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameMtAuthorNames(MtLoA that){ return false; } // are the names of authors in this list the same // as the names of authors in the given list? public boolean sameConsAuthorNames(ConsLoA that){ return this.first.name.equals(that.first.name) && this.rest.sameAuthorNames(that.rest); } } // to represent an empty list of books interface ILoB{ // is this list of books the same as the given one boolean sameBooks(ILoB that); // is this empty list of books the same as the given empty list of books? public boolean sameMtBooks(MtLoB that); // is this empty list of books the same as the given nonempty list of books? public boolean sameConsBooks(ConsLoB that); } //to represent a list of books class MtLoB implements ILoB{ MtLoB(){} // is this empty list of books the same as the given list of books? public boolean sameBooks(ILoB that){ return that.sameMtBooks(this); } // is this empty list of books the same as the given empty list of books? public boolean sameMtBooks(MtLoB that){ return true; } // is this empty list of books the same as the given nonempty list of books? public boolean sameConsBooks(ConsLoB that){ return false; } } //to represent a nonempty list of books class ConsLoB implements ILoB{ Book first; ILoB rest; ConsLoB(Book first, ILoB rest){ this.first = first; this.rest = rest; } /* TEMPLATE ... this.first ... -- Book ... this.rest ... -- ILoB METHODS: ... this.sameBooks(ILoB that) ... -- boolean ... this.sameMtBooks(MtLoB that) ... -- boolean ... this.sameConsBooks(ConsLoB that) ... -- boolean METHODS FOR FIELDS: ... this.first.sameBook(Book that) ... -- boolean ... this.rest.sameBooks(ILoB that) ... -- boolean ... this.rest.sameMtBooks(MtLoB that) ... -- boolean ... this.rest.sameConsBooks(ConsLoB that) ... -- boolean */ // is this empty list of books the same as the given one public boolean sameBooks(ILoB that){ return that.sameConsBooks(this); } // is this empty list of books the same as the given empty list of books? public boolean sameMtBooks(MtLoB that){ return false; } // is this empty list of books the same as the given nonempty list of books? public boolean sameConsBooks(ConsLoB that){ return this.first.sameBook(that.first) && this.rest.sameBooks(that.rest); } } // examples and tests for books and authors class ExamplesBooks{ ExamplesBooks(){} // we would like the following books and authors: // HtDP by MF, SK // LL by MF, DF // LS by MF, DF // PLAI by SK Author mf = new Author("MF"); Author df = new Author("DF"); Author sk = new Author("SK"); ILoA htdpauthors = new ConsLoA(this.mf, new ConsLoA(this.sk, new MtLoA())); ILoA lsauthors = new ConsLoA(this.mf, new ConsLoA(this.df, new MtLoA())); ILoA plaiauthors = new ConsLoA(this.sk, new MtLoA()); Book htdp = new Book("HtDP", this.htdpauthors); Book ll = new Book("LL", this.lsauthors); Book ls = new Book("LS", this.lsauthors); Book plai = new Book("PLAI", this.plaiauthors); ILoB mfbooks = new ConsLoB(this.ls, new ConsLoB(this.ll, new ConsLoB(this.htdp, new MtLoB()))); // test addBook in the Author class void testAddBook(Tester t){ // setup: make an author, a book with no author Author xx = new Author("XX"); Book bb = new Book("BB", new MtLoA()); // now add book to the author xx.addBook(bb); // run the test t.checkExpect(xx.books, new ConsLoB(bb, new MtLoB())); // no need to reset - all variables are local } // test addBook in the classes for lists of authors void testAddBookList(Tester t){ // setup: make two authors and a list Author xx = new Author("XX"); Author yy = new Author("YY"); ILoA xxyy = new ConsLoA(xx, new ConsLoA(yy, new MtLoA())); //a book with no author Book bb = new Book("BB", new MtLoA()); // now add book to the author list xxyy.addBook(bb); // run the test t.checkExpect(xx.books, new ConsLoB(bb, new MtLoB())); t.checkExpect(yy.books, new ConsLoB(bb, new MtLoB())); t.checkExpect(xxyy, new ConsLoA(xx, new ConsLoA(yy, new MtLoA()))); // no need to reset - all variables are local } // test the constructors for the author and book classes void testAuthors(Tester t){ t.checkExpect(this.mf.books, this.mfbooks); t.checkExpect(this.ll.authors, this.ls.authors); } Author mfx = new Author("MF"); Author dfx = new Author("DF"); Author skx = new Author("SK"); ILoA htdpauthorsx = new ConsLoA(this.mfx, new ConsLoA(this.skx, new MtLoA())); ILoA lsauthorsx = new ConsLoA(this.mfx, new ConsLoA(this.dfx, new MtLoA())); ILoA plaiauthorsx = new ConsLoA(this.skx, new MtLoA()); Book htdpx = new Book("HtDP", this.htdpauthorsx); Book llx = new Book("LL", this.lsauthorsx); Book lsx = new Book("LS", this.lsauthorsx); Book plaix = new Book("PLAI", this.plaiauthorsx); // test the method sameBook for the class Book void testSameBook(Tester t){ t.checkExpect(this.htdp.sameBook(this.htdpx), true); t.checkExpect(this.llx.sameBook(this.ll), true); } // test the method sameAuthor for the class Author void testSameAuthor(Tester t){ t.checkExpect(this.mf.sameAuthor(this.mfx), true); t.checkExpect(this.skx.sameAuthor(this.sk), true); t.checkExpect(this.mf.sameAuthor(this.sk), false); t.checkExpect(this.mf.sameAuthor(this.df), false); } // test the method sameBooks for the classes that implement ILoB void testSameBooks(Tester t){ t.checkExpect(this.mf.books.sameBooks(this.mfx.books), true); t.checkExpect(this.skx.books.sameBooks(this.sk.books), true); t.checkExpect(this.mf.books.sameBooks(this.sk.books), false); t.checkExpect(this.mf.books.sameBooks(this.df.books), false); } // test the method sameAuthorNames for the classes that implement ILoA void testSameAuthorsNames(Tester t){ t.checkExpect(this.htdp.authors.sameAuthorNames(this.htdpx.authors), true); t.checkExpect(this.llx.authors.sameAuthorNames(this.ll.authors), true); t.checkExpect(this.htdp.authors.sameAuthorNames(this.ll.authors), false); } }