Skip to content

Commit 89f27e0

Browse files
committed
Merge branch 'alternative_record_key' into dev
2 parents 4b55e73 + 47c08c8 commit 89f27e0

File tree

2 files changed

+65
-43
lines changed

2 files changed

+65
-43
lines changed

src/main/java/org/radarbase/output/path/RecordPathFactory.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ abstract class RecordPathFactory : Plugin {
154154
}
155155
""".trimIndent())
156156

157-
private fun GenericRecord.getOrNull(fieldName: String): Any? = if (hasField(fieldName)) get(fieldName) else null
157+
fun GenericRecord.getFieldOrNull(fieldName: String): Schema.Field? {
158+
return schema.fields
159+
.find { it.name().equals(fieldName, ignoreCase = true) }
160+
}
161+
162+
fun GenericRecord.getOrNull(fieldName: String): Any? = getFieldOrNull(fieldName)
163+
?.let { get(it.pos()) }
158164
}
159165
}

src/main/java/org/radarbase/output/util/TimeUtil.kt

Lines changed: 58 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package org.radarbase.output.util
33
import com.fasterxml.jackson.databind.JsonNode
44
import org.apache.avro.Schema
55
import org.apache.avro.generic.GenericRecord
6+
import org.radarbase.output.path.RecordPathFactory.Companion.getFieldOrNull
7+
import org.radarbase.output.path.RecordPathFactory.Companion.getOrNull
68
import java.math.RoundingMode
79
import java.time.*
810
import java.time.format.DateTimeParseException
@@ -21,73 +23,74 @@ object TimeUtil {
2123
fun getDate(key: GenericRecord?,
2224
value: GenericRecord?): Instant? {
2325
value?.timeOrNull("time")
24-
?.let { return it }
26+
?.let { return it }
2527

2628
key?.run {
2729
timeOrNull("timeStart")
28-
?.let { return it }
29-
30+
?.let { return it }
3031

31-
schema.getField("start")
32-
?.takeIf { it.schema().type == Schema.Type.LONG }
33-
?.let { return Instant.ofEpochMilli(get(it.pos()) as Long) }
32+
getFieldOrNull("start")
33+
?.takeIf { it.hasType(Schema.Type.LONG) }
34+
?.let { get(it.pos()) as? Long }
35+
?.let { return Instant.ofEpochMilli(it) }
3436
}
3537

3638
value?.run {
3739
dateTimeOrNull("dateTime")
38-
?.let { return it }
40+
?.let { return it }
3941

4042
dateOrNull("date")
41-
?.let { return it }
43+
?.let { return it }
4244

4345
timeOrNull("timeReceived")
44-
?.let { return it }
46+
?.let { return it }
4547
timeOrNull("timeCompleted")
46-
?.let { return it }
48+
?.let { return it }
4749
}
4850

4951
return null
5052
}
5153

5254
fun getDate(key: JsonNode?, value: JsonNode?): Double? {
53-
value?.get("time")
54-
?.takeIf { it.isNumber }
55-
?.let { return it.asDouble() }
55+
value?.getOrNull("time")
56+
?.takeIf { it.isNumber }
57+
?.let { return it.asDouble() }
5658

5759
key?.run {
58-
get("timeStart")
59-
?.takeIf { it.isNumber }
60-
?.let { return it.asDouble() }
60+
getOrNull("timeStart")
61+
?.takeIf { it.isNumber }
62+
?.let { return it.asDouble() }
6163

62-
get("start")
63-
?.takeIf { it.isNumber }
64-
?.let { return it.asLong() / 1000.0 }
64+
getOrNull("start")
65+
?.takeIf { it.isNumber }
66+
?.let { return it.asLong() / 1000.0 }
6567
}
6668

6769
value?.run {
68-
get("dateTime")
69-
?.takeIf { it.isTextual }
70-
?.let { node -> return node.asText().parseDateTime()?.toDouble() }
70+
getOrNull("dateTime")
71+
?.takeIf { it.isTextual }
72+
?.let { node -> return node.asText().parseDateTime()?.toDouble() }
7173

72-
get("date")
73-
?.takeIf { it.isTextual }
74-
?.let { node -> return node.asText().parseDate()?.toDouble() }
74+
getOrNull("date")
75+
?.takeIf { it.isTextual }
76+
?.let { node -> return node.asText().parseDate()?.toDouble() }
7577

76-
get("timeReceived")
77-
?.takeIf { it.isNumber }
78-
?.let { return it.asDouble() }
78+
getOrNull("timeReceived")
79+
?.takeIf { it.isNumber }
80+
?.let { return it.asDouble() }
7981

80-
get("timeCompleted")
81-
?.takeIf { it.isNumber }
82-
?.let { return it.asDouble() }
82+
getOrNull("timeCompleted")
83+
?.takeIf { it.isNumber }
84+
?.let { return it.asDouble() }
8385
}
8486

8587
return null
8688
}
8789

88-
private fun GenericRecord.timeOrNull(fieldName: String): Instant? = schema.getField(fieldName)
89-
?.takeIf { it.schema().type == Schema.Type.DOUBLE }
90-
?.let { (get(it.pos()) as Double).toInstant() }
90+
private fun GenericRecord.timeOrNull(fieldName: String): Instant? = getFieldOrNull(fieldName)
91+
?.takeIf { it.hasType(Schema.Type.DOUBLE) }
92+
?.let { (get(it.pos()) as? Double) }
93+
?.toInstant()
9194

9295
/**
9396
* Parse the dateTime field of a record, if present.
@@ -96,9 +99,11 @@ object TimeUtil {
9699
* @return `Instant` representing the dateTime or `null` if the field cannot be
97100
* found or parsed.
98101
*/
99-
private fun GenericRecord.dateTimeOrNull(fieldName: String): Instant? = schema.getField(fieldName)
100-
?.takeIf { it.schema().type == Schema.Type.STRING }
101-
?.let { get(it.pos()).toString().parseDateTime() }
102+
private fun GenericRecord.dateTimeOrNull(fieldName: String): Instant? = getFieldOrNull(fieldName)
103+
?.takeIf { it.hasType(Schema.Type.STRING) }
104+
?.let { get(it.pos()) }
105+
?.toString()
106+
?.parseDateTime()
102107

103108
/**
104109
* Parse the date field of a record, if present.
@@ -107,9 +112,11 @@ object TimeUtil {
107112
* @return `Instant` representing the start of given date or `null` if the field
108113
* cannot be found or parsed.
109114
*/
110-
private fun GenericRecord.dateOrNull(fieldName: String): Instant? = schema.getField(fieldName)
111-
?.takeIf { it.schema().type == Schema.Type.STRING }
112-
?.let { get(it.pos()).toString().parseDate() }
115+
private fun GenericRecord.dateOrNull(fieldName: String): Instant? = getFieldOrNull(fieldName)
116+
?.takeIf { it.hasType(Schema.Type.STRING) }
117+
?.let { get(it.pos()) }
118+
?.toString()
119+
?.parseDate()
113120

114121
private fun Double.toInstant(): Instant {
115122
val time = toBigDecimal()
@@ -122,8 +129,8 @@ object TimeUtil {
122129

123130
fun String.parseDate(): Instant? = try {
124131
LocalDate.parse(this)
125-
.atStartOfDay(ZoneOffset.UTC)
126-
.toInstant()
132+
.atStartOfDay(ZoneOffset.UTC)
133+
.toInstant()
127134
} catch (ex: DateTimeParseException) {
128135
null
129136
}
@@ -142,6 +149,15 @@ object TimeUtil {
142149
+ (nano.toBigDecimal().divide(NANO_MULTIPLIER, 9, RoundingMode.HALF_UP))
143150
).toDouble()
144151

152+
private fun JsonNode.getOrNull(fieldName: String): JsonNode? = fields().asSequence()
153+
.find { (name, _) -> name.equals(fieldName, ignoreCase = true) }
154+
?.value
155+
156+
private fun Schema.Field.hasType(type: Schema.Type): Boolean {
157+
val s = schema()
158+
return s.type == type
159+
|| (s.type == Schema.Type.UNION && s.types.any { it.type == type })
160+
}
145161

146162
fun Temporal.durationSince(): Duration = Duration.between(this, Instant.now())
147163
}

0 commit comments

Comments
 (0)