From a188cf9598c3551498f002efe299eb72c8a21c03 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 22 Aug 2019 08:09:49 +0800 Subject: [PATCH] moved natural sorting directly in Serie (for books) and BookMetadata (for pages) --- .../gotson/komga/domain/model/BookMetadata.kt | 20 ++++++-- .../org/gotson/komga/domain/model/Serie.kt | 10 +++- .../gotson/komga/domain/service/BookParser.kt | 2 +- .../archive/ArchiveExtractor.kt | 4 -- .../infrastructure/archive/RarExtractor.kt | 3 -- .../infrastructure/archive/ZipExtractor.kt | 3 -- .../komga/interfaces/web/SerieController.kt | 10 +--- .../V20190819161603__First_Version.sql | 4 +- .../domain/persistence/PersistenceTest.kt | 48 +++++++++++++++++++ 9 files changed, 77 insertions(+), 27 deletions(-) diff --git a/komga/src/main/kotlin/org/gotson/komga/domain/model/BookMetadata.kt b/komga/src/main/kotlin/org/gotson/komga/domain/model/BookMetadata.kt index 6679dbb83..81961367c 100644 --- a/komga/src/main/kotlin/org/gotson/komga/domain/model/BookMetadata.kt +++ b/komga/src/main/kotlin/org/gotson/komga/domain/model/BookMetadata.kt @@ -1,5 +1,7 @@ package org.gotson.komga.domain.model +import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator +import java.util.* import javax.persistence.CollectionTable import javax.persistence.Column import javax.persistence.ElementCollection @@ -12,8 +14,11 @@ import javax.persistence.Id import javax.persistence.JoinColumn import javax.persistence.Lob import javax.persistence.OneToOne +import javax.persistence.OrderColumn import javax.persistence.Table +private val natSortComparator: Comparator = CaseInsensitiveSimpleNaturalComparator.getInstance() + @Entity @Table(name = "book_metadata") class BookMetadata( @@ -40,21 +45,26 @@ class BookMetadata( @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "book_metadata_page", joinColumns = [JoinColumn(name = "book_metadata_id")]) - var pages: MutableList = mutableListOf() + @OrderColumn(name = "number") + private var _pages: MutableList = mutableListOf() + + var pages: List + get() = _pages.toList() set(value) { - pages.clear() - pages.addAll(value) + _pages.clear() + _pages.addAll(value.sortedWith(compareBy(natSortComparator) { it.fileName })) } + fun reset() { status = Status.UNKNOWN mediaType = null thumbnail = null - pages.clear() + _pages.clear() } init { - this.pages = pages.toMutableList() + this.pages = pages.toList() } } diff --git a/komga/src/main/kotlin/org/gotson/komga/domain/model/Serie.kt b/komga/src/main/kotlin/org/gotson/komga/domain/model/Serie.kt index dd5b439eb..374371ce9 100644 --- a/komga/src/main/kotlin/org/gotson/komga/domain/model/Serie.kt +++ b/komga/src/main/kotlin/org/gotson/komga/domain/model/Serie.kt @@ -1,7 +1,9 @@ package org.gotson.komga.domain.model +import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator import java.net.URL import java.time.LocalDateTime +import java.util.* import javax.persistence.CascadeType import javax.persistence.Column import javax.persistence.Entity @@ -9,9 +11,12 @@ import javax.persistence.FetchType import javax.persistence.GeneratedValue import javax.persistence.Id import javax.persistence.OneToMany +import javax.persistence.OrderColumn import javax.persistence.Table import javax.validation.constraints.NotBlank +private val natSortComparator: Comparator = CaseInsensitiveSimpleNaturalComparator.getInstance() + @Entity @Table(name = "serie") class Serie( @@ -34,6 +39,7 @@ class Serie( var id: Long = 0 @OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "serie") + @OrderColumn(name = "index") private var _books: MutableList = mutableListOf() var books: List @@ -41,10 +47,10 @@ class Serie( set(value) { _books.clear() value.forEach { it.serie = this } - _books.addAll(value) + _books.addAll(value.sortedWith(compareBy(natSortComparator) { it.name })) } init { - this.books = books.toMutableList() + this.books = books.toList() } } \ No newline at end of file diff --git a/komga/src/main/kotlin/org/gotson/komga/domain/service/BookParser.kt b/komga/src/main/kotlin/org/gotson/komga/domain/service/BookParser.kt index af8a9ce97..5809fffac 100644 --- a/komga/src/main/kotlin/org/gotson/komga/domain/service/BookParser.kt +++ b/komga/src/main/kotlin/org/gotson/komga/domain/service/BookParser.kt @@ -56,7 +56,7 @@ class BookParser( null } - return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pages.toMutableList(), thumbnail = thumbnail) + return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pages, thumbnail = thumbnail) } fun getPageContent(book: Book, number: Int): ByteArray { diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/ArchiveExtractor.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/ArchiveExtractor.kt index 9971631b6..56f724db2 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/ArchiveExtractor.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/ArchiveExtractor.kt @@ -1,13 +1,9 @@ package org.gotson.komga.infrastructure.archive -import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator import org.gotson.komga.domain.model.BookPage import java.nio.file.Path -import java.util.* abstract class ArchiveExtractor { - protected val natSortComparator: Comparator = CaseInsensitiveSimpleNaturalComparator.getInstance() - abstract fun getPagesList(path: Path): List abstract fun getPageStream(path: Path, entryName: String): ByteArray } \ No newline at end of file diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/RarExtractor.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/RarExtractor.kt index d885f0abd..986d83323 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/RarExtractor.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/RarExtractor.kt @@ -22,9 +22,6 @@ class RarExtractor( ) } .filter { contentDetector.isImage(it.mediaType) } - .sortedWith( - compareBy(natSortComparator) { it.fileName } - ) } override fun getPageStream(path: Path, entryName: String): ByteArray = diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/ZipExtractor.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/ZipExtractor.kt index 9407b24ae..5d7add7f2 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/ZipExtractor.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/archive/ZipExtractor.kt @@ -21,9 +21,6 @@ class ZipExtractor( ) } .filter { contentDetector.isImage(it.mediaType) } - .sortedWith( - compareBy(natSortComparator) { it.fileName } - ) } override fun getPageStream(path: Path, entryName: String): ByteArray = diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/web/SerieController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/web/SerieController.kt index 3993e5374..db957f0cb 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/web/SerieController.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/web/SerieController.kt @@ -90,16 +90,10 @@ class SerieController( page: Pageable ): Page { if (!serieRepository.existsById(id)) throw ResponseStatusException(HttpStatus.NOT_FOUND) - val pageRequest = PageRequest.of( - page.pageNumber, - page.pageSize, - if (page.sort.isSorted) page.sort - else Sort.by(Sort.Order.asc("name").ignoreCase()) - ) return if (readyFilter) { - bookRepository.findAllByMetadataStatusAndSerieId(Status.READY, id, pageRequest) + bookRepository.findAllByMetadataStatusAndSerieId(Status.READY, id, page) } else { - bookRepository.findAllBySerieId(id, pageRequest) + bookRepository.findAllBySerieId(id, page) }.map { it.toDto() } } diff --git a/komga/src/main/resources/db/migration/V20190819161603__First_Version.sql b/komga/src/main/resources/db/migration/V20190819161603__First_Version.sql index 16f94ba6f..3ac6ea5fc 100644 --- a/komga/src/main/resources/db/migration/V20190819161603__First_Version.sql +++ b/komga/src/main/resources/db/migration/V20190819161603__First_Version.sql @@ -10,6 +10,7 @@ create table book url varchar not null, book_metadata_id bigint not null, serie_id bigint not null, + index integer, primary key (id) ); @@ -26,7 +27,8 @@ create table book_metadata_page ( book_metadata_id bigint not null, file_name varchar not null, - media_type varchar not null + media_type varchar not null, + number integer ); create table serie diff --git a/komga/src/test/kotlin/org/gotson/komga/domain/persistence/PersistenceTest.kt b/komga/src/test/kotlin/org/gotson/komga/domain/persistence/PersistenceTest.kt index 3280d707b..89cf4408e 100644 --- a/komga/src/test/kotlin/org/gotson/komga/domain/persistence/PersistenceTest.kt +++ b/komga/src/test/kotlin/org/gotson/komga/domain/persistence/PersistenceTest.kt @@ -44,6 +44,26 @@ class PersistenceTest( assertThat(bookMetadataRepository.count()).isEqualTo(1) } + @Test + fun `given serie with unordered books when saving then books are ordered with natural sort`() { + // given + val serie = makeSerie(name = "serie", books = listOf( + makeBook("book 1"), + makeBook("book 05"), + makeBook("book 6"), + makeBook("book 002") + )) + + // when + serieRepository.save(serie) + + // then + assertThat(serieRepository.count()).isEqualTo(1) + assertThat(bookRepository.count()).isEqualTo(4) + assertThat(serieRepository.findAll().first().books.map { it.name }) + .containsExactly("book 1", "book 002", "book 05", "book 6") + } + @Test fun `given existing book when updating metadata then new metadata is saved`() { // given @@ -67,4 +87,32 @@ class PersistenceTest( assertThat(it.pages.first().fileName).isEqualTo("page1") } } + + @Test + fun `given book pages unordered when saving then pages are ordered with natural sort`() { + // given + val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"))) + serieRepository.save(serie) + + // when + val book = bookRepository.findAll().first() + book.metadata = BookMetadata(status = Status.READY, mediaType = "test", pages = listOf( + makeBookPage("2"), + makeBookPage("003"), + makeBookPage("001") + )) + + bookRepository.save(book) + + // then + assertThat(serieRepository.count()).isEqualTo(1) + assertThat(bookRepository.count()).isEqualTo(1) + assertThat(bookMetadataRepository.count()).isEqualTo(1) + bookMetadataRepository.findAll().first().let { + assertThat(it.status == Status.READY) + assertThat(it.mediaType == "test") + assertThat(it.pages).hasSize(3) + assertThat(it.pages.map { it.fileName }).containsExactly("001", "2", "003") + } + } } \ No newline at end of file