Skip to content

Commit 3d01fbf

Browse files
committed
Use proper factory pattern
1 parent f09712c commit 3d01fbf

File tree

5 files changed

+106
-84
lines changed

5 files changed

+106
-84
lines changed

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

Lines changed: 62 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,70 +5,79 @@ import org.slf4j.LoggerFactory
55
import java.time.ZoneOffset
66
import java.time.format.DateTimeFormatter
77

8-
class FixedPathFormatterPlugin : PathFormatterPlugin() {
9-
private lateinit var timeBinFormat: DateTimeFormatter
10-
override val name: String = "fixed"
8+
class FixedPathFormatterPlugin : PathFormatterPlugin.Factory {
9+
override fun create(
10+
properties: Map<String, String>
11+
): PathFormatterPlugin = Plugin(properties)
1112

12-
override val allowedFormats: String = allowedParamNames.joinToString(separator = ", ")
13+
internal class Plugin(properties: Map<String, String>) : PathFormatterPlugin() {
14+
private val timeBinFormat: DateTimeFormatter
15+
override val name: String = "fixed"
1316

14-
override fun init(properties: Map<String, String>) {
15-
super.init(properties)
16-
timeBinFormat = createTimeBinFormatter(properties["timeBinFormat"])
17-
}
17+
override val allowedFormats: String = allowedParamNames.joinToString(separator = ", ")
1818

19-
private fun createTimeBinFormatter(pattern: String?): DateTimeFormatter {
20-
pattern ?: return HOURLY_TIME_BIN_FORMAT
19+
init {
20+
timeBinFormat = createTimeBinFormatter(properties["timeBinFormat"])
21+
}
2122

22-
return try {
23-
DateTimeFormatter
24-
.ofPattern(pattern)
25-
.withZone(ZoneOffset.UTC)
26-
} catch (ex: IllegalArgumentException) {
27-
logger.error(
28-
"Cannot use time bin format {}, using {} instead",
29-
pattern,
30-
HOURLY_TIME_BIN_FORMAT,
31-
ex,
32-
)
33-
HOURLY_TIME_BIN_FORMAT
23+
private fun createTimeBinFormatter(pattern: String?): DateTimeFormatter {
24+
pattern ?: return HOURLY_TIME_BIN_FORMAT
25+
26+
return try {
27+
DateTimeFormatter
28+
.ofPattern(pattern)
29+
.withZone(ZoneOffset.UTC)
30+
} catch (ex: IllegalArgumentException) {
31+
logger.error(
32+
"Cannot use time bin format {}, using {} instead",
33+
pattern,
34+
HOURLY_TIME_BIN_FORMAT,
35+
ex,
36+
)
37+
HOURLY_TIME_BIN_FORMAT
38+
}
3439
}
35-
}
3640

37-
override fun lookup(parameterContents: String): PathFormatParameters.() -> String = when (parameterContents) {
38-
"projectId" -> ({ sanitizeId(key.get("projectId"), "unknown-project") })
39-
"userId" -> ({ sanitizeId(key.get("userId"), "unknown-user") })
40-
"sourceId" -> ({ sanitizeId(key.get("sourceId"), "unknown-source") })
41-
"topic" -> ({ topic })
42-
"filename" -> (
43-
{
44-
val timeBin = sanitizeId(time?.let { timeBinFormat.format(it) }, "unknown-time")
45-
timeBin + attempt.toAttemptSuffix() + extension
41+
override fun lookup(parameterContents: String): PathFormatParameters.() -> String =
42+
when (parameterContents) {
43+
"projectId" -> ({ sanitizeId(key.get("projectId"), "unknown-project") })
44+
"userId" -> ({ sanitizeId(key.get("userId"), "unknown-user") })
45+
"sourceId" -> ({ sanitizeId(key.get("sourceId"), "unknown-source") })
46+
"topic" -> ({ topic })
47+
"filename" -> {
48+
{
49+
val timeBin = if (time != null) {
50+
timeBinFormat.format(time)
51+
} else "unknown-time"
52+
timeBin + attempt.toAttemptSuffix() + extension
53+
}
54+
}
55+
"attempt" -> ({ attempt.toAttemptSuffix() })
56+
"extension" -> ({ extension })
57+
else -> throw IllegalArgumentException("Unknown path parameter $parameterContents")
4658
}
47-
)
48-
"attempt" -> ({ attempt.toAttemptSuffix() })
49-
"extension" -> ({ extension })
50-
else -> throw IllegalArgumentException("Unknown path parameter $parameterContents")
51-
}
5259

53-
override fun extractParamContents(paramName: String): String? = paramName.takeIf { it in allowedParamNames }
60+
override fun extractParamContents(paramName: String): String? =
61+
paramName.takeIf { it in allowedParamNames }
5462

55-
companion object {
56-
val allowedParamNames = setOf(
57-
"projectId",
58-
"userId",
59-
"sourceId",
60-
"topic",
61-
"filename",
62-
"attempt",
63-
"extension",
64-
)
63+
companion object {
64+
val allowedParamNames = setOf(
65+
"projectId",
66+
"userId",
67+
"sourceId",
68+
"topic",
69+
"filename",
70+
"attempt",
71+
"extension",
72+
)
6573

66-
val HOURLY_TIME_BIN_FORMAT: DateTimeFormatter = DateTimeFormatter
67-
.ofPattern("yyyyMMdd_HH'00'")
68-
.withZone(ZoneOffset.UTC)
74+
val HOURLY_TIME_BIN_FORMAT: DateTimeFormatter = DateTimeFormatter
75+
.ofPattern("yyyyMMdd_HH'00'")
76+
.withZone(ZoneOffset.UTC)
6977

70-
private fun Int.toAttemptSuffix() = if (this == 0) "" else "_$this"
78+
private fun Int.toAttemptSuffix() = if (this == 0) "" else "_$this"
7179

72-
private val logger = LoggerFactory.getLogger(FixedPathFormatterPlugin::class.java)
80+
private val logger = LoggerFactory.getLogger(Plugin::class.java)
81+
}
7382
}
7483
}

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

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,25 +68,32 @@ open class FormattedPathFactory : RecordPathFactory() {
6868
)
6969
private val logger = LoggerFactory.getLogger(FormattedPathFactory::class.java)
7070

71-
internal fun String.toPathFormatterPlugin(): PathFormatterPlugin? = when (this) {
72-
"fixed" -> FixedPathFormatterPlugin()
71+
internal fun String.toPathFormatterPlugin(
72+
properties: Map<String, String>,
73+
): PathFormatterPlugin? = when (this) {
74+
"fixed" -> FixedPathFormatterPlugin().create(properties)
7375
"time" -> TimePathFormatterPlugin()
7476
"key" -> KeyPathFormatterPlugin()
7577
"value" -> ValuePathFormatterPlugin()
7678
else -> {
7779
try {
78-
Class.forName(this).getConstructor()
79-
.newInstance() as PathFormatterPlugin
80+
val clazz = Class.forName(this)
81+
when (val plugin = clazz.getConstructor().newInstance()) {
82+
is PathFormatterPlugin -> plugin
83+
is PathFormatterPlugin.Factory -> plugin.create(properties)
84+
else -> {
85+
logger.error(
86+
"Failed to instantiate plugin {}, it does not extend {} or {}",
87+
this,
88+
PathFormatterPlugin::class.jvmName,
89+
PathFormatterPlugin.Factory::class.jvmName
90+
)
91+
null
92+
}
93+
}
8094
} catch (ex: ReflectiveOperationException) {
8195
logger.error("Failed to instantiate plugin {}", this)
8296
null
83-
} catch (ex: ClassCastException) {
84-
logger.error(
85-
"Failed to instantiate plugin {}, it does not extend {}",
86-
this,
87-
PathFormatterPlugin::class.jvmName
88-
)
89-
null
9097
}
9198
}
9299
}
@@ -99,8 +106,7 @@ open class FormattedPathFactory : RecordPathFactory() {
99106
fun createPlugins(): List<PathFormatterPlugin> = pluginNames
100107
.trim()
101108
.split("\\s+".toRegex())
102-
.mapNotNull { it.toPathFormatterPlugin() }
103-
.onEach { it.init(properties) }
109+
.mapNotNull { it.toPathFormatterPlugin(properties) }
104110

105111
fun withValues(values: Map<String, String>): PathFormatterConfig {
106112
val newProperties = HashMap(properties).apply {

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package org.radarbase.output.path
22

3-
import org.radarbase.output.Plugin
4-
5-
abstract class PathFormatterPlugin : Plugin {
3+
abstract class PathFormatterPlugin {
64
/**
75
* Short name to reference this plugin by.
86
*/
@@ -52,4 +50,13 @@ abstract class PathFormatterPlugin : Plugin {
5250
* @throws IllegalArgumentException if the parameter contents are invalid.
5351
*/
5452
protected abstract fun lookup(parameterContents: String): PathFormatParameters.() -> String
53+
54+
interface Factory {
55+
/**
56+
* Factory to create new plugin with.
57+
*/
58+
fun create(
59+
properties: Map<String, String> = emptyMap(),
60+
): PathFormatterPlugin
61+
}
5562
}

src/test/java/org/radarbase/output/path/FormattedPathFactoryTest.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,22 +107,22 @@ internal class FormattedPathFactoryTest {
107107

108108
@Test
109109
fun testNamedPluginCreate() {
110-
assertThat("fixed".toPathFormatterPlugin(), instanceOf(FixedPathFormatterPlugin::class.java))
111-
assertThat("time".toPathFormatterPlugin(), instanceOf(TimePathFormatterPlugin::class.java))
112-
assertThat("key".toPathFormatterPlugin(), instanceOf(KeyPathFormatterPlugin::class.java))
113-
assertThat("value".toPathFormatterPlugin(), instanceOf(ValuePathFormatterPlugin::class.java))
110+
assertThat("fixed".toPathFormatterPlugin(emptyMap()), instanceOf(PathFormatterPlugin::class.java))
111+
assertThat("time".toPathFormatterPlugin(emptyMap()), instanceOf(PathFormatterPlugin::class.java))
112+
assertThat("key".toPathFormatterPlugin(emptyMap()), instanceOf(PathFormatterPlugin::class.java))
113+
assertThat("value".toPathFormatterPlugin(emptyMap()), instanceOf(PathFormatterPlugin::class.java))
114114
}
115115

116116
@Test
117117
fun testBadPluginCreate() {
118-
assertThat("unknown".toPathFormatterPlugin(), nullValue())
118+
assertThat("unknown".toPathFormatterPlugin(emptyMap()), nullValue())
119119
}
120120

121121
@Test
122122
fun testClassPathPluginCreate() {
123123
assertThat(
124-
FixedPathFormatterPlugin::class.jvmName.toPathFormatterPlugin(),
125-
instanceOf(FixedPathFormatterPlugin::class.java),
124+
FixedPathFormatterPlugin::class.jvmName.toPathFormatterPlugin(emptyMap()),
125+
instanceOf(PathFormatterPlugin::class.java),
126126
)
127127
}
128128
}

src/test/java/org/radarbase/output/path/PathFormatterTest.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal class PathFormatterTest {
3939
val formatter = PathFormatter(
4040
format = FormattedPathFactory.Companion.DEFAULTS.format,
4141
plugins = listOf(
42-
FixedPathFormatterPlugin(),
42+
FixedPathFormatterPlugin().create(),
4343
TimePathFormatterPlugin(),
4444
KeyPathFormatterPlugin(),
4545
ValuePathFormatterPlugin(),
@@ -53,7 +53,7 @@ internal class PathFormatterTest {
5353
val formatter = PathFormatter(
5454
format = FormattedPathFactory.Companion.DEFAULTS.format,
5555
plugins = listOf(
56-
FixedPathFormatterPlugin(),
56+
FixedPathFormatterPlugin().create(),
5757
)
5858
)
5959
assertThat(formatter.format(params), equalTo(Paths.get("p/u/my_topic/19700101_0000.csv")))
@@ -64,7 +64,7 @@ internal class PathFormatterTest {
6464
val formatter = PathFormatter(
6565
format = FormattedPathFactory.Companion.DEFAULTS.format,
6666
plugins = listOf(
67-
FixedPathFormatterPlugin(),
67+
FixedPathFormatterPlugin().create(),
6868
)
6969
)
7070
assertThat(formatter.format(params.copy(time = null)), equalTo(Paths.get("p/u/my_topic/unknown-time.csv")))
@@ -89,7 +89,7 @@ internal class PathFormatterTest {
8989
val formatter = PathFormatter(
9090
format = "\${topic}/\${time:YYYY-MM-dd_HH:mm:ss}\${attempt}\${extension}",
9191
plugins = listOf(
92-
FixedPathFormatterPlugin(),
92+
FixedPathFormatterPlugin().create(),
9393
TimePathFormatterPlugin(),
9494
),
9595
)
@@ -102,7 +102,7 @@ internal class PathFormatterTest {
102102
PathFormatter(
103103
format = "\${topic}/\${time:VVV}\${attempt}\${extension}",
104104
plugins = listOf(
105-
FixedPathFormatterPlugin(),
105+
FixedPathFormatterPlugin().create(),
106106
TimePathFormatterPlugin(),
107107
)
108108
)
@@ -114,7 +114,7 @@ internal class PathFormatterTest {
114114
val formatter = PathFormatter(
115115
format = "\${topic}/\${key:projectId}\${attempt}\${extension}",
116116
plugins = listOf(
117-
FixedPathFormatterPlugin(),
117+
FixedPathFormatterPlugin().create(),
118118
KeyPathFormatterPlugin(),
119119
)
120120
)
@@ -127,7 +127,7 @@ internal class PathFormatterTest {
127127
val formatter = PathFormatter(
128128
format = "\${topic}/\${key:doesNotExist}\${attempt}\${extension}",
129129
plugins = listOf(
130-
FixedPathFormatterPlugin(),
130+
FixedPathFormatterPlugin().create(),
131131
KeyPathFormatterPlugin(),
132132
)
133133
)
@@ -140,7 +140,7 @@ internal class PathFormatterTest {
140140
val formatter = PathFormatter(
141141
format = "\${topic}/\${value:serverStatus}\${attempt}\${extension}",
142142
plugins = listOf(
143-
FixedPathFormatterPlugin(),
143+
FixedPathFormatterPlugin().create(),
144144
ValuePathFormatterPlugin(),
145145
)
146146
)

0 commit comments

Comments
 (0)