Commit 3c47e8f8 authored by Jonas Waeber's avatar Jonas Waeber
Browse files

Refactor reporting of builders. These report messages are now collected and...

Refactor reporting of builders. These report messages are now collected and not just logged (at least for dates).
Update tests.
Add check to make sure the normalized date value has at least a four digit year value.
parent 58eca486
Pipeline #43351 passed with stages
in 4 minutes and 16 seconds
......@@ -52,8 +52,8 @@ class DocumentsSearchDocBuilder(
) {
private val log = LogManager.getLogger(this::class.java)
fun transform(key: String, input: Map<String, JsonObject>): Schema {
fun transform(key: String, input: Map<String, JsonObject>): Pair<Schema, List<String>> {
val warningMessages = mutableListOf<String>()
val record =
input[JsonUtility.recordTag] ?: throw InvalidInputException("No record defined in the message $key.")
val digitalObject =
......@@ -150,7 +150,7 @@ class DocumentsSearchDocBuilder(
languages
)) {
if (builder.filter(item.value)) {
builder.append(key, item.value)
warningMessages.addAll(builder.append(key, item.value))
}
if (digitalIdentifierReferences.contains(item.key))
......@@ -229,7 +229,7 @@ class DocumentsSearchDocBuilder(
val recordSetId = extractRecordSet(record)
return DocumentsSearchDoc(
return Pair(DocumentsSearchDoc(
title = Extract.typedEntityByType(recordTitles, "type", "main", "title"),
seriesTitle = Extract.typedEntityByType(recordTitles, "type", "series", "title"),
broadcastTitle = Extract.typedEntityByType(recordTitles, "type", "broadcast", "title"),
......@@ -369,6 +369,6 @@ class DocumentsSearchDocBuilder(
published = (record[Constants.isPublished] as Boolean?) ?: false,
suggest = suggestContainerBuilder.build()[0]
)
), warningMessages.filter { x -> x.isNotEmpty() })
}
}
......@@ -79,12 +79,13 @@ class KafkaTopology(
val recordStream = branchedStream[0]
.mapValues { readOnlyKey, value ->
try {
val results = documentSearchDocBuilder.transform(readOnlyKey, value)
Pair(
documentSearchDocBuilder.transform(readOnlyKey, value),
results.first,
Report(
readOnlyKey,
ReportStatus.success,
"",
if (results.second.isEmpty()) ReportStatus.success else ReportStatus.warning,
if (results.second.isEmpty()) "" else results.second.joinToString("\n"),
step
)
)
......
......@@ -51,7 +51,7 @@ class AgentContainerBuilder(
}
}
override fun append(key: String, jsonObject: JsonObject): String {
override fun append(key: String, jsonObject: JsonObject): List<String> {
val names = Extract.languageContainer("agent-name", jsonObject[Constants.name])
val name = if (names.isNotEmpty())
names.reduce { acc, languageContainer -> acc.merge(languageContainer) }
......@@ -88,7 +88,7 @@ class AgentContainerBuilder(
facet = filterAndFacet.second
)
)
return "Created person container for person ${jsonObject[Constants.entityId]}"
return emptyList()
}
override fun build(): List<AgentWithRelationContainer> {
......
......@@ -29,7 +29,7 @@ import org.apache.logging.log4j.LogManager
class DateSearchFieldBuilder(private val containedIds: List<String>, private val type: String) : IFieldBuilder {
private val log = LogManager.getLogger("DateContainerBuilder")
private val issues = mutableListOf<String>()
private val dateSearchFields = mutableListOf<DateSearchField>()
private val dateFacetFields = mutableListOf<DateFacetField>()
......@@ -40,7 +40,8 @@ class DateSearchFieldBuilder(private val containedIds: List<String>, private val
false
}
override fun append(key: String, jsonObject: JsonObject): String {
override fun append(key: String, jsonObject: JsonObject): List<String> {
issues.clear()
val isNormalized = jsonObject.containsKey("normalizedDateValue")
val date = if (isNormalized) {
jsonObject["normalizedDateValue"] as String
......@@ -68,6 +69,7 @@ class DateSearchFieldBuilder(private val containedIds: List<String>, private val
isNormalized, date, key, it
)
}
issues.addAll(DateFacetBuildHelpers.issues)
dateSearchFields.add(
DateSearchField(
date = date,
......@@ -88,7 +90,7 @@ class DateSearchFieldBuilder(private val containedIds: List<String>, private val
)
)
return "Transformed date to date container."
return issues
}
override fun build(): Pair<List<DateSearchField>, List<DateFacetField>> {
......@@ -102,7 +104,7 @@ class DateSearchFieldBuilder(private val containedIds: List<String>, private val
key: String,
language: String
): List<String> {
return when (jsonObject["@type"] as String) {
return when (val type = jsonObject["@type"] as String) {
NS.rico + "SingleDate" ->
if (isNormalized)
DateFacetBuildHelpers.buildFromNormalizedSingleDate(date, language)
......@@ -113,12 +115,17 @@ class DateSearchFieldBuilder(private val containedIds: List<String>, private val
DateFacetBuildHelpers.buildFromNormalizedDateRange(date, language)
} catch (ex: NumberFormatException) {
log.error("Could not parse normalized date $date in resource $key.")
issues.add("Could not parse normalized date $date in resource $key.")
emptyList<String>()
}
} else {
emptyList()
}
else -> emptyList()
else -> {
log.error("Could not process date as it is of type $type. (not rico:DateRange or rico:SingleDate).")
issues.add("Could not process date as it is of type $type. (not rico:DateRange or rico:SingleDate).")
emptyList()
}
}
}
}
\ No newline at end of file
......@@ -43,14 +43,14 @@ class EnrichedFacetContainerBuilder(
return true
}
override fun append(key: String, jsonObject: JsonObject): String {
override fun append(key: String, jsonObject: JsonObject): List<String> {
val names = Extract.languageContainer(targetType, jsonObject[nameProperty])
.reduce { acc, languageContainer -> acc.merge(languageContainer) }.fillInEmpty()
val ricoType = jsonObject[Constants.ricoType] as String?
val activityId = jsonObject[Constants.resultsFrom]
if (!fullGraph.containsKey(activityId)) {
log.error("Could not find activity with id $activityId in record $key.")
return "Could not find activity with id $activityId in record $key."
return listOf("Could not find activity with id $activityId in record $key.")
}
val activity = fullGraph[activityId] as JsonObject
return if (activity.containsKey(Constants.affects)) {
......@@ -61,10 +61,10 @@ class EnrichedFacetContainerBuilder(
containers.add(
EnrichedFacetContainer(displayNames, names, ricoType)
)
""
emptyList()
} else {
log.error("Could not find activity with id $activityId in record $key.")
"Activity without source entity: $activityId in record $key."
listOf("Activity without source entity: $activityId in record $key.")
}
}
......
......@@ -40,7 +40,7 @@ class FacettedContainerBuilder(
return identifiers.contains(jsonObject[Constants.entityId])
}
override fun append(key: String, jsonObject: JsonObject): String {
override fun append(key: String, jsonObject: JsonObject): List<String> {
val filterAndFacet = facetFunction(jsonObject)
containers.add(
FacetContainer(
......@@ -50,7 +50,7 @@ class FacettedContainerBuilder(
facet = filterAndFacet.second
)
)
return ""
return emptyList()
}
override fun build(): List<FacetContainer> {
......
......@@ -22,6 +22,6 @@ import com.beust.klaxon.JsonObject
interface IFieldBuilder {
fun filter(jsonObject: JsonObject): Boolean
fun append(key: String, jsonObject: JsonObject): String
fun append(key: String, jsonObject: JsonObject): List<String>
fun build(): Any
}
......@@ -39,7 +39,7 @@ class PersonFacetBuilder : IFieldBuilder {
}
}
override fun append(key: String, jsonObject: JsonObject): String {
override fun append(key: String, jsonObject: JsonObject): List<String> {
val result = FacetBuildHelpers.person(jsonObject)
return if (result.second.isNotEmpty()) {
result.first.let {
......@@ -47,11 +47,11 @@ class PersonFacetBuilder : IFieldBuilder {
personsNames.add(it)
}
personFacetValues.addAll(result.second)
""
emptyList()
} else {
val message = "Failed to create facet values for persons: ${jsonObject[Constants.entityId]}."
log.warn(message)
message
listOf(message)
}
}
......
......@@ -39,7 +39,7 @@ class PlaceFacetBuilder : IFieldBuilder {
}
}
override fun append(key: String, jsonObject: JsonObject): String {
override fun append(key: String, jsonObject: JsonObject): List<String> {
val result = FacetBuildHelpers.place(jsonObject)
return if (result.second.isNotEmpty()) {
result.first.let {
......@@ -47,11 +47,11 @@ class PlaceFacetBuilder : IFieldBuilder {
placeNames.add(it)
}
placeFacetValues.addAll(result.second)
""
emptyList()
} else {
val message = "Failed to create facet values for place: ${jsonObject[Constants.entityId]}."
log.warn(message)
message
listOf(message)
}
}
......
......@@ -40,47 +40,47 @@ class SuggestContainerBuilder(private val hasSubjectIds: List<String>) : IFieldB
}
}
override fun append(key: String, jsonObject: JsonObject): String {
override fun append(key: String, jsonObject: JsonObject): List<String> {
return when (jsonObject[Constants.atType]) {
NS.skos + Constants.Concept -> parseKeywords(jsonObject)
NS.rico + Constants.Title -> parseTitles(jsonObject)
else -> ""
else -> emptyList()
}
}
private fun parseTitles(jsonObject: JsonObject): String {
private fun parseTitles(jsonObject: JsonObject): List<String> {
return when (jsonObject[Constants.ricoType]) {
Constants.TitleTypes.main -> {
titles.addAll(
Extract.languageContainer("main-title", jsonObject[Constants.title])
.reduce { acc, languageContainer -> acc.merge(languageContainer) }.toList()
)
""
emptyList()
}
Constants.TitleTypes.series -> {
seriesTitles.addAll(
Extract.languageContainer("series-title", jsonObject[Constants.title])
.reduce { acc, languageContainer -> acc.merge(languageContainer) }.toList()
)
""
emptyList()
}
Constants.TitleTypes.broadcast -> {
broadcastTitles.addAll(
Extract.languageContainer("broadcast-title", jsonObject[Constants.title])
.reduce { acc, languageContainer -> acc.merge(languageContainer) }.toList()
)
""
emptyList()
}
else -> "Unknown title type ${jsonObject[Constants.ricoType]}."
else -> listOf("Unknown title type ${jsonObject[Constants.ricoType]}.")
}
}
private fun parseKeywords(jsonObject: JsonObject): String {
private fun parseKeywords(jsonObject: JsonObject): List<String> {
keywords.addAll(
Extract.languageContainer("keywords-concept", jsonObject[Constants.prefLabel])
.reduce { acc, languageContainer -> acc.merge(languageContainer) }.toList()
)
return ""
return emptyList()
}
override fun build(): List<SuggestContainer> {
......
......@@ -21,6 +21,7 @@ import org.apache.logging.log4j.LogManager
object DateFacetBuildHelpers {
private val log = LogManager.getLogger(DateFacetBuildHelpers.javaClass.canonicalName)
val issues = mutableListOf<String>()
private const val separator = "~"
......@@ -41,6 +42,7 @@ object DateFacetBuildHelpers {
* @return The facet values to construct the hierarchy with century and decade.
*/
fun buildFromNormalizedSingleDate(date: String, language: String): List<String> {
issues.clear()
val century = getCentury(date.substring(0, 4), language)
val decade = getDecade(date.substring(0, 4))
return listOf(
......@@ -59,8 +61,10 @@ object DateFacetBuildHelpers {
* @return The facet values used by outermedia.
*/
fun buildFromNormalizedDateRange(date: String, language: String): List<String> {
issues.clear()
if (date.length <= 3) {
log.error("Normalized date range has less than 4 characters: $date.")
issues.add("Normalized date range has less than 4 characters: $date.")
return emptyList()
}
val from = date.substring(0, 4)
......@@ -69,9 +73,10 @@ object DateFacetBuildHelpers {
val matchResult = yearRegex.matchEntire(secondPart)
matchResult.let { m ->
if (m != null) {
m.groups[1]?.value ?: ""
m.groups[1]!!.value
} else {
log.warn("Could not match year in normalized date range until value: $date.")
issues.add("Could not match year in normalized date range until value: $date.")
""
}
}
......
......@@ -29,6 +29,7 @@ import java.nio.charset.Charset
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.assertAll
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class TestDocumentsSearchDoc {
......@@ -63,7 +64,7 @@ class TestDocumentsSearchDoc {
"TestIdentifier",
mappedInput
)
assertThat(output.toJson())
assertThat(output.first.toJson())
.isEqualTo(
DocumentsSearchDoc.DEFAULT.toJson()
)
......@@ -105,9 +106,18 @@ class TestDocumentsSearchDoc {
)
)
assertThat(output.toJson())
.isEqualTo(
JsonUtility.parse(readFile("test_data_facet_search_and_facet_fields.json")).toJsonString()
)
assertAll(
"head",
{
assertThat(output.first.toJson())
.isEqualTo(
JsonUtility.parse(readFile("test_data_facet_search_and_facet_fields.json")).toJsonString()
)
},
{
assertThat(output.second).isEqualTo(emptyList<String>())
}
)
}
}
\ No newline at end of file
......@@ -57,7 +57,7 @@ class TestFacetBuilders {
json { obj(Pair("@type", NS.rico + "Record")) },
mapOf(),
"",
"",
emptyList(),
emptyList()
),
PersonFacetBuilderParams(
......@@ -70,7 +70,7 @@ class TestFacetBuilders {
},
mapOf(Pair("identifier", json { obj(Pair(Constants.ricoType, Constants.creator)) })),
Constants.creator,
"",
emptyList(),
listOf(
"0~E~",
"1~E~Einstein, Albert~"
......@@ -87,7 +87,7 @@ class TestFacetBuilders {
},
mapOf(Pair("identifier", json { obj(Pair(Constants.ricoType, Constants.contributor)) })),
Constants.contributor,
"",
emptyList(),
listOf(
"0~E~",
"1~E~Einstein~"
......@@ -104,7 +104,7 @@ class TestFacetBuilders {
},
mapOf(Pair("identifier", json { obj(Pair(Constants.ricoType, Constants.contributor)) })),
Constants.contributor,
"",
emptyList(),
listOf(
"0~A~",
"1~A~Albert~"
......
......@@ -23,6 +23,6 @@ data class PersonFacetBuilderParams(
val source: JsonObject,
val map: Map<String, JsonObject>,
val ricoType: String,
val log: String,
val log: List<String>,
val result: List<String>
)
......@@ -79,7 +79,7 @@
{
"@id": "_:b19",
"@type": "https://www.ica.org/standards/RiC/ontology#DateRange",
"expressedDate": "um 1930"
"normalizedDateValue": "1930"
},
{
"@id": "_:b2",
......
{"title":[{"de":[],"fr":[],"it":[],"un":["Diaserie zum Thema Säuglingspflege; \"Ablesen des Thermometers.\" - Krankenschwester am Fieber messen bei einem Säugling; Deutsches Hygiene-Museum, Dresden; um 1930"]}],"type":{"name":{"de":["Fotografie"],"fr":["Photographie"],"it":["Fotografia"],"un":[]},"filter":"Foto"},"sourceID":"Sozarch_F_5146-Gb-40-042","oldMemobaseId":"SozArch-Sozarch_F_5146-Gb-40-042","rightsHolder":[{"de":[],"fr":[],"it":[],"un":["Schweizerisches Sozialarchiv"]}],"sameAs":["http://www.bild-video-ton.ch/bestand/objekt/Sozarch_F_5146-Gb-40-042"],"format":[{"displayLabel":{"de":[],"fr":[],"it":[],"un":["Glaspositiv"]},"name":{"de":["Fotoplatte"],"fr":["plaque photographique"],"it":["lastra fotografica"],"un":[]}}],"language":[{"displayLabel":{"de":[],"fr":[],"it":[],"un":["ger"]},"name":{"de":["Deutsch"],"fr":["allemand"],"it":["tedesco"],"un":[]},"type":"content"}],"keywords":{"de":[],"fr":[],"it":[],"un":["soziale Fragen","Altersgliederung","Bevölkerung","Bevölkerungsaufbau","frühe Kindheit; soziale Fragen","Gesundheit","Gesundheitsförderung","Gesundheitspolitik"]},"personsFacet":{},"agentCreator":[{"name":{"de":[],"fr":[],"it":[],"un":["Unbekannt"]},"relation":{"de":[],"fr":[],"it":[],"un":["Author"]}}],"placeFacet":{},"temporal":[{"date":"1921-1930 / 1931-1940"}],"dateCreated":[{"date":"um 1930"}],"dateFacetField":[{"display":"um 1930","sort":null,"type":"created","facet":{"de":[],"fr":[],"it":[],"un":[]}}],"institution":[{"name":{"de":["soz"],"fr":["soz"],"it":["soz"],"un":["soz"]},"filter":"soz","facet":["soz"]}],"recordSet":{"name":{"de":["soz-004"],"fr":["soz-004"],"it":["soz-004"],"un":["soz-004"]},"facet":["soz-004"]},"memoriavClaim":true,"locator":"https://media.memobase.k8s.unibas.ch/memo/soz-004-Sozarch_F_5146-Gb-40-042-1","mediaLocation":"local","accessDigital":[{"name":{"de":["Online"],"fr":["En ligne"],"it":["Online"],"un":[]},"filter":"public"}],"usageDigital":["http://rightsstatements.org/vocab/CNE/1.0/"],"usageDigitalGroup":[{"displayLabel":{"de":["Urheberrechtsschutz nicht bewertet"],"fr":["Droit d'auteur non évalué"],"it":["Copyright non esaminato"],"un":[]},"name":{"de":["Unklar (Copyright nicht bekannt)"],"fr":["Inconnu (Copyright inconnu)"],"it":["Non chiaro (Copyright non conosciuto)"],"un":[]},"type":"http://rightsstatements.org/vocab/CNE/1.0/"}],"digital":{},"callNumber":["Sozarch_F_5146-Gb-40-042"],"accessPhysical":[{"name":{"de":["vor Ort"],"fr":["Sur place"],"it":["Nel local"],"un":[]},"filter":"onsite"}],"usagePhysical":["http://rightsstatements.org/vocab/CNE/1.0/"],"colourPhysical":[{"de":[],"fr":[],"it":[],"un":["s-w"]}],"access":[{"name":{"de":["Online"],"fr":["En ligne"],"it":["Online"],"un":[]},"filter":"public"},{"name":{"de":["vor Ort"],"fr":["Sur place"],"it":["Nel local"],"un":[]},"filter":"onsite"}],"published":false,"suggest":{"title":["Diaserie zum Thema Säuglingspflege; \"Ablesen des Thermometers.\" - Krankenschwester am Fieber messen bei einem Säugling; Deutsches Hygiene-Museum, Dresden; um 1930"],"keywords":["soziale Fragen","Altersgliederung","Bevölkerung","Bevölkerungsaufbau","Gesundheit","frühe Kindheit; soziale Fragen","Gesundheitsförderung","Gesundheitspolitik"]},"id":"fad-001-DON3196"}
\ No newline at end of file
{"title":[{"de":[],"fr":[],"it":[],"un":["Diaserie zum Thema Säuglingspflege; \"Ablesen des Thermometers.\" - Krankenschwester am Fieber messen bei einem Säugling; Deutsches Hygiene-Museum, Dresden; um 1930"]}],"type":{"name":{"de":["Fotografie"],"fr":["Photographie"],"it":["Fotografia"],"un":[]},"filter":"Foto"},"sourceID":"Sozarch_F_5146-Gb-40-042","oldMemobaseId":"SozArch-Sozarch_F_5146-Gb-40-042","rightsHolder":[{"de":[],"fr":[],"it":[],"un":["Schweizerisches Sozialarchiv"]}],"sameAs":["http://www.bild-video-ton.ch/bestand/objekt/Sozarch_F_5146-Gb-40-042"],"format":[{"displayLabel":{"de":[],"fr":[],"it":[],"un":["Glaspositiv"]},"name":{"de":["Fotoplatte"],"fr":["plaque photographique"],"it":["lastra fotografica"],"un":[]}}],"language":[{"displayLabel":{"de":[],"fr":[],"it":[],"un":["ger"]},"name":{"de":["Deutsch"],"fr":["allemand"],"it":["tedesco"],"un":[]},"type":"content"}],"keywords":{"de":[],"fr":[],"it":[],"un":["soziale Fragen","Altersgliederung","Bevölkerung","Bevölkerungsaufbau","frühe Kindheit; soziale Fragen","Gesundheit","Gesundheitsförderung","Gesundheitspolitik"]},"personsFacet":{},"agentCreator":[{"name":{"de":[],"fr":[],"it":[],"un":["Unbekannt"]},"relation":{"de":[],"fr":[],"it":[],"un":["Author"]}}],"placeFacet":{},"temporal":[{"date":"1921-1930 / 1931-1940"}],"dateCreated":[{"date":"1930"}],"dateFacetField":[{"display":"1930","sort":"1930","type":"created","facet":{"de":["0~20. Jahrhundert~","1~20. Jahrhundert~1921-1930~"],"fr":["0~20. siècle~","1~20. siècle~1921-1930~"],"it":["0~20. secolo~","1~20. secolo~1921-1930~"],"un":[]}}],"institution":[{"name":{"de":["soz"],"fr":["soz"],"it":["soz"],"un":["soz"]},"filter":"soz","facet":["soz"]}],"recordSet":{"name":{"de":["soz-004"],"fr":["soz-004"],"it":["soz-004"],"un":["soz-004"]},"facet":["soz-004"]},"memoriavClaim":true,"locator":"https://media.memobase.k8s.unibas.ch/memo/soz-004-Sozarch_F_5146-Gb-40-042-1","mediaLocation":"local","accessDigital":[{"name":{"de":["Online"],"fr":["En ligne"],"it":["Online"],"un":[]},"filter":"public"}],"usageDigital":["http://rightsstatements.org/vocab/CNE/1.0/"],"usageDigitalGroup":[{"displayLabel":{"de":["Urheberrechtsschutz nicht bewertet"],"fr":["Droit d'auteur non évalué"],"it":["Copyright non esaminato"],"un":[]},"name":{"de":["Unklar (Copyright nicht bekannt)"],"fr":["Inconnu (Copyright inconnu)"],"it":["Non chiaro (Copyright non conosciuto)"],"un":[]},"type":"http://rightsstatements.org/vocab/CNE/1.0/"}],"digital":{},"callNumber":["Sozarch_F_5146-Gb-40-042"],"accessPhysical":[{"name":{"de":["vor Ort"],"fr":["Sur place"],"it":["Nel local"],"un":[]},"filter":"onsite"}],"usagePhysical":["http://rightsstatements.org/vocab/CNE/1.0/"],"colourPhysical":[{"de":[],"fr":[],"it":[],"un":["s-w"]}],"access":[{"name":{"de":["Online"],"fr":["En ligne"],"it":["Online"],"un":[]},"filter":"public"},{"name":{"de":["vor Ort"],"fr":["Sur place"],"it":["Nel local"],"un":[]},"filter":"onsite"}],"published":false,"suggest":{"title":["Diaserie zum Thema Säuglingspflege; \"Ablesen des Thermometers.\" - Krankenschwester am Fieber messen bei einem Säugling; Deutsches Hygiene-Museum, Dresden; um 1930"],"keywords":["soziale Fragen","Altersgliederung","Bevölkerung","Bevölkerungsaufbau","Gesundheit","frühe Kindheit; soziale Fragen","Gesundheitsförderung","Gesundheitspolitik"]},"id":"fad-001-DON3196"}
\ No newline at end of file
{
"type": {
"name": {
"de": [
"Andere"
],
"fr": [
"Autres"
],
"it": [
"Altri"
],
"un": []
},
"filter": "Andere"
},
"sourceID": "NoSourceIdFound",
"keywords": {
"de": [],
"fr": [],
"it": [],
"un": []
},
"personsFacet": {},
"placeFacet": {},
"dateCreated": [
{
"date": "1921/2001"
}
],
"dateIssued": [
{
"date": "1910/2014"
}
],
"dateFacetField": [
{
"display": "1921/2001",
"sort": "1921/2001",
"type": "created",
"facet": {
"de": [
"0~20. Jahrhundert~",
"0~21. Jahrhundert~",
"1~20. Jahrhundert~1921-1930~",
"1~20. Jahrhundert~1931-1940~",
"1~20. Jahrhundert~1941-1950~",
"1~20. Jahrhundert~1951-1960~",
"1~20. Jahrhundert~1961-1970~",
"1~20. Jahrhundert~1971-1980~",
"1~20. Jahrhundert~1981-1990~",
"1~20. Jahrhundert~1991-2000~",
"1~21. Jahrhundert~2001-2010~"
],
"fr": [
"0~20. siècle~",
"0~21. siècle~",
"1~20. siècle~1921-1930~",
"1~20. siècle~1931-1940~",
"1~20. siècle~1941-1950~",
"1~20. siècle~1951-1960~",
"1~20. siècle~1961-1970~",
"1~20. siècle~1971-1980~",
"1~20. siècle~1981-1990~",
"1~20. siècle~1991-2000~",
"1~21. siècle~2001-2010~"
],
"it": [
"0~20. secolo~",
"0~21. secolo~",
"1~20. secolo~1921-1930~",
"1~20. secolo~1931-1940~",
"1~20. secolo~1941-1950~",
"1~20. secolo~1951-1960~",
"1~20. secolo~1961-1970~",
"1~20. secolo~1971-1980~",
"1~20. secolo~1981-1990~",
"1~20. secolo~1991-2000~",
"1~21. secolo~2001-2010~"
],
"un": []
}
},
{
"display": "1910/2014",
"sort": "1910/2014",
"type": "issued",
"facet": {
"de": [
"0~20. Jahrhundert~",
"0~21. Jahrhundert~",
"1~20. Jahrhundert~1901-1910~",
"1~20. Jahrhundert~1911-1920~",
"1~20. Jahrhundert~1921-1930~",
"1~20. Jahrhundert~1931-1940~",
"1~20. Jahrhundert~1941-1950~",
"1~20. Jahrhundert~1951-1960~",
"1~20. Jahrhundert~1961-1970~",
"1~20. Jahrhundert~1971-1980~",
"1~20. Jahrhundert~1981-1990~",
"1~20. Jahrhundert~1991-2000~",
"1~21. Jahrhundert~2001-2010~",
"1~21. Jahrhundert~2011-2020~"
],
"fr": [
"0~20. siècle~",
"0~21. siècle~",
"1~20. siècle~1901-1910~",
"1~20. siècle~1911-1920~",
"1~20. siècle~1921-1930~",
"1~20. siècle~1931-1940~",
"1~20. siècle~1941-1950~",
"1~20. siècle~1951-1960~",
"1~20. siècle~1961-1970~",
"1~20. siècle~1971-1980~",
"1~20. siècle~1981-1990~",
"1~20. siècle~1991-2000~",
"1~21. siècle~2001-2010~",
"1~21. siècle~2011-2020~"
],
"it": [
"0~20. secolo~",
"0~21. secolo~",
"1~20. secolo~1901-1910~",
"1~20. secolo~1911-1920~",
"1~20. secolo~1921-1930~",
"1~20. secolo~1931-1940~",
"1~20. secolo~1941-1950~",
"1~20. secolo~1951-1960~",