From 66c3009e47cdb1c9929d9c342279a837f870e5ba Mon Sep 17 00:00:00 2001 From: "Anthony D. Mays" Date: Wed, 20 Mar 2024 23:04:26 +0000 Subject: [PATCH 1/4] feat: adds library implementation and tests --- .../lesson10/library/Book.java | 104 ++++++++++ .../lesson10/library/Library.java | 185 ++++++++++++++++++ .../lesson10/library/Patron.java | 79 ++++++++ .../exceptions/BookCheckedOutException.java | 7 + .../exceptions/LibraryNotSetException.java | 7 + .../exceptions/WrongLibraryException.java | 7 + .../lesson10/library/BookTest.java | 85 ++++++++ .../lesson10/library/LibraryTest.java | 150 ++++++++++++++ .../lesson10/library/PatronTest.java | 80 ++++++++ 9 files changed, 704 insertions(+) create mode 100644 lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Book.java create mode 100644 lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Library.java create mode 100644 lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Patron.java create mode 100644 lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/BookCheckedOutException.java create mode 100644 lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/LibraryNotSetException.java create mode 100644 lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/WrongLibraryException.java create mode 100644 lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/BookTest.java create mode 100644 lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/LibraryTest.java create mode 100644 lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/PatronTest.java diff --git a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Book.java b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Book.java new file mode 100644 index 00000000..c966fea0 --- /dev/null +++ b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Book.java @@ -0,0 +1,104 @@ +package com.codedifferently.lesson10.library; + +import com.codedifferently.lesson10.library.exceptions.LibraryNotSetException; +import com.codedifferently.lesson10.library.exceptions.WrongLibraryException; +import java.util.List; +import java.util.Objects; + +/** Represents a book. */ +public class Book { + private Library library; + private String title; + private String isbn; + private List authors; + private int numberOfPages; + + /** + * Create a new book with the given title, isbn, authors, and number of pages. + * + * @param title The title of the book. + * @param isbn The ISBN of the book. + * @param authors The authors of the book. + * @param numberOfPages The number of pages in the book. + */ + public Book(String title, String isbn, List authors, int numberOfPages) { + this.title = title; + this.isbn = isbn; + this.authors = authors; + this.numberOfPages = numberOfPages; + } + + /** + * Get the id of the book. + * + * @return The id of the book. + */ + public String getId() { + return this.isbn; + } + + /** + * Get the library that the book is in. + * + * @param library The library that the book is in. + * @throws WrongLibraryException If the book is not in the library. + */ + public void setLibrary(Library library) throws WrongLibraryException { + if (library != null && !library.hasBook(this)) { + throw new WrongLibraryException( + "Book " + this.getId() + " is not in library " + library.getId()); + } + this.library = library; + } + + /** Get the title of the book. */ + public String getTitle() { + return title; + } + + /** Get the ISBN of the book. */ + public String getIsbn() { + return isbn; + } + + /** Get the authors of the book. */ + public List getAuthors() { + return authors; + } + + /** Get the number of pages in the book. */ + public int getNumberOfPages() { + return numberOfPages; + } + + /** + * Check if the book is checked out. + * + * @return True if the book is checked out, false otherwise. + * @throws LibraryNotSetException If the library is not set for the book. + */ + public boolean isCheckedOut() throws LibraryNotSetException { + if (this.library == null) { + throw new LibraryNotSetException("Library not set for book " + this.getId()); + } + return library.isCheckedOut(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Book)) return false; + Book book = (Book) o; + return Objects.equals(getIsbn(), book.getIsbn()); + } + + @Override + public int hashCode() { + return Objects.hash(getId()); + } + + @Override + public String toString() { + return "Book{" + "id='" + getId() + '\'' + ", title='" + getTitle() + '\'' + '}'; + } +} diff --git a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Library.java b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Library.java new file mode 100644 index 00000000..08154409 --- /dev/null +++ b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Library.java @@ -0,0 +1,185 @@ +package com.codedifferently.lesson10.library; + +import com.codedifferently.lesson10.library.exceptions.BookCheckedOutException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** Represents a library. */ +public class Library { + private Set bookIds = new HashSet<>(); + private Set checkedOutIsbns = new HashSet<>(); + private Map> checkedOutBooksByPatron = new HashMap<>(); + private Set patronIds = new HashSet<>(); + private String id; + + /** + * Create a new library with the given id. + * + * @param id The id of the library. + */ + public Library(String id) { + this.id = id; + } + + /** + * Get the id of the library. + * + * @return The id of the library. + */ + public String getId() { + return this.id; + } + + /** + * Add a book to the library. + * + * @param book The book to add. + */ + public void addBook(Book book) { + this.bookIds.add(book.getId()); + book.setLibrary(this); + } + + /** + * Remove a book from the library. + * + * @param book The book to remove. + */ + public void removeBook(Book book) throws BookCheckedOutException { + if (this.isCheckedOut(book)) { + throw new BookCheckedOutException("Cannot remove checked out book."); + } + this.bookIds.remove(book.getId()); + book.setLibrary(null); + } + + /** + * Add a patron to the library. + * + * @param patron The patron to add. + */ + public void addPatron(Patron patron) { + this.patronIds.add(patron.getId()); + this.checkedOutBooksByPatron.put(patron.getId(), new HashSet<>()); + patron.setLibrary(this); + } + + /** + * Remove a patron from the library. + * + * @param patron The patron to remove. + */ + public void removePatron(Patron patron) throws BookCheckedOutException { + if (this.checkedOutBooksByPatron.get(patron.getId()).size() > 0) { + throw new BookCheckedOutException("Cannot remove patron with checked out books."); + } + this.patronIds.remove(patron.getId()); + this.checkedOutBooksByPatron.remove(patron.getId()); + patron.setLibrary(null); + } + + /** + * Check out a book to a patron. + * + * @param book The book to check out. + * @param patron The patron to check out the book to. + * @return True if the book was checked out, false otherwise. + */ + public boolean checkOutBook(Book book, Patron patron) { + if (!this.canCheckOutBook(book, patron)) { + return false; + } + this.checkedOutIsbns.add(book.getIsbn()); + this.checkedOutBooksByPatron.get(patron.getId()).add(book); + return true; + } + + private boolean canCheckOutBook(Book book, Patron patron) { + if (!this.hasBook(book)) { + return false; + } + if (this.isCheckedOut(book)) { + return false; + } + if (!this.hasPatron(patron)) { + return false; + } + return true; + } + + /** + * Check if the library has the given book. + * + * @param book The book to check for. + * @return True if the library has the book, false otherwise. + */ + public boolean hasBook(Book book) { + return this.bookIds.contains(book.getId()); + } + + /** + * Check if the given book is checked out. + * + * @param book The book to check. + * @return True if the book is checked out, false otherwise. + */ + public boolean isCheckedOut(Book book) { + return this.checkedOutIsbns.contains(book.getIsbn()); + } + + /** + * Check if the library has the given patron. + * + * @param patron The patron to check for. + * @return True if the library has the patron, false otherwise. + */ + public boolean hasPatron(Patron patron) { + return this.patronIds.contains(patron.getId()); + } + + /** + * Return a book to the library. + * + * @param book The book to return. + * @param patron The patron returning the book. + * @return True if the book was returned, false otherwise. + */ + public boolean checkInBook(Book book, Patron patron) { + if (!this.bookBelongsToLibrary(book)) { + return false; + } + this.checkedOutIsbns.remove(book.getIsbn()); + this.checkedOutBooksByPatron.get(patron.getId()).remove(book); + return true; + } + + private boolean bookBelongsToLibrary(Book book) { + return this.bookIds.contains(book.getId()); + } + + /** + * Get the books checked out by a patron. + * + * @param patron The patron to get the books for. + * @return The books checked out by the patron. + */ + public Set getCheckedOutByPatron(Patron patron) { + return this.checkedOutBooksByPatron.get(patron.getId()); + } + + @Override + public String toString() { + return "Library{" + + "bookIds=" + + bookIds + + ", checkedOutIsbns=" + + checkedOutIsbns + + ", checkedOutBooksByPatron=" + + checkedOutBooksByPatron + + ", patronIds=" + + patronIds + + '}'; + } +} diff --git a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Patron.java b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Patron.java new file mode 100644 index 00000000..35e033f4 --- /dev/null +++ b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Patron.java @@ -0,0 +1,79 @@ +package com.codedifferently.lesson10.library; + +import com.codedifferently.lesson10.library.exceptions.LibraryNotSetException; +import com.codedifferently.lesson10.library.exceptions.WrongLibraryException; +import java.util.Objects; +import java.util.Set; + +/** Represents a patron of a library. */ +public class Patron { + private Library library; + private String name; + private String email; + + /** + * Create a new patron with the given name and email. + * + * @param name The name of the patron. + * @param email The email of the patron. + */ + public Patron(String name, String email) { + this.name = name; + this.email = email; + } + + /** + * Get the library that the patron is in. + * + * @param library The library that the patron is in. + * @throws WrongLibraryException If the patron is not in the library. + */ + public void setLibrary(Library library) throws WrongLibraryException { + if (library != null && !library.hasPatron(this)) { + throw new WrongLibraryException( + "Patron " + this.getId() + " is not in library " + library.getId()); + } + this.library = library; + } + + /** Get the name of the patron. */ + public String getName() { + return this.name; + } + + /** Get the email of the patron. */ + public String getId() { + return this.email; + } + + /** + * Gets the books currently checked out to the patron. + * + * @return The books currently checked out to the patron. + * @throws LibraryNotSetException If the library is not set for the patron. + */ + public Set getCheckedOutBooks() throws LibraryNotSetException { + if (this.library == null) { + throw new LibraryNotSetException("Library not set for patron " + this.getId()); + } + return this.library.getCheckedOutByPatron(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Patron)) return false; + Patron patron = (Patron) o; + return Objects.equals(getId(), patron.getId()); + } + + @Override + public int hashCode() { + return Objects.hash(getId()); + } + + @Override + public String toString() { + return "Patron{" + "id='" + getId() + '\'' + ", name='" + getName() + '\'' + '}'; + } +} diff --git a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/BookCheckedOutException.java b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/BookCheckedOutException.java new file mode 100644 index 00000000..efbdadad --- /dev/null +++ b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/BookCheckedOutException.java @@ -0,0 +1,7 @@ +package com.codedifferently.lesson10.library.exceptions; + +public class BookCheckedOutException extends RuntimeException { + public BookCheckedOutException(String message) { + super(message); + } +} diff --git a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/LibraryNotSetException.java b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/LibraryNotSetException.java new file mode 100644 index 00000000..90e5c87e --- /dev/null +++ b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/LibraryNotSetException.java @@ -0,0 +1,7 @@ +package com.codedifferently.lesson10.library.exceptions; + +public class LibraryNotSetException extends RuntimeException { + public LibraryNotSetException(String message) { + super(message); + } +} diff --git a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/WrongLibraryException.java b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/WrongLibraryException.java new file mode 100644 index 00000000..dc4e2a2f --- /dev/null +++ b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/exceptions/WrongLibraryException.java @@ -0,0 +1,7 @@ +package com.codedifferently.lesson10.library.exceptions; + +public class WrongLibraryException extends RuntimeException { + public WrongLibraryException(String message) { + super(message); + } +} diff --git a/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/BookTest.java b/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/BookTest.java new file mode 100644 index 00000000..6bfd265e --- /dev/null +++ b/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/BookTest.java @@ -0,0 +1,85 @@ +package com.codedifferently.lesson10.library; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +import com.codedifferently.lesson10.library.exceptions.LibraryNotSetException; +import com.codedifferently.lesson10.library.exceptions.WrongLibraryException; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class BookTest { + + private Book classUnderTest; + private Library library; + + @BeforeEach + void setUp() { + classUnderTest = + new Book("To Kill a Mockingbird", "978-0061120084", List.of("Harper Lee"), 281); + library = mock(Library.class); + when(library.getId()).thenReturn("Library 1"); + when(library.hasBook(classUnderTest)).thenReturn(true); + classUnderTest.setLibrary(library); + } + + @Test + void testPatron_created() { + // Assert + assertThat(classUnderTest.getTitle()).isEqualTo("To Kill a Mockingbird"); + assertThat(classUnderTest.getIsbn()).isEqualTo("978-0061120084"); + assertThat(classUnderTest.getAuthors()).isEqualTo(List.of("Harper Lee")); + assertThat(classUnderTest.getNumberOfPages()).isEqualTo(281); + } + + @Test + void testSetLibrary_WrongLibrary() { + // Arrange + Library otherLibrary = mock(Library.class); + when(otherLibrary.hasBook(classUnderTest)).thenReturn(false); + when(otherLibrary.getId()).thenReturn("Library 2"); + + // Act & Assert + assertThatThrownBy(() -> classUnderTest.setLibrary(otherLibrary)) + .isInstanceOf(WrongLibraryException.class) + .hasMessageContaining("Book 978-0061120084 is not in library Library 2"); + } + + @Test + void testIsCheckedOut_LibraryNotSet() { + // Arrange + classUnderTest.setLibrary(null); + + // Act & Assert + assertThatThrownBy(() -> classUnderTest.isCheckedOut()) + .isInstanceOf(LibraryNotSetException.class) + .hasMessageContaining("Library not set for book 978-0061120084"); + } + + @Test + void testIsCheckedOut() { + // Arrange + when(library.isCheckedOut(classUnderTest)).thenReturn(true); + + // Act & Assert + assertThat(classUnderTest.isCheckedOut()).isTrue(); + } + + @Test + void testIsCheckedOut_whenNotCheckedOut() { + // Arrange + when(library.isCheckedOut(classUnderTest)).thenReturn(false); + + // Act & Assert + assertThat(classUnderTest.isCheckedOut()).isFalse(); + } + + @Test + void testToString() { + // Act & Assert + assertThat(classUnderTest.toString()) + .isEqualTo("Book{id='978-0061120084', title='To Kill a Mockingbird'}"); + } +} diff --git a/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/LibraryTest.java b/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/LibraryTest.java new file mode 100644 index 00000000..48ca8c19 --- /dev/null +++ b/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/LibraryTest.java @@ -0,0 +1,150 @@ +package com.codedifferently.lesson10.library; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.codedifferently.lesson10.library.exceptions.BookCheckedOutException; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class LibraryTest { + private Library classUnderTest; + + @BeforeEach + void setUp() { + classUnderTest = new Library("compton-library"); + } + + @Test + void testLibrary_canAddBooks() { + // Arrange + Book book1 = + new Book("The Great Gatsby", "978-0743273565", List.of("F. Scott Fitzgerald"), 180); + Book book2 = new Book("To Kill a Mockingbird", "978-0061120084", List.of("Harper Lee"), 281); + // Act + classUnderTest.addBook(book1); + classUnderTest.addBook(book2); + // Assert + assertThat(classUnderTest.hasBook(book1)).isTrue(); + assertThat(classUnderTest.hasBook(book2)).isTrue(); + } + + @Test + void testLibrary_canRemoveBooks() { + // Arrange + Book book1 = + new Book("The Great Gatsby", "978-0743273565", List.of("F. Scott Fitzgerald"), 180); + Book book2 = new Book("To Kill a Mockingbird", "978-0061120084", List.of("Harper Lee"), 281); + classUnderTest.addBook(book1); + classUnderTest.addBook(book2); + // Act + classUnderTest.removeBook(book1); + classUnderTest.removeBook(book2); + // Assert + assertThat(classUnderTest.hasBook(book1)).isFalse(); + assertThat(classUnderTest.hasBook(book2)).isFalse(); + } + + @Test + void testLibrary_canAddPatrons() { + // Arrange + Patron patron1 = new Patron("John Doe", "john@example.com"); + Patron patron2 = new Patron("Jane Doe", "jane@example.com"); + // Act + classUnderTest.addPatron(patron1); + classUnderTest.addPatron(patron2); + // Assert + assertThat(classUnderTest.hasPatron(patron1)).isTrue(); + assertThat(classUnderTest.hasPatron(patron2)).isTrue(); + } + + @Test + void testLibrary_canRemovePatrons() { + // Arrange + Patron patron1 = new Patron("John Doe", "john@example.com"); + Patron patron2 = new Patron("Jane Doe", "jane@example.com"); + classUnderTest.addPatron(patron1); + classUnderTest.addPatron(patron2); + // Act + classUnderTest.removePatron(patron1); + classUnderTest.removePatron(patron2); + // Assert + assertThat(classUnderTest.hasPatron(patron1)).isFalse(); + assertThat(classUnderTest.hasPatron(patron2)).isFalse(); + } + + @Test + void testLibrary_allowsPatronToCheckoutBook() { + // Arrange + Book book = new Book("The Great Gatsby", "978-0743273565", List.of("F. Scott Fitzgerald"), 180); + Patron patron = new Patron("John Doe", "john@example.com"); + classUnderTest.addBook(book); + classUnderTest.addPatron(patron); + // Act + boolean wasCheckedOut = classUnderTest.checkOutBook(book, patron); + // Assert + assertThat(wasCheckedOut).isTrue(); + assertThat(classUnderTest.isCheckedOut(book)).isTrue(); + assertThat(patron.getCheckedOutBooks().contains(book)).isTrue(); + } + + @Test + void testLibrary_allowPatronToCheckInBook() { + // Arrange + Book book = new Book("The Great Gatsby", "978-0743273565", List.of("F. Scott Fitzgerald"), 180); + Patron patron = new Patron("John Doe", "john@example.com"); + classUnderTest.addBook(book); + classUnderTest.addPatron(patron); + classUnderTest.checkOutBook(book, patron); + // Act + boolean wasReturned = classUnderTest.checkInBook(book, patron); + // Assert + assertThat(wasReturned).isTrue(); + assertThat(classUnderTest.isCheckedOut(book)).isFalse(); + assertThat(patron.getCheckedOutBooks().contains(book)).isFalse(); + } + + @Test + void testLibrary_preventsMultipleCheckouts() { + // Arrange + Book book = new Book("The Great Gatsby", "978-0743273565", List.of("F. Scott Fitzgerald"), 180); + Patron patron = new Patron("John Doe", "john@example.com"); + classUnderTest.addBook(book); + classUnderTest.addPatron(patron); + classUnderTest.checkOutBook(book, patron); + // Act + boolean wasCheckedOut = classUnderTest.checkOutBook(book, patron); + // Assert + assertThat(wasCheckedOut).isFalse(); + assertThat(classUnderTest.isCheckedOut(book)).isTrue(); + } + + @Test + void testLibrary_preventsRemovingPatronWithCheckedOutBooks() { + // Arrange + Book book = new Book("The Great Gatsby", "978-0743273565", List.of("F. Scott Fitzgerald"), 180); + Patron patron = new Patron("John Doe", "john@example.com"); + classUnderTest.addBook(book); + classUnderTest.addPatron(patron); + classUnderTest.checkOutBook(book, patron); + // Act + assertThatThrownBy(() -> classUnderTest.removePatron(patron)) + .isInstanceOf(BookCheckedOutException.class) + .hasMessage("Cannot remove patron with checked out books."); + } + + @Test + void testLibrary_preventsRemovingCheckedOutBooks() { + // Arrange + Book book = new Book("The Great Gatsby", "978-0743273565", List.of("F. Scott Fitzgerald"), 180); + Patron patron = new Patron("Jane Doe", "jane@example.com"); + classUnderTest.addBook(book); + classUnderTest.addPatron(patron); + classUnderTest.checkOutBook(book, patron); + // Act + assertThatThrownBy(() -> classUnderTest.removeBook(book)) + .isInstanceOf(BookCheckedOutException.class) + .hasMessage("Cannot remove checked out book."); + } +} diff --git a/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/PatronTest.java b/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/PatronTest.java new file mode 100644 index 00000000..496de811 --- /dev/null +++ b/lesson_10/solid/solid_app/src/test/java/com/codedifferently/lesson10/library/PatronTest.java @@ -0,0 +1,80 @@ +package com.codedifferently.lesson10.library; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.codedifferently.lesson10.library.exceptions.LibraryNotSetException; +import com.codedifferently.lesson10.library.exceptions.WrongLibraryException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class PatronTest { + + private Patron classUnderTest; + private Library library; + + @BeforeEach + void setUp() { + classUnderTest = new Patron("John Doe", "johndoe@example.com"); + library = new Library("Library 1"); + library.addPatron(classUnderTest); + } + + @Test + void testPatron_created() { + // Assert + assertThat(classUnderTest.getName()).isEqualTo("John Doe"); + assertThat(classUnderTest.getId()).isEqualTo("johndoe@example.com"); + } + + @Test + void testSetLibrary_WrongLibrary() { + // Arrange + Library otherLibrary = new Library("Library 2"); + + // Act & Assert + assertThatThrownBy(() -> classUnderTest.setLibrary(otherLibrary)) + .isInstanceOf(WrongLibraryException.class) + .hasMessageContaining("Patron johndoe@example.com is not in library Library 2"); + } + + @Test + void testGetCheckedOutBooks_LibraryNotSet() { + // Arrange + classUnderTest.setLibrary(null); + + // Act & Assert + assertThatThrownBy(() -> classUnderTest.getCheckedOutBooks()) + .isInstanceOf(LibraryNotSetException.class) + .hasMessageContaining("Library not set for patron johndoe@example.com"); + } + + @Test + void testGetCheckedOutBooks() { + // Arrange + Book book1 = + new Book("The Great Gatsby", "978-0743273565", List.of("F. Scott Fitzgerald"), 180); + Book book2 = new Book("To Kill a Mockingbird", "978-0061120084", List.of("Harper Lee"), 281); + Set expectedBooks = new HashSet<>(); + expectedBooks.add(book1); + expectedBooks.add(book2); + + library.addBook(book1); + library.addBook(book2); + library.checkOutBook(book1, classUnderTest); + library.checkOutBook(book2, classUnderTest); + + // Act & Assert + assertThat(classUnderTest.getCheckedOutBooks()).isEqualTo(expectedBooks); + } + + @Test + void testToString() { + // Act & Assert + assertThat(classUnderTest.toString()) + .isEqualTo("Patron{id='johndoe@example.com', name='John Doe'}"); + } +} From 272b86ec54afd30c595b23930ac9acfab6357aab Mon Sep 17 00:00:00 2001 From: "Anthony D. Mays" Date: Wed, 20 Mar 2024 23:07:16 +0000 Subject: [PATCH 2/4] chore: updated doco comment. --- .../main/java/com/codedifferently/lesson10/library/Book.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Book.java b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Book.java index c966fea0..2c86dad5 100644 --- a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Book.java +++ b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Book.java @@ -14,7 +14,7 @@ public class Book { private int numberOfPages; /** - * Create a new book with the given title, isbn, authors, and number of pages. + * Create a new book with the given title, ISBN, authors, and number of pages. * * @param title The title of the book. * @param isbn The ISBN of the book. From 343db4111edf3c5cdac221aeacc0f23d33035a07 Mon Sep 17 00:00:00 2001 From: "Anthony D. Mays" Date: Wed, 20 Mar 2024 23:24:48 +0000 Subject: [PATCH 3/4] docs: adds additional assignment details --- lesson_10/README.md | 10 +++++++++- .../com/codedifferently/lesson10/library/Library.java | 6 +----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lesson_10/README.md b/lesson_10/README.md index da39f5f2..02375258 100644 --- a/lesson_10/README.md +++ b/lesson_10/README.md @@ -20,4 +20,12 @@ ## Applying SOLID Principles -* TODO(anthonydmays): Add details +In this assignment, you will be given starting implementations for the `Library`, `Book`, and `Patron` classes. You will need to add the following enhancements to support new functionality: + +* We now want to support the concept of a `Librarian`. A librarian should be able to check out or check in books just like other patrons. Books can no longer be added or removed from the `Library` without a librarian. +* We also want to support other types of media formats, including `Dvd`, `Magazine`, and `Newspaper` types. Patrons cannot check out `Magazine` or `Newspaper` items. +* [Stretch] Add the ability to search for items in the library by title, ISBN, author, or type. Extra credit will not be assigned unless the previous requirements have been met. + +You will need to make changes to code in the [solid/][solid-folder] sub-folder and submit your PR for credit. Don't forget to follow the Conventional Commit spec for your commit messages and pull requests title and descriptions. + +[solid-folder]: ./solid/ diff --git a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Library.java b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Library.java index 08154409..c8593c53 100644 --- a/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Library.java +++ b/lesson_10/solid/solid_app/src/main/java/com/codedifferently/lesson10/library/Library.java @@ -147,7 +147,7 @@ public boolean hasPatron(Patron patron) { * @return True if the book was returned, false otherwise. */ public boolean checkInBook(Book book, Patron patron) { - if (!this.bookBelongsToLibrary(book)) { + if (!this.hasBook(book)) { return false; } this.checkedOutIsbns.remove(book.getIsbn()); @@ -155,10 +155,6 @@ public boolean checkInBook(Book book, Patron patron) { return true; } - private boolean bookBelongsToLibrary(Book book) { - return this.bookIds.contains(book.getId()); - } - /** * Get the books checked out by a patron. * From 59bb5d4cbead1c4b78b168723aa04dffed2b4767 Mon Sep 17 00:00:00 2001 From: "Anthony D. Mays" Date: Wed, 20 Mar 2024 23:26:03 +0000 Subject: [PATCH 4/4] chore: updates section title. --- lesson_10/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lesson_10/README.md b/lesson_10/README.md index 02375258..ecc4cd02 100644 --- a/lesson_10/README.md +++ b/lesson_10/README.md @@ -18,7 +18,7 @@ * Read HFDP 1-2. * Complete [Applying SOLID principles](#applying-solid-principles) exercise. -## Applying SOLID Principles +## Applying SOLID Principles (Library Management System, Part II) In this assignment, you will be given starting implementations for the `Library`, `Book`, and `Patron` classes. You will need to add the following enhancements to support new functionality: