Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adds Lesson 10 homework assignment and stretch requirement. #284

Merged
merged 4 commits into from Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 10 additions & 2 deletions lesson_10/README.md
Expand Up @@ -18,6 +18,14 @@
* Read HFDP 1-2.
* Complete [Applying SOLID principles](#applying-solid-principles) exercise.

## Applying SOLID Principles
## Applying SOLID Principles (Library Management System, Part II)

* 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/
@@ -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<String> 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<String> 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<String> 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() + '\'' + '}';
}
}
@@ -0,0 +1,181 @@
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<String> bookIds = new HashSet<>();
private Set<String> checkedOutIsbns = new HashSet<>();
private Map<String, Set<Book>> checkedOutBooksByPatron = new HashMap<>();
private Set<String> 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.hasBook(book)) {
return false;
}
this.checkedOutIsbns.remove(book.getIsbn());
this.checkedOutBooksByPatron.get(patron.getId()).remove(book);
return true;
}

/**
* 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<Book> getCheckedOutByPatron(Patron patron) {
return this.checkedOutBooksByPatron.get(patron.getId());
}

@Override
public String toString() {
return "Library{"
+ "bookIds="
+ bookIds
+ ", checkedOutIsbns="
+ checkedOutIsbns
+ ", checkedOutBooksByPatron="
+ checkedOutBooksByPatron
+ ", patronIds="
+ patronIds
+ '}';
}
}
@@ -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<Book> 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() + '\'' + '}';
}
}
@@ -0,0 +1,7 @@
package com.codedifferently.lesson10.library.exceptions;

public class BookCheckedOutException extends RuntimeException {
public BookCheckedOutException(String message) {
super(message);
}
}
@@ -0,0 +1,7 @@
package com.codedifferently.lesson10.library.exceptions;

public class LibraryNotSetException extends RuntimeException {
public LibraryNotSetException(String message) {
super(message);
}
}