/*
+--------------+
| Book         |
+--------------+
| String title |
| int year     |
+--------------+
*/

class Book {
  String title;
  int year;
  
  Book(String title, int year){
    this.title = title; 
    this.year = year;
  }

  boolean same(Book that){
    return 
      this.title.equals(that.title)
    && this.year == that.year;
  }
}

/*
            +---------+                
            | ILoBook |<------------+
            +---------+             |
                / \                 |
                 |                  |
       - - - - - - - - - -          |
       |                 |          |
  +----------+    +--------------+  |
  | MTLoBook |    | ConsLoBook   |  |
  +----------+    +--------------+  |
  +----------+  +-| Book first   |  |
                | | ILoBook rest |--+
                | +--------------+ 
                |
                v
       +---------------+
       | Book          |
       +---------------+
       | String title  |
       | int year      |
       +---------------+
*/
interface ILoBook{
  // to compute the size of this list
  int size();

  // is the given book in this list?
  boolean contains (Book that);
}

class MTLoBook implements ILoBook{
  MTLoBook() {}

  int size(){ return 0; }

  boolean contains (Book that){
    return false;
  }
}

class ConsLoBook implements ILoBook{
  Book first;
  ILoBook rest;

  ConsLoBook(Book first, ILoBook rest){
    this.first = first;
    this.rest = rest;
  }

/* TEMPLATE:
... this.first ...                 -- Book
... this.rest ...                  -- ILoBook
... this.rest.size() ...           -- int
... this.rest.contains( Book ) ... -- boolean
*/
  int size(){ 
    return 1 + this.rest.size(); 
  }

  boolean contains (Book that){
    return this.first.same(that)
        || this.rest.contains(that);
  }
}

class Examples{
  Examples () {}

  Book b1 = new Book("DVC", 2003);
  Book b2 = new Book("LPP", 1942);
  Book b3 = new Book("HtDP", 2001);
  
  ILoBook mtbooks = new MTLoBook();
  ILoBook booklist = 
            new ConsLoBook(b1,
            new ConsLoBook(b2,
                           mtbooks));

  boolean testSize1 = mtbooks.size() == 0;
  boolean testSize2 = booklist.size() == 2;

  boolean testContains1 = this.mtbooks.contains(this.b1) == false;
  boolean testContains2 = this.booklist.contains(this.b2) == true;
  boolean testContains3 = this.booklist.contains(b3) == false;
}
