Skip to content

Commit 3965b06

Browse files
authored
EPUB 2 meta tags should be superseded by EPUB 3 ones (#437)
1 parent 97b9ec0 commit 3965b06

File tree

2 files changed

+81
-50
lines changed

2 files changed

+81
-50
lines changed

readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/MetadataParser.kt

Lines changed: 80 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,50 @@ internal class MetadataParser(
2323
return resolveItemsHierarchy(items)
2424
}
2525

26-
private fun parseElements(metadataElement: ElementNode, filePath: Url): List<MetadataItem> =
27-
metadataElement.getAll().mapNotNull { e ->
28-
when {
29-
e.namespace == Namespaces.DC ->
30-
parseDcElement(e)
31-
e.namespace == Namespaces.OPF && e.name == "meta" ->
32-
parseMetaElement(e)
33-
e.namespace == Namespaces.OPF && e.name == "link" ->
34-
parseLinkElement(e, filePath)
35-
else -> null
26+
private fun parseElements(metadataElement: ElementNode, filePath: Url): List<MetadataItem> {
27+
val oldMetas: MutableList<ElementNode> = mutableListOf()
28+
val newMetas: MutableList<ElementNode> = mutableListOf()
29+
val links: MutableList<ElementNode> = mutableListOf()
30+
val dcItems: MutableList<ElementNode> = mutableListOf()
31+
32+
metadataElement
33+
.getAll()
34+
.forEach { e ->
35+
when {
36+
e.namespace == Namespaces.DC -> {
37+
dcItems.add(e)
38+
}
39+
e.namespace == Namespaces.OPF && e.name == "meta" -> {
40+
if (e.getAttr("property") == null) {
41+
oldMetas.add(e)
42+
} else {
43+
newMetas.add(e)
44+
}
45+
}
46+
e.namespace == Namespaces.OPF && e.name == "link" -> {
47+
links.add(e)
48+
}
49+
else -> {}
50+
}
3651
}
37-
}
52+
53+
val parsedNewMetas = newMetas
54+
.mapNotNull { parseNewMetaElement(it) }
55+
56+
val propertiesFromGlobalNewMetas = parsedNewMetas
57+
.filter { it.refines == null }
58+
.map { it.property }
59+
.toSet()
60+
61+
val parsedOldMetas = oldMetas
62+
.mapNotNull { parseOldMetaElement(it) }
63+
// Ignore EPUB2 fallbacks in EPUB3
64+
.filter { it.property !in propertiesFromGlobalNewMetas }
65+
66+
return parsedNewMetas + parsedOldMetas +
67+
dcItems.mapNotNull { parseDcElement(it) } +
68+
links.mapNotNull { parseLinkElement(it, filePath) }
69+
}
3870

3971
private fun parseLinkElement(element: ElementNode, filePath: Url): MetadataItem.Link? {
4072
val href = element.getAttr("href")?.let { Url.fromEpubHref(it) } ?: return null
@@ -60,43 +92,43 @@ internal class MetadataParser(
6092
)
6193
}
6294

63-
private fun parseMetaElement(element: ElementNode): MetadataItem.Meta? {
64-
return if (element.getAttr("property") == null) {
65-
val name = element.getAttr("name")?.trim()?.ifEmpty { null }
66-
?: return null
67-
val content = element.getAttr("content")?.trim()?.ifEmpty { null }
68-
?: return null
69-
val resolvedName = resolveProperty(name, prefixMap)
70-
MetadataItem.Meta(
71-
id = element.id,
72-
refines = null,
73-
property = resolvedName,
74-
value = content,
75-
lang = element.lang
76-
)
77-
} else {
78-
val propName = element.getAttr("property")?.trim()?.ifEmpty { null }
79-
?: return null
80-
val propValue = element.text?.trim()?.ifEmpty { null }
81-
?: return null
82-
val resolvedProp = resolveProperty(propName, prefixMap, DEFAULT_VOCAB.META)
83-
val resolvedScheme =
84-
element.getAttr("scheme")?.trim()?.ifEmpty { null }?.let {
85-
resolveProperty(
86-
it,
87-
prefixMap
88-
)
89-
}
90-
val refines = element.getAttr("refines")?.removePrefix("#")
91-
MetadataItem.Meta(
92-
id = element.id,
93-
refines = refines,
94-
property = resolvedProp,
95-
value = propValue,
96-
lang = element.lang,
97-
scheme = resolvedScheme
98-
)
99-
}
95+
private fun parseNewMetaElement(element: ElementNode): MetadataItem.Meta? {
96+
val propName = element.getAttr("property")?.trim()?.ifEmpty { null }
97+
?: return null
98+
val propValue = element.text?.trim()?.ifEmpty { null }
99+
?: return null
100+
val resolvedProp = resolveProperty(propName, prefixMap, DEFAULT_VOCAB.META)
101+
val resolvedScheme =
102+
element.getAttr("scheme")?.trim()?.ifEmpty { null }?.let {
103+
resolveProperty(
104+
it,
105+
prefixMap
106+
)
107+
}
108+
val refines = element.getAttr("refines")?.removePrefix("#")
109+
return MetadataItem.Meta(
110+
id = element.id,
111+
refines = refines,
112+
property = resolvedProp,
113+
value = propValue,
114+
lang = element.lang,
115+
scheme = resolvedScheme
116+
)
117+
}
118+
119+
private fun parseOldMetaElement(element: ElementNode): MetadataItem.Meta? {
120+
val name = element.getAttr("name")?.trim()?.ifEmpty { null }
121+
?: return null
122+
val content = element.getAttr("content")?.trim()?.ifEmpty { null }
123+
?: return null
124+
val resolvedName = resolveProperty(name, prefixMap)
125+
return MetadataItem.Meta(
126+
id = element.id,
127+
refines = null,
128+
property = resolvedName,
129+
value = content,
130+
lang = element.lang
131+
)
100132
}
101133

102134
private fun parseDcElement(element: ElementNode): MetadataItem.Meta? {

readium/streamer/src/test/java/org/readium/r2/streamer/parser/epub/MetadataTest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,8 @@ class MetadataMiscTest {
362362
entry(
363363
Vocabularies.DCTERMS + "source",
364364
listOf(
365-
"Feedbooks",
366365
mapOf("@value" to "Web", "http://my.url/#scheme" to "http"),
367-
"Internet"
366+
"Feedbooks"
368367
)
369368
),
370369
entry(

0 commit comments

Comments
 (0)