moved natural sorting directly in Serie (for books) and BookMetadata (for pages)

This commit is contained in:
Gauthier Roebroeck 2019-08-22 08:09:49 +08:00
parent db7e5e3c53
commit a188cf9598
9 changed files with 77 additions and 27 deletions

View file

@ -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<String> = 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<BookPage> = mutableListOf()
@OrderColumn(name = "number")
private var _pages: MutableList<BookPage> = mutableListOf()
var pages: List<BookPage>
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()
}
}

View file

@ -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<String> = 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<Book> = mutableListOf()
var books: List<Book>
@ -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()
}
}

View file

@ -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 {

View file

@ -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<String> = CaseInsensitiveSimpleNaturalComparator.getInstance()
abstract fun getPagesList(path: Path): List<BookPage>
abstract fun getPageStream(path: Path, entryName: String): ByteArray
}

View file

@ -22,9 +22,6 @@ class RarExtractor(
)
}
.filter { contentDetector.isImage(it.mediaType) }
.sortedWith(
compareBy(natSortComparator) { it.fileName }
)
}
override fun getPageStream(path: Path, entryName: String): ByteArray =

View file

@ -21,9 +21,6 @@ class ZipExtractor(
)
}
.filter { contentDetector.isImage(it.mediaType) }
.sortedWith(
compareBy(natSortComparator) { it.fileName }
)
}
override fun getPageStream(path: Path, entryName: String): ByteArray =

View file

@ -90,16 +90,10 @@ class SerieController(
page: Pageable
): Page<BookDto> {
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() }
}

View file

@ -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

View file

@ -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")
}
}
}