diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/converter/BookConverter.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/converter/BookConverter.java new file mode 100644 index 0000000..7cd1df9 --- /dev/null +++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/converter/BookConverter.java @@ -0,0 +1,42 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.book.converter; + +import fr.iut_fbleau.but3.dev62.mylibrary.book.BookDTO; +import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo; +import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book; + +public final class BookConverter { + + private BookConverter() { + } + + public static Book toDomain(BookInfo bookInfo) { + return Book.builder() + .isbn(bookInfo.isbn()) + .title(bookInfo.title()) + .author(bookInfo.author()) + .publisher(bookInfo.publisher()) + .publicationDate(bookInfo.publicationDate()) + .price(bookInfo.price()) + .stock(bookInfo.initialStock()) + .categories(bookInfo.categories()) + .description(bookInfo.description()) + .language(bookInfo.language()) + .build(); + } + + public static BookDTO toDTO(Book book) { + return BookDTO.builder() + .id(book.getId()) + .isbn(book.getIsbn()) + .title(book.getTitle()) + .author(book.getAuthor()) + .publisher(book.getPublisher()) + .publicationDate(book.getPublicationDate()) + .price(book.getPrice()) + .stock(book.getStock()) + .categories(book.getCategories()) + .description(book.getDescription()) + .language(book.getLanguage()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/entity/Book.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/entity/Book.java new file mode 100644 index 0000000..86f306e --- /dev/null +++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/entity/Book.java @@ -0,0 +1,30 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.book.entity; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import java.util.UUID; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Book { + + private UUID id; + private String isbn; + private String title; + private String author; + private String publisher; + private LocalDate publicationDate; + private BigDecimal price; + private int stock; + private List categories; + private String description; + private String language; + + public void setRandomUUID() { + this.id = UUID.randomUUID(); + } +} + \ No newline at end of file diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/exception/BookNotFoundException.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/exception/BookNotFoundException.java new file mode 100644 index 0000000..5d59c9c --- /dev/null +++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/exception/BookNotFoundException.java @@ -0,0 +1,14 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.book.exception; + +import java.text.MessageFormat; +import java.util.UUID; + +public class BookNotFoundException extends Exception { + + public static final String THE_BOOK_WITH_ID_DOES_NOT_EXIST_MESSAGE = "The book with id {0} does not exist"; + + public BookNotFoundException(UUID uuid) { + super(MessageFormat.format(THE_BOOK_WITH_ID_DOES_NOT_EXIST_MESSAGE, uuid)); + } +} + \ No newline at end of file diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/exception/NotValidBookException.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/exception/NotValidBookException.java new file mode 100644 index 0000000..aad876f --- /dev/null +++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/exception/NotValidBookException.java @@ -0,0 +1,9 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.book.exception; + +public class NotValidBookException extends Exception { + + public NotValidBookException(String message) { + super(message); + } +} + \ No newline at end of file diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/repository/BookRepository.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/repository/BookRepository.java new file mode 100644 index 0000000..fa3e92b --- /dev/null +++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/repository/BookRepository.java @@ -0,0 +1,54 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.book.repository; + +import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public final class BookRepository { + + private final List books = new ArrayList<>(); + + public List findAll() { + return books; + } + + public void deleteAll() { + books.clear(); + } + + public Book save(Book newBook) { + if (newBook.getId() == null) { + newBook.setRandomUUID(); + } + Optional optionalBookWithSameId = this.findById(newBook.getId()); + optionalBookWithSameId.ifPresent(books::remove); + this.books.add(newBook); + return newBook; + } + + public Optional findById(UUID uuid) { + return this.books.stream() + .filter(book -> book.getId().equals(uuid)) + .findFirst(); + } + + public boolean existsById(UUID uuid) { + return this.books.stream() + .anyMatch(book -> book.getId().equals(uuid)); + } + + public Optional findByIsbn(String isbn) { + return this.books.stream() + .filter(book -> book.getIsbn().equals(isbn)) + .findFirst(); + } + + public void delete(Book book) { + this.books.remove(book); + } +} + \ No newline at end of file diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/usecase/BookUseCase.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/usecase/BookUseCase.java new file mode 100644 index 0000000..662b721 --- /dev/null +++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/usecase/BookUseCase.java @@ -0,0 +1,67 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.book.usecase; + +import fr.iut_fbleau.but3.dev62.mylibrary.book.BookDTO; +import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo; +import fr.iut_fbleau.but3.dev62.mylibrary.book.converter.BookConverter; +import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book; +import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.BookNotFoundException; +import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException; +import fr.iut_fbleau.but3.dev62.mylibrary.book.repository.BookRepository; +import fr.iut_fbleau.but3.dev62.mylibrary.book.validator.BookValidator; +import java.util.Optional; +import java.util.UUID; + +public final class BookUseCase { + + private final BookRepository bookRepository; + + public BookUseCase(BookRepository bookRepository) { + this.bookRepository = bookRepository; + } + + public String registerBook(BookInfo bookInfo) throws NotValidBookException { + BookValidator.validate(bookInfo); + Book bookToRegister = BookConverter.toDomain(bookInfo); + Book registeredBook = bookRepository.save(bookToRegister); + return registeredBook.getIsbn(); + } + + public Optional findBookByIsbn(String isbn) { + Optional optionalBook = bookRepository.findByIsbn(isbn); + return optionalBook.map(BookConverter::toDTO); + } + + public BookDTO updateBook(UUID uuid, BookInfo bookInfo) throws BookNotFoundException, NotValidBookException { + BookValidator.validate(bookInfo); + Book existingBook = getBookIfNotFoundThrowException(uuid); + Book updatedBook = Book.builder() + .id(uuid) + .isbn(bookInfo.isbn()) + .title(bookInfo.title()) + .author(bookInfo.author()) + .publisher(bookInfo.publisher()) + .publicationDate(bookInfo.publicationDate()) + .price(bookInfo.price()) + .stock(existingBook.getStock()) + .categories(bookInfo.categories()) + .description(bookInfo.description()) + .language(bookInfo.language()) + .build(); + Book saved = bookRepository.save(updatedBook); + return BookConverter.toDTO(saved); + } + + public void deleteBook(UUID uuid) throws BookNotFoundException { + Book bookToDelete = getBookIfNotFoundThrowException(uuid); + bookRepository.delete(bookToDelete); + } + + private Book getBookIfNotFoundThrowException(UUID uuid) throws BookNotFoundException { + Optional optionalBook = bookRepository.findById(uuid); + if (optionalBook.isEmpty()) { + throw new BookNotFoundException(uuid); + } + return optionalBook.get(); + } +} + \ No newline at end of file diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/validator/BookValidator.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/validator/BookValidator.java new file mode 100644 index 0000000..e0cce37 --- /dev/null +++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/book/validator/BookValidator.java @@ -0,0 +1,59 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.book.validator; + +import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo; +import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException; +import java.math.BigDecimal; + +public final class BookValidator { + + public static final String ISBN_IS_NOT_VALID = "ISBN is not valid"; + public static final String PRICE_MUST_BE_POSITIVE = "Price must be positive"; + public static final String TITLE_CANNOT_BE_BLANK = "Title cannot be blank"; + public static final String AUTHOR_CANNOT_BE_BLANK = "Author cannot be blank"; + public static final String PUBLISHER_CANNOT_BE_BLANK = "Publisher cannot be blank"; + public static final String ISBN_REGEX = "\\d{13}"; + + private BookValidator() { + } + + public static void validate(BookInfo bookInfo) throws NotValidBookException { + validateIsbn(bookInfo); + validateTitle(bookInfo); + validateAuthor(bookInfo); + validatePublisher(bookInfo); + validatePrice(bookInfo); + } + + private static void validateIsbn(BookInfo bookInfo) throws NotValidBookException { + if (bookInfo.isbn() == null || bookInfo.isbn().isBlank()) { + throw new NotValidBookException(ISBN_IS_NOT_VALID); + } + if (!bookInfo.isbn().matches(ISBN_REGEX)) { + throw new NotValidBookException(ISBN_IS_NOT_VALID); + } + } + + private static void validateTitle(BookInfo bookInfo) throws NotValidBookException { + if (bookInfo.title() == null || bookInfo.title().isBlank()) { + throw new NotValidBookException(TITLE_CANNOT_BE_BLANK); + } + } + + private static void validateAuthor(BookInfo bookInfo) throws NotValidBookException { + if (bookInfo.author() == null || bookInfo.author().isBlank()) { + throw new NotValidBookException(AUTHOR_CANNOT_BE_BLANK); + } + } + + private static void validatePublisher(BookInfo bookInfo) throws NotValidBookException { + if (bookInfo.publisher() == null || bookInfo.publisher().isBlank()) { + throw new NotValidBookException(PUBLISHER_CANNOT_BE_BLANK); + } + } + + private static void validatePrice(BookInfo bookInfo) throws NotValidBookException { + if (bookInfo.price() == null || bookInfo.price().compareTo(BigDecimal.ZERO) <= 0) { + throw new NotValidBookException(PRICE_MUST_BE_POSITIVE); + } + } +} \ No newline at end of file