From 06863854e398ef3b431d9e755b11b9290359636f Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:37:23 +0530 Subject: [PATCH 01/87] Add new entity representing series of books. --- .../karankumar/booksapi/model/BookSeries.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/model/BookSeries.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java new file mode 100644 index 00000000..a291443c --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -0,0 +1,30 @@ +package com.karankumar.booksapi.model; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.*; +import java.util.List; + +@Entity +@Getter +@Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class BookSeries { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Setter(AccessLevel.NONE) + private Long id; + + @Column(nullable = false) + private String seriesName; + + @OneToMany(mappedBy = "bookSeries") + private List bookSeriesMapping; + + public BookSeries(String seriesName){ + this.seriesName = seriesName; + } +} From c5d2ca8b2e2cce4d861f355aa3546d225c4ce93c Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:38:32 +0530 Subject: [PATCH 02/87] Add new entity mapping series of books and books with a serial order number. --- .../booksapi/model/BookSeriesMapping.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java new file mode 100644 index 00000000..3a7cae70 --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -0,0 +1,38 @@ +package com.karankumar.booksapi.model; + +import lombok.*; + +import javax.persistence.*; + +@Getter @Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity + +@Table( + name="Book_To_BookSeries_Mapping", + uniqueConstraints = + @UniqueConstraint( columnNames = {"book_id","book_series_id","serialNumber"} ) +) + +public class BookSeriesMapping { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Setter(AccessLevel.NONE) + private long id; + + @ManyToOne + private BookSeries bookSeries; + + @ManyToOne + private Book book; + + @Column(nullable = false, name = "serialNumber") + private int serialNumber; + + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull int serialNumber) { + this.bookSeries = bookSeries; + this.book = bookInSeries; + this.serialNumber = serialNumber; + } +} From 3590469221c3bb2881c502e99ac16620ddcc95be Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:39:36 +0530 Subject: [PATCH 03/87] Add bookSeriesMapping to Book --- src/main/java/com/karankumar/booksapi/model/Book.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/Book.java b/src/main/java/com/karankumar/booksapi/model/Book.java index 1a723fc4..4dea849b 100644 --- a/src/main/java/com/karankumar/booksapi/model/Book.java +++ b/src/main/java/com/karankumar/booksapi/model/Book.java @@ -30,8 +30,10 @@ import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; @Entity @@ -75,8 +77,11 @@ public class Book { @Column(nullable = false) private BookFormat format; - public Book(@NonNull String title, @NonNull Author[] authors, @NonNull Language language, - @NonNull String blurb, @NonNull BookGenre genre, @NonNull BookFormat format) { + @OneToMany(mappedBy = "book") + private List bookSeriesMapping; + + public Book(@NonNull String title, @NonNull Author[] authors, @NonNull Language language, @NonNull String blurb, + @NonNull BookGenre genre, @NonNull BookFormat format) { this.title = title; Arrays.stream(authors).forEach(this::addAuthor); this.language = language; From b8aed122ffc8910dc9c7bb436b0058f7595fa734 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 14 Mar 2021 12:38:46 +0530 Subject: [PATCH 04/87] Add copyright text --- .../com/karankumar/booksapi/model/BookSeries.java | 14 ++++++++++++++ .../booksapi/model/BookSeriesMapping.java | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index a291443c..9a133c8d 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -1,3 +1,17 @@ +/* +The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. +Copyright (C) 2020 Karan Kumar + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. +If not, see . +*/ + package com.karankumar.booksapi.model; import lombok.AccessLevel; diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index 3a7cae70..afb9fb1f 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -1,3 +1,17 @@ +/* +The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. +Copyright (C) 2020 Karan Kumar + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. +If not, see . +*/ + package com.karankumar.booksapi.model; import lombok.*; From e21db5a4b2254a2adadfb0778114a68da5a7626c Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:28:09 +0530 Subject: [PATCH 05/87] Update BookSeries entity's member "seriesName" --- src/main/java/com/karankumar/booksapi/model/BookSeries.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index 9a133c8d..cefabc80 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -18,6 +18,7 @@ License, or (at your option) any later version. import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.NonNull; import javax.persistence.*; import java.util.List; @@ -32,13 +33,13 @@ public class BookSeries { @Setter(AccessLevel.NONE) private Long id; - @Column(nullable = false) + @Column(nullable = false, name = "series_name") private String seriesName; @OneToMany(mappedBy = "bookSeries") private List bookSeriesMapping; - public BookSeries(String seriesName){ + public BookSeries(@NonNull String seriesName){ this.seriesName = seriesName; } } From 75ccd9d7dcabd1194914acc6042e176ad051a3f2 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:33:48 +0530 Subject: [PATCH 06/87] Update BookSeriesMapping entity - Unique constraint, Relationship fields are Not Null, minor corrections --- .../booksapi/model/BookSeriesMapping.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index afb9fb1f..deda1ede 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -21,11 +21,12 @@ License, or (at your option) any later version. @Getter @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity - @Table( name="Book_To_BookSeries_Mapping", - uniqueConstraints = - @UniqueConstraint( columnNames = {"book_id","book_series_id","serialNumber"} ) + uniqueConstraints = { + @UniqueConstraint( name = "UK_bookSeriesId_bookId", columnNames = {"book_series_id","book_id"} ), + @UniqueConstraint( name = "UK_bookSeriesId_serialNumber", columnNames = {"book_series_id","serial_number"} ) + } ) public class BookSeriesMapping { @@ -33,18 +34,18 @@ public class BookSeriesMapping { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Setter(AccessLevel.NONE) - private long id; + private Long id; - @ManyToOne + @ManyToOne(optional = false) private BookSeries bookSeries; - @ManyToOne + @ManyToOne(optional = false) private Book book; - @Column(nullable = false, name = "serialNumber") - private int serialNumber; + @Column(nullable = false, name="serial_number") + private Integer serialNumber; - public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull int serialNumber) { + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull Integer serialNumber) { this.bookSeries = bookSeries; this.book = bookInSeries; this.serialNumber = serialNumber; From e0718d1fdecdc9f170034051305de522ff8a930f Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:35:45 +0530 Subject: [PATCH 07/87] Add tests for entities Book Series Mapping and Book Series. --- .../booksapi/model/BookSeriesMappingTest.java | 86 +++++++++++++++++++ .../booksapi/model/BookSeriesTest.java | 33 +++++++ 2 files changed, 119 insertions(+) create mode 100644 src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java create mode 100644 src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java new file mode 100644 index 00000000..ce740261 --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +@DisplayName("Book Series Mapping should") +public class BookSeriesMappingTest { + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Serial Number") + void notAcceptNullSerialNumber(){ + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + Book book = new Book( + "Harry Potter and the Philosopher's stone", + new Author[] {author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book.setYearOfPublication(1997); + book.setIsbn13("9781408810545"); + book.setPublishedBy(Publisher.BLOOMSBURY); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); + } + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book") + void notAcceptNullBook(){ + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(bookSeries, null, 1)); + } + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") + void notAcceptNullBookSeries(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + Book book = new Book( + "Harry Potter and the Philosopher's stone", + new Author[] {author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book.setYearOfPublication(1997); + book.setIsbn13("9781408810545"); + book.setPublishedBy(Publisher.BLOOMSBURY); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(null, book, 1)); + } +} diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java new file mode 100644 index 00000000..67acdedb --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +@DisplayName("Book series should") +public class BookSeriesTest { + + @Test + @DisplayName("throw a null pointer exception on an attempt to create with a null Series Name.") + void notAcceptNullSeriesName(){ + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy( ()->new BookSeries(null) ); + } +} From 2af638cb2af96ed16efe3fa43ca3bc6d41712a16 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:37:20 +0530 Subject: [PATCH 08/87] Add boilerplate code for entity repositories. --- .../BookSeriesMappingRepository.java | 22 +++++++++++++++++++ .../repository/BookSeriesRepository.java | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java create mode 100644 src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java new file mode 100644 index 00000000..c421f8ea --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.model.BookSeriesMapping; +import org.springframework.data.repository.CrudRepository; + +public interface BookSeriesMappingRepository extends CrudRepository { +} diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java new file mode 100644 index 00000000..7a167b33 --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.model.BookSeries; +import org.springframework.data.repository.CrudRepository; + +public interface BookSeriesRepository extends CrudRepository { +} From eee400ee0f24ba46c3e721039dd6a8a159341fef Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:39:02 +0530 Subject: [PATCH 09/87] Add repository methods for Book, BookSeriesMapping --- .../booksapi/repository/BookRepository.java | 11 +++++++++++ .../repository/BookSeriesMappingRepository.java | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index 02538887..01857d8d 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -16,6 +16,8 @@ package com.karankumar.booksapi.repository; import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; @@ -32,4 +34,13 @@ public interface BookRepository extends CrudRepository { Book findBookByIsbn13(String isbn13); Book findByTitleIgnoreCase(String title); + + // Lists all BookSeries for a Book entry + @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") + List getAllBookSeriesForBook(Book book); + + // Returns position of a book in a Book Series + @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") + Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); + } diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java index c421f8ea..1d5bcebd 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -15,8 +15,17 @@ package com.karankumar.booksapi.repository; +import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; +import java.util.List; + public interface BookSeriesMappingRepository extends CrudRepository { + + // Lists all Books in a Book Series + @Query("SELECT a.book FROM BookSeriesMapping a WHERE a.bookSeries = ?1") + List getAllBooksByBookSeries(BookSeries bookSeries); } From 370dc0b660ab8bb68648b06c224b1ec5e380209a Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:41:14 +0530 Subject: [PATCH 10/87] Add test classes for BookSeries & BookSeriesMapping repository --- .../BookSeriesMappingRepositoryTest.java | 101 ++++++++++++++++++ .../repository/BookSeriesRepositoryTest.java | 26 +++++ 2 files changed, 127 insertions(+) create mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java create mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java new file mode 100644 index 00000000..a685399b --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -0,0 +1,101 @@ +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; +import com.karankumar.booksapi.model.Author; +import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookFormat; +import com.karankumar.booksapi.model.BookGenre; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; +import com.karankumar.booksapi.model.Language; +import com.karankumar.booksapi.model.Publisher; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaIntegrationTest +@DisplayName("BookSeriesMappingRepository should") +public class BookSeriesMappingRepositoryTest { + + private final BookRepository bookRepository; + private final AuthorRepository authorRepository; + private final BookSeriesRepository bookSeriesRepository; + private final BookSeriesMappingRepository bookSeriesMappingRepository; + + @Autowired + BookSeriesMappingRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository){ + + this.bookRepository = bookRepository; + this.authorRepository = authorRepository; + this.bookSeriesRepository = bookSeriesRepository; + this.bookSeriesMappingRepository = bookSeriesMappingRepository; + } + + @BeforeEach + void setUp() { + bookSeriesMappingRepository.deleteAll(); + authorRepository.deleteAll(); + bookRepository.deleteAll(); + bookSeriesRepository.deleteAll(); + } + + @Test + @DisplayName("return all books in a series.") + void fetchAllBooksInBookSeries(){ + + BookSeries bs = createBookSeriesMapping(); + List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); + + List bookList = new ArrayList<>(); + bookList.add(bookRepository.findBookByIsbn13("9781408810545")); + bookList.add(bookRepository.findBookByIsbn13("1234567898765")); + + assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); + } + + private BookSeries createBookSeriesMapping(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + authorRepository.save(author); + + Book book1 = new Book( + "Harry Potter and the Philosopher's stone", new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + book1.setYearOfPublication(1997); + book1.setIsbn13("9781408810545"); + book1.setPublishedBy(Publisher.BLOOMSBURY); + bookRepository.save(book1); + + Book book2 = new Book( + "Harry Potter and the Chamber of Secrets", + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book2.setIsbn13("1234567898765"); + book2.setGenre(BookGenre.FANTASY); + book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setFormat(BookFormat.PAPERBACK); + bookRepository.save(book2); + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + bookSeriesRepository.save(bookSeries); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries, book2, 2)); + + return bookSeries; + } +} diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java new file mode 100644 index 00000000..cd0403fe --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DataJpaIntegrationTest +@DisplayName("BookSeries Repository should") +public class BookSeriesRepositoryTest { + +} From d10d70517bbd0d9aba639189155064e9a4b6e44c Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:47:12 +0530 Subject: [PATCH 11/87] Add new tests for Book repository --- .../repository/BookRepositoryTest.java | 92 ++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index e88b165b..86b3989c 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -20,12 +20,16 @@ import com.karankumar.booksapi.model.Book; import com.karankumar.booksapi.model.BookFormat; import com.karankumar.booksapi.model.BookGenre; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; +import com.karankumar.booksapi.model.Publisher; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -42,19 +46,26 @@ class BookRepositoryTest { private final BookRepository bookRepository; private final AuthorRepository authorRepository; + private final BookSeriesRepository bookSeriesRepository; + private final BookSeriesMappingRepository bookSeriesMappingRepository; private Author author1; private Author author2; @Autowired - BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository) { + BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; + this.bookSeriesRepository = bookSeriesRepository; + this.bookSeriesMappingRepository = bookSeriesMappingRepository; } @BeforeEach void setUp() { + bookSeriesMappingRepository.deleteAll(); authorRepository.deleteAll(); bookRepository.deleteAll(); + bookSeriesRepository.deleteAll(); } @Test @@ -173,4 +184,83 @@ void findBookByTitleCaseInsensitive() { private void saveAllAuthors(Author... authors) { Arrays.stream(authors).forEach(authorRepository::save); } + + @Test + @DisplayName("find all Book Series for a Book") + void findBookSeriesForBook(){ + List assertion = addBookToSeries(); + Book book = bookRepository.findBookByIsbn13("9781408810545"); + + List result = bookRepository.getAllBookSeriesForBook(book); + + assertThat(result).containsExactlyInAnyOrderElementsOf(assertion); + } + + @Test + @DisplayName("find book position in Book Series") + void findBookPositionInSeries(){ + + // Get book and book series from repo + List allSeries = addBookToSeries(); + Book book = bookRepository.findBookByIsbn13("9781408810545"); + BookSeries assertion = null; + for (BookSeries series : allSeries) { + if(series.getSeriesName().equals("Harry Potter Series")){ + assertion = series; + break; + } + } + + assertThat(bookRepository.getBookPositionInBookSeries(book, assertion)).isEqualTo(1); + } + + // Utility method + private List addBookToSeries(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + authorRepository.save(author); + + Book book1 = new Book( + "Harry Potter and the Philosopher's stone", new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + book1.setYearOfPublication(1997); + book1.setIsbn13("9781408810545"); + book1.setPublishedBy(Publisher.BLOOMSBURY); + bookRepository.save(book1); + + Book book2 = new Book( + "Harry Potter and the Chamber of Secrets", + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book2.setIsbn13("1234567898765"); + book2.setGenre(BookGenre.FANTASY); + book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setFormat(BookFormat.PAPERBACK); + bookRepository.save(book2); + + BookSeries bookSeries1 = new BookSeries("Harry Potter Series"); + bookSeriesRepository.save(bookSeries1); + + BookSeries bookSeries2 = new BookSeries("J.K. Rowling Specials"); + bookSeriesRepository.save(bookSeries2); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries1, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries1, book2, 2)); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book2, 2)); + + List bs = new ArrayList<>(); + bs.add(bookSeries1); + bs.add(bookSeries2); + + return bs; + } } From 8309e31cf75cb5c227522e03ab3b6d300718caab Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:49:40 +0530 Subject: [PATCH 12/87] Update setup method to clear tables with Foreign Key dependencies first --- .../karankumar/booksapi/repository/AuthorRepositoryTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java index 492e2f5e..f986ea1d 100644 --- a/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java @@ -33,15 +33,18 @@ class AuthorRepositoryTest { private final BookRepository bookRepository; private final AuthorRepository authorRepository; + private final BookSeriesMappingRepository bookSeriesMappingRepository; @Autowired - AuthorRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository) { + AuthorRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; + this.bookSeriesMappingRepository = bookSeriesMappingRepository; } @BeforeEach void setUp() { + bookSeriesMappingRepository.deleteAll(); authorRepository.deleteAll(); bookRepository.deleteAll(); } From fe14f80893e4d8e84b8d0bc66ccc70c2f7771252 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 18:01:24 +0530 Subject: [PATCH 13/87] Fix test issues due to merge --- .../booksapi/model/BookSeriesMappingTest.java | 10 +++++----- .../booksapi/repository/BookRepositoryTest.java | 8 ++++---- .../repository/BookSeriesMappingRepositoryTest.java | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java index ce740261..1c569db9 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -29,7 +29,7 @@ void notAcceptNullSerialNumber(){ BookSeries bookSeries = new BookSeries("Harry Potter Series"); - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); Book book = new Book( @@ -42,7 +42,7 @@ void notAcceptNullSerialNumber(){ ); book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); - book.setPublishedBy(Publisher.BLOOMSBURY); + book.setPublisher(PublisherName.BLOOMSBURY); assertThatExceptionOfType(NullPointerException.class) .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); @@ -54,7 +54,7 @@ void notAcceptNullBook(){ BookSeries bookSeries = new BookSeries("Harry Potter Series"); - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); assertThatExceptionOfType(NullPointerException.class) @@ -65,7 +65,7 @@ void notAcceptNullBook(){ @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") void notAcceptNullBookSeries(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); Book book = new Book( @@ -78,7 +78,7 @@ void notAcceptNullBookSeries(){ ); book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); - book.setPublishedBy(Publisher.BLOOMSBURY); + book.setPublisher(PublisherName.BLOOMSBURY); assertThatExceptionOfType(NullPointerException.class) .isThrownBy(()->new BookSeriesMapping(null, book, 1)); diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index 86b3989c..6558636a 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -23,7 +23,7 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.Publisher; +import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -217,7 +217,7 @@ void findBookPositionInSeries(){ // Utility method private List addBookToSeries(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); @@ -228,7 +228,7 @@ private List addBookToSeries(){ ); book1.setYearOfPublication(1997); book1.setIsbn13("9781408810545"); - book1.setPublishedBy(Publisher.BLOOMSBURY); + book1.setPublisher(PublisherName.BLOOMSBURY); bookRepository.save(book1); Book book2 = new Book( @@ -241,7 +241,7 @@ private List addBookToSeries(){ ); book2.setIsbn13("1234567898765"); book2.setGenre(BookGenre.FANTASY); - book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setPublisher(PublisherName.BLOOMSBURY); book2.setFormat(BookFormat.PAPERBACK); bookRepository.save(book2); diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index a685399b..1c66de4c 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -8,7 +8,7 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.Publisher; +import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -62,7 +62,7 @@ void fetchAllBooksInBookSeries(){ private BookSeries createBookSeriesMapping(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); @@ -73,7 +73,7 @@ private BookSeries createBookSeriesMapping(){ ); book1.setYearOfPublication(1997); book1.setIsbn13("9781408810545"); - book1.setPublishedBy(Publisher.BLOOMSBURY); + book1.setPublisher(PublisherName.BLOOMSBURY); bookRepository.save(book1); Book book2 = new Book( @@ -86,7 +86,7 @@ private BookSeries createBookSeriesMapping(){ ); book2.setIsbn13("1234567898765"); book2.setGenre(BookGenre.FANTASY); - book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setPublisher(PublisherName.BLOOMSBURY); book2.setFormat(BookFormat.PAPERBACK); bookRepository.save(book2); From d2381420b00636b03121fbe935e73716d8d7b292 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:11:31 +0000 Subject: [PATCH 14/87] Remove wildcard imports & adhere to 100 char limit --- .../com/karankumar/booksapi/model/Book.java | 4 +-- .../karankumar/booksapi/model/BookSeries.java | 28 +++++++++++-------- .../booksapi/model/BookSeriesMapping.java | 19 +++++++++---- .../booksapi/repository/BookRepository.java | 2 -- .../BookSeriesMappingRepository.java | 2 -- 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/Book.java b/src/main/java/com/karankumar/booksapi/model/Book.java index 4dea849b..4c700a2a 100644 --- a/src/main/java/com/karankumar/booksapi/model/Book.java +++ b/src/main/java/com/karankumar/booksapi/model/Book.java @@ -80,8 +80,8 @@ public class Book { @OneToMany(mappedBy = "book") private List bookSeriesMapping; - public Book(@NonNull String title, @NonNull Author[] authors, @NonNull Language language, @NonNull String blurb, - @NonNull BookGenre genre, @NonNull BookFormat format) { + public Book(@NonNull String title, @NonNull Author[] authors, @NonNull Language language, + @NonNull String blurb, @NonNull BookGenre genre, @NonNull BookFormat format) { this.title = title; Arrays.stream(authors).forEach(this::addAuthor); this.language = language; diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index cefabc80..bd0cea9b 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -1,16 +1,17 @@ /* -The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. -Copyright (C) 2020 Karan Kumar + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program. -If not, see . -*/ + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ package com.karankumar.booksapi.model; @@ -20,7 +21,12 @@ License, or (at your option) any later version. import lombok.Setter; import lombok.NonNull; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; import java.util.List; @Entity diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index deda1ede..66e24c29 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -18,17 +18,23 @@ License, or (at your option) any later version. import javax.persistence.*; -@Getter @Setter +@Getter +@Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @Table( name="Book_To_BookSeries_Mapping", uniqueConstraints = { - @UniqueConstraint( name = "UK_bookSeriesId_bookId", columnNames = {"book_series_id","book_id"} ), - @UniqueConstraint( name = "UK_bookSeriesId_serialNumber", columnNames = {"book_series_id","serial_number"} ) + @UniqueConstraint( + name = "UK_bookSeriesId_bookId", + columnNames = {"book_series_id","book_id"} + ), + @UniqueConstraint( + name = "UK_bookSeriesId_serialNumber", + columnNames = {"book_series_id","serial_number"} + ) } ) - public class BookSeriesMapping { @Id @@ -42,10 +48,11 @@ public class BookSeriesMapping { @ManyToOne(optional = false) private Book book; - @Column(nullable = false, name="serial_number") + @Column(nullable = false, name = "serial_number") private Integer serialNumber; - public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull Integer serialNumber) { + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, + @NonNull Integer serialNumber) { this.bookSeries = bookSeries; this.book = bookInSeries; this.serialNumber = serialNumber; diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index 01857d8d..a636f315 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -35,11 +35,9 @@ public interface BookRepository extends CrudRepository { Book findByTitleIgnoreCase(String title); - // Lists all BookSeries for a Book entry @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") List getAllBookSeriesForBook(Book book); - // Returns position of a book in a Book Series @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java index 1d5bcebd..35766441 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -24,8 +24,6 @@ import java.util.List; public interface BookSeriesMappingRepository extends CrudRepository { - - // Lists all Books in a Book Series @Query("SELECT a.book FROM BookSeriesMapping a WHERE a.bookSeries = ?1") List getAllBooksByBookSeries(BookSeries bookSeries); } From 2208799d8e1fa1a152e53ee478821d4b226adb3f Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:17:57 +0000 Subject: [PATCH 15/87] Extract create book code to method --- .../java/com/karankumar/booksapi/model/BookSeriesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java index 67acdedb..f3f21af9 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java @@ -22,12 +22,12 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @DisplayName("Book series should") -public class BookSeriesTest { +class BookSeriesTest { @Test @DisplayName("throw a null pointer exception on an attempt to create with a null Series Name.") void notAcceptNullSeriesName(){ assertThatExceptionOfType(NullPointerException.class) - .isThrownBy( ()->new BookSeries(null) ); + .isThrownBy(() -> new BookSeries(null)); } } From ca4627242e4a5bfd89cdec146647c6faf243a50b Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:18:55 +0000 Subject: [PATCH 16/87] Extract create book code to method --- .../booksapi/model/BookSeriesMappingTest.java | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java index 1c569db9..c00a50ec 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -21,20 +21,22 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @DisplayName("Book Series Mapping should") -public class BookSeriesMappingTest { +class BookSeriesMappingTest { @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Serial Number") - void notAcceptNullSerialNumber(){ - + void notAcceptNullSerialNumber() { BookSeries bookSeries = new BookSeries("Harry Potter Series"); + Book book = createBook(); - Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> new BookSeriesMapping(bookSeries, book, null)); + } + private Book createBook() { Book book = new Book( "Harry Potter and the Philosopher's stone", - new Author[] {author}, + new Author[] {new Author("J.K. Rowling")}, Language.ENGLISH, "Sample blurb value", BookGenre.FANTASY, @@ -43,14 +45,12 @@ void notAcceptNullSerialNumber(){ book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); book.setPublisher(PublisherName.BLOOMSBURY); - - assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); + return book; } @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book") - void notAcceptNullBook(){ + void notAcceptNullBook() { BookSeries bookSeries = new BookSeries("Harry Potter Series"); @@ -58,29 +58,15 @@ void notAcceptNullBook(){ author.setAbout("A fantastic author"); assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(bookSeries, null, 1)); + .isThrownBy(() -> new BookSeriesMapping(bookSeries, null, 1)); } @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") - void notAcceptNullBookSeries(){ - - Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); - - Book book = new Book( - "Harry Potter and the Philosopher's stone", - new Author[] {author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book.setYearOfPublication(1997); - book.setIsbn13("9781408810545"); - book.setPublisher(PublisherName.BLOOMSBURY); + void notAcceptNullBookSeries() { + Book book = createBook(); assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(null, book, 1)); + .isThrownBy(() -> new BookSeriesMapping(null, book, 1)); } } From 8dc9835ad746aed92a400b5565080e934173d28c Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:21:24 +0000 Subject: [PATCH 17/87] Add missing copyright notice --- .../BookSeriesMappingRepositoryTest.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index 1c66de4c..7a85342d 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + package com.karankumar.booksapi.repository; import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; @@ -21,7 +36,7 @@ @DataJpaIntegrationTest @DisplayName("BookSeriesMappingRepository should") -public class BookSeriesMappingRepositoryTest { +class BookSeriesMappingRepositoryTest { private final BookRepository bookRepository; private final AuthorRepository authorRepository; @@ -29,8 +44,10 @@ public class BookSeriesMappingRepositoryTest { private final BookSeriesMappingRepository bookSeriesMappingRepository; @Autowired - BookSeriesMappingRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, - BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository){ + BookSeriesMappingRepositoryTest(BookRepository bookRepository, + AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, + BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; @@ -48,8 +65,7 @@ void setUp() { @Test @DisplayName("return all books in a series.") - void fetchAllBooksInBookSeries(){ - + void fetchAllBooksInBookSeries() { BookSeries bs = createBookSeriesMapping(); List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); @@ -60,7 +76,7 @@ void fetchAllBooksInBookSeries(){ assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); } - private BookSeries createBookSeriesMapping(){ + private BookSeries createBookSeriesMapping() { Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); From 9b37d9d9b15d23974fa146992e737e8f56c59ab3 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:26:44 +0000 Subject: [PATCH 18/87] Extract create book code to method --- .../BookSeriesMappingRepositoryTest.java | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index 7a85342d..c68f0538 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -77,33 +77,14 @@ void fetchAllBooksInBookSeries() { } private BookSeries createBookSeriesMapping() { - Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = new Book( - "Harry Potter and the Philosopher's stone", new Author[]{author}, - Language.ENGLISH, "Sample blurb value", - BookGenre.FANTASY, BookFormat.PAPERBACK - ); - book1.setYearOfPublication(1997); - book1.setIsbn13("9781408810545"); - book1.setPublisher(PublisherName.BLOOMSBURY); + Book book1 = createBook(author, "Harry Potter and the Philosopher's stone"); bookRepository.save(book1); - Book book2 = new Book( - "Harry Potter and the Chamber of Secrets", - new Author[]{author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book2.setIsbn13("1234567898765"); - book2.setGenre(BookGenre.FANTASY); - book2.setPublisher(PublisherName.BLOOMSBURY); - book2.setFormat(BookFormat.PAPERBACK); + Book book2 = createBook(author, "Harry Potter and the Chamber of Secrets"); bookRepository.save(book2); BookSeries bookSeries = new BookSeries("Harry Potter Series"); @@ -114,4 +95,12 @@ private BookSeries createBookSeriesMapping() { return bookSeries; } + + private Book createBook(Author author, String title) { + return new Book( + title, new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + } } From d0cde5c7ce5b0e700e1d0961aa6e3400eb51bab9 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:33:52 +0000 Subject: [PATCH 19/87] Find by title --- .../repository/BookSeriesMappingRepositoryTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index c68f0538..ef1d6234 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -37,11 +37,12 @@ @DataJpaIntegrationTest @DisplayName("BookSeriesMappingRepository should") class BookSeriesMappingRepositoryTest { - private final BookRepository bookRepository; private final AuthorRepository authorRepository; private final BookSeriesRepository bookSeriesRepository; private final BookSeriesMappingRepository bookSeriesMappingRepository; + private final String book1Title = "Harry Potter and the Philosopher's stone"; + private final String book2Title = "Harry Potter and the Chamber of Secrets"; @Autowired BookSeriesMappingRepositoryTest(BookRepository bookRepository, @@ -70,21 +71,20 @@ void fetchAllBooksInBookSeries() { List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); List bookList = new ArrayList<>(); - bookList.add(bookRepository.findBookByIsbn13("9781408810545")); - bookList.add(bookRepository.findBookByIsbn13("1234567898765")); + bookList.add(bookRepository.findByTitleIgnoreCase(book1Title)); + bookList.add(bookRepository.findByTitleIgnoreCase(book2Title)); assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); } private BookSeries createBookSeriesMapping() { Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = createBook(author, "Harry Potter and the Philosopher's stone"); + Book book1 = createBook(author, book1Title); bookRepository.save(book1); - Book book2 = createBook(author, "Harry Potter and the Chamber of Secrets"); + Book book2 = createBook(author, book2Title); bookRepository.save(book2); BookSeries bookSeries = new BookSeries("Harry Potter Series"); From 254c14bc0670166576a0c2f3a49a1d37998cf7f9 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:50:24 +0000 Subject: [PATCH 20/87] Extract duplicate code to method --- .../repository/BookRepositoryTest.java | 62 +++++++------------ 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index 6558636a..63b31be5 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -23,13 +23,11 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -48,13 +46,16 @@ class BookRepositoryTest { private final AuthorRepository authorRepository; private final BookSeriesRepository bookSeriesRepository; private final BookSeriesMappingRepository bookSeriesMappingRepository; - + private final String harryPotter1Title = "Harry Potter and the Philosopher's stone"; + private final String harryPotterSeriesName = "Harry Potter Series"; + private Author author1; private Author author2; @Autowired BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, - BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { + BookSeriesRepository bookSeriesRepository, + BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; this.bookSeriesRepository = bookSeriesRepository; @@ -189,7 +190,7 @@ private void saveAllAuthors(Author... authors) { @DisplayName("find all Book Series for a Book") void findBookSeriesForBook(){ List assertion = addBookToSeries(); - Book book = bookRepository.findBookByIsbn13("9781408810545"); + Book book = bookRepository.findByTitleIgnoreCase(harryPotter1Title); List result = bookRepository.getAllBookSeriesForBook(book); @@ -198,14 +199,13 @@ void findBookSeriesForBook(){ @Test @DisplayName("find book position in Book Series") - void findBookPositionInSeries(){ - + void findBookPositionInSeries() { // Get book and book series from repo List allSeries = addBookToSeries(); - Book book = bookRepository.findBookByIsbn13("9781408810545"); + Book book = bookRepository.findByTitleIgnoreCase(harryPotter1Title); BookSeries assertion = null; for (BookSeries series : allSeries) { - if(series.getSeriesName().equals("Harry Potter Series")){ + if (series.getSeriesName().equals(harryPotterSeriesName)) { assertion = series; break; } @@ -214,38 +214,17 @@ void findBookPositionInSeries(){ assertThat(bookRepository.getBookPositionInBookSeries(book, assertion)).isEqualTo(1); } - // Utility method - private List addBookToSeries(){ - + private List addBookToSeries() { Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = new Book( - "Harry Potter and the Philosopher's stone", new Author[]{author}, - Language.ENGLISH, "Sample blurb value", - BookGenre.FANTASY, BookFormat.PAPERBACK - ); - book1.setYearOfPublication(1997); - book1.setIsbn13("9781408810545"); - book1.setPublisher(PublisherName.BLOOMSBURY); + Book book1 = createSeriesBook(author, harryPotter1Title); bookRepository.save(book1); - Book book2 = new Book( - "Harry Potter and the Chamber of Secrets", - new Author[]{author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book2.setIsbn13("1234567898765"); - book2.setGenre(BookGenre.FANTASY); - book2.setPublisher(PublisherName.BLOOMSBURY); - book2.setFormat(BookFormat.PAPERBACK); + Book book2 = createSeriesBook(author, "Harry Potter and the Chamber of Secrets"); bookRepository.save(book2); - BookSeries bookSeries1 = new BookSeries("Harry Potter Series"); + BookSeries bookSeries1 = new BookSeries(harryPotterSeriesName); bookSeriesRepository.save(bookSeries1); BookSeries bookSeries2 = new BookSeries("J.K. Rowling Specials"); @@ -257,10 +236,17 @@ private List addBookToSeries(){ bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book1, 1)); bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book2, 2)); - List bs = new ArrayList<>(); - bs.add(bookSeries1); - bs.add(bookSeries2); + return List.of(bookSeries1, bookSeries2); + } - return bs; + private Book createSeriesBook(Author author, String title) { + return new Book( + title, + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); } } From 168886640f1420b7ffa7f13fb7e520d4c2a8926e Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sat, 27 Mar 2021 23:33:44 +0530 Subject: [PATCH 21/87] Resolve for PR-81 comments --- .../booksapi/model/BookSeriesMapping.java | 6 ++--- .../booksapi/repository/BookRepository.java | 2 +- .../repository/BookSeriesRepositoryTest.java | 26 ------------------- 3 files changed, 4 insertions(+), 30 deletions(-) delete mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index 66e24c29..0f519f85 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -49,12 +49,12 @@ public class BookSeriesMapping { private Book book; @Column(nullable = false, name = "serial_number") - private Integer serialNumber; + private Integer seriesPosition; public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, - @NonNull Integer serialNumber) { + @NonNull Integer seriesPosition) { this.bookSeries = bookSeries; this.book = bookInSeries; - this.serialNumber = serialNumber; + this.seriesPosition = seriesPosition; } } diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index a636f315..1530c5be 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -38,7 +38,7 @@ public interface BookRepository extends CrudRepository { @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") List getAllBookSeriesForBook(Book book); - @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") + @Query("SELECT a.seriesPosition FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); } diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java deleted file mode 100644 index cd0403fe..00000000 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 Karan Kumar - * - * This program is free software: you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along with this program. - * If not, see . - */ - -package com.karankumar.booksapi.repository; - -import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -@DataJpaIntegrationTest -@DisplayName("BookSeries Repository should") -public class BookSeriesRepositoryTest { - -} From 5ba90da77fc04bfb24f0207c9fea5081ca5c7fbd Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 29 Mar 2021 12:07:15 +0530 Subject: [PATCH 22/87] Add DDL for Flyway migration. --- .../V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql | 15 +++++++++++++++ .../db/migration/V009_CREATE_BOOKSERIES.sql | 8 ++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql create mode 100644 src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql diff --git a/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql b/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql new file mode 100644 index 00000000..fb8a36d2 --- /dev/null +++ b/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql @@ -0,0 +1,15 @@ +CREATE TABLE `book_to_book_series_mapping` +( + `id` bigint NOT NULL AUTO_INCREMENT, + `serial_number` int NOT NULL, + `book_id` bigint NOT NULL, + `book_series_id` bigint NOT NULL, + + PRIMARY KEY (`id`), + + UNIQUE KEY `UK_bookSeriesId_bookId` (`book_series_id`,`book_id`), + UNIQUE KEY `UK_bookSeriesId_serialNumber` (`book_series_id`,`serial_number`), + CONSTRAINT `FK_book_id` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`), + CONSTRAINT `FK_book_series_id` FOREIGN KEY (`book_series_id`) REFERENCES `book_series` (`id`) + +) ENGINE=InnoDB \ No newline at end of file diff --git a/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql b/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql new file mode 100644 index 00000000..2c887b28 --- /dev/null +++ b/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql @@ -0,0 +1,8 @@ +CREATE TABLE `book_series` +( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `series_name` varchar(255) NOT NULL, + + PRIMARY KEY (`id`) + +) ENGINE=InnoDB \ No newline at end of file From 11057c4baec8e44ac615fd47535327f217f4e2fa Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:37:23 +0530 Subject: [PATCH 23/87] Add new entity representing series of books. --- .../karankumar/booksapi/model/BookSeries.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/model/BookSeries.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java new file mode 100644 index 00000000..a291443c --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -0,0 +1,30 @@ +package com.karankumar.booksapi.model; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.*; +import java.util.List; + +@Entity +@Getter +@Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class BookSeries { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Setter(AccessLevel.NONE) + private Long id; + + @Column(nullable = false) + private String seriesName; + + @OneToMany(mappedBy = "bookSeries") + private List bookSeriesMapping; + + public BookSeries(String seriesName){ + this.seriesName = seriesName; + } +} From a2930784c44675dde7251bdf4a459e3eaf5f7eff Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:38:32 +0530 Subject: [PATCH 24/87] Add new entity mapping series of books and books with a serial order number. --- .../booksapi/model/BookSeriesMapping.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java new file mode 100644 index 00000000..3a7cae70 --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -0,0 +1,38 @@ +package com.karankumar.booksapi.model; + +import lombok.*; + +import javax.persistence.*; + +@Getter @Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity + +@Table( + name="Book_To_BookSeries_Mapping", + uniqueConstraints = + @UniqueConstraint( columnNames = {"book_id","book_series_id","serialNumber"} ) +) + +public class BookSeriesMapping { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Setter(AccessLevel.NONE) + private long id; + + @ManyToOne + private BookSeries bookSeries; + + @ManyToOne + private Book book; + + @Column(nullable = false, name = "serialNumber") + private int serialNumber; + + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull int serialNumber) { + this.bookSeries = bookSeries; + this.book = bookInSeries; + this.serialNumber = serialNumber; + } +} From 11ff6e4a27c92c254f777d1d51c0aaab0c96e56e Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:39:36 +0530 Subject: [PATCH 25/87] Rebase onto main --- src/main/java/com/karankumar/booksapi/model/Book.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/karankumar/booksapi/model/Book.java b/src/main/java/com/karankumar/booksapi/model/Book.java index 82312b8c..e0a8c410 100644 --- a/src/main/java/com/karankumar/booksapi/model/Book.java +++ b/src/main/java/com/karankumar/booksapi/model/Book.java @@ -30,7 +30,10 @@ import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; +import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; @Entity @@ -75,6 +78,9 @@ public class Book { @Column(nullable = false) private BookFormat format; + @OneToMany(mappedBy = "book") + private List bookSeriesMapping; + public Book(@NonNull String title, @NonNull Language language, @NonNull String blurb, @NonNull BookGenre genre, @NonNull BookFormat format) { this.title = title; From c3826fb8b9b040703ed76529fd652e7ba5955253 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 14 Mar 2021 12:38:46 +0530 Subject: [PATCH 26/87] Add copyright text --- .../com/karankumar/booksapi/model/BookSeries.java | 14 ++++++++++++++ .../booksapi/model/BookSeriesMapping.java | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index a291443c..9a133c8d 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -1,3 +1,17 @@ +/* +The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. +Copyright (C) 2020 Karan Kumar + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. +If not, see . +*/ + package com.karankumar.booksapi.model; import lombok.AccessLevel; diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index 3a7cae70..afb9fb1f 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -1,3 +1,17 @@ +/* +The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. +Copyright (C) 2020 Karan Kumar + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. +If not, see . +*/ + package com.karankumar.booksapi.model; import lombok.*; From ebebbd5c140bd1d11b1e2e9589349a108dde67a8 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:28:09 +0530 Subject: [PATCH 27/87] Update BookSeries entity's member "seriesName" --- src/main/java/com/karankumar/booksapi/model/BookSeries.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index 9a133c8d..cefabc80 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -18,6 +18,7 @@ License, or (at your option) any later version. import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.NonNull; import javax.persistence.*; import java.util.List; @@ -32,13 +33,13 @@ public class BookSeries { @Setter(AccessLevel.NONE) private Long id; - @Column(nullable = false) + @Column(nullable = false, name = "series_name") private String seriesName; @OneToMany(mappedBy = "bookSeries") private List bookSeriesMapping; - public BookSeries(String seriesName){ + public BookSeries(@NonNull String seriesName){ this.seriesName = seriesName; } } From 789e0bd369a01c418b0f9933049ba1499d07137c Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:33:48 +0530 Subject: [PATCH 28/87] Update BookSeriesMapping entity - Unique constraint, Relationship fields are Not Null, minor corrections --- .../booksapi/model/BookSeriesMapping.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index afb9fb1f..deda1ede 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -21,11 +21,12 @@ License, or (at your option) any later version. @Getter @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity - @Table( name="Book_To_BookSeries_Mapping", - uniqueConstraints = - @UniqueConstraint( columnNames = {"book_id","book_series_id","serialNumber"} ) + uniqueConstraints = { + @UniqueConstraint( name = "UK_bookSeriesId_bookId", columnNames = {"book_series_id","book_id"} ), + @UniqueConstraint( name = "UK_bookSeriesId_serialNumber", columnNames = {"book_series_id","serial_number"} ) + } ) public class BookSeriesMapping { @@ -33,18 +34,18 @@ public class BookSeriesMapping { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Setter(AccessLevel.NONE) - private long id; + private Long id; - @ManyToOne + @ManyToOne(optional = false) private BookSeries bookSeries; - @ManyToOne + @ManyToOne(optional = false) private Book book; - @Column(nullable = false, name = "serialNumber") - private int serialNumber; + @Column(nullable = false, name="serial_number") + private Integer serialNumber; - public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull int serialNumber) { + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull Integer serialNumber) { this.bookSeries = bookSeries; this.book = bookInSeries; this.serialNumber = serialNumber; From 58ebd539006a3485ab6f1df11a45c0df8fbb2dc0 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:35:45 +0530 Subject: [PATCH 29/87] Add tests for entities Book Series Mapping and Book Series. --- .../booksapi/model/BookSeriesMappingTest.java | 86 +++++++++++++++++++ .../booksapi/model/BookSeriesTest.java | 33 +++++++ 2 files changed, 119 insertions(+) create mode 100644 src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java create mode 100644 src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java new file mode 100644 index 00000000..ce740261 --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +@DisplayName("Book Series Mapping should") +public class BookSeriesMappingTest { + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Serial Number") + void notAcceptNullSerialNumber(){ + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + Book book = new Book( + "Harry Potter and the Philosopher's stone", + new Author[] {author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book.setYearOfPublication(1997); + book.setIsbn13("9781408810545"); + book.setPublishedBy(Publisher.BLOOMSBURY); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); + } + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book") + void notAcceptNullBook(){ + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(bookSeries, null, 1)); + } + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") + void notAcceptNullBookSeries(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + Book book = new Book( + "Harry Potter and the Philosopher's stone", + new Author[] {author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book.setYearOfPublication(1997); + book.setIsbn13("9781408810545"); + book.setPublishedBy(Publisher.BLOOMSBURY); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(null, book, 1)); + } +} diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java new file mode 100644 index 00000000..67acdedb --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +@DisplayName("Book series should") +public class BookSeriesTest { + + @Test + @DisplayName("throw a null pointer exception on an attempt to create with a null Series Name.") + void notAcceptNullSeriesName(){ + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy( ()->new BookSeries(null) ); + } +} From 89248b08907ed9cbce25635bec5141eaf8594edb Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:37:20 +0530 Subject: [PATCH 30/87] Add boilerplate code for entity repositories. --- .../BookSeriesMappingRepository.java | 22 +++++++++++++++++++ .../repository/BookSeriesRepository.java | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java create mode 100644 src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java new file mode 100644 index 00000000..c421f8ea --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.model.BookSeriesMapping; +import org.springframework.data.repository.CrudRepository; + +public interface BookSeriesMappingRepository extends CrudRepository { +} diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java new file mode 100644 index 00000000..7a167b33 --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.model.BookSeries; +import org.springframework.data.repository.CrudRepository; + +public interface BookSeriesRepository extends CrudRepository { +} From fe11c63078caf538088d9a2c12826adf61f2b248 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:39:02 +0530 Subject: [PATCH 31/87] Add repository methods for Book, BookSeriesMapping --- .../booksapi/repository/BookRepository.java | 11 +++++++++++ .../repository/BookSeriesMappingRepository.java | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index 02538887..01857d8d 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -16,6 +16,8 @@ package com.karankumar.booksapi.repository; import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; @@ -32,4 +34,13 @@ public interface BookRepository extends CrudRepository { Book findBookByIsbn13(String isbn13); Book findByTitleIgnoreCase(String title); + + // Lists all BookSeries for a Book entry + @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") + List getAllBookSeriesForBook(Book book); + + // Returns position of a book in a Book Series + @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") + Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); + } diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java index c421f8ea..1d5bcebd 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -15,8 +15,17 @@ package com.karankumar.booksapi.repository; +import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; +import java.util.List; + public interface BookSeriesMappingRepository extends CrudRepository { + + // Lists all Books in a Book Series + @Query("SELECT a.book FROM BookSeriesMapping a WHERE a.bookSeries = ?1") + List getAllBooksByBookSeries(BookSeries bookSeries); } From 5b7dc1c391aa3261a03c4d58f7ace9adfcc41e3b Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:41:14 +0530 Subject: [PATCH 32/87] Add test classes for BookSeries & BookSeriesMapping repository --- .../BookSeriesMappingRepositoryTest.java | 101 ++++++++++++++++++ .../repository/BookSeriesRepositoryTest.java | 26 +++++ 2 files changed, 127 insertions(+) create mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java create mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java new file mode 100644 index 00000000..a685399b --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -0,0 +1,101 @@ +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; +import com.karankumar.booksapi.model.Author; +import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookFormat; +import com.karankumar.booksapi.model.BookGenre; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; +import com.karankumar.booksapi.model.Language; +import com.karankumar.booksapi.model.Publisher; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaIntegrationTest +@DisplayName("BookSeriesMappingRepository should") +public class BookSeriesMappingRepositoryTest { + + private final BookRepository bookRepository; + private final AuthorRepository authorRepository; + private final BookSeriesRepository bookSeriesRepository; + private final BookSeriesMappingRepository bookSeriesMappingRepository; + + @Autowired + BookSeriesMappingRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository){ + + this.bookRepository = bookRepository; + this.authorRepository = authorRepository; + this.bookSeriesRepository = bookSeriesRepository; + this.bookSeriesMappingRepository = bookSeriesMappingRepository; + } + + @BeforeEach + void setUp() { + bookSeriesMappingRepository.deleteAll(); + authorRepository.deleteAll(); + bookRepository.deleteAll(); + bookSeriesRepository.deleteAll(); + } + + @Test + @DisplayName("return all books in a series.") + void fetchAllBooksInBookSeries(){ + + BookSeries bs = createBookSeriesMapping(); + List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); + + List bookList = new ArrayList<>(); + bookList.add(bookRepository.findBookByIsbn13("9781408810545")); + bookList.add(bookRepository.findBookByIsbn13("1234567898765")); + + assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); + } + + private BookSeries createBookSeriesMapping(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + authorRepository.save(author); + + Book book1 = new Book( + "Harry Potter and the Philosopher's stone", new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + book1.setYearOfPublication(1997); + book1.setIsbn13("9781408810545"); + book1.setPublishedBy(Publisher.BLOOMSBURY); + bookRepository.save(book1); + + Book book2 = new Book( + "Harry Potter and the Chamber of Secrets", + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book2.setIsbn13("1234567898765"); + book2.setGenre(BookGenre.FANTASY); + book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setFormat(BookFormat.PAPERBACK); + bookRepository.save(book2); + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + bookSeriesRepository.save(bookSeries); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries, book2, 2)); + + return bookSeries; + } +} diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java new file mode 100644 index 00000000..cd0403fe --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DataJpaIntegrationTest +@DisplayName("BookSeries Repository should") +public class BookSeriesRepositoryTest { + +} From 346f34416764d0cf98716a928aeb9bd0a3d1d3dd Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:47:12 +0530 Subject: [PATCH 33/87] Rebase onto main --- .../repository/BookRepositoryTest.java | 103 +++++++++++++++++- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index 79ee3fae..83fe76cd 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Karan Kumar + * Copyright (C) 2020 Karan Kumar * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of the @@ -20,13 +20,17 @@ import com.karankumar.booksapi.model.Book; import com.karankumar.booksapi.model.BookFormat; import com.karankumar.booksapi.model.BookGenre; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; +import com.karankumar.booksapi.model.Publisher; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static com.karankumar.booksapi.repository.RepositoryTestUtils.createBook; @@ -38,19 +42,27 @@ class BookRepositoryTest { private static final String ISBN = "978-3-16-148410-0"; private static final String TITLE = "Harry Potter"; + private static final String AUTHOR1_FULL_NAME = "Kevlin Henney"; private final BookRepository bookRepository; private final AuthorRepository authorRepository; - + private final BookSeriesRepository bookSeriesRepository; + private final BookSeriesMappingRepository bookSeriesMappingRepository; + @Autowired - BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository) { + BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; + this.bookSeriesRepository = bookSeriesRepository; + this.bookSeriesMappingRepository = bookSeriesMappingRepository; } @BeforeEach void setUp() { + bookSeriesMappingRepository.deleteAll(); authorRepository.deleteAll(); bookRepository.deleteAll(); + bookSeriesRepository.deleteAll(); } @Test @@ -155,4 +167,87 @@ void findBookByTitleCaseInsensitive() { // then assertThat(result).isEqualTo(book); } + + private void saveAllAuthors(Author... authors) { + Arrays.stream(authors).forEach(authorRepository::save); + } + + @Test + @DisplayName("find all Book Series for a Book") + void findBookSeriesForBook(){ + List assertion = addBookToSeries(); + Book book = bookRepository.findBookByIsbn13("9781408810545"); + + List result = bookRepository.getAllBookSeriesForBook(book); + + assertThat(result).containsExactlyInAnyOrderElementsOf(assertion); + } + + @Test + @DisplayName("find book position in Book Series") + void findBookPositionInSeries(){ + + // Get book and book series from repo + List allSeries = addBookToSeries(); + Book book = bookRepository.findBookByIsbn13("9781408810545"); + BookSeries assertion = null; + for (BookSeries series : allSeries) { + if(series.getSeriesName().equals("Harry Potter Series")){ + assertion = series; + break; + } + } + + assertThat(bookRepository.getBookPositionInBookSeries(book, assertion)).isEqualTo(1); + } + + // Utility method + private List addBookToSeries(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + authorRepository.save(author); + + Book book1 = new Book( + "Harry Potter and the Philosopher's stone", new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + book1.setYearOfPublication(1997); + book1.setIsbn13("9781408810545"); + book1.setPublishedBy(Publisher.BLOOMSBURY); + bookRepository.save(book1); + + Book book2 = new Book( + "Harry Potter and the Chamber of Secrets", + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book2.setIsbn13("1234567898765"); + book2.setGenre(BookGenre.FANTASY); + book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setFormat(BookFormat.PAPERBACK); + bookRepository.save(book2); + + BookSeries bookSeries1 = new BookSeries("Harry Potter Series"); + bookSeriesRepository.save(bookSeries1); + + BookSeries bookSeries2 = new BookSeries("J.K. Rowling Specials"); + bookSeriesRepository.save(bookSeries2); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries1, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries1, book2, 2)); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book2, 2)); + + List bs = new ArrayList<>(); + bs.add(bookSeries1); + bs.add(bookSeries2); + + return bs; + } } From 84a2e532e67b5c0e2af2d7f1a2b64ced494c2f91 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:49:40 +0530 Subject: [PATCH 34/87] Update setup method to clear tables with Foreign Key dependencies first --- .../karankumar/booksapi/repository/AuthorRepositoryTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java index 272116a7..f6341816 100644 --- a/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java @@ -34,15 +34,18 @@ class AuthorRepositoryTest { private final BookRepository bookRepository; private final AuthorRepository authorRepository; + private final BookSeriesMappingRepository bookSeriesMappingRepository; @Autowired - AuthorRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository) { + AuthorRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; + this.bookSeriesMappingRepository = bookSeriesMappingRepository; } @BeforeEach void setUp() { + bookSeriesMappingRepository.deleteAll(); authorRepository.deleteAll(); bookRepository.deleteAll(); } From 42a6622fde56d9fac388c4be8ec56c4a3ec0043d Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 18:01:24 +0530 Subject: [PATCH 35/87] Fix test issues due to merge --- .../booksapi/model/BookSeriesMappingTest.java | 10 +++++----- .../booksapi/repository/BookRepositoryTest.java | 8 ++++---- .../repository/BookSeriesMappingRepositoryTest.java | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java index ce740261..1c569db9 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -29,7 +29,7 @@ void notAcceptNullSerialNumber(){ BookSeries bookSeries = new BookSeries("Harry Potter Series"); - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); Book book = new Book( @@ -42,7 +42,7 @@ void notAcceptNullSerialNumber(){ ); book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); - book.setPublishedBy(Publisher.BLOOMSBURY); + book.setPublisher(PublisherName.BLOOMSBURY); assertThatExceptionOfType(NullPointerException.class) .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); @@ -54,7 +54,7 @@ void notAcceptNullBook(){ BookSeries bookSeries = new BookSeries("Harry Potter Series"); - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); assertThatExceptionOfType(NullPointerException.class) @@ -65,7 +65,7 @@ void notAcceptNullBook(){ @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") void notAcceptNullBookSeries(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); Book book = new Book( @@ -78,7 +78,7 @@ void notAcceptNullBookSeries(){ ); book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); - book.setPublishedBy(Publisher.BLOOMSBURY); + book.setPublisher(PublisherName.BLOOMSBURY); assertThatExceptionOfType(NullPointerException.class) .isThrownBy(()->new BookSeriesMapping(null, book, 1)); diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index 83fe76cd..d9fceb40 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -23,7 +23,7 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.Publisher; +import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -204,7 +204,7 @@ void findBookPositionInSeries(){ // Utility method private List addBookToSeries(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); @@ -215,7 +215,7 @@ private List addBookToSeries(){ ); book1.setYearOfPublication(1997); book1.setIsbn13("9781408810545"); - book1.setPublishedBy(Publisher.BLOOMSBURY); + book1.setPublisher(PublisherName.BLOOMSBURY); bookRepository.save(book1); Book book2 = new Book( @@ -228,7 +228,7 @@ private List addBookToSeries(){ ); book2.setIsbn13("1234567898765"); book2.setGenre(BookGenre.FANTASY); - book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setPublisher(PublisherName.BLOOMSBURY); book2.setFormat(BookFormat.PAPERBACK); bookRepository.save(book2); diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index a685399b..1c66de4c 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -8,7 +8,7 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.Publisher; +import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -62,7 +62,7 @@ void fetchAllBooksInBookSeries(){ private BookSeries createBookSeriesMapping(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); @@ -73,7 +73,7 @@ private BookSeries createBookSeriesMapping(){ ); book1.setYearOfPublication(1997); book1.setIsbn13("9781408810545"); - book1.setPublishedBy(Publisher.BLOOMSBURY); + book1.setPublisher(PublisherName.BLOOMSBURY); bookRepository.save(book1); Book book2 = new Book( @@ -86,7 +86,7 @@ private BookSeries createBookSeriesMapping(){ ); book2.setIsbn13("1234567898765"); book2.setGenre(BookGenre.FANTASY); - book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setPublisher(PublisherName.BLOOMSBURY); book2.setFormat(BookFormat.PAPERBACK); bookRepository.save(book2); From a78fc25ca27948cc8f52919dd903925abbb666a6 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:11:31 +0000 Subject: [PATCH 36/87] Remove wildcard imports & adhere to 100 char limit --- .../karankumar/booksapi/model/BookSeries.java | 28 +++++++++++-------- .../booksapi/model/BookSeriesMapping.java | 19 +++++++++---- .../booksapi/repository/BookRepository.java | 2 -- .../BookSeriesMappingRepository.java | 2 -- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index cefabc80..bd0cea9b 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -1,16 +1,17 @@ /* -The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. -Copyright (C) 2020 Karan Kumar + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program. -If not, see . -*/ + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ package com.karankumar.booksapi.model; @@ -20,7 +21,12 @@ License, or (at your option) any later version. import lombok.Setter; import lombok.NonNull; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; import java.util.List; @Entity diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index deda1ede..66e24c29 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -18,17 +18,23 @@ License, or (at your option) any later version. import javax.persistence.*; -@Getter @Setter +@Getter +@Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @Table( name="Book_To_BookSeries_Mapping", uniqueConstraints = { - @UniqueConstraint( name = "UK_bookSeriesId_bookId", columnNames = {"book_series_id","book_id"} ), - @UniqueConstraint( name = "UK_bookSeriesId_serialNumber", columnNames = {"book_series_id","serial_number"} ) + @UniqueConstraint( + name = "UK_bookSeriesId_bookId", + columnNames = {"book_series_id","book_id"} + ), + @UniqueConstraint( + name = "UK_bookSeriesId_serialNumber", + columnNames = {"book_series_id","serial_number"} + ) } ) - public class BookSeriesMapping { @Id @@ -42,10 +48,11 @@ public class BookSeriesMapping { @ManyToOne(optional = false) private Book book; - @Column(nullable = false, name="serial_number") + @Column(nullable = false, name = "serial_number") private Integer serialNumber; - public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull Integer serialNumber) { + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, + @NonNull Integer serialNumber) { this.bookSeries = bookSeries; this.book = bookInSeries; this.serialNumber = serialNumber; diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index 01857d8d..a636f315 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -35,11 +35,9 @@ public interface BookRepository extends CrudRepository { Book findByTitleIgnoreCase(String title); - // Lists all BookSeries for a Book entry @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") List getAllBookSeriesForBook(Book book); - // Returns position of a book in a Book Series @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java index 1d5bcebd..35766441 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -24,8 +24,6 @@ import java.util.List; public interface BookSeriesMappingRepository extends CrudRepository { - - // Lists all Books in a Book Series @Query("SELECT a.book FROM BookSeriesMapping a WHERE a.bookSeries = ?1") List getAllBooksByBookSeries(BookSeries bookSeries); } From b62559f0411a20917c5f68dc61c8ffcf4d9747b8 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:17:57 +0000 Subject: [PATCH 37/87] Extract create book code to method --- .../java/com/karankumar/booksapi/model/BookSeriesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java index 67acdedb..f3f21af9 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java @@ -22,12 +22,12 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @DisplayName("Book series should") -public class BookSeriesTest { +class BookSeriesTest { @Test @DisplayName("throw a null pointer exception on an attempt to create with a null Series Name.") void notAcceptNullSeriesName(){ assertThatExceptionOfType(NullPointerException.class) - .isThrownBy( ()->new BookSeries(null) ); + .isThrownBy(() -> new BookSeries(null)); } } From 7863aad76f0eb5ba745c8a7b9f781c9fb267ad13 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:18:55 +0000 Subject: [PATCH 38/87] Extract create book code to method --- .../booksapi/model/BookSeriesMappingTest.java | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java index 1c569db9..c00a50ec 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -21,20 +21,22 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @DisplayName("Book Series Mapping should") -public class BookSeriesMappingTest { +class BookSeriesMappingTest { @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Serial Number") - void notAcceptNullSerialNumber(){ - + void notAcceptNullSerialNumber() { BookSeries bookSeries = new BookSeries("Harry Potter Series"); + Book book = createBook(); - Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> new BookSeriesMapping(bookSeries, book, null)); + } + private Book createBook() { Book book = new Book( "Harry Potter and the Philosopher's stone", - new Author[] {author}, + new Author[] {new Author("J.K. Rowling")}, Language.ENGLISH, "Sample blurb value", BookGenre.FANTASY, @@ -43,14 +45,12 @@ void notAcceptNullSerialNumber(){ book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); book.setPublisher(PublisherName.BLOOMSBURY); - - assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); + return book; } @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book") - void notAcceptNullBook(){ + void notAcceptNullBook() { BookSeries bookSeries = new BookSeries("Harry Potter Series"); @@ -58,29 +58,15 @@ void notAcceptNullBook(){ author.setAbout("A fantastic author"); assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(bookSeries, null, 1)); + .isThrownBy(() -> new BookSeriesMapping(bookSeries, null, 1)); } @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") - void notAcceptNullBookSeries(){ - - Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); - - Book book = new Book( - "Harry Potter and the Philosopher's stone", - new Author[] {author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book.setYearOfPublication(1997); - book.setIsbn13("9781408810545"); - book.setPublisher(PublisherName.BLOOMSBURY); + void notAcceptNullBookSeries() { + Book book = createBook(); assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(null, book, 1)); + .isThrownBy(() -> new BookSeriesMapping(null, book, 1)); } } From 4327b42e539e5df8ea7e85a6842dc2005cf0f71d Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:21:24 +0000 Subject: [PATCH 39/87] Add missing copyright notice --- .../BookSeriesMappingRepositoryTest.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index 1c66de4c..7a85342d 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + package com.karankumar.booksapi.repository; import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; @@ -21,7 +36,7 @@ @DataJpaIntegrationTest @DisplayName("BookSeriesMappingRepository should") -public class BookSeriesMappingRepositoryTest { +class BookSeriesMappingRepositoryTest { private final BookRepository bookRepository; private final AuthorRepository authorRepository; @@ -29,8 +44,10 @@ public class BookSeriesMappingRepositoryTest { private final BookSeriesMappingRepository bookSeriesMappingRepository; @Autowired - BookSeriesMappingRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, - BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository){ + BookSeriesMappingRepositoryTest(BookRepository bookRepository, + AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, + BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; @@ -48,8 +65,7 @@ void setUp() { @Test @DisplayName("return all books in a series.") - void fetchAllBooksInBookSeries(){ - + void fetchAllBooksInBookSeries() { BookSeries bs = createBookSeriesMapping(); List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); @@ -60,7 +76,7 @@ void fetchAllBooksInBookSeries(){ assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); } - private BookSeries createBookSeriesMapping(){ + private BookSeries createBookSeriesMapping() { Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); From 06ec459fde702cd4f6afdbab13141772d2d0f618 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:26:44 +0000 Subject: [PATCH 40/87] Extract create book code to method --- .../BookSeriesMappingRepositoryTest.java | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index 7a85342d..c68f0538 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -77,33 +77,14 @@ void fetchAllBooksInBookSeries() { } private BookSeries createBookSeriesMapping() { - Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = new Book( - "Harry Potter and the Philosopher's stone", new Author[]{author}, - Language.ENGLISH, "Sample blurb value", - BookGenre.FANTASY, BookFormat.PAPERBACK - ); - book1.setYearOfPublication(1997); - book1.setIsbn13("9781408810545"); - book1.setPublisher(PublisherName.BLOOMSBURY); + Book book1 = createBook(author, "Harry Potter and the Philosopher's stone"); bookRepository.save(book1); - Book book2 = new Book( - "Harry Potter and the Chamber of Secrets", - new Author[]{author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book2.setIsbn13("1234567898765"); - book2.setGenre(BookGenre.FANTASY); - book2.setPublisher(PublisherName.BLOOMSBURY); - book2.setFormat(BookFormat.PAPERBACK); + Book book2 = createBook(author, "Harry Potter and the Chamber of Secrets"); bookRepository.save(book2); BookSeries bookSeries = new BookSeries("Harry Potter Series"); @@ -114,4 +95,12 @@ private BookSeries createBookSeriesMapping() { return bookSeries; } + + private Book createBook(Author author, String title) { + return new Book( + title, new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + } } From 4866d662d4c9459a573e4aa3db9d6707f124da5f Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:33:52 +0000 Subject: [PATCH 41/87] Find by title --- .../repository/BookSeriesMappingRepositoryTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index c68f0538..ef1d6234 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -37,11 +37,12 @@ @DataJpaIntegrationTest @DisplayName("BookSeriesMappingRepository should") class BookSeriesMappingRepositoryTest { - private final BookRepository bookRepository; private final AuthorRepository authorRepository; private final BookSeriesRepository bookSeriesRepository; private final BookSeriesMappingRepository bookSeriesMappingRepository; + private final String book1Title = "Harry Potter and the Philosopher's stone"; + private final String book2Title = "Harry Potter and the Chamber of Secrets"; @Autowired BookSeriesMappingRepositoryTest(BookRepository bookRepository, @@ -70,21 +71,20 @@ void fetchAllBooksInBookSeries() { List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); List bookList = new ArrayList<>(); - bookList.add(bookRepository.findBookByIsbn13("9781408810545")); - bookList.add(bookRepository.findBookByIsbn13("1234567898765")); + bookList.add(bookRepository.findByTitleIgnoreCase(book1Title)); + bookList.add(bookRepository.findByTitleIgnoreCase(book2Title)); assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); } private BookSeries createBookSeriesMapping() { Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = createBook(author, "Harry Potter and the Philosopher's stone"); + Book book1 = createBook(author, book1Title); bookRepository.save(book1); - Book book2 = createBook(author, "Harry Potter and the Chamber of Secrets"); + Book book2 = createBook(author, book2Title); bookRepository.save(book2); BookSeries bookSeries = new BookSeries("Harry Potter Series"); From bfcc19c0b51c71e6ac72e00fe870a3f9641a80df Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:50:24 +0000 Subject: [PATCH 42/87] Extract duplicate code to method --- .../repository/BookRepositoryTest.java | 63 ++++++++----------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index d9fceb40..43b858ef 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -23,13 +23,11 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -48,10 +46,16 @@ class BookRepositoryTest { private final AuthorRepository authorRepository; private final BookSeriesRepository bookSeriesRepository; private final BookSeriesMappingRepository bookSeriesMappingRepository; + private final String harryPotter1Title = "Harry Potter and the Philosopher's stone"; + private final String harryPotterSeriesName = "Harry Potter Series"; + + private Author author1; + private Author author2; @Autowired BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, - BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { + BookSeriesRepository bookSeriesRepository, + BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; this.bookSeriesRepository = bookSeriesRepository; @@ -176,7 +180,7 @@ private void saveAllAuthors(Author... authors) { @DisplayName("find all Book Series for a Book") void findBookSeriesForBook(){ List assertion = addBookToSeries(); - Book book = bookRepository.findBookByIsbn13("9781408810545"); + Book book = bookRepository.findByTitleIgnoreCase(harryPotter1Title); List result = bookRepository.getAllBookSeriesForBook(book); @@ -185,14 +189,13 @@ void findBookSeriesForBook(){ @Test @DisplayName("find book position in Book Series") - void findBookPositionInSeries(){ - + void findBookPositionInSeries() { // Get book and book series from repo List allSeries = addBookToSeries(); - Book book = bookRepository.findBookByIsbn13("9781408810545"); + Book book = bookRepository.findByTitleIgnoreCase(harryPotter1Title); BookSeries assertion = null; for (BookSeries series : allSeries) { - if(series.getSeriesName().equals("Harry Potter Series")){ + if (series.getSeriesName().equals(harryPotterSeriesName)) { assertion = series; break; } @@ -201,38 +204,17 @@ void findBookPositionInSeries(){ assertThat(bookRepository.getBookPositionInBookSeries(book, assertion)).isEqualTo(1); } - // Utility method - private List addBookToSeries(){ - + private List addBookToSeries() { Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = new Book( - "Harry Potter and the Philosopher's stone", new Author[]{author}, - Language.ENGLISH, "Sample blurb value", - BookGenre.FANTASY, BookFormat.PAPERBACK - ); - book1.setYearOfPublication(1997); - book1.setIsbn13("9781408810545"); - book1.setPublisher(PublisherName.BLOOMSBURY); + Book book1 = createSeriesBook(author, harryPotter1Title); bookRepository.save(book1); - Book book2 = new Book( - "Harry Potter and the Chamber of Secrets", - new Author[]{author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book2.setIsbn13("1234567898765"); - book2.setGenre(BookGenre.FANTASY); - book2.setPublisher(PublisherName.BLOOMSBURY); - book2.setFormat(BookFormat.PAPERBACK); + Book book2 = createSeriesBook(author, "Harry Potter and the Chamber of Secrets"); bookRepository.save(book2); - BookSeries bookSeries1 = new BookSeries("Harry Potter Series"); + BookSeries bookSeries1 = new BookSeries(harryPotterSeriesName); bookSeriesRepository.save(bookSeries1); BookSeries bookSeries2 = new BookSeries("J.K. Rowling Specials"); @@ -244,10 +226,17 @@ private List addBookToSeries(){ bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book1, 1)); bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book2, 2)); - List bs = new ArrayList<>(); - bs.add(bookSeries1); - bs.add(bookSeries2); + return List.of(bookSeries1, bookSeries2); + } - return bs; + private Book createSeriesBook(Author author, String title) { + return new Book( + title, + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); } } From f4fedf8eb27ad932c4c15beaff8180eef232b0e2 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sat, 27 Mar 2021 23:33:44 +0530 Subject: [PATCH 43/87] Resolve for PR-81 comments --- .../booksapi/model/BookSeriesMapping.java | 6 ++--- .../booksapi/repository/BookRepository.java | 2 +- .../repository/BookSeriesRepositoryTest.java | 26 ------------------- 3 files changed, 4 insertions(+), 30 deletions(-) delete mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index 66e24c29..0f519f85 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -49,12 +49,12 @@ public class BookSeriesMapping { private Book book; @Column(nullable = false, name = "serial_number") - private Integer serialNumber; + private Integer seriesPosition; public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, - @NonNull Integer serialNumber) { + @NonNull Integer seriesPosition) { this.bookSeries = bookSeries; this.book = bookInSeries; - this.serialNumber = serialNumber; + this.seriesPosition = seriesPosition; } } diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index a636f315..1530c5be 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -38,7 +38,7 @@ public interface BookRepository extends CrudRepository { @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") List getAllBookSeriesForBook(Book book); - @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") + @Query("SELECT a.seriesPosition FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); } diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java deleted file mode 100644 index cd0403fe..00000000 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 Karan Kumar - * - * This program is free software: you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along with this program. - * If not, see . - */ - -package com.karankumar.booksapi.repository; - -import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -@DataJpaIntegrationTest -@DisplayName("BookSeries Repository should") -public class BookSeriesRepositoryTest { - -} From d76c2d51d094d073e50413273e13cb6b87152d64 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 29 Mar 2021 12:07:15 +0530 Subject: [PATCH 44/87] Add DDL for Flyway migration. --- .../V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql | 15 +++++++++++++++ .../db/migration/V009_CREATE_BOOKSERIES.sql | 8 ++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql create mode 100644 src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql diff --git a/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql b/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql new file mode 100644 index 00000000..fb8a36d2 --- /dev/null +++ b/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql @@ -0,0 +1,15 @@ +CREATE TABLE `book_to_book_series_mapping` +( + `id` bigint NOT NULL AUTO_INCREMENT, + `serial_number` int NOT NULL, + `book_id` bigint NOT NULL, + `book_series_id` bigint NOT NULL, + + PRIMARY KEY (`id`), + + UNIQUE KEY `UK_bookSeriesId_bookId` (`book_series_id`,`book_id`), + UNIQUE KEY `UK_bookSeriesId_serialNumber` (`book_series_id`,`serial_number`), + CONSTRAINT `FK_book_id` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`), + CONSTRAINT `FK_book_series_id` FOREIGN KEY (`book_series_id`) REFERENCES `book_series` (`id`) + +) ENGINE=InnoDB \ No newline at end of file diff --git a/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql b/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql new file mode 100644 index 00000000..2c887b28 --- /dev/null +++ b/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql @@ -0,0 +1,8 @@ +CREATE TABLE `book_series` +( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `series_name` varchar(255) NOT NULL, + + PRIMARY KEY (`id`) + +) ENGINE=InnoDB \ No newline at end of file From e36fc6eba0439fea081296cf5cbd1317b026fb83 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Wed, 14 Apr 2021 13:01:10 +0530 Subject: [PATCH 45/87] Update tests to new model --- .../booksapi/model/BookSeriesMappingTest.java | 5 ----- .../repository/BookRepositoryTest.java | 10 ++++------ .../BookSeriesMappingRepositoryTest.java | 18 ++++++++---------- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java index c00a50ec..f63aa466 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -36,7 +36,6 @@ void notAcceptNullSerialNumber() { private Book createBook() { Book book = new Book( "Harry Potter and the Philosopher's stone", - new Author[] {new Author("J.K. Rowling")}, Language.ENGLISH, "Sample blurb value", BookGenre.FANTASY, @@ -44,7 +43,6 @@ private Book createBook() { ); book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); - book.setPublisher(PublisherName.BLOOMSBURY); return book; } @@ -54,9 +52,6 @@ void notAcceptNullBook() { BookSeries bookSeries = new BookSeries("Harry Potter Series"); - Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); - assertThatExceptionOfType(NullPointerException.class) .isThrownBy(() -> new BookSeriesMapping(bookSeries, null, 1)); } diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index 43b858ef..f102bb5b 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -23,6 +23,7 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; +import java.util.HashSet; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -205,13 +206,11 @@ void findBookPositionInSeries() { } private List addBookToSeries() { - Author author = new Author("J.K. Rowling"); - authorRepository.save(author); - Book book1 = createSeriesBook(author, harryPotter1Title); + Book book1 = createSeriesBook(harryPotter1Title); bookRepository.save(book1); - Book book2 = createSeriesBook(author, "Harry Potter and the Chamber of Secrets"); + Book book2 = createSeriesBook("Harry Potter and the Chamber of Secrets"); bookRepository.save(book2); BookSeries bookSeries1 = new BookSeries(harryPotterSeriesName); @@ -229,10 +228,9 @@ private List addBookToSeries() { return List.of(bookSeries1, bookSeries2); } - private Book createSeriesBook(Author author, String title) { + private Book createSeriesBook(String title) { return new Book( title, - new Author[]{author}, Language.ENGLISH, "Sample blurb value", BookGenre.FANTASY, diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index ef1d6234..75fc1675 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -16,14 +16,12 @@ package com.karankumar.booksapi.repository; import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; -import com.karankumar.booksapi.model.Author; import com.karankumar.booksapi.model.Book; import com.karankumar.booksapi.model.BookFormat; import com.karankumar.booksapi.model.BookGenre; import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -78,13 +76,11 @@ void fetchAllBooksInBookSeries() { } private BookSeries createBookSeriesMapping() { - Author author = new Author("J.K. Rowling"); - authorRepository.save(author); - Book book1 = createBook(author, book1Title); + Book book1 = createBook(book1Title); bookRepository.save(book1); - Book book2 = createBook(author, book2Title); + Book book2 = createBook(book2Title); bookRepository.save(book2); BookSeries bookSeries = new BookSeries("Harry Potter Series"); @@ -96,11 +92,13 @@ private BookSeries createBookSeriesMapping() { return bookSeries; } - private Book createBook(Author author, String title) { + private Book createBook(String title) { return new Book( - title, new Author[]{author}, - Language.ENGLISH, "Sample blurb value", - BookGenre.FANTASY, BookFormat.PAPERBACK + title, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK ); } } From 896946b9bdd4b8234a28c2cf47b054f2d73b10c9 Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 21 Apr 2021 07:39:29 +0100 Subject: [PATCH 46/87] Use constants --- build.gradle | 12 ++++++++++-- .../booksapi/datafetchers/BookDataFetcher.java | 9 +++++---- .../booksapi/mutations/AuthorMutation.java | 3 ++- .../karankumar/booksapi/mutations/BookMutation.java | 5 +++-- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index b1407b22..45fb2796 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,20 @@ +buildscript { + dependencies { + classpath 'com.netflix.graphql.dgs.codegen:graphql-dgs-codegen-gradle:4.5.2' + } +} + plugins { id 'org.springframework.boot' version '2.4.3' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id 'jacoco' - id "com.netflix.dgs.codegen" version "4.0.10" +// id "com.netflix.dgs.codegen" version "4.5.2" id "org.flywaydb.flyway" version "7.5.4" } +apply plugin: 'com.netflix.dgs.codegen' + group = 'com.karankumar' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' @@ -24,7 +32,7 @@ repositories { generateJava { schemaPaths = ["${projectDir}/src/main/resources/schema"] // List of directories containing schema files packageName = 'com.karankumar.booksapi' // The package name to use to generate sources - generateClient = true // Enable generating the type safe query API + generateClient = false // Enable generating the type safe query API } dependencies { diff --git a/src/main/java/com/karankumar/booksapi/datafetchers/BookDataFetcher.java b/src/main/java/com/karankumar/booksapi/datafetchers/BookDataFetcher.java index e5df202d..8e43aaa0 100644 --- a/src/main/java/com/karankumar/booksapi/datafetchers/BookDataFetcher.java +++ b/src/main/java/com/karankumar/booksapi/datafetchers/BookDataFetcher.java @@ -15,6 +15,7 @@ package com.karankumar.booksapi.datafetchers; +import com.karankumar.booksapi.DgsConstants; import com.karankumar.booksapi.model.Book; import com.karankumar.booksapi.service.BookService; import com.netflix.graphql.dgs.DgsComponent; @@ -31,22 +32,22 @@ public BookDataFetcher(BookService bookService) { this.bookService = bookService; } - @DgsData(parentType = "Query", field = "findAllBooks") + @DgsData(parentType = DgsConstants.QUERY_TYPE, field = DgsConstants.QUERY.FindAllBooks) public List findAllBooks() { return bookService.findAll(); } - @DgsData(parentType = "Query", field = "findBookByIsbn13") + @DgsData(parentType = DgsConstants.QUERY_TYPE, field = DgsConstants.QUERY.FindBookByIsbn13) public Book findBookByIsbn13(@InputArgument("isbn13") String isbn13) { return bookService.findBookByIsbn13(isbn13); } - @DgsData(parentType = "Query", field = "findByAuthor") + @DgsData(parentType = DgsConstants.QUERY_TYPE, field = DgsConstants.QUERY.FindByAuthor) public List findByAuthor(@InputArgument("fullName") String fullName) { return bookService.findByAuthor(fullName); } - @DgsData(parentType = "Query", field = "findByTitleIgnoreCase") + @DgsData(parentType = DgsConstants.QUERY_TYPE, field = DgsConstants.QUERY.FindByTitleIgnoreCase) public Book findByTitle(@InputArgument("title") String title) { return bookService.findByTitle(title); } diff --git a/src/main/java/com/karankumar/booksapi/mutations/AuthorMutation.java b/src/main/java/com/karankumar/booksapi/mutations/AuthorMutation.java index cc4a5f08..c06ae1a3 100644 --- a/src/main/java/com/karankumar/booksapi/mutations/AuthorMutation.java +++ b/src/main/java/com/karankumar/booksapi/mutations/AuthorMutation.java @@ -15,6 +15,7 @@ package com.karankumar.booksapi.mutations; +import com.karankumar.booksapi.DgsConstants; import com.karankumar.booksapi.model.Author; import com.karankumar.booksapi.service.AuthorService; import com.netflix.graphql.dgs.DgsComponent; @@ -31,7 +32,7 @@ public AuthorMutation(AuthorService authorService) { this.authorService = authorService; } - @DgsData(parentType = "Mutation", field = "addAuthor") + @DgsData(parentType = "Mutation", field = DgsConstants.MUTATION.AddAuthor) public Author addAuthor(DataFetchingEnvironment dataFetchingEnvironment) { String fullName = dataFetchingEnvironment.getArgument("fullName"); return authorService.save(new Author(fullName, new HashSet<>())); diff --git a/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java b/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java index 08e34bd9..60dd4ff9 100644 --- a/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java +++ b/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java @@ -15,6 +15,7 @@ package com.karankumar.booksapi.mutations; +import com.karankumar.booksapi.DgsConstants; import com.karankumar.booksapi.exception.InvalidISBN10Exception; import com.karankumar.booksapi.exception.InvalidISBN13Exception; import com.karankumar.booksapi.model.Book; @@ -37,7 +38,7 @@ public BookMutation(BookService bookService) { } // TODO: change this to update a book rather than updating a specific field - @DgsData(parentType = "Mutation", field = "addIsbn13") + @DgsData(parentType = "Mutation", field = DgsConstants.MUTATION.AddIsbn13) public Book addIsbn13(DataFetchingEnvironment dataFetchingEnvironment) throws InvalidISBN10Exception, InvalidISBN13Exception { Optional optionalBook = bookService.findById( @@ -54,7 +55,7 @@ public Book addIsbn13(DataFetchingEnvironment dataFetchingEnvironment) return bookService.save(optionalBook.get()); } - @DgsData(parentType = "Mutation", field = "deleteBook") + @DgsData(parentType = "Mutation", field = DgsConstants.MUTATION.DeleteBook) public Book deleteBook(DataFetchingEnvironment dataFetchingEnvironment) { Long id = dataFetchingEnvironment.getArgument("bookId"); if (id == null) { From 7ce51f19fd810d77c92b7f6061761e44a6948bd7 Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 21 Apr 2021 16:52:15 +0100 Subject: [PATCH 47/87] Use constants for input arguments --- .../karankumar/booksapi/datafetchers/BookDataFetcher.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/datafetchers/BookDataFetcher.java b/src/main/java/com/karankumar/booksapi/datafetchers/BookDataFetcher.java index 8e43aaa0..df77e6c5 100644 --- a/src/main/java/com/karankumar/booksapi/datafetchers/BookDataFetcher.java +++ b/src/main/java/com/karankumar/booksapi/datafetchers/BookDataFetcher.java @@ -38,17 +38,17 @@ public List findAllBooks() { } @DgsData(parentType = DgsConstants.QUERY_TYPE, field = DgsConstants.QUERY.FindBookByIsbn13) - public Book findBookByIsbn13(@InputArgument("isbn13") String isbn13) { + public Book findBookByIsbn13(@InputArgument(DgsConstants.BOOK.Isbn13) String isbn13) { return bookService.findBookByIsbn13(isbn13); } @DgsData(parentType = DgsConstants.QUERY_TYPE, field = DgsConstants.QUERY.FindByAuthor) - public List findByAuthor(@InputArgument("fullName") String fullName) { + public List findByAuthor(@InputArgument(DgsConstants.AUTHOR.FullName) String fullName) { return bookService.findByAuthor(fullName); } @DgsData(parentType = DgsConstants.QUERY_TYPE, field = DgsConstants.QUERY.FindByTitleIgnoreCase) - public Book findByTitle(@InputArgument("title") String title) { + public Book findByTitle(@InputArgument(DgsConstants.BOOK.Title) String title) { return bookService.findByTitle(title); } } From 743b14e97022b8c653f4cc289b4ffac369d860e1 Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 21 Apr 2021 16:56:58 +0100 Subject: [PATCH 48/87] Use Dgs constants --- .../karankumar/booksapi/mutations/AuthorMutation.java | 4 ++-- .../karankumar/booksapi/mutations/BookMutation.java | 10 +++++----- src/main/resources/schema/mutation.graphqls | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/mutations/AuthorMutation.java b/src/main/java/com/karankumar/booksapi/mutations/AuthorMutation.java index c06ae1a3..29c0c15f 100644 --- a/src/main/java/com/karankumar/booksapi/mutations/AuthorMutation.java +++ b/src/main/java/com/karankumar/booksapi/mutations/AuthorMutation.java @@ -32,9 +32,9 @@ public AuthorMutation(AuthorService authorService) { this.authorService = authorService; } - @DgsData(parentType = "Mutation", field = DgsConstants.MUTATION.AddAuthor) + @DgsData(parentType = DgsConstants.MUTATION.TYPE_NAME, field = DgsConstants.MUTATION.AddAuthor) public Author addAuthor(DataFetchingEnvironment dataFetchingEnvironment) { - String fullName = dataFetchingEnvironment.getArgument("fullName"); + String fullName = dataFetchingEnvironment.getArgument(DgsConstants.AUTHOR.FullName); return authorService.save(new Author(fullName, new HashSet<>())); } } diff --git a/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java b/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java index 60dd4ff9..22769741 100644 --- a/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java +++ b/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java @@ -38,26 +38,26 @@ public BookMutation(BookService bookService) { } // TODO: change this to update a book rather than updating a specific field - @DgsData(parentType = "Mutation", field = DgsConstants.MUTATION.AddIsbn13) + @DgsData(parentType = DgsConstants.MUTATION.TYPE_NAME, field = DgsConstants.MUTATION.AddIsbn13) public Book addIsbn13(DataFetchingEnvironment dataFetchingEnvironment) throws InvalidISBN10Exception, InvalidISBN13Exception { Optional optionalBook = bookService.findById( - dataFetchingEnvironment.getArgument("bookId") + dataFetchingEnvironment.getArgument(DgsConstants.BOOK.Id) ); if (optionalBook.isEmpty()) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, NOT_FOUND_ERROR_MESSAGE); } - String isbn13 = dataFetchingEnvironment.getArgument("isbn13"); + String isbn13 = dataFetchingEnvironment.getArgument(DgsConstants.BOOK.Isbn13); Book book = optionalBook.get(); book.setIsbn13(isbn13); return bookService.save(optionalBook.get()); } - @DgsData(parentType = "Mutation", field = DgsConstants.MUTATION.DeleteBook) + @DgsData(parentType = DgsConstants.MUTATION.TYPE_NAME, field = DgsConstants.MUTATION.DeleteBook) public Book deleteBook(DataFetchingEnvironment dataFetchingEnvironment) { - Long id = dataFetchingEnvironment.getArgument("bookId"); + Long id = dataFetchingEnvironment.getArgument(DgsConstants.BOOK.Id); if (id == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, NOT_FOUND_ERROR_MESSAGE); } diff --git a/src/main/resources/schema/mutation.graphqls b/src/main/resources/schema/mutation.graphqls index 6e5bc24a..41307af5 100644 --- a/src/main/resources/schema/mutation.graphqls +++ b/src/main/resources/schema/mutation.graphqls @@ -1,7 +1,7 @@ type Mutation { - addIsbn13(bookId: Long!, isbn13: String): Book + addIsbn13(id: Long!, isbn13: String): Book addAuthor(fullName: String!): Author - deleteBook(bookId: Long!): Book + deleteBook(id: Long!): Book } scalar Long From fcd10081df7dedd0d7e90ad457d6dbfe48107d9e Mon Sep 17 00:00:00 2001 From: Karan Date: Tue, 27 Apr 2021 19:17:57 +0100 Subject: [PATCH 49/87] Remove dependency in test --- ...PPING.sql => V011_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql} | 0 .../karankumar/booksapi/repository/AuthorRepositoryTest.java | 5 +---- 2 files changed, 1 insertion(+), 4 deletions(-) rename src/main/resources/db/migration/{V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql => V011_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql} (100%) diff --git a/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql b/src/main/resources/db/migration/V011_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql similarity index 100% rename from src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql rename to src/main/resources/db/migration/V011_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql diff --git a/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java index f6341816..272116a7 100644 --- a/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java @@ -34,18 +34,15 @@ class AuthorRepositoryTest { private final BookRepository bookRepository; private final AuthorRepository authorRepository; - private final BookSeriesMappingRepository bookSeriesMappingRepository; @Autowired - AuthorRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { + AuthorRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; - this.bookSeriesMappingRepository = bookSeriesMappingRepository; } @BeforeEach void setUp() { - bookSeriesMappingRepository.deleteAll(); authorRepository.deleteAll(); bookRepository.deleteAll(); } From 719a31321df8d237e187180fd0bc4033c7ccb135 Mon Sep 17 00:00:00 2001 From: Karan Date: Tue, 27 Apr 2021 19:26:07 +0100 Subject: [PATCH 50/87] Add book series to GraphQL schema --- src/main/resources/schema/bookseries.graphqls | 5 +++++ src/main/resources/schema/query.graphqls | 1 + 2 files changed, 6 insertions(+) create mode 100644 src/main/resources/schema/bookseries.graphqls diff --git a/src/main/resources/schema/bookseries.graphqls b/src/main/resources/schema/bookseries.graphqls new file mode 100644 index 00000000..4a247212 --- /dev/null +++ b/src/main/resources/schema/bookseries.graphqls @@ -0,0 +1,5 @@ +type BookSeries { + id: ID! + seriesName: String! + books: [Book]! +} diff --git a/src/main/resources/schema/query.graphqls b/src/main/resources/schema/query.graphqls index 882a1c3e..cd14bede 100644 --- a/src/main/resources/schema/query.graphqls +++ b/src/main/resources/schema/query.graphqls @@ -3,4 +3,5 @@ type Query { findBookByIsbn13(isbn13: String!): Book! findByAuthor(firstName: String!, lastName: String!): [Book]! findByTitleIgnoreCase(title: String!): Book +# findSeriesForBook(book: Book!): [BookSeries]! // TODO: fix. Cannot use Book as an input type } From 690df7d2dd035b2be376aa44633fc424c279e954 Mon Sep 17 00:00:00 2001 From: Karan Date: Tue, 27 Apr 2021 19:28:23 +0100 Subject: [PATCH 51/87] Remove unused variables --- .../karankumar/booksapi/repository/BookRepositoryTest.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index f102bb5b..fdee1cf1 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Karan Kumar + * Copyright (C) 2021 Karan Kumar * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of the @@ -41,7 +41,6 @@ class BookRepositoryTest { private static final String ISBN = "978-3-16-148410-0"; private static final String TITLE = "Harry Potter"; - private static final String AUTHOR1_FULL_NAME = "Kevlin Henney"; private final BookRepository bookRepository; private final AuthorRepository authorRepository; @@ -50,9 +49,6 @@ class BookRepositoryTest { private final String harryPotter1Title = "Harry Potter and the Philosopher's stone"; private final String harryPotterSeriesName = "Harry Potter Series"; - private Author author1; - private Author author2; - @Autowired BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, BookSeriesRepository bookSeriesRepository, From bb3ca70484c821c632920922a04d5c6273b7b9d4 Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 28 Apr 2021 07:35:48 +0100 Subject: [PATCH 52/87] Remove BookRepository dependency --- .../booksapi/repository/AuthorRepositoryTest.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java index 272116a7..00eeff81 100644 --- a/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/AuthorRepositoryTest.java @@ -25,26 +25,22 @@ import java.util.HashSet; import java.util.List; -import static com.karankumar.booksapi.repository.RepositoryTestUtils.createBook; import static org.assertj.core.api.Assertions.assertThat; @DataJpaIntegrationTest @DisplayName("AuthorRepository should") class AuthorRepositoryTest { - private final BookRepository bookRepository; private final AuthorRepository authorRepository; @Autowired - AuthorRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository) { - this.bookRepository = bookRepository; + AuthorRepositoryTest(AuthorRepository authorRepository) { this.authorRepository = authorRepository; } @BeforeEach void setUp() { authorRepository.deleteAll(); - bookRepository.deleteAll(); } @Test @@ -53,7 +49,6 @@ void findSavedAuthors() { // given Author author1 = createAndSaveAuthor("Kevlin", "Henney"); Author author2 = createAndSaveAuthor("Trisha", "Gee"); - saveBook(); // when List result = authorRepository.findAllAuthors(); @@ -61,10 +56,6 @@ void findSavedAuthors() { // then assertThat(result).containsExactlyInAnyOrder(author1, author2); } - - private void saveBook() { - bookRepository.save(createBook()); - } private Author createAndSaveAuthor(String firstName, String lastName) { String fullName = firstName + " " + lastName; From 0c8a58b436a04a916255ea3fd230e445ac669ef1 Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 28 Apr 2021 08:01:26 +0100 Subject: [PATCH 53/87] Use ID instead of Long --- .../karankumar/booksapi/BooksApiApplication.java | 1 - .../booksapi/mutations/BookMutation.java | 5 +++-- .../booksapi/scalars/LongScalarRegistration.java | 14 -------------- src/main/resources/schema/mutation.graphqls | 6 ++---- 4 files changed, 5 insertions(+), 21 deletions(-) delete mode 100644 src/main/java/com/karankumar/booksapi/scalars/LongScalarRegistration.java diff --git a/src/main/java/com/karankumar/booksapi/BooksApiApplication.java b/src/main/java/com/karankumar/booksapi/BooksApiApplication.java index 6b09f0d4..158730ea 100644 --- a/src/main/java/com/karankumar/booksapi/BooksApiApplication.java +++ b/src/main/java/com/karankumar/booksapi/BooksApiApplication.java @@ -29,7 +29,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; -import java.util.List; import java.util.Set; @SpringBootApplication diff --git a/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java b/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java index 22769741..858b34ad 100644 --- a/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java +++ b/src/main/java/com/karankumar/booksapi/mutations/BookMutation.java @@ -57,10 +57,11 @@ public Book addIsbn13(DataFetchingEnvironment dataFetchingEnvironment) @DgsData(parentType = DgsConstants.MUTATION.TYPE_NAME, field = DgsConstants.MUTATION.DeleteBook) public Book deleteBook(DataFetchingEnvironment dataFetchingEnvironment) { - Long id = dataFetchingEnvironment.getArgument(DgsConstants.BOOK.Id); - if (id == null) { + String stringId = dataFetchingEnvironment.getArgument(DgsConstants.BOOK.Id); + if (stringId == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, NOT_FOUND_ERROR_MESSAGE); } + Long id = Long.parseLong(stringId); Optional book = bookService.findById(id); if (book.isEmpty()) { diff --git a/src/main/java/com/karankumar/booksapi/scalars/LongScalarRegistration.java b/src/main/java/com/karankumar/booksapi/scalars/LongScalarRegistration.java deleted file mode 100644 index cd84a7a4..00000000 --- a/src/main/java/com/karankumar/booksapi/scalars/LongScalarRegistration.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.karankumar.booksapi.scalars; - -import com.netflix.graphql.dgs.DgsComponent; -import com.netflix.graphql.dgs.DgsRuntimeWiring; -import graphql.Scalars; -import graphql.schema.idl.RuntimeWiring; - -@DgsComponent -public class LongScalarRegistration { - @DgsRuntimeWiring - public RuntimeWiring.Builder addScalar(RuntimeWiring.Builder builder) { - return builder.scalar(Scalars.GraphQLLong); - } -} diff --git a/src/main/resources/schema/mutation.graphqls b/src/main/resources/schema/mutation.graphqls index 41307af5..648d95a6 100644 --- a/src/main/resources/schema/mutation.graphqls +++ b/src/main/resources/schema/mutation.graphqls @@ -1,7 +1,5 @@ type Mutation { - addIsbn13(id: Long!, isbn13: String): Book + addIsbn13(id: ID!, isbn13: String): Book addAuthor(fullName: String!): Author - deleteBook(id: Long!): Book + deleteBook(id: ID!): Book } - -scalar Long From bd97e707693bc87d3a266c053c35036d5a7c18ea Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 28 Apr 2021 08:45:27 +0100 Subject: [PATCH 54/87] Test findAllBooks() --- build.gradle | 2 +- .../datafetcher/BookDataFetcherTest.java | 94 +++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java diff --git a/build.gradle b/build.gradle index 45fb2796..76b935cd 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ repositories { generateJava { schemaPaths = ["${projectDir}/src/main/resources/schema"] // List of directories containing schema files packageName = 'com.karankumar.booksapi' // The package name to use to generate sources - generateClient = false // Enable generating the type safe query API + generateClient = true // Enable generating the type safe query API } dependencies { diff --git a/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java b/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java new file mode 100644 index 00000000..11277ef7 --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.datafetcher; + +import com.karankumar.booksapi.client.FindAllBooksGraphQLQuery; +import com.karankumar.booksapi.client.FindAllBooksProjectionRoot; +import com.karankumar.booksapi.datafetchers.BookDataFetcher; +import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookFormat; +import com.karankumar.booksapi.model.BookGenre; +import com.karankumar.booksapi.model.Language; +import com.karankumar.booksapi.service.BookService; +import com.netflix.graphql.dgs.DgsQueryExecutor; +import com.netflix.graphql.dgs.autoconfig.DgsAutoConfiguration; +import com.netflix.graphql.dgs.client.codegen.GraphQLQueryRequest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +@SpringBootTest(classes = {DgsAutoConfiguration.class, BookDataFetcher.class}) +@ActiveProfiles("test") +class BookDataFetcherTest { + @Autowired + DgsQueryExecutor queryExecutor; + + @MockBean + BookService bookService; + + @Test + void findAllBooks_returnsEmptyList_whenNoBooksExist() { + // Given + given(bookService.findAll()).willReturn(new ArrayList<>()); + GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest( + new FindAllBooksGraphQLQuery(), + new FindAllBooksProjectionRoot().title() + ); + + // When + List bookTitles = queryExecutor.executeAndExtractJsonPath( + graphQLQueryRequest.serialize(), + "data.findAllBooks[*].title" + ); + + // Then + assertThat(bookTitles.size()).isZero(); + } + + @Test + void findAllBooks_returnsNonEmptyList_whenBooksExist() { + // Given + final String title = "How to avoid a climate disaster"; + given(bookService.findAll()).willReturn(List.of(createBook(title))); + GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest( + new FindAllBooksGraphQLQuery(), + new FindAllBooksProjectionRoot().title() + ); + + // When + List bookTitles = queryExecutor.executeAndExtractJsonPath( + graphQLQueryRequest.serialize(), + "data.findAllBooks[*].title" + ); + + // Then + assertThat(bookTitles).containsExactly(title); + } + + private Book createBook(String title) { + return new Book( + title, Language.ENGLISH, "blurb", BookGenre.CRIME, BookFormat.PAPERBACK + ); + } +} From 55054fbdcbcc5e93035eaacbde2658747bd2e60f Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 28 Apr 2021 19:27:12 +0100 Subject: [PATCH 55/87] Test findBookByIsbn13() --- .../datafetcher/BookDataFetcherTest.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java b/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java index 11277ef7..b0dce91a 100644 --- a/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java +++ b/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java @@ -17,6 +17,8 @@ import com.karankumar.booksapi.client.FindAllBooksGraphQLQuery; import com.karankumar.booksapi.client.FindAllBooksProjectionRoot; +import com.karankumar.booksapi.client.FindBookByIsbn13GraphQLQuery; +import com.karankumar.booksapi.client.FindBookByIsbn13ProjectionRoot; import com.karankumar.booksapi.datafetchers.BookDataFetcher; import com.karankumar.booksapi.model.Book; import com.karankumar.booksapi.model.BookFormat; @@ -70,7 +72,10 @@ void findAllBooks_returnsEmptyList_whenNoBooksExist() { void findAllBooks_returnsNonEmptyList_whenBooksExist() { // Given final String title = "How to avoid a climate disaster"; - given(bookService.findAll()).willReturn(List.of(createBook(title))); + Book book = new Book( + title, Language.ENGLISH, "blurb", BookGenre.CRIME, BookFormat.PAPERBACK + ); + given(bookService.findAll()).willReturn(List.of(book)); GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest( new FindAllBooksGraphQLQuery(), new FindAllBooksProjectionRoot().title() @@ -86,9 +91,27 @@ void findAllBooks_returnsNonEmptyList_whenBooksExist() { assertThat(bookTitles).containsExactly(title); } - private Book createBook(String title) { - return new Book( - title, Language.ENGLISH, "blurb", BookGenre.CRIME, BookFormat.PAPERBACK + @Test + void findBookByIsbn13_returnsNonNullBook_whenIsbnMatchesABook() { + // Given + final String isbn13 = "1234567898765"; + Book book = new Book( + "title", Language.ENGLISH, "blurb", BookGenre.CRIME, BookFormat.PAPERBACK + ); + book.setIsbn13(isbn13); + given(bookService.findBookByIsbn13(isbn13)).willReturn(book); + GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest( + new FindBookByIsbn13GraphQLQuery(isbn13), + new FindBookByIsbn13ProjectionRoot().isbn13() ); + + // When + String actual = queryExecutor.executeAndExtractJsonPath( + graphQLQueryRequest.serialize(), + "data.findBookByIsbn13.isbn13" + ); + + // Then + assertThat(actual).isEqualTo(isbn13); } } From 0af57f122fab01e8d6e2807bf1dc8ff13a814fc1 Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 28 Apr 2021 19:45:33 +0100 Subject: [PATCH 56/87] Make findBookByIsbn13() nullable --- src/main/resources/schema/query.graphqls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/schema/query.graphqls b/src/main/resources/schema/query.graphqls index 882a1c3e..cbfb9d1e 100644 --- a/src/main/resources/schema/query.graphqls +++ b/src/main/resources/schema/query.graphqls @@ -1,6 +1,6 @@ type Query { findAllBooks: [Book]! - findBookByIsbn13(isbn13: String!): Book! + findBookByIsbn13(isbn13: String!): Book findByAuthor(firstName: String!, lastName: String!): [Book]! findByTitleIgnoreCase(title: String!): Book } From 778096d50f7cf0c173d6fd1da4cdbb49c0e9cf92 Mon Sep 17 00:00:00 2001 From: Karan Date: Wed, 28 Apr 2021 19:46:06 +0100 Subject: [PATCH 57/87] Test findByTitle() when title not matched --- .../datafetcher/BookDataFetcherTest.java | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java b/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java index b0dce91a..129afacd 100644 --- a/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java +++ b/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java @@ -15,10 +15,13 @@ package com.karankumar.booksapi.datafetcher; +import com.karankumar.booksapi.DgsConstants; import com.karankumar.booksapi.client.FindAllBooksGraphQLQuery; import com.karankumar.booksapi.client.FindAllBooksProjectionRoot; import com.karankumar.booksapi.client.FindBookByIsbn13GraphQLQuery; import com.karankumar.booksapi.client.FindBookByIsbn13ProjectionRoot; +import com.karankumar.booksapi.client.FindByTitleIgnoreCaseGraphQLQuery; +import com.karankumar.booksapi.client.FindByTitleIgnoreCaseProjectionRoot; import com.karankumar.booksapi.datafetchers.BookDataFetcher; import com.karankumar.booksapi.model.Book; import com.karankumar.booksapi.model.BookFormat; @@ -49,6 +52,8 @@ class BookDataFetcherTest { @MockBean BookService bookService; + private final String ROOT = "data."; + @Test void findAllBooks_returnsEmptyList_whenNoBooksExist() { // Given @@ -61,7 +66,7 @@ void findAllBooks_returnsEmptyList_whenNoBooksExist() { // When List bookTitles = queryExecutor.executeAndExtractJsonPath( graphQLQueryRequest.serialize(), - "data.findAllBooks[*].title" + ROOT + DgsConstants.QUERY.FindAllBooks + "[*]." + DgsConstants.BOOK.Title ); // Then @@ -84,7 +89,7 @@ void findAllBooks_returnsNonEmptyList_whenBooksExist() { // When List bookTitles = queryExecutor.executeAndExtractJsonPath( graphQLQueryRequest.serialize(), - "data.findAllBooks[*].title" + ROOT + DgsConstants.QUERY.FindAllBooks + "[*]." + DgsConstants.BOOK.Title ); // Then @@ -108,10 +113,51 @@ void findBookByIsbn13_returnsNonNullBook_whenIsbnMatchesABook() { // When String actual = queryExecutor.executeAndExtractJsonPath( graphQLQueryRequest.serialize(), - "data.findBookByIsbn13.isbn13" + ROOT + DgsConstants.QUERY.FindBookByIsbn13 + "." + DgsConstants.BOOK.Isbn13 ); // Then assertThat(actual).isEqualTo(isbn13); } + + @Test + void findBookByIsbn13_returnsNullBook_whenIsbnDoesNotMatchABook() { + // Given + final String isbn13 = "1234567898765"; + given(bookService.findBookByIsbn13(isbn13)).willReturn(null); + GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest( + new FindBookByIsbn13GraphQLQuery(isbn13), + new FindBookByIsbn13ProjectionRoot().isbn13() + ); + + // When + String actual = queryExecutor.executeAndExtractJsonPath( + graphQLQueryRequest.serialize(), + ROOT + DgsConstants.QUERY.FindBookByIsbn13 + ); + + // Then + assertThat(actual).isNull(); + } + + @Test + void findByTitle_returnsNullBook_whenTitleNotFound() { + // Given + String title = "title"; + given(bookService.findByTitle(title)).willReturn(null); + GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest( + new FindByTitleIgnoreCaseGraphQLQuery(title), + new FindByTitleIgnoreCaseProjectionRoot().title() + ); + + // When + String actual = queryExecutor.executeAndExtractJsonPath( + graphQLQueryRequest.serialize(), + ROOT + DgsConstants.QUERY.FindByTitleIgnoreCase + ); + + // Then + assertThat(actual).isNull(); + } + } From bfb35fde6d0cdd7a7e25869c7e3494df45115bfd Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 29 Apr 2021 18:51:22 +0100 Subject: [PATCH 58/87] Remove comments --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 76b935cd..80a2197a 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,6 @@ plugins { id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id 'jacoco' -// id "com.netflix.dgs.codegen" version "4.5.2" id "org.flywaydb.flyway" version "7.5.4" } @@ -41,7 +40,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation "org.flywaydb:flyway-core:7.5.4" - // https://mvnrepository.com/artifact/commons-validator/commons-validator implementation "commons-validator:commons-validator:1.7" compileOnly 'org.projectlombok:lombok' From afaa49e8716f8c2bdf1d56696ced94e0040cf786 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 29 Apr 2021 18:54:13 +0100 Subject: [PATCH 59/87] Update query --- src/main/resources/schema/query.graphqls | 2 +- .../datafetcher/BookDataFetcherTest.java | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/main/resources/schema/query.graphqls b/src/main/resources/schema/query.graphqls index cbfb9d1e..fb6b925e 100644 --- a/src/main/resources/schema/query.graphqls +++ b/src/main/resources/schema/query.graphqls @@ -1,6 +1,6 @@ type Query { findAllBooks: [Book]! findBookByIsbn13(isbn13: String!): Book - findByAuthor(firstName: String!, lastName: String!): [Book]! + findByAuthor(fullName: String!): [Book]! findByTitleIgnoreCase(title: String!): Book } diff --git a/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java b/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java index 129afacd..0b689e71 100644 --- a/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java +++ b/src/test/java/com/karankumar/booksapi/datafetcher/BookDataFetcherTest.java @@ -20,6 +20,8 @@ import com.karankumar.booksapi.client.FindAllBooksProjectionRoot; import com.karankumar.booksapi.client.FindBookByIsbn13GraphQLQuery; import com.karankumar.booksapi.client.FindBookByIsbn13ProjectionRoot; +import com.karankumar.booksapi.client.FindByAuthorGraphQLQuery; +import com.karankumar.booksapi.client.FindByAuthorProjectionRoot; import com.karankumar.booksapi.client.FindByTitleIgnoreCaseGraphQLQuery; import com.karankumar.booksapi.client.FindByTitleIgnoreCaseProjectionRoot; import com.karankumar.booksapi.datafetchers.BookDataFetcher; @@ -41,6 +43,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; @SpringBootTest(classes = {DgsAutoConfiguration.class, BookDataFetcher.class}) @@ -140,6 +143,28 @@ void findBookByIsbn13_returnsNullBook_whenIsbnDoesNotMatchABook() { assertThat(actual).isNull(); } + @Test + void findByAuthor_returnsNonEmptyList_whenBookNotFound() { + // Given + Book book = new Book( + "title", Language.ENGLISH, "blurb", BookGenre.CRIME, BookFormat.PAPERBACK + ); + given(bookService.findByAuthor(any(String.class))).willReturn(List.of(book)); + GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest( + new FindByAuthorGraphQLQuery("name"), + new FindByAuthorProjectionRoot().title() + ); + + // When + List actual = queryExecutor.executeAndExtractJsonPath( + graphQLQueryRequest.serialize(), + ROOT + DgsConstants.QUERY.FindByAuthor + "[*]." + DgsConstants.BOOK.Title + ); + + // Then + assertThat(actual).isNotEmpty(); + } + @Test void findByTitle_returnsNullBook_whenTitleNotFound() { // Given @@ -160,4 +185,26 @@ void findByTitle_returnsNullBook_whenTitleNotFound() { assertThat(actual).isNull(); } + @Test + void findByTitle_returnsNonNullBook_whenTitleFound() { + // Given + String title = "title"; + Book book = new Book( + title, Language.ENGLISH, "blurb", BookGenre.CRIME, BookFormat.PAPERBACK + ); + given(bookService.findByTitle(title)).willReturn(book); + GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest( + new FindByTitleIgnoreCaseGraphQLQuery(title), + new FindByTitleIgnoreCaseProjectionRoot().title() + ); + + // When + String actual = queryExecutor.executeAndExtractJsonPath( + graphQLQueryRequest.serialize(), + ROOT + DgsConstants.QUERY.FindByTitleIgnoreCase + ".title" + ); + + // Then + assertThat(actual).isNotNull(); + } } From 87fe614c7726810ae550d1828eaebe7d62e607df Mon Sep 17 00:00:00 2001 From: Karan Kumar Date: Fri, 7 May 2021 18:03:42 +0100 Subject: [PATCH 60/87] Update to non-expiring Slack link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bad794cb..6d7c4e8d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - + Slack From 0efc126aab35d9dca6263e7e8d67289abea98f52 Mon Sep 17 00:00:00 2001 From: Karan Date: Sun, 9 May 2021 10:09:55 +0100 Subject: [PATCH 61/87] Test AuthorService --- .../booksapi/service/AuthorServiceTest.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/test/java/com/karankumar/booksapi/service/AuthorServiceTest.java diff --git a/src/test/java/com/karankumar/booksapi/service/AuthorServiceTest.java b/src/test/java/com/karankumar/booksapi/service/AuthorServiceTest.java new file mode 100644 index 00000000..8e13776c --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/service/AuthorServiceTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ +package com.karankumar.booksapi.service; + +import com.karankumar.booksapi.model.Author; +import com.karankumar.booksapi.repository.AuthorRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.HashSet; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class AuthorServiceTest { + private AuthorService underTest; + private AuthorRepository authorRepository; + + @BeforeEach + void setUp() { + authorRepository = mock(AuthorRepository.class); + underTest = new AuthorService(authorRepository); + } + + @Test + void canSave() { + // given + Author expected = new Author("test", new HashSet<>()); + ArgumentCaptor authorArgumentCaptor = ArgumentCaptor.forClass(Author.class); + + // when + underTest.save(expected); + + // then + verify(authorRepository).save(authorArgumentCaptor.capture()); + assertThat(authorArgumentCaptor.getValue()).isEqualTo(expected); + } + + @Test + void findById_throwsNullPointerException_ifIdIsNull() { + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> underTest.findById(null)); + verify((authorRepository), never()).findById(anyLong()); + } + + @Test + void canFindByNonNullId() { + // given + Long expected = 1L; + ArgumentCaptor longArgumentCaptor = ArgumentCaptor.forClass(Long.class); + + // when + underTest.findById(expected); + + // then + verify(authorRepository).findById(longArgumentCaptor.capture()); + assertThat(longArgumentCaptor.getValue()).isEqualTo(expected); + } + + @Test + void canFindAll() { + underTest.findAll(); + verify(authorRepository).findAllAuthors(); + } +} \ No newline at end of file From c64ce11fd1bb1be654dfba538100b0d15b7ce522 Mon Sep 17 00:00:00 2001 From: Karan Date: Sun, 9 May 2021 19:17:41 +0100 Subject: [PATCH 62/87] Test Book Service --- .../booksapi/service/BookService.java | 10 +- .../booksapi/service/BookServiceTest.java | 245 ++++++++++++++++++ 2 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/karankumar/booksapi/service/BookServiceTest.java diff --git a/src/main/java/com/karankumar/booksapi/service/BookService.java b/src/main/java/com/karankumar/booksapi/service/BookService.java index 435a8065..1b6a6ace 100644 --- a/src/main/java/com/karankumar/booksapi/service/BookService.java +++ b/src/main/java/com/karankumar/booksapi/service/BookService.java @@ -29,6 +29,8 @@ @Service public class BookService { private final BookRepository bookRepository; + private static final String INVALID_ISBN10_MESSAGE = "%s is not a valid ISBN 10"; + private static final String INVALID_ISBN13_MESSAGE = "%s is not a valid ISBN 13"; public BookService(BookRepository bookRepository) { this.bookRepository = bookRepository; @@ -36,10 +38,14 @@ public BookService(BookRepository bookRepository) { public Book save(@NonNull Book book) throws InvalidISBN10Exception, InvalidISBN13Exception { if (book.getIsbn10() != null && isIsbn10Invalid(book.getIsbn10())) { - throw new InvalidISBN10Exception("Not a valid ISBN 10: " + book.getIsbn10()); + throw new InvalidISBN10Exception( + String.format(INVALID_ISBN10_MESSAGE, book.getIsbn10()) + ); } if (book.getIsbn13() != null && isIsbn13Invalid(book.getIsbn13())) { - throw new InvalidISBN13Exception("Not a valid ISBN 13: " + book.getIsbn13()); + throw new InvalidISBN13Exception( + String.format(INVALID_ISBN13_MESSAGE, book.getIsbn13()) + ); } return bookRepository.save(book); } diff --git a/src/test/java/com/karankumar/booksapi/service/BookServiceTest.java b/src/test/java/com/karankumar/booksapi/service/BookServiceTest.java new file mode 100644 index 00000000..ecae552c --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/service/BookServiceTest.java @@ -0,0 +1,245 @@ +package com.karankumar.booksapi.service; + +import com.karankumar.booksapi.exception.InvalidISBN10Exception; +import com.karankumar.booksapi.exception.InvalidISBN13Exception; +import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookFormat; +import com.karankumar.booksapi.model.BookGenre; +import com.karankumar.booksapi.model.Language; +import com.karankumar.booksapi.repository.BookRepository; +import org.assertj.core.api.ThrowableAssert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +class BookServiceTest { + + private BookService underTest; + private BookRepository bookRepository; + + @BeforeEach + void setUp() { + bookRepository = mock(BookRepository.class); + underTest = new BookService(bookRepository); + } + + @Test + void save_throwsNullPointerExceptionIfBookIsNull() { + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> underTest.save(null)); + verify(bookRepository, never()).save(null); + } + + @Test + void save_throwsInvalidIsbn10_ifIsbn10IsInvalid() { + // given + Book bookWithInvalidIsbn10 = new Book( + "title", + Language.ENGLISH, + "blurb", + BookGenre.CRIME, + BookFormat.EBOOK + ); + bookWithInvalidIsbn10.setIsbn10("1234567890"); + + // when + ThrowableAssert.ThrowingCallable throwingCallable = + () -> underTest.save(bookWithInvalidIsbn10); + + // then + assertThatExceptionOfType(InvalidISBN10Exception.class) + .isThrownBy(throwingCallable); + verify(bookRepository, never()).save(any(Book.class)); + } + + @Test + void save_throwsInvalidIsbn13_ifIsbn13IsInvalid() { + // given + Book bookWithInvalidIsbn13 = new Book( + "title", + Language.ENGLISH, + "blurb", + BookGenre.CRIME, + BookFormat.EBOOK + ); + bookWithInvalidIsbn13.setIsbn13("1234567890123"); + + assertThatExceptionOfType(InvalidISBN13Exception.class) + .isThrownBy(() -> underTest.save(bookWithInvalidIsbn13)); + verify(bookRepository, never()).save(any(Book.class)); + } + + @Test + void canSaveBookWithValidIsbn10() throws InvalidISBN13Exception, InvalidISBN10Exception { + // given + Book bookWithValidIsbn10 = new Book( + "title", + Language.ENGLISH, + "blurb", + BookGenre.CRIME, + BookFormat.EBOOK + ); + bookWithValidIsbn10.setIsbn10("1843560283"); + ArgumentCaptor bookArgumentCaptor = ArgumentCaptor.forClass(Book.class); + + // when + underTest.save(bookWithValidIsbn10); + + // then + verify(bookRepository).save(bookArgumentCaptor.capture()); + assertThat(bookArgumentCaptor.getValue()).isEqualTo(bookWithValidIsbn10); + } + + @Test + void canSaveBookWithValidIsbn13() throws InvalidISBN13Exception, InvalidISBN10Exception { + // given + Book book = new Book( + "title", + Language.ENGLISH, + "blurb", + BookGenre.CRIME, + BookFormat.EBOOK + ); + book.setIsbn13("9783161484100"); + ArgumentCaptor bookArgumentCaptor = ArgumentCaptor.forClass(Book.class); + + // when + underTest.save(book); + + // then + verify(bookRepository).save(bookArgumentCaptor.capture()); + assertThat(bookArgumentCaptor.getValue()).isEqualTo(book); + } + + @Test + void canSaveBookWithoutIsbn10Or13() throws InvalidISBN13Exception, InvalidISBN10Exception { + // given + Book book = new Book( + "title", + Language.ENGLISH, + "blurb", + BookGenre.CRIME, + BookFormat.EBOOK + ); + ArgumentCaptor bookArgumentCaptor = ArgumentCaptor.forClass(Book.class); + + // when + underTest.save(book); + + // then + verify(bookRepository).save(bookArgumentCaptor.capture()); + assertThat(bookArgumentCaptor.getValue()).isEqualTo(book); + } + + @Test + void canFindByNonNullId() { + // given + Long expected = 1L; + ArgumentCaptor longArgumentCaptor = ArgumentCaptor.forClass(Long.class); + + // when + underTest.findById(expected); + + // then + verify(bookRepository).findById(longArgumentCaptor.capture()); + assertThat(longArgumentCaptor.getValue()).isEqualTo(expected); + } + + @Test + void canFindAll() { + underTest.findAll(); + verify(bookRepository).findAllBooks(); + } + + @Test + void findByAuthor_throwsNullPointerException_ifAuthorIsNull() { + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> underTest.findByAuthor(null)); + verify(bookRepository, never()).findByAuthor(anyString()); + } + + @Test + void canFindByAuthorIfStringNotNull() { + // given + String expected = "test"; + ArgumentCaptor stringArgumentCaptor = ArgumentCaptor.forClass(String.class); + + // when + underTest.findByAuthor(expected); + + // then + verify(bookRepository).findByAuthor(stringArgumentCaptor.capture()); + assertThat(stringArgumentCaptor.getValue()).isEqualTo(expected); + } + + @Test + void findBookByIsbn13_throwsNullPointerException_ifIsbnIsNull() { + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> underTest.findBookByIsbn13(null)); + verify(bookRepository, never()).findBookByIsbn13(anyString()); + } + + @Test + void canFindByNonNullIsbn13() { + // given + String expected = "isbn"; + ArgumentCaptor stringArgumentCaptor = ArgumentCaptor.forClass(String.class); + + // when + underTest.findBookByIsbn13(expected); + + // then + verify(bookRepository).findBookByIsbn13(stringArgumentCaptor.capture()); + assertThat(stringArgumentCaptor.getValue()).isEqualTo(expected); + } + + @Test + void findByTitle_throwsNullPointerException_ifTitleIsNull() { + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> underTest.findByTitle(null)); + verify(bookRepository, never()).findByTitleIgnoreCase(anyString()); + } + + @Test + void canFindByNonNullTitle() { + // given + String expected = "test"; + ArgumentCaptor stringArgumentCaptor = ArgumentCaptor.forClass(String.class); + + // when + underTest.findByTitle(expected); + + // then + verify(bookRepository).findByTitleIgnoreCase(stringArgumentCaptor.capture()); + assertThat(stringArgumentCaptor.getValue()).isEqualTo(expected); + } + + @Test + void deleteBook_throwsNullPointerException_ifIdIsNull() { + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> underTest.deleteBook(null)); + verify(bookRepository, never()).delete(any(Book.class)); + } + + @Test + void canDeleteBookIfIdIsNotNull() { + // given + Long expected = 1L; + ArgumentCaptor longArgumentCaptor = ArgumentCaptor.forClass(Long.class); + + // when + underTest.deleteBook(expected); + + // then + verify(bookRepository).deleteById(longArgumentCaptor.capture()); + assertThat(longArgumentCaptor.getValue()).isEqualTo(expected); + } +} \ No newline at end of file From 2eecb6686beb448f4e803eb5e644625722cc4b95 Mon Sep 17 00:00:00 2001 From: Karan Date: Tue, 18 May 2021 08:33:27 +0100 Subject: [PATCH 63/87] Fix publisher book not saved --- src/main/java/com/karankumar/booksapi/BooksApiApplication.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/karankumar/booksapi/BooksApiApplication.java b/src/main/java/com/karankumar/booksapi/BooksApiApplication.java index 158730ea..6a591ba2 100644 --- a/src/main/java/com/karankumar/booksapi/BooksApiApplication.java +++ b/src/main/java/com/karankumar/booksapi/BooksApiApplication.java @@ -43,7 +43,6 @@ public CommandLineRunner populateData(AuthorRepository authorRepository, PublisherRepository publisherRepository) { return args -> { Publisher publisher = new Publisher("Bloomsbury"); - publisherRepository.save(publisher); Book book1 = createBook( "Harry Potter and the Philosopher's stone", @@ -76,6 +75,8 @@ public CommandLineRunner populateData(AuthorRepository authorRepository, Author author = new Author("J.K. Rowling", Set.of(book1, book2, book3)); author.setAbout("A fantastic author"); authorRepository.save(author); + + publisherRepository.save(publisher); }; } From dd067a0cccb929a4e9aeb3227bc5678abd9d1d6c Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:37:23 +0530 Subject: [PATCH 64/87] Add new entity representing series of books. --- .../karankumar/booksapi/model/BookSeries.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/model/BookSeries.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java new file mode 100644 index 00000000..a291443c --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -0,0 +1,30 @@ +package com.karankumar.booksapi.model; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.*; +import java.util.List; + +@Entity +@Getter +@Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class BookSeries { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Setter(AccessLevel.NONE) + private Long id; + + @Column(nullable = false) + private String seriesName; + + @OneToMany(mappedBy = "bookSeries") + private List bookSeriesMapping; + + public BookSeries(String seriesName){ + this.seriesName = seriesName; + } +} From 28d3e3f297dd496db1d4fd10078ee6e9836a0382 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:38:32 +0530 Subject: [PATCH 65/87] Add new entity mapping series of books and books with a serial order number. --- .../booksapi/model/BookSeriesMapping.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java new file mode 100644 index 00000000..3a7cae70 --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -0,0 +1,38 @@ +package com.karankumar.booksapi.model; + +import lombok.*; + +import javax.persistence.*; + +@Getter @Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity + +@Table( + name="Book_To_BookSeries_Mapping", + uniqueConstraints = + @UniqueConstraint( columnNames = {"book_id","book_series_id","serialNumber"} ) +) + +public class BookSeriesMapping { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Setter(AccessLevel.NONE) + private long id; + + @ManyToOne + private BookSeries bookSeries; + + @ManyToOne + private Book book; + + @Column(nullable = false, name = "serialNumber") + private int serialNumber; + + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull int serialNumber) { + this.bookSeries = bookSeries; + this.book = bookInSeries; + this.serialNumber = serialNumber; + } +} From f206601f93e822a89412484f6af32153ff8514df Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Thu, 11 Mar 2021 20:39:36 +0530 Subject: [PATCH 66/87] Rebase onto main --- src/main/java/com/karankumar/booksapi/model/Book.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/karankumar/booksapi/model/Book.java b/src/main/java/com/karankumar/booksapi/model/Book.java index 82312b8c..e0a8c410 100644 --- a/src/main/java/com/karankumar/booksapi/model/Book.java +++ b/src/main/java/com/karankumar/booksapi/model/Book.java @@ -30,7 +30,10 @@ import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; +import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; @Entity @@ -75,6 +78,9 @@ public class Book { @Column(nullable = false) private BookFormat format; + @OneToMany(mappedBy = "book") + private List bookSeriesMapping; + public Book(@NonNull String title, @NonNull Language language, @NonNull String blurb, @NonNull BookGenre genre, @NonNull BookFormat format) { this.title = title; From a204d88fde381611dcef24b57e5e2c9744639cdf Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 14 Mar 2021 12:38:46 +0530 Subject: [PATCH 67/87] Add copyright text --- .../com/karankumar/booksapi/model/BookSeries.java | 14 ++++++++++++++ .../booksapi/model/BookSeriesMapping.java | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index a291443c..9a133c8d 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -1,3 +1,17 @@ +/* +The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. +Copyright (C) 2020 Karan Kumar + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. +If not, see . +*/ + package com.karankumar.booksapi.model; import lombok.AccessLevel; diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index 3a7cae70..afb9fb1f 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -1,3 +1,17 @@ +/* +The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. +Copyright (C) 2020 Karan Kumar + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. +If not, see . +*/ + package com.karankumar.booksapi.model; import lombok.*; From 67f4009fa813ec2c48ab3df5809df83e1709e0da Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:28:09 +0530 Subject: [PATCH 68/87] Update BookSeries entity's member "seriesName" --- src/main/java/com/karankumar/booksapi/model/BookSeries.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index 9a133c8d..cefabc80 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -18,6 +18,7 @@ License, or (at your option) any later version. import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.NonNull; import javax.persistence.*; import java.util.List; @@ -32,13 +33,13 @@ public class BookSeries { @Setter(AccessLevel.NONE) private Long id; - @Column(nullable = false) + @Column(nullable = false, name = "series_name") private String seriesName; @OneToMany(mappedBy = "bookSeries") private List bookSeriesMapping; - public BookSeries(String seriesName){ + public BookSeries(@NonNull String seriesName){ this.seriesName = seriesName; } } From 5e29ba8294c3c3d9006554934f62028e3eb1949c Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:33:48 +0530 Subject: [PATCH 69/87] Update BookSeriesMapping entity - Unique constraint, Relationship fields are Not Null, minor corrections --- .../booksapi/model/BookSeriesMapping.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index afb9fb1f..deda1ede 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -21,11 +21,12 @@ License, or (at your option) any later version. @Getter @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity - @Table( name="Book_To_BookSeries_Mapping", - uniqueConstraints = - @UniqueConstraint( columnNames = {"book_id","book_series_id","serialNumber"} ) + uniqueConstraints = { + @UniqueConstraint( name = "UK_bookSeriesId_bookId", columnNames = {"book_series_id","book_id"} ), + @UniqueConstraint( name = "UK_bookSeriesId_serialNumber", columnNames = {"book_series_id","serial_number"} ) + } ) public class BookSeriesMapping { @@ -33,18 +34,18 @@ public class BookSeriesMapping { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Setter(AccessLevel.NONE) - private long id; + private Long id; - @ManyToOne + @ManyToOne(optional = false) private BookSeries bookSeries; - @ManyToOne + @ManyToOne(optional = false) private Book book; - @Column(nullable = false, name = "serialNumber") - private int serialNumber; + @Column(nullable = false, name="serial_number") + private Integer serialNumber; - public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull int serialNumber) { + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull Integer serialNumber) { this.bookSeries = bookSeries; this.book = bookInSeries; this.serialNumber = serialNumber; From ecb3100d2557dbc2415ae4d0040b6732668f10e0 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:35:45 +0530 Subject: [PATCH 70/87] Add tests for entities Book Series Mapping and Book Series. --- .../booksapi/model/BookSeriesMappingTest.java | 86 +++++++++++++++++++ .../booksapi/model/BookSeriesTest.java | 33 +++++++ 2 files changed, 119 insertions(+) create mode 100644 src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java create mode 100644 src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java new file mode 100644 index 00000000..ce740261 --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +@DisplayName("Book Series Mapping should") +public class BookSeriesMappingTest { + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Serial Number") + void notAcceptNullSerialNumber(){ + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + Book book = new Book( + "Harry Potter and the Philosopher's stone", + new Author[] {author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book.setYearOfPublication(1997); + book.setIsbn13("9781408810545"); + book.setPublishedBy(Publisher.BLOOMSBURY); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); + } + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book") + void notAcceptNullBook(){ + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(bookSeries, null, 1)); + } + + @Test + @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") + void notAcceptNullBookSeries(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + + Book book = new Book( + "Harry Potter and the Philosopher's stone", + new Author[] {author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book.setYearOfPublication(1997); + book.setIsbn13("9781408810545"); + book.setPublishedBy(Publisher.BLOOMSBURY); + + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(()->new BookSeriesMapping(null, book, 1)); + } +} diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java new file mode 100644 index 00000000..67acdedb --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +@DisplayName("Book series should") +public class BookSeriesTest { + + @Test + @DisplayName("throw a null pointer exception on an attempt to create with a null Series Name.") + void notAcceptNullSeriesName(){ + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy( ()->new BookSeries(null) ); + } +} From 2255b070f9bee739dd595411f3017366d0eb1be7 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 15 Mar 2021 00:37:20 +0530 Subject: [PATCH 71/87] Add boilerplate code for entity repositories. --- .../BookSeriesMappingRepository.java | 22 +++++++++++++++++++ .../repository/BookSeriesRepository.java | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java create mode 100644 src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java new file mode 100644 index 00000000..c421f8ea --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.model.BookSeriesMapping; +import org.springframework.data.repository.CrudRepository; + +public interface BookSeriesMappingRepository extends CrudRepository { +} diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java new file mode 100644 index 00000000..7a167b33 --- /dev/null +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesRepository.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.model.BookSeries; +import org.springframework.data.repository.CrudRepository; + +public interface BookSeriesRepository extends CrudRepository { +} From 2144a9fd26201a55c30a5929a2a4ba757170d723 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:39:02 +0530 Subject: [PATCH 72/87] Add repository methods for Book, BookSeriesMapping --- .../booksapi/repository/BookRepository.java | 11 +++++++++++ .../repository/BookSeriesMappingRepository.java | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index 02538887..01857d8d 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -16,6 +16,8 @@ package com.karankumar.booksapi.repository; import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; @@ -32,4 +34,13 @@ public interface BookRepository extends CrudRepository { Book findBookByIsbn13(String isbn13); Book findByTitleIgnoreCase(String title); + + // Lists all BookSeries for a Book entry + @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") + List getAllBookSeriesForBook(Book book); + + // Returns position of a book in a Book Series + @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") + Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); + } diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java index c421f8ea..1d5bcebd 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -15,8 +15,17 @@ package com.karankumar.booksapi.repository; +import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; +import java.util.List; + public interface BookSeriesMappingRepository extends CrudRepository { + + // Lists all Books in a Book Series + @Query("SELECT a.book FROM BookSeriesMapping a WHERE a.bookSeries = ?1") + List getAllBooksByBookSeries(BookSeries bookSeries); } From d3debb2d4946d0a11b6d9705e28c898122eb6ff8 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:41:14 +0530 Subject: [PATCH 73/87] Add test classes for BookSeries & BookSeriesMapping repository --- .../BookSeriesMappingRepositoryTest.java | 101 ++++++++++++++++++ .../repository/BookSeriesRepositoryTest.java | 26 +++++ 2 files changed, 127 insertions(+) create mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java create mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java new file mode 100644 index 00000000..a685399b --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -0,0 +1,101 @@ +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; +import com.karankumar.booksapi.model.Author; +import com.karankumar.booksapi.model.Book; +import com.karankumar.booksapi.model.BookFormat; +import com.karankumar.booksapi.model.BookGenre; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; +import com.karankumar.booksapi.model.Language; +import com.karankumar.booksapi.model.Publisher; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaIntegrationTest +@DisplayName("BookSeriesMappingRepository should") +public class BookSeriesMappingRepositoryTest { + + private final BookRepository bookRepository; + private final AuthorRepository authorRepository; + private final BookSeriesRepository bookSeriesRepository; + private final BookSeriesMappingRepository bookSeriesMappingRepository; + + @Autowired + BookSeriesMappingRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository){ + + this.bookRepository = bookRepository; + this.authorRepository = authorRepository; + this.bookSeriesRepository = bookSeriesRepository; + this.bookSeriesMappingRepository = bookSeriesMappingRepository; + } + + @BeforeEach + void setUp() { + bookSeriesMappingRepository.deleteAll(); + authorRepository.deleteAll(); + bookRepository.deleteAll(); + bookSeriesRepository.deleteAll(); + } + + @Test + @DisplayName("return all books in a series.") + void fetchAllBooksInBookSeries(){ + + BookSeries bs = createBookSeriesMapping(); + List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); + + List bookList = new ArrayList<>(); + bookList.add(bookRepository.findBookByIsbn13("9781408810545")); + bookList.add(bookRepository.findBookByIsbn13("1234567898765")); + + assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); + } + + private BookSeries createBookSeriesMapping(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + authorRepository.save(author); + + Book book1 = new Book( + "Harry Potter and the Philosopher's stone", new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + book1.setYearOfPublication(1997); + book1.setIsbn13("9781408810545"); + book1.setPublishedBy(Publisher.BLOOMSBURY); + bookRepository.save(book1); + + Book book2 = new Book( + "Harry Potter and the Chamber of Secrets", + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book2.setIsbn13("1234567898765"); + book2.setGenre(BookGenre.FANTASY); + book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setFormat(BookFormat.PAPERBACK); + bookRepository.save(book2); + + BookSeries bookSeries = new BookSeries("Harry Potter Series"); + bookSeriesRepository.save(bookSeries); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries, book2, 2)); + + return bookSeries; + } +} diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java new file mode 100644 index 00000000..cd0403fe --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DataJpaIntegrationTest +@DisplayName("BookSeries Repository should") +public class BookSeriesRepositoryTest { + +} From 2bfae375c8fc55ab048c5b05f21dbf88c7b6d90b Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:47:12 +0530 Subject: [PATCH 74/87] Rebase onto main --- .../repository/BookRepositoryTest.java | 103 +++++++++++++++++- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index 79ee3fae..83fe76cd 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Karan Kumar + * Copyright (C) 2020 Karan Kumar * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of the @@ -20,13 +20,17 @@ import com.karankumar.booksapi.model.Book; import com.karankumar.booksapi.model.BookFormat; import com.karankumar.booksapi.model.BookGenre; +import com.karankumar.booksapi.model.BookSeries; +import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; +import com.karankumar.booksapi.model.Publisher; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static com.karankumar.booksapi.repository.RepositoryTestUtils.createBook; @@ -38,19 +42,27 @@ class BookRepositoryTest { private static final String ISBN = "978-3-16-148410-0"; private static final String TITLE = "Harry Potter"; + private static final String AUTHOR1_FULL_NAME = "Kevlin Henney"; private final BookRepository bookRepository; private final AuthorRepository authorRepository; - + private final BookSeriesRepository bookSeriesRepository; + private final BookSeriesMappingRepository bookSeriesMappingRepository; + @Autowired - BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository) { + BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; + this.bookSeriesRepository = bookSeriesRepository; + this.bookSeriesMappingRepository = bookSeriesMappingRepository; } @BeforeEach void setUp() { + bookSeriesMappingRepository.deleteAll(); authorRepository.deleteAll(); bookRepository.deleteAll(); + bookSeriesRepository.deleteAll(); } @Test @@ -155,4 +167,87 @@ void findBookByTitleCaseInsensitive() { // then assertThat(result).isEqualTo(book); } + + private void saveAllAuthors(Author... authors) { + Arrays.stream(authors).forEach(authorRepository::save); + } + + @Test + @DisplayName("find all Book Series for a Book") + void findBookSeriesForBook(){ + List assertion = addBookToSeries(); + Book book = bookRepository.findBookByIsbn13("9781408810545"); + + List result = bookRepository.getAllBookSeriesForBook(book); + + assertThat(result).containsExactlyInAnyOrderElementsOf(assertion); + } + + @Test + @DisplayName("find book position in Book Series") + void findBookPositionInSeries(){ + + // Get book and book series from repo + List allSeries = addBookToSeries(); + Book book = bookRepository.findBookByIsbn13("9781408810545"); + BookSeries assertion = null; + for (BookSeries series : allSeries) { + if(series.getSeriesName().equals("Harry Potter Series")){ + assertion = series; + break; + } + } + + assertThat(bookRepository.getBookPositionInBookSeries(book, assertion)).isEqualTo(1); + } + + // Utility method + private List addBookToSeries(){ + + Author author = new Author("J.K.", "Rowling"); + author.setAbout("A fantastic author"); + authorRepository.save(author); + + Book book1 = new Book( + "Harry Potter and the Philosopher's stone", new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + book1.setYearOfPublication(1997); + book1.setIsbn13("9781408810545"); + book1.setPublishedBy(Publisher.BLOOMSBURY); + bookRepository.save(book1); + + Book book2 = new Book( + "Harry Potter and the Chamber of Secrets", + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); + book2.setIsbn13("1234567898765"); + book2.setGenre(BookGenre.FANTASY); + book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setFormat(BookFormat.PAPERBACK); + bookRepository.save(book2); + + BookSeries bookSeries1 = new BookSeries("Harry Potter Series"); + bookSeriesRepository.save(bookSeries1); + + BookSeries bookSeries2 = new BookSeries("J.K. Rowling Specials"); + bookSeriesRepository.save(bookSeries2); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries1, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries1, book2, 2)); + + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book1, 1)); + bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book2, 2)); + + List bs = new ArrayList<>(); + bs.add(bookSeries1); + bs.add(bookSeries2); + + return bs; + } } From 69e65ff78bff8be95657dd90ccb7d0fea1ea9bd3 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 18:01:24 +0530 Subject: [PATCH 75/87] Fix test issues due to merge --- .../booksapi/model/BookSeriesMappingTest.java | 10 +++++----- .../booksapi/repository/BookRepositoryTest.java | 8 ++++---- .../repository/BookSeriesMappingRepositoryTest.java | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java index ce740261..1c569db9 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -29,7 +29,7 @@ void notAcceptNullSerialNumber(){ BookSeries bookSeries = new BookSeries("Harry Potter Series"); - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); Book book = new Book( @@ -42,7 +42,7 @@ void notAcceptNullSerialNumber(){ ); book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); - book.setPublishedBy(Publisher.BLOOMSBURY); + book.setPublisher(PublisherName.BLOOMSBURY); assertThatExceptionOfType(NullPointerException.class) .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); @@ -54,7 +54,7 @@ void notAcceptNullBook(){ BookSeries bookSeries = new BookSeries("Harry Potter Series"); - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); assertThatExceptionOfType(NullPointerException.class) @@ -65,7 +65,7 @@ void notAcceptNullBook(){ @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") void notAcceptNullBookSeries(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); Book book = new Book( @@ -78,7 +78,7 @@ void notAcceptNullBookSeries(){ ); book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); - book.setPublishedBy(Publisher.BLOOMSBURY); + book.setPublisher(PublisherName.BLOOMSBURY); assertThatExceptionOfType(NullPointerException.class) .isThrownBy(()->new BookSeriesMapping(null, book, 1)); diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index 83fe76cd..d9fceb40 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -23,7 +23,7 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.Publisher; +import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -204,7 +204,7 @@ void findBookPositionInSeries(){ // Utility method private List addBookToSeries(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); @@ -215,7 +215,7 @@ private List addBookToSeries(){ ); book1.setYearOfPublication(1997); book1.setIsbn13("9781408810545"); - book1.setPublishedBy(Publisher.BLOOMSBURY); + book1.setPublisher(PublisherName.BLOOMSBURY); bookRepository.save(book1); Book book2 = new Book( @@ -228,7 +228,7 @@ private List addBookToSeries(){ ); book2.setIsbn13("1234567898765"); book2.setGenre(BookGenre.FANTASY); - book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setPublisher(PublisherName.BLOOMSBURY); book2.setFormat(BookFormat.PAPERBACK); bookRepository.save(book2); diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index a685399b..1c66de4c 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -8,7 +8,7 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.Publisher; +import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -62,7 +62,7 @@ void fetchAllBooksInBookSeries(){ private BookSeries createBookSeriesMapping(){ - Author author = new Author("J.K.", "Rowling"); + Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); @@ -73,7 +73,7 @@ private BookSeries createBookSeriesMapping(){ ); book1.setYearOfPublication(1997); book1.setIsbn13("9781408810545"); - book1.setPublishedBy(Publisher.BLOOMSBURY); + book1.setPublisher(PublisherName.BLOOMSBURY); bookRepository.save(book1); Book book2 = new Book( @@ -86,7 +86,7 @@ private BookSeries createBookSeriesMapping(){ ); book2.setIsbn13("1234567898765"); book2.setGenre(BookGenre.FANTASY); - book2.setPublishedBy(Publisher.BLOOMSBURY); + book2.setPublisher(PublisherName.BLOOMSBURY); book2.setFormat(BookFormat.PAPERBACK); bookRepository.save(book2); From 58ae2604d3ccde5ddffe0b86f41e7b00d63f6eb1 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:11:31 +0000 Subject: [PATCH 76/87] Remove wildcard imports & adhere to 100 char limit --- .../karankumar/booksapi/model/BookSeries.java | 28 +++++++++++-------- .../booksapi/model/BookSeriesMapping.java | 19 +++++++++---- .../booksapi/repository/BookRepository.java | 2 -- .../BookSeriesMappingRepository.java | 2 -- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeries.java b/src/main/java/com/karankumar/booksapi/model/BookSeries.java index cefabc80..bd0cea9b 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeries.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeries.java @@ -1,16 +1,17 @@ /* -The book project lets a user keep track of different books they would like to read, are currently reading, have read or did not finish. -Copyright (C) 2020 Karan Kumar + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program. -If not, see . -*/ + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ package com.karankumar.booksapi.model; @@ -20,7 +21,12 @@ License, or (at your option) any later version. import lombok.Setter; import lombok.NonNull; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; import java.util.List; @Entity diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index deda1ede..66e24c29 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -18,17 +18,23 @@ License, or (at your option) any later version. import javax.persistence.*; -@Getter @Setter +@Getter +@Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @Table( name="Book_To_BookSeries_Mapping", uniqueConstraints = { - @UniqueConstraint( name = "UK_bookSeriesId_bookId", columnNames = {"book_series_id","book_id"} ), - @UniqueConstraint( name = "UK_bookSeriesId_serialNumber", columnNames = {"book_series_id","serial_number"} ) + @UniqueConstraint( + name = "UK_bookSeriesId_bookId", + columnNames = {"book_series_id","book_id"} + ), + @UniqueConstraint( + name = "UK_bookSeriesId_serialNumber", + columnNames = {"book_series_id","serial_number"} + ) } ) - public class BookSeriesMapping { @Id @@ -42,10 +48,11 @@ public class BookSeriesMapping { @ManyToOne(optional = false) private Book book; - @Column(nullable = false, name="serial_number") + @Column(nullable = false, name = "serial_number") private Integer serialNumber; - public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, @NonNull Integer serialNumber) { + public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, + @NonNull Integer serialNumber) { this.bookSeries = bookSeries; this.book = bookInSeries; this.serialNumber = serialNumber; diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index 01857d8d..a636f315 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -35,11 +35,9 @@ public interface BookRepository extends CrudRepository { Book findByTitleIgnoreCase(String title); - // Lists all BookSeries for a Book entry @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") List getAllBookSeriesForBook(Book book); - // Returns position of a book in a Book Series @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); diff --git a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java index 1d5bcebd..35766441 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookSeriesMappingRepository.java @@ -24,8 +24,6 @@ import java.util.List; public interface BookSeriesMappingRepository extends CrudRepository { - - // Lists all Books in a Book Series @Query("SELECT a.book FROM BookSeriesMapping a WHERE a.bookSeries = ?1") List getAllBooksByBookSeries(BookSeries bookSeries); } From db84fa05f681ebc5aa928e66fd6710eed1c1a8da Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:17:57 +0000 Subject: [PATCH 77/87] Extract create book code to method --- .../java/com/karankumar/booksapi/model/BookSeriesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java index 67acdedb..f3f21af9 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesTest.java @@ -22,12 +22,12 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @DisplayName("Book series should") -public class BookSeriesTest { +class BookSeriesTest { @Test @DisplayName("throw a null pointer exception on an attempt to create with a null Series Name.") void notAcceptNullSeriesName(){ assertThatExceptionOfType(NullPointerException.class) - .isThrownBy( ()->new BookSeries(null) ); + .isThrownBy(() -> new BookSeries(null)); } } From be0ee0b386bdad9cf690f3a8c549dd3e41b67719 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:18:55 +0000 Subject: [PATCH 78/87] Extract create book code to method --- .../booksapi/model/BookSeriesMappingTest.java | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java index 1c569db9..c00a50ec 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -21,20 +21,22 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @DisplayName("Book Series Mapping should") -public class BookSeriesMappingTest { +class BookSeriesMappingTest { @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Serial Number") - void notAcceptNullSerialNumber(){ - + void notAcceptNullSerialNumber() { BookSeries bookSeries = new BookSeries("Harry Potter Series"); + Book book = createBook(); - Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> new BookSeriesMapping(bookSeries, book, null)); + } + private Book createBook() { Book book = new Book( "Harry Potter and the Philosopher's stone", - new Author[] {author}, + new Author[] {new Author("J.K. Rowling")}, Language.ENGLISH, "Sample blurb value", BookGenre.FANTASY, @@ -43,14 +45,12 @@ void notAcceptNullSerialNumber(){ book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); book.setPublisher(PublisherName.BLOOMSBURY); - - assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(bookSeries, book, null)); + return book; } @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book") - void notAcceptNullBook(){ + void notAcceptNullBook() { BookSeries bookSeries = new BookSeries("Harry Potter Series"); @@ -58,29 +58,15 @@ void notAcceptNullBook(){ author.setAbout("A fantastic author"); assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(bookSeries, null, 1)); + .isThrownBy(() -> new BookSeriesMapping(bookSeries, null, 1)); } @Test @DisplayName("throw a Null Pointer Exception on an attempt to create with Null Book Series.") - void notAcceptNullBookSeries(){ - - Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); - - Book book = new Book( - "Harry Potter and the Philosopher's stone", - new Author[] {author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book.setYearOfPublication(1997); - book.setIsbn13("9781408810545"); - book.setPublisher(PublisherName.BLOOMSBURY); + void notAcceptNullBookSeries() { + Book book = createBook(); assertThatExceptionOfType(NullPointerException.class) - .isThrownBy(()->new BookSeriesMapping(null, book, 1)); + .isThrownBy(() -> new BookSeriesMapping(null, book, 1)); } } From 6bd042c45d06c1c615ecd8ab7905fcbe9732d5f1 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:21:24 +0000 Subject: [PATCH 79/87] Add missing copyright notice --- .../BookSeriesMappingRepositoryTest.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index 1c66de4c..7a85342d 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + package com.karankumar.booksapi.repository; import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; @@ -21,7 +36,7 @@ @DataJpaIntegrationTest @DisplayName("BookSeriesMappingRepository should") -public class BookSeriesMappingRepositoryTest { +class BookSeriesMappingRepositoryTest { private final BookRepository bookRepository; private final AuthorRepository authorRepository; @@ -29,8 +44,10 @@ public class BookSeriesMappingRepositoryTest { private final BookSeriesMappingRepository bookSeriesMappingRepository; @Autowired - BookSeriesMappingRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, - BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository){ + BookSeriesMappingRepositoryTest(BookRepository bookRepository, + AuthorRepository authorRepository, + BookSeriesRepository bookSeriesRepository, + BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; @@ -48,8 +65,7 @@ void setUp() { @Test @DisplayName("return all books in a series.") - void fetchAllBooksInBookSeries(){ - + void fetchAllBooksInBookSeries() { BookSeries bs = createBookSeriesMapping(); List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); @@ -60,7 +76,7 @@ void fetchAllBooksInBookSeries(){ assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); } - private BookSeries createBookSeriesMapping(){ + private BookSeries createBookSeriesMapping() { Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); From de6a3a7de9cda239eaffc0e02c7c0656fbd3c176 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:26:44 +0000 Subject: [PATCH 80/87] Extract create book code to method --- .../BookSeriesMappingRepositoryTest.java | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index 7a85342d..c68f0538 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -77,33 +77,14 @@ void fetchAllBooksInBookSeries() { } private BookSeries createBookSeriesMapping() { - Author author = new Author("J.K. Rowling"); author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = new Book( - "Harry Potter and the Philosopher's stone", new Author[]{author}, - Language.ENGLISH, "Sample blurb value", - BookGenre.FANTASY, BookFormat.PAPERBACK - ); - book1.setYearOfPublication(1997); - book1.setIsbn13("9781408810545"); - book1.setPublisher(PublisherName.BLOOMSBURY); + Book book1 = createBook(author, "Harry Potter and the Philosopher's stone"); bookRepository.save(book1); - Book book2 = new Book( - "Harry Potter and the Chamber of Secrets", - new Author[]{author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book2.setIsbn13("1234567898765"); - book2.setGenre(BookGenre.FANTASY); - book2.setPublisher(PublisherName.BLOOMSBURY); - book2.setFormat(BookFormat.PAPERBACK); + Book book2 = createBook(author, "Harry Potter and the Chamber of Secrets"); bookRepository.save(book2); BookSeries bookSeries = new BookSeries("Harry Potter Series"); @@ -114,4 +95,12 @@ private BookSeries createBookSeriesMapping() { return bookSeries; } + + private Book createBook(Author author, String title) { + return new Book( + title, new Author[]{author}, + Language.ENGLISH, "Sample blurb value", + BookGenre.FANTASY, BookFormat.PAPERBACK + ); + } } From 530fe66eaad9b8a0df410d5406f0f09bbfacf025 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:33:52 +0000 Subject: [PATCH 81/87] Find by title --- .../repository/BookSeriesMappingRepositoryTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index c68f0538..ef1d6234 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -37,11 +37,12 @@ @DataJpaIntegrationTest @DisplayName("BookSeriesMappingRepository should") class BookSeriesMappingRepositoryTest { - private final BookRepository bookRepository; private final AuthorRepository authorRepository; private final BookSeriesRepository bookSeriesRepository; private final BookSeriesMappingRepository bookSeriesMappingRepository; + private final String book1Title = "Harry Potter and the Philosopher's stone"; + private final String book2Title = "Harry Potter and the Chamber of Secrets"; @Autowired BookSeriesMappingRepositoryTest(BookRepository bookRepository, @@ -70,21 +71,20 @@ void fetchAllBooksInBookSeries() { List assertion = bookSeriesMappingRepository.getAllBooksByBookSeries(bs); List bookList = new ArrayList<>(); - bookList.add(bookRepository.findBookByIsbn13("9781408810545")); - bookList.add(bookRepository.findBookByIsbn13("1234567898765")); + bookList.add(bookRepository.findByTitleIgnoreCase(book1Title)); + bookList.add(bookRepository.findByTitleIgnoreCase(book2Title)); assertThat(assertion).hasSize(bookList.size()).hasSameElementsAs(bookList); } private BookSeries createBookSeriesMapping() { Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = createBook(author, "Harry Potter and the Philosopher's stone"); + Book book1 = createBook(author, book1Title); bookRepository.save(book1); - Book book2 = createBook(author, "Harry Potter and the Chamber of Secrets"); + Book book2 = createBook(author, book2Title); bookRepository.save(book2); BookSeries bookSeries = new BookSeries("Harry Potter Series"); From afad6898c47b4c16d694dd03d024c08f6953c7b1 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 25 Mar 2021 14:50:24 +0000 Subject: [PATCH 82/87] Extract duplicate code to method --- .../repository/BookRepositoryTest.java | 63 ++++++++----------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index d9fceb40..43b858ef 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -23,13 +23,11 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -48,10 +46,16 @@ class BookRepositoryTest { private final AuthorRepository authorRepository; private final BookSeriesRepository bookSeriesRepository; private final BookSeriesMappingRepository bookSeriesMappingRepository; + private final String harryPotter1Title = "Harry Potter and the Philosopher's stone"; + private final String harryPotterSeriesName = "Harry Potter Series"; + + private Author author1; + private Author author2; @Autowired BookRepositoryTest(BookRepository bookRepository, AuthorRepository authorRepository, - BookSeriesRepository bookSeriesRepository, BookSeriesMappingRepository bookSeriesMappingRepository) { + BookSeriesRepository bookSeriesRepository, + BookSeriesMappingRepository bookSeriesMappingRepository) { this.bookRepository = bookRepository; this.authorRepository = authorRepository; this.bookSeriesRepository = bookSeriesRepository; @@ -176,7 +180,7 @@ private void saveAllAuthors(Author... authors) { @DisplayName("find all Book Series for a Book") void findBookSeriesForBook(){ List assertion = addBookToSeries(); - Book book = bookRepository.findBookByIsbn13("9781408810545"); + Book book = bookRepository.findByTitleIgnoreCase(harryPotter1Title); List result = bookRepository.getAllBookSeriesForBook(book); @@ -185,14 +189,13 @@ void findBookSeriesForBook(){ @Test @DisplayName("find book position in Book Series") - void findBookPositionInSeries(){ - + void findBookPositionInSeries() { // Get book and book series from repo List allSeries = addBookToSeries(); - Book book = bookRepository.findBookByIsbn13("9781408810545"); + Book book = bookRepository.findByTitleIgnoreCase(harryPotter1Title); BookSeries assertion = null; for (BookSeries series : allSeries) { - if(series.getSeriesName().equals("Harry Potter Series")){ + if (series.getSeriesName().equals(harryPotterSeriesName)) { assertion = series; break; } @@ -201,38 +204,17 @@ void findBookPositionInSeries(){ assertThat(bookRepository.getBookPositionInBookSeries(book, assertion)).isEqualTo(1); } - // Utility method - private List addBookToSeries(){ - + private List addBookToSeries() { Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); authorRepository.save(author); - Book book1 = new Book( - "Harry Potter and the Philosopher's stone", new Author[]{author}, - Language.ENGLISH, "Sample blurb value", - BookGenre.FANTASY, BookFormat.PAPERBACK - ); - book1.setYearOfPublication(1997); - book1.setIsbn13("9781408810545"); - book1.setPublisher(PublisherName.BLOOMSBURY); + Book book1 = createSeriesBook(author, harryPotter1Title); bookRepository.save(book1); - Book book2 = new Book( - "Harry Potter and the Chamber of Secrets", - new Author[]{author}, - Language.ENGLISH, - "Sample blurb value", - BookGenre.FANTASY, - BookFormat.PAPERBACK - ); - book2.setIsbn13("1234567898765"); - book2.setGenre(BookGenre.FANTASY); - book2.setPublisher(PublisherName.BLOOMSBURY); - book2.setFormat(BookFormat.PAPERBACK); + Book book2 = createSeriesBook(author, "Harry Potter and the Chamber of Secrets"); bookRepository.save(book2); - BookSeries bookSeries1 = new BookSeries("Harry Potter Series"); + BookSeries bookSeries1 = new BookSeries(harryPotterSeriesName); bookSeriesRepository.save(bookSeries1); BookSeries bookSeries2 = new BookSeries("J.K. Rowling Specials"); @@ -244,10 +226,17 @@ private List addBookToSeries(){ bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book1, 1)); bookSeriesMappingRepository.save(new BookSeriesMapping(bookSeries2, book2, 2)); - List bs = new ArrayList<>(); - bs.add(bookSeries1); - bs.add(bookSeries2); + return List.of(bookSeries1, bookSeries2); + } - return bs; + private Book createSeriesBook(Author author, String title) { + return new Book( + title, + new Author[]{author}, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK + ); } } From 22a5c120c3912fd5549d927ed995e0c1ca161fbb Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sat, 27 Mar 2021 23:33:44 +0530 Subject: [PATCH 83/87] Resolve for PR-81 comments --- .../booksapi/model/BookSeriesMapping.java | 6 ++--- .../booksapi/repository/BookRepository.java | 2 +- .../repository/BookSeriesRepositoryTest.java | 26 ------------------- 3 files changed, 4 insertions(+), 30 deletions(-) delete mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java diff --git a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java index 66e24c29..0f519f85 100644 --- a/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java +++ b/src/main/java/com/karankumar/booksapi/model/BookSeriesMapping.java @@ -49,12 +49,12 @@ public class BookSeriesMapping { private Book book; @Column(nullable = false, name = "serial_number") - private Integer serialNumber; + private Integer seriesPosition; public BookSeriesMapping(@NonNull BookSeries bookSeries, @NonNull Book bookInSeries, - @NonNull Integer serialNumber) { + @NonNull Integer seriesPosition) { this.bookSeries = bookSeries; this.book = bookInSeries; - this.serialNumber = serialNumber; + this.seriesPosition = seriesPosition; } } diff --git a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java index a636f315..1530c5be 100644 --- a/src/main/java/com/karankumar/booksapi/repository/BookRepository.java +++ b/src/main/java/com/karankumar/booksapi/repository/BookRepository.java @@ -38,7 +38,7 @@ public interface BookRepository extends CrudRepository { @Query("SELECT a.bookSeries FROM BookSeriesMapping a WHERE a.book = ?1") List getAllBookSeriesForBook(Book book); - @Query("SELECT a.serialNumber FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") + @Query("SELECT a.seriesPosition FROM BookSeriesMapping a WHERE a.book = ?1 AND a.bookSeries = ?2") Integer getBookPositionInBookSeries(Book book, BookSeries bookSeries); } diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java deleted file mode 100644 index cd0403fe..00000000 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 Karan Kumar - * - * This program is free software: you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along with this program. - * If not, see . - */ - -package com.karankumar.booksapi.repository; - -import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -@DataJpaIntegrationTest -@DisplayName("BookSeries Repository should") -public class BookSeriesRepositoryTest { - -} From 269574346454a64d6604bda16b11329010b91ed3 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Mon, 29 Mar 2021 12:07:15 +0530 Subject: [PATCH 84/87] Add DDL for Flyway migration. --- .../V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql | 15 +++++++++++++++ .../db/migration/V009_CREATE_BOOKSERIES.sql | 8 ++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql create mode 100644 src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql diff --git a/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql b/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql new file mode 100644 index 00000000..fb8a36d2 --- /dev/null +++ b/src/main/resources/db/migration/V0010_CREATE_BOOK_TO_BOOK_SERIES_MAPPING.sql @@ -0,0 +1,15 @@ +CREATE TABLE `book_to_book_series_mapping` +( + `id` bigint NOT NULL AUTO_INCREMENT, + `serial_number` int NOT NULL, + `book_id` bigint NOT NULL, + `book_series_id` bigint NOT NULL, + + PRIMARY KEY (`id`), + + UNIQUE KEY `UK_bookSeriesId_bookId` (`book_series_id`,`book_id`), + UNIQUE KEY `UK_bookSeriesId_serialNumber` (`book_series_id`,`serial_number`), + CONSTRAINT `FK_book_id` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`), + CONSTRAINT `FK_book_series_id` FOREIGN KEY (`book_series_id`) REFERENCES `book_series` (`id`) + +) ENGINE=InnoDB \ No newline at end of file diff --git a/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql b/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql new file mode 100644 index 00000000..2c887b28 --- /dev/null +++ b/src/main/resources/db/migration/V009_CREATE_BOOKSERIES.sql @@ -0,0 +1,8 @@ +CREATE TABLE `book_series` +( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `series_name` varchar(255) NOT NULL, + + PRIMARY KEY (`id`) + +) ENGINE=InnoDB \ No newline at end of file From 98208245c79931ac4cc6ad0c0c0e4f71cc4ea68d Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Wed, 14 Apr 2021 13:01:10 +0530 Subject: [PATCH 85/87] Update tests to new model --- .../booksapi/model/BookSeriesMappingTest.java | 5 ----- .../repository/BookRepositoryTest.java | 10 ++++------ .../BookSeriesMappingRepositoryTest.java | 18 ++++++++---------- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java index c00a50ec..f63aa466 100644 --- a/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java +++ b/src/test/java/com/karankumar/booksapi/model/BookSeriesMappingTest.java @@ -36,7 +36,6 @@ void notAcceptNullSerialNumber() { private Book createBook() { Book book = new Book( "Harry Potter and the Philosopher's stone", - new Author[] {new Author("J.K. Rowling")}, Language.ENGLISH, "Sample blurb value", BookGenre.FANTASY, @@ -44,7 +43,6 @@ private Book createBook() { ); book.setYearOfPublication(1997); book.setIsbn13("9781408810545"); - book.setPublisher(PublisherName.BLOOMSBURY); return book; } @@ -54,9 +52,6 @@ void notAcceptNullBook() { BookSeries bookSeries = new BookSeries("Harry Potter Series"); - Author author = new Author("J.K. Rowling"); - author.setAbout("A fantastic author"); - assertThatExceptionOfType(NullPointerException.class) .isThrownBy(() -> new BookSeriesMapping(bookSeries, null, 1)); } diff --git a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java index 43b858ef..f102bb5b 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookRepositoryTest.java @@ -23,6 +23,7 @@ import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; +import java.util.HashSet; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -205,13 +206,11 @@ void findBookPositionInSeries() { } private List addBookToSeries() { - Author author = new Author("J.K. Rowling"); - authorRepository.save(author); - Book book1 = createSeriesBook(author, harryPotter1Title); + Book book1 = createSeriesBook(harryPotter1Title); bookRepository.save(book1); - Book book2 = createSeriesBook(author, "Harry Potter and the Chamber of Secrets"); + Book book2 = createSeriesBook("Harry Potter and the Chamber of Secrets"); bookRepository.save(book2); BookSeries bookSeries1 = new BookSeries(harryPotterSeriesName); @@ -229,10 +228,9 @@ private List addBookToSeries() { return List.of(bookSeries1, bookSeries2); } - private Book createSeriesBook(Author author, String title) { + private Book createSeriesBook(String title) { return new Book( title, - new Author[]{author}, Language.ENGLISH, "Sample blurb value", BookGenre.FANTASY, diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java index ef1d6234..75fc1675 100644 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesMappingRepositoryTest.java @@ -16,14 +16,12 @@ package com.karankumar.booksapi.repository; import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; -import com.karankumar.booksapi.model.Author; import com.karankumar.booksapi.model.Book; import com.karankumar.booksapi.model.BookFormat; import com.karankumar.booksapi.model.BookGenre; import com.karankumar.booksapi.model.BookSeries; import com.karankumar.booksapi.model.BookSeriesMapping; import com.karankumar.booksapi.model.Language; -import com.karankumar.booksapi.model.PublisherName; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -78,13 +76,11 @@ void fetchAllBooksInBookSeries() { } private BookSeries createBookSeriesMapping() { - Author author = new Author("J.K. Rowling"); - authorRepository.save(author); - Book book1 = createBook(author, book1Title); + Book book1 = createBook(book1Title); bookRepository.save(book1); - Book book2 = createBook(author, book2Title); + Book book2 = createBook(book2Title); bookRepository.save(book2); BookSeries bookSeries = new BookSeries("Harry Potter Series"); @@ -96,11 +92,13 @@ private BookSeries createBookSeriesMapping() { return bookSeries; } - private Book createBook(Author author, String title) { + private Book createBook(String title) { return new Book( - title, new Author[]{author}, - Language.ENGLISH, "Sample blurb value", - BookGenre.FANTASY, BookFormat.PAPERBACK + title, + Language.ENGLISH, + "Sample blurb value", + BookGenre.FANTASY, + BookFormat.PAPERBACK ); } } From cd3c9da8e939c81c86bd616d3520024170fd9091 Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sun, 21 Mar 2021 15:41:14 +0530 Subject: [PATCH 86/87] rebase from main (upstream) --- .../repository/BookSeriesRepositoryTest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java new file mode 100644 index 00000000..cd0403fe --- /dev/null +++ b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Karan Kumar + * + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +package com.karankumar.booksapi.repository; + +import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DataJpaIntegrationTest +@DisplayName("BookSeries Repository should") +public class BookSeriesRepositoryTest { + +} From 166ec56375adcae8250bdbe07d2026b3a9c112ac Mon Sep 17 00:00:00 2001 From: Vivek Kaul Date: Sat, 27 Mar 2021 23:33:44 +0530 Subject: [PATCH 87/87] Resolve for PR-81 comments --- .../repository/BookSeriesRepositoryTest.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java diff --git a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java b/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java deleted file mode 100644 index cd0403fe..00000000 --- a/src/test/java/com/karankumar/booksapi/repository/BookSeriesRepositoryTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 Karan Kumar - * - * This program is free software: you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along with this program. - * If not, see . - */ - -package com.karankumar.booksapi.repository; - -import com.karankumar.booksapi.annotations.DataJpaIntegrationTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -@DataJpaIntegrationTest -@DisplayName("BookSeries Repository should") -public class BookSeriesRepositoryTest { - -}