Justin Fiedler
08/09/2021, 2:26 PMJustin Fiedler
08/09/2021, 2:27 PM// BASE GENERIC CLASSES
open class PluginCallOptions: HashMap<String, Any?>()
open class CallOptions: HashMap<String, PluginCallOptions>()
abstract class Plugin<I: PluginCallOptions, G: PluginCallOptions>(
private val id: String
) {
fun id(): String {
return id
}
open fun identify(userId: String?, options: I? = null) {
println("identify $id $options")
}
open fun group(userId: String?, options: G? = null) {
println("group $id $options")
}
}
// PLUGIN SUBCLASSES
class MyIdentifyOptions(val iProp: String): PluginCallOptions()
class MyGroupOptions(val gProp: String): PluginCallOptions()
class MyPlugin: Plugin<MyIdentifyOptions, MyGroupOptions>("myPlugin") {
override fun identify(userId: String?, options: MyIdentifyOptions?) {
super.identify(userId, options)
}
override fun group(userId: String?, options: MyGroupOptions?) {
super.group(userId, options)
}
}
class MyOtherIdentifyOptions(val iProp: String): PluginCallOptions()
class MyOtherGroupOptions(val gProp: String): PluginCallOptions()
class MyOtherPlugin: Plugin<MyOtherIdentifyOptions, MyOtherGroupOptions>("myOtherPlugin") {
override fun identify(userId: String?, options: MyOtherIdentifyOptions?) {
super.identify(userId, options)
}
override fun group(userId: String?, options: MyOtherGroupOptions?) {
super.group(userId, options)
}
}
class IdentifyOptions(
var myPlugin: MyIdentifyOptions? = null,
var myOtherPlugin: MyOtherIdentifyOptions? = null,
): CallOptions()
class GroupOptions(
var myPlugin: MyGroupOptions? = null,
var myOtherPlugin: MyOtherGroupOptions? = null,
): CallOptions()
class Iterator(val plugins: List<Plugin<out PluginCallOptions, out PluginCallOptions>>) {
fun identify(userId: String, callOptions: IdentifyOptions) {
// ERROR here
iterate { plugin -> plugin.identify(userId, callOptions.get(plugin.id())) }
}
fun group(userId: String, callOptions: GroupOptions) {
// ERROR here
iterate { plugin -> plugin.group(userId, callOptions.get(plugin.id())) }
}
fun iterate(method: (plugin: Plugin<out PluginCallOptions, out PluginCallOptions>) -> Unit) {
plugins.forEach {
method(it)
}
}
}
// EXAMPLE USAGE
val iter = Iterator(plugins = arrayListOf(MyPlugin(), MyOtherPlugin()))
iter.identify("user-id", IdentifyOptions(
myPlugin = MyIdentifyOptions(iProp = "Identify value")
))
iter.group("user-id", GroupOptions(
myOtherPlugin = MyOtherGroupOptions(gProp = "Group value")
))
Justin Fiedler
08/09/2021, 2:28 PMJustin Fiedler
08/09/2021, 2:36 PMin
instead but then I need to typecast the values in the plugins
array and the PluginCallOptions values never make it to the underlying Plugins.
// BASE GENERIC CLASSES
open class PluginCallOptions: HashMap<String, Any?>()
open class CallOptions: HashMap<String, PluginCallOptions>()
abstract class Plugin<in I: PluginCallOptions, in G: PluginCallOptions>(
private val id: String
) {
fun id(): String {
return id
}
open fun identify(userId: String?, options: I? = null) {
println("identify $id $options")
}
open fun group(userId: String?, options: G? = null) {
println("group $id $options")
}
}
// PLUGIN SUBCLASSES
class MyIdentifyOptions(val iProp: String): PluginCallOptions()
class MyGroupOptions(val gProp: String): PluginCallOptions()
class MyPlugin: Plugin<MyIdentifyOptions, MyGroupOptions>("myPlugin") {
override fun identify(userId: String?, options: MyIdentifyOptions?) {
super.identify(userId, options)
}
override fun group(userId: String?, options: MyGroupOptions?) {
super.group(userId, options)
}
}
class MyOtherIdentifyOptions(val iProp: String): PluginCallOptions()
class MyOtherGroupOptions(val gProp: String): PluginCallOptions()
class MyOtherPlugin: Plugin<MyOtherIdentifyOptions, MyOtherGroupOptions>("myOtherPlugin") {
override fun identify(userId: String?, options: MyOtherIdentifyOptions?) {
super.identify(userId, options)
}
override fun group(userId: String?, options: MyOtherGroupOptions?) {
super.group(userId, options)
}
}
class IdentifyOptions(
var myPlugin: MyIdentifyOptions? = null,
var myOtherPlugin: MyOtherIdentifyOptions? = null,
): CallOptions()
class GroupOptions(
var myPlugin: MyGroupOptions? = null,
var myOtherPlugin: MyOtherGroupOptions? = null,
): CallOptions()
class Iterator(val plugins: List<Plugin<in PluginCallOptions, in PluginCallOptions>>) {
fun identify(userId: String, callOptions: IdentifyOptions) {
iterate { plugin -> plugin.identify(userId, callOptions.get(plugin.id())) }
}
fun group(userId: String, callOptions: GroupOptions) {
iterate { plugin -> plugin.group(userId, callOptions.get(plugin.id())) }
}
fun iterate(method: (plugin: Plugin<in PluginCallOptions, in PluginCallOptions>) -> Unit) {
plugins.forEach {
method(it)
}
}
}
val iter = Iterator(plugins = arrayListOf(
MyPlugin() as Plugin<PluginCallOptions, PluginCallOptions>,
MyOtherPlugin() as Plugin<PluginCallOptions, PluginCallOptions>
))
iter.identify("user-id", IdentifyOptions(
myPlugin = MyIdentifyOptions(iProp = "Identify value")
))
iter.group("user-id", GroupOptions(
myOtherPlugin = MyOtherGroupOptions(gProp = "Group value")
))