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

Library Managment System Solution #8

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions src/main/java/fr/d2factory/libraryapp/book/Book.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,43 @@
package fr.d2factory.libraryapp.book;

import java.util.Objects;

/**
* A simple representation of a book
*/
public class Book {
String title;
String author;
ISBN isbn;
private String title;
private String author;
private ISBN isbn;

public Book() {}

public String getTitle() {
return title;
}

public String getAuthor() {
return author;
}

public ISBN getIsbn() {
return isbn;
}

@Override
public boolean equals(Object o) {
boolean result = false;
if(o instanceof Book) {
Book book = (Book) o;
result = Objects.equals(title, book.title) &&
Objects.equals(author, book.author) &&
Objects.equals(isbn, book.isbn);
}
return result;
}

@Override
public int hashCode() {
return Objects.hash(title, author, isbn);
}
}
38 changes: 32 additions & 6 deletions src/main/java/fr/d2factory/libraryapp/book/BookRepository.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,58 @@
package fr.d2factory.libraryapp.book;

import fr.d2factory.libraryapp.member.Member;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* The book repository emulates a database via 2 HashMaps
*/
public class BookRepository {
private Map<ISBN, Book> availableBooks = new HashMap<>();
private Map<Book, LocalDate> borrowedBooks = new HashMap<>();
private Map<Book, Member> borrower = new HashMap<>();

public void addBooks(List<Book> books){
//TODO implement the missing feature
books.stream().filter(b->!availableBooks.containsKey(b.getIsbn()))
.forEach(b->availableBooks.put(b.getIsbn(), b));
}

public Book findBook(long isbnCode) {
//TODO implement the missing feature
return null;
return availableBooks.get(new ISBN(isbnCode));
}

public Member findBorrower(Book book) {
return borrower.get(book);
}

public void saveBookBorrow(Book book, LocalDate borrowedAt){
//TODO implement the missing feature
availableBooks.remove(book.getIsbn());
borrowedBooks.put(book, borrowedAt);
}

public void saveBorrower(Book book, Member member){
borrower.put(book, member);
}

public LocalDate findBorrowedBookDate(Book book) {
//TODO implement the missing feature
return null;
return borrowedBooks.get(book);
}

public void returnBook(Book book){
borrowedBooks.remove(book);
availableBooks.put(book.getIsbn(), book);
borrower.remove(book);
}


public Map<Member, List<Book>> booksBorrowedByMember(){
return borrower.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
}

}
27 changes: 27 additions & 0 deletions src/main/java/fr/d2factory/libraryapp/book/ISBN.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,34 @@
public class ISBN {
long isbnCode;

public ISBN(){
}

public ISBN(long isbnCode) {
this.isbnCode = isbnCode;
}


public long getIsbnCode() {
return isbnCode;
}

public void setIsbnCode(long isbnCode) {
this.isbnCode = isbnCode;
}

@Override
public int hashCode(){
return Long.hashCode(isbnCode);
}

@Override
public boolean equals(Object o){
boolean result = false;
if(o instanceof ISBN){
ISBN isbn = (ISBN)o;
result = isbnCode == isbn.getIsbnCode();
}
return result;
}
}
1 change: 1 addition & 0 deletions src/main/java/fr/d2factory/libraryapp/library/Library.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ public interface Library {
* @see Member#payBook(int)
*/
void returnBook(Book book, Member member);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package fr.d2factory.libraryapp.library;

import fr.d2factory.libraryapp.book.Book;
import fr.d2factory.libraryapp.book.BookRepository;
import fr.d2factory.libraryapp.member.Member;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

public class LibraryManagmentSystem implements Library {

private BookRepository bookRepository;

public LibraryManagmentSystem(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}

@Override
public Book borrowBook(long isbnCode, Member member, LocalDate borrowedAt){
Book book = null;
if(isLate(member)){
throw new HasLateBooksException();
}
book = bookRepository.findBook(isbnCode);
Optional<Book> opBook = Optional.ofNullable(book);
Consumer<Book> c1= b -> bookRepository.saveBookBorrow(b, borrowedAt);
Consumer<Book> c2 = c1.andThen(b-> bookRepository.saveBorrower(b, member));
opBook.ifPresent(c2);
return book;
}

@Override
public void returnBook(Book book, Member member){
int numberOfDays = (int)bookRepository.findBorrowedBookDate(book).until(LocalDate.now(), ChronoUnit.DAYS);
bookRepository.returnBook(book);
member.payBook(numberOfDays);
}


private boolean isLate(Member member){
boolean result = false;
List<Book> booksBorrowedByTheMember = bookRepository.booksBorrowedByMember().get(member);
if(booksBorrowedByTheMember != null){
int memberMaxPeriod = member.getConfig().getMaxPeriod();
result = booksBorrowedByTheMember.stream()
.anyMatch(b->bookNotReturned(b, memberMaxPeriod));
}
return result;
}

private boolean bookNotReturned(Book book, int maxPeriod){
boolean result = false;
int daysBorrowed = daysBorrowed(book);
result = daysBorrowed > maxPeriod;
return result;
}


private int daysBorrowed(Book book){
int daysBorrowed = 0;
LocalDate now = LocalDate.now();
LocalDate borrowedAt = bookRepository.findBorrowedBookDate(book);
daysBorrowed = (int)borrowedAt.until(now, ChronoUnit.DAYS);
return daysBorrowed;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package fr.d2factory.libraryapp.library;

public class NoEnoughFundInTheWallet extends RuntimeException {
}
75 changes: 75 additions & 0 deletions src/main/java/fr/d2factory/libraryapp/member/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,103 @@

import fr.d2factory.libraryapp.library.Library;

import java.util.Objects;

/**
* A member is a person who can borrow and return books to a {@link Library}
* A member can be either a student or a resident
*/
public abstract class Member {


private String id;

private String firstName;

private String lastName;

/**
* An initial sum of money the member has
*/
private float wallet;

private Profil config;


public Member( String id, String firstName, String lastName,float wallet, Profil config) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.wallet = wallet;
this.config = config;
}

/**
* The member should pay their books when they are returned to the library
*
* @param numberOfDays the number of days they kept the book
*/
public abstract void payBook(int numberOfDays);


public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public void setConfig(Profil config) {
this.config = config;
}


public float getWallet() {

return wallet;
}

public void setWallet(float wallet) {

this.wallet = wallet;
}

public Profil getConfig() {
return config;
}


@Override
public boolean equals(Object o) {
boolean result = false;
if(o instanceof Member){
Member member = (Member)o;
result = id.equals(member.id) &&
firstName.equals(member.firstName) &&
lastName.equals(member.lastName);
}
return result;
}

@Override
public int hashCode() {
return Objects.hash(id, firstName, lastName);
}
}
36 changes: 36 additions & 0 deletions src/main/java/fr/d2factory/libraryapp/member/Profil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package fr.d2factory.libraryapp.member;

public enum Profil {

RESIDENT(60, 0, 0.10f, 0.20f),
STUDENT(30,0,0.10f,0.10f),
STUDENT_1ST_YEAR(30,15,0.10f,0.10f);

private final int maxPeriod;
private final int freePeriod;
private final float amountChargedBefore;
private final float amountChargedAfter;

Profil(int maxPeriod, int freePeriod, float amountChargedBefore, float amountChargedAfter) {
this.maxPeriod = maxPeriod;
this.freePeriod = freePeriod;
this.amountChargedBefore = amountChargedBefore;
this.amountChargedAfter = amountChargedAfter;
}

public int getMaxPeriod() {
return maxPeriod;
}

public int getFreePeriod() {
return freePeriod;
}

public float getAmountChargedBefore() {
return amountChargedBefore;
}

public float getAmountChargedAfter() {
return amountChargedAfter;
}
}
25 changes: 25 additions & 0 deletions src/main/java/fr/d2factory/libraryapp/member/ResidentMember.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package fr.d2factory.libraryapp.member;

import fr.d2factory.libraryapp.library.NoEnoughFundInTheWallet;

public class ResidentMember extends Member {


public ResidentMember(String id, String firstName, String lastName, float wallet, Profil config) {
super(id, firstName, lastName, wallet, config);
}


@Override
public void payBook(int numberOfDays) {
int maxPeriod = getConfig().getMaxPeriod();
float amountToPay = Math.min(maxPeriod, numberOfDays ) * getConfig().getAmountChargedBefore()
+ Math.max(0, numberOfDays - maxPeriod) * getConfig().getAmountChargedAfter();
if(amountToPay < getWallet()){
setWallet(getWallet()-amountToPay);
}else{
throw new NoEnoughFundInTheWallet();

}
}
}
Loading