Skip to content

Commit d91c43e

Browse files
authored
Merge pull request #143 from andannn/detail_page_ndc
Detail page ndc
2 parents aeb1ffd + 65833f6 commit d91c43e

File tree

15 files changed

+147
-77
lines changed

15 files changed

+147
-77
lines changed

core/data/src/commonMain/kotlin/me/andannn/aozora/core/data/mapper/BookEntityMapper.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import me.andannn.aozora.core.database.entity.BookEntity
88
import me.andannn.aozora.core.domain.model.AozoraBookCard
99
import me.andannn.aozora.core.domain.model.AuthorData
1010
import me.andannn.aozora.core.domain.model.StaffData
11+
import me.andannn.aozora.core.domain.model.asNDCClassification
1112

1213
internal fun BookEntity.toModel() =
1314
AozoraBookCard(
@@ -19,7 +20,7 @@ internal fun BookEntity.toModel() =
1920
zipUrl = textFileUrl,
2021
htmlUrl = htmlFileUrl,
2122
authorUrl = null,
22-
category = categoryNo,
23+
categories = categoryNo?.asNDCClassification() ?: emptyList(),
2324
source = firstAppearance,
2425
characterType = orthography,
2526
haveCopyRight = this.workCopyrightFlag == "あり",

core/domain/src/commonMain/kotlin/me/andannn/aozora/core/domain/model/AozoraBookCard.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ data class AozoraBookCard constructor(
1919
val zipUrl: String?,
2020
val subTitle: String? = null,
2121
val htmlUrl: String? = null,
22-
val category: String? = null,
2322
val source: String? = null,
2423
val characterType: String? = null,
2524
val staffData: StaffData? = null,
25+
val categories: List<NDCClassification> = emptyList(),
2626
val authorDataList: List<AuthorData>,
2727
)
2828

core/domain/src/commonMain/kotlin/me/andannn/aozora/core/domain/model/NdcData.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package me.andannn.aozora.core.domain.model
66

7+
import io.github.aakira.napier.Napier
78
import kotlin.jvm.JvmInline
89

910
data class NdcData(
@@ -70,3 +71,31 @@ fun NDCClassification.isChildOf(other: NDCClassification): Boolean =
7071
this.mainClassNum == other.mainClassNum &&
7172
this.divisionNum == other.divisionNum
7273
}
74+
75+
/**
76+
* Parses the NDC classification from a string.
77+
*
78+
* Patterns:
79+
* - "NDC 931" -> [NDCClassification("931")]
80+
* - "NDC 931 123" -> [NDCClassification("931"), NDCClassification("123")]
81+
*/
82+
fun String.asNDCClassification(): List<NDCClassification> =
83+
split(" ")
84+
.let { splitList ->
85+
if (splitList.size >= 2) {
86+
splitList
87+
.subList(1, splitList.size)
88+
.filter { it.isNotBlank() && it.isNotEmpty() }
89+
.map {
90+
NDCClassification(it.parseDigits())
91+
}
92+
} else {
93+
Napier.e { "Invalid NDC classification format: $this" }
94+
emptyList()
95+
}
96+
}
97+
98+
private fun String.parseDigits() =
99+
this.filter {
100+
it.isDigit()
101+
}

core/domain/src/commonMain/kotlin/me/andannn/aozora/core/domain/pagesource/BookPageSource.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ import me.andannn.aozora.core.domain.model.TableOfContentsModel
1818
val LocalBookPageSource: ProvidableCompositionLocal<BookPageSource> =
1919
compositionLocalOf { error("no book source") }
2020

21+
class SourceNotFoundException(
22+
override val cause: Throwable?,
23+
) : Exception("Book source not found", cause)
24+
2125
/**
2226
* Book page source.
2327
*/
@@ -27,7 +31,8 @@ interface BookPageSource {
2731
*
2832
* @param pageMetaData page meta data.
2933
* @param readingProgress initial start progress of book page source. every 64 bytes is One Unit of progress.
30-
* @throws Exception when error occurred.
34+
* @throws SourceNotFoundException when error occurred.
35+
* @throws CopyRightRetainedException when try to download source with copyright.
3136
*/
3237
fun getPagerSnapShotFlow(
3338
pageMetaData: PageMetaData,
@@ -36,11 +41,15 @@ interface BookPageSource {
3641

3742
/**
3843
* get book meta. return empty list when error occurred.
44+
* @throws SourceNotFoundException when error occurred.
45+
* @throws CopyRightRetainedException when try to download source with copyright.
3946
*/
4047
suspend fun getTableOfContents(): List<TableOfContentsModel>
4148

4249
/**
4350
* get total block count. return null when error occurred.
51+
* @throws SourceNotFoundException when error occurred.
52+
* @throws CopyRightRetainedException when try to download source with copyright.
4453
*/
4554
suspend fun getTotalBlockCount(): Int?
4655

core/domain/src/commonTest/kotlin/me/andannn/aozora/core/domain/model/NDCClassificationTest.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package me.andannn.aozora.core.domain.model
66

77
import kotlin.test.Test
8+
import kotlin.test.assertEquals
89
import kotlin.test.assertFails
910
import kotlin.test.assertTrue
1011

@@ -62,4 +63,26 @@ class NDCClassificationTest {
6263
assertTrue(!section.isChildOf(section))
6364
assertTrue(!mainClass.isChildOf(mainClass))
6465
}
66+
67+
@Test
68+
fun testParseStringAsNDCClassification() {
69+
val input1 = "NDC 931"
70+
val input2 = "NDC 931 123"
71+
val input3 = "NDC K726"
72+
val input4 = "NDC 369 453 524"
73+
74+
val result1 = input1.asNDCClassification()
75+
val result2 = input2.asNDCClassification()
76+
val result3 = input3.asNDCClassification()
77+
val result4 = input4.asNDCClassification()
78+
79+
assertEquals(1, result1.size)
80+
assertEquals("931", result1[0].value)
81+
assertEquals(2, result2.size)
82+
assertEquals("931", result2[0].value)
83+
assertEquals("123", result2[1].value)
84+
assertEquals(1, result3.size)
85+
assertEquals("726", result3[0].value)
86+
assertEquals(3, result4.size)
87+
}
6588
}

core/pagesource/src/commonMain/kotlin/me/andannn/aozora/core/pagesource/measure/Measurer.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import kotlin.math.ceil
1919
import kotlin.math.floor
2020
import kotlin.math.min
2121

22-
data class ElementMeasureResult(
22+
internal data class ElementMeasureResult(
2323
val widthDp: Dp,
2424
val heightDp: Dp,
2525
val fontStyle: FontStyle? = null,
2626
)
2727

28-
data class BlockMeasureResult(
28+
internal data class BlockMeasureResult(
2929
val lineCount: Int,
3030
val lineHeightDpPerLine: Dp,
3131
val availableTextCountPerLine: Int,
@@ -39,7 +39,7 @@ internal fun interface BlockMeasurer {
3939
fun measure(block: AozoraBlock): BlockMeasureResult
4040
}
4141

42-
fun interface ElementMeasurer {
42+
internal fun interface ElementMeasurer {
4343
fun measure(
4444
element: AozoraElement,
4545
style: AozoraTextStyle?,

core/pagesource/src/commonMain/kotlin/me/andannn/aozora/core/pagesource/parser/html/matchers/SpecialParagraphMatcher.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import me.andannn.aozora.core.domain.model.AozoraElement
1010
import me.andannn.aozora.core.pagesource.parser.html.ElementMatcher
1111
import me.andannn.aozora.core.pagesource.parser.html.parseAsAozoraElements
1212

13-
object SpecialParagraphMatcher : ElementMatcher {
13+
internal object SpecialParagraphMatcher : ElementMatcher {
1414
override fun match(node: Node): AozoraElement? {
1515
if (node !is Element) return null
1616
if (node.tagName() != "div") return null

core/pagesource/src/commonMain/kotlin/me/andannn/aozora/core/pagesource/raw/RemoteOrLocalCacheBookRawSource.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import me.andannn.aozora.core.domain.exceptions.CopyRightRetainedException
3131
import me.andannn.aozora.core.domain.exceptions.DownloadBookFailedException
3232
import me.andannn.aozora.core.domain.model.AozoraBookCard
3333
import me.andannn.aozora.core.domain.model.AozoraElement
34+
import me.andannn.aozora.core.domain.pagesource.SourceNotFoundException
3435
import me.andannn.aozora.core.pagesource.page.AozoraBlock
3536
import me.andannn.aozora.core.pagesource.parser.DefaultAozoraBlockParser
3637
import me.andannn.aozora.core.pagesource.parser.html.HtmlLineParser
@@ -61,9 +62,12 @@ internal class RemoteOrLocalCacheBookRawSource(
6162
try {
6263
bookModelStateFlow.value =
6364
SourceState.Success(createBookRawSource(card, cacheDictionary))
65+
} catch (e: CopyRightRetainedException) {
66+
Napier.e { "CopyRightRetainedException thrown when create book raw source. $e" }
67+
bookModelStateFlow.value = SourceState.Error(e)
6468
} catch (e: Exception) {
6569
Napier.e { "Exception thrown when create book raw source. $e" }
66-
bookModelStateFlow.value = SourceState.Error(e)
70+
bookModelStateFlow.value = SourceState.Error(SourceNotFoundException(cause = e))
6771
}
6872
}
6973
}

core/syncer/src/commonMain/kotlin/me/andannn/aozora/syncer/internal/util/NdcParserUtil.kt

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
*/
55
package me.andannn.aozora.syncer.internal.util
66

7-
import io.github.aakira.napier.Napier
87
import me.andannn.aozora.core.database.entity.BookEntity
98
import me.andannn.aozora.core.database.entity.BookIdWithBookCategory
10-
import me.andannn.aozora.core.domain.model.NDCClassification
9+
import me.andannn.aozora.core.domain.model.asNDCClassification
1110

1211
internal fun BookEntity.parseAsBookIdWithBookCategory(): List<BookIdWithBookCategory> {
1312
val parsed = categoryNo?.asNDCClassification() ?: emptyList()
@@ -21,31 +20,3 @@ internal fun BookEntity.parseAsBookIdWithBookCategory(): List<BookIdWithBookCate
2120
)
2221
}
2322
}
24-
25-
/**
26-
* Parses the NDC classification from a string.
27-
*
28-
* Patterns:
29-
* - "NDC 931" -> [NDCClassification("931")]
30-
* - "NDC 931 123" -> [NDCClassification("931"), NDCClassification("123")]
31-
*/
32-
internal fun String.asNDCClassification(): List<NDCClassification> =
33-
split(" ")
34-
.let { splitList ->
35-
if (splitList.size >= 2) {
36-
splitList
37-
.subList(1, splitList.size)
38-
.filter { it.isNotBlank() && it.isNotEmpty() }
39-
.map {
40-
NDCClassification(it.parseDigits())
41-
}
42-
} else {
43-
Napier.e { "Invalid NDC classification format: $this" }
44-
emptyList()
45-
}
46-
}
47-
48-
private fun String.parseDigits() =
49-
this.filter {
50-
it.isDigit()
51-
}

core/syncer/src/commonTest/kotlin/me/andannn/aozora/syncer/internal/util/NdcParserUtilTest.kt

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)