|
16 | 16 |
|
17 | 17 | package org.radarbase.output.path
|
18 | 18 |
|
| 19 | +import org.apache.avro.Schema |
19 | 20 | import org.apache.avro.generic.GenericRecord
|
| 21 | +import org.apache.avro.generic.GenericRecordBuilder |
20 | 22 | import org.radarbase.output.Plugin
|
21 | 23 | import org.radarbase.output.util.TimeUtil
|
22 | 24 | import org.slf4j.LoggerFactory
|
@@ -55,19 +57,29 @@ abstract class RecordPathFactory : Plugin {
|
55 | 57 | */
|
56 | 58 | open fun getRecordOrganization(topic: String,
|
57 | 59 | record: GenericRecord, attempt: Int): RecordOrganization {
|
58 |
| - val keyField = record.get("key") as? GenericRecord |
| 60 | + val keyField = record.get("key") |
59 | 61 | val valueField = record.get("value") as? GenericRecord
|
60 | 62 |
|
61 | 63 | if (keyField == null || valueField == null) {
|
62 | 64 | logger.error("Failed to process {}", record)
|
63 | 65 | throw IllegalArgumentException("Failed to process $record; no key or value")
|
64 | 66 | }
|
65 | 67 |
|
66 |
| - val time = TimeUtil.getDate(keyField, valueField) |
| 68 | + val keyRecord: GenericRecord = if (keyField is GenericRecord) { |
| 69 | + keyField |
| 70 | + } else { |
| 71 | + GenericRecordBuilder(observationKeySchema) |
| 72 | + .set("projectId", valueField.getOrNull("projectId")) |
| 73 | + .set("userId", keyField.toString()) |
| 74 | + .set("sourceId", valueField.getOrNull("sourceId") ?: "unknown") |
| 75 | + .build() |
| 76 | + } |
| 77 | + |
| 78 | + val time = TimeUtil.getDate(keyRecord, valueField) |
67 | 79 |
|
68 |
| - val relativePath = getRelativePath(topic, keyField, valueField, time, attempt) |
| 80 | + val relativePath = getRelativePath(topic, keyRecord, valueField, time, attempt) |
69 | 81 | val outputPath = root.resolve(relativePath)
|
70 |
| - val category = getCategory(keyField, valueField) |
| 82 | + val category = getCategory(keyRecord, valueField) |
71 | 83 | return RecordOrganization(outputPath, category, time)
|
72 | 84 | }
|
73 | 85 |
|
@@ -119,5 +131,21 @@ abstract class RecordPathFactory : Plugin {
|
119 | 131 | ?.let { ILLEGAL_CHARACTER_PATTERN.matcher(it.toString()).replaceAll("") }
|
120 | 132 | ?.takeIf { it.isNotEmpty() }
|
121 | 133 | ?: defaultValue
|
| 134 | + |
| 135 | + private val observationKeySchema = Schema.Parser().parse(""" |
| 136 | + { |
| 137 | + "namespace": "org.radarcns.kafka", |
| 138 | + "type": "record", |
| 139 | + "name": "ObservationKey", |
| 140 | + "doc": "Key of an observation.", |
| 141 | + "fields": [ |
| 142 | + {"name": "projectId", "type": ["null", "string"], "doc": "Project identifier. Null if unknown or the user is not enrolled in a project.", "default": null}, |
| 143 | + {"name": "userId", "type": "string", "doc": "User Identifier created during the enrolment."}, |
| 144 | + {"name": "sourceId", "type": "string", "doc": "Unique identifier associated with the source."} |
| 145 | + ] |
| 146 | + } |
| 147 | + """.trimIndent()) |
| 148 | + |
| 149 | + private fun GenericRecord.getOrNull(fieldName: String): Any? = if (hasField(fieldName)) get(fieldName) else null |
122 | 150 | }
|
123 | 151 | }
|
0 commit comments