Commit 0cf7b176 authored by Jonas Waeber's avatar Jonas Waeber
Browse files

Refactor field parser defintions

parent 1e5a08e6
......@@ -24,6 +24,7 @@ import org.memobase.mapping.fields.AnnotationField
import org.memobase.mapping.fields.ConfigField
import org.memobase.mapping.fields.ConstantField
import org.memobase.mapping.fields.DirectMapField
import org.memobase.mapping.fields.FieldParsers
import org.memobase.mapping.fields.LanguageField
import org.memobase.mapping.fields.ListField
import org.memobase.mapping.fields.PrefixField
......@@ -100,7 +101,7 @@ class MappingConfig(directory: String) {
when (val key = entry.key) {
KEYS.uri -> uriField = entry.value as String
KEYS.type -> {
localRecordType = parseSimpleAnnotationField(key, entry.value)
localRecordType = FieldParsers.parseSimpleAnnotationField(key, entry.value)
}
KEYS.isSponsoredByMemoriav -> {
sponsoredByMemoriav = entry.value as Boolean
......@@ -119,7 +120,7 @@ class MappingConfig(directory: String) {
KEYS.placeOfCapture, KEYS.relatedPlaces ->
recordFieldMappers.addAll(buildPlaceMapper(key, entry.value))
KEYS.creationDate, KEYS.issuedDate, KEYS.temporal ->
when (val value = parseAnnotationField(entry)) {
when (val value = FieldParsers.parseAnnotationField(entry)) {
is DirectMapField -> recordFieldMappers.add(
DateFieldMapper(value)
)
......@@ -163,7 +164,7 @@ class MappingConfig(directory: String) {
}
private fun buildAnnotationMappers(value: Any?): IFieldMapper {
return when (val field = parseAnnotationField(value as Map.Entry<String, Any>)) {
return when (val field = FieldParsers.parseAnnotationField(value as Map.Entry<String, Any>)) {
is DirectMapField -> DirectFieldMapper(field)
is ConstantField -> ConstantFieldMapper(field)
is ListField -> ListFieldMapper(field)
......@@ -172,7 +173,6 @@ class MappingConfig(directory: String) {
}
}
private fun buildRicoConceptMappers(key: String, value: Any?): List<IFieldMapper> {
return when (value) {
is Map<*, *> -> {
......@@ -195,7 +195,7 @@ class MappingConfig(directory: String) {
return map.entries.map { entry ->
KEYS.ricoConceptCategoryToTypesMap[key].let { typeList ->
if (typeList != null)
parseFieldWithKeyValidation(key, entry, typeList)
FieldParsers.parseFieldWithKeyValidation(key, entry, typeList)
else
throw InvalidMappingException("Could not find a types configuration for field $key.")
}
......@@ -224,11 +224,11 @@ class MappingConfig(directory: String) {
return value.entries.map {
when (it.key) {
KEYS.usage ->
ExpandedRuleFieldMapper(it.key as String, parseSubFieldProperties(it.key as String, (it.value as Map<String, Any>).entries, KEYS.usageSubPropertiesList))
ExpandedRuleFieldMapper(it.key as String, FieldParsers.parseSubFieldProperties(it.key as String, (it.value as Map<String, Any>).entries, KEYS.usageSubPropertiesList))
KEYS.access ->
return@map RuleFieldMapper(parseAnnotationField(it as Map.Entry<String, Any>))
return@map RuleFieldMapper(FieldParsers.parseAnnotationField(it as Map.Entry<String, Any>))
KEYS.holder ->
return@map RuleFieldMapper(parseAnnotationField(it as Map.Entry<String, Any>))
return@map RuleFieldMapper(FieldParsers.parseAnnotationField(it as Map.Entry<String, Any>))
else -> throw InvalidMappingException("Rights section has a fixed set of valid types: ${KEYS.rights}.")
}
}
......@@ -302,7 +302,7 @@ class MappingConfig(directory: String) {
val configFields = mutableListOf<ConfigField>()
for (entry in value.entries) {
configFields.add(
parseFieldWithKeyValidation(
FieldParsers.parseFieldWithKeyValidation(
key,
entry,
validationList
......@@ -313,123 +313,6 @@ class MappingConfig(directory: String) {
instance.setFields(key, configFields)
return instance
}
private fun parsePrefixField(key: String, values: Map<String, String>): PrefixField {
return values["field"].let { field ->
if (field != null) {
values["value"].let { value ->
if (value != null) {
PrefixField(key, value, field.trim())
} else {
throw InvalidMappingException("Section: $key. A 'value' subfield in prefix definition is required.")
}
}
} else {
throw InvalidMappingException("Section: $key. A 'field' subfield in prefix definition is required.")
}
}
}
private fun parseSimpleAnnotationField(key: String, item: Any): SimpleAnnotationField {
return when (item) {
is String -> DirectMapField(key, item.trim())
is Map<*, *> -> {
when {
item.containsKey("const") -> {
ConstantField(key, item["const"] as String)
}
item.containsKey("prefix") -> {
try {
parsePrefixField(key, item["prefix"] as Map<String, String>)
} catch (ex: ClassCastException) {
throw InvalidMappingException("Invalid structure for prefix field in section $key.")
}
}
else -> {
throw InvalidMappingException("Invalid key for a simple annotation field in section $key. Expected 'const' or 'prefix'.")
}
}
}
else -> throw InvalidMappingException("Invalid value for a simple annotation field in section $key. Expected 'const' or 'prefix' or a direct map.")
}
}
private fun parseFieldList(key: String, items: List<Any>): List<SimpleAnnotationField> {
return items.map {
parseSimpleAnnotationField(key, it)
}
}
private fun parseAnnotationField(entry: Map.Entry<String, Any>): AnnotationField {
when (val value = entry.value) {
is String -> return DirectMapField(entry.key, value)
is Map<*, *> -> {
return if (value.containsKey("const")) {
ConstantField(entry.key, value["const"] as String)
} else if (value.containsKey("prefix")) {
try {
parsePrefixField(entry.key, value["prefix"] as Map<String, String>)
} catch (ex: ClassCastException) {
throw InvalidMappingException("Invalid structure for prefix field in section ${entry.key}.")
}
} else {
val mutableList = mutableListOf<Pair<String, List<SimpleAnnotationField>>>()
for (k in value.keys) {
if (k is String && listOf("de", "it", "fr").contains(k)) {
val resultAnnotations = when (val items = value[k]) {
is List<*> -> {
parseFieldList(entry.key, items as List<Any>)
}
is Any -> listOf(parseSimpleAnnotationField(entry.key, items))
else -> throw InvalidMappingException("Language map definition may not be empty.")
}
if (resultAnnotations.isEmpty()) {
throw InvalidMappingException("No valid definitions found under language tag $k in section ${entry.key}")
}
mutableList.add(Pair(k, resultAnnotations))
}
}
if (mutableList.isNotEmpty()) {
LanguageField(entry.key, mutableList)
} else {
throw InvalidMappingException("Unknown key values in field mapping: $value. Use 'const' or 'de', 'fr', 'it' language tags!")
}
}
}
is List<*> -> return ListField(
entry.key,
parseFieldList(entry.key, value as List<Any>)
)
else -> throw InvalidMappingException("Unknown structure for field mapping: $entry")
}
}
private fun parseFieldWithKeyValidation(
parent: String,
entry: Map.Entry<String, Any>,
list: List<String>
): AnnotationField {
if (list.contains(entry.key)) {
return parseAnnotationField(entry)
} else {
throw InvalidMappingException("The section $parent does not allow the key: ${entry.key}. Use any of $list.")
}
}
private fun parseSubFieldProperties(
parent: String,
entries: Set<Map.Entry<String, Any>>,
allowedSubFields: List<String>
): List<AnnotationField> {
return entries.map { entry ->
if (allowedSubFields.contains(entry.key)) {
return@map parseAnnotationField(entry)
} else {
throw InvalidMappingException("The section $parent only allows the following subfields: $allowedSubFields.")
}
}
}
}
......
/*
* mapper-service
* Copyright (C) 2020 Memoriav
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.memobase.mapping.fields
import org.memobase.mapping.exceptions.InvalidMappingException
@Suppress("UNCHECKED_CAST")
object FieldParsers {
private fun parsePrefixField(key: String, values: Map<String, String>): PrefixField {
return values["field"].let { field ->
if (field != null) {
values["value"].let { value ->
if (value != null) {
PrefixField(key, value, field.trim())
} else {
throw InvalidMappingException("Section: $key. A 'value' subfield in prefix definition is required.")
}
}
} else {
throw InvalidMappingException("Section: $key. A 'field' subfield in prefix definition is required.")
}
}
}
fun parseSimpleAnnotationField(key: String, item: Any): SimpleAnnotationField {
return when (item) {
is String -> DirectMapField(key, item.trim())
is Map<*, *> -> {
when {
item.containsKey("const") -> {
ConstantField(key, item["const"] as String)
}
item.containsKey("prefix") -> {
try {
parsePrefixField(key, item["prefix"] as Map<String, String>)
} catch (ex: ClassCastException) {
throw InvalidMappingException("Invalid structure for prefix field in section $key.")
}
}
else -> {
throw InvalidMappingException("Invalid key for a simple annotation field in section $key. Expected 'const' or 'prefix'.")
}
}
}
else -> throw InvalidMappingException("Invalid value for a simple annotation field in section $key. Expected 'const' or 'prefix' or a direct map.")
}
}
private fun parseFieldList(key: String, items: List<Any>): List<SimpleAnnotationField> {
return items.map {
parseSimpleAnnotationField(key, it)
}
}
fun parseAnnotationField(entry: Map.Entry<String, Any>): AnnotationField {
when (val value = entry.value) {
is String -> return DirectMapField(entry.key, value)
is Map<*, *> -> {
return if (value.containsKey("const")) {
ConstantField(entry.key, value["const"] as String)
} else if (value.containsKey("prefix")) {
try {
parsePrefixField(entry.key, value["prefix"] as Map<String, String>)
} catch (ex: ClassCastException) {
throw InvalidMappingException("Invalid structure for prefix field in section ${entry.key}.")
}
} else {
val mutableList = mutableListOf<Pair<String, List<SimpleAnnotationField>>>()
for (k in value.keys) {
if (k is String && listOf("de", "it", "fr").contains(k)) {
val resultAnnotations = when (val items = value[k]) {
is List<*> -> {
parseFieldList(entry.key, items as List<Any>)
}
is Any -> listOf(parseSimpleAnnotationField(entry.key, items))
else -> throw InvalidMappingException("Language map definition may not be empty.")
}
if (resultAnnotations.isEmpty()) {
throw InvalidMappingException("No valid definitions found under language tag $k in section ${entry.key}")
}
mutableList.add(Pair(k, resultAnnotations))
}
}
if (mutableList.isNotEmpty()) {
LanguageField(entry.key, mutableList)
} else {
throw InvalidMappingException("Unknown key values in field mapping: $value. Use 'const' or 'de', 'fr', 'it' language tags!")
}
}
}
is List<*> -> return ListField(
entry.key,
parseFieldList(entry.key, value as List<Any>)
)
else -> throw InvalidMappingException("Unknown structure for field mapping: $entry")
}
}
fun parseFieldWithKeyValidation(
parent: String,
entry: Map.Entry<String, Any>,
list: List<String>
): AnnotationField {
if (list.contains(entry.key)) {
return parseAnnotationField(entry)
} else {
throw InvalidMappingException("The section $parent does not allow the key: ${entry.key}. Use any of $list.")
}
}
fun parseSubFieldProperties(
parent: String,
entries: Set<Map.Entry<String, Any>>,
allowedSubFields: List<String>
): List<AnnotationField> {
return entries.map { entry ->
if (allowedSubFields.contains(entry.key)) {
return@map parseAnnotationField(entry)
} else {
throw InvalidMappingException("The section $parent only allows the following subfields: $allowedSubFields.")
}
}
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment