-
Notifications
You must be signed in to change notification settings - Fork 0
Extensions
Extensions of events can add new properties, functions, and implement functions of the base event.
Early Note: You can specify both extensionClass and implement in same @Extension annotation, but we will not show this in these examples.
If you only wish to create a variant with more properties, you can simply define an interface:
interface BusinessEvent : Event {
val business: Business
}To define the Extension you can use @Extension annotation in a new function of Factory interface:
interface MyFactory {
fun createBuyEvent(product: Product, amount: Int): BuyEvent
@Extension(implement = BusinessEvent::class)
fun createBuyEvent(product: Product, amount: Int, business: Business): BuyEvent
}Or create event with EventGenerator.createEventClass and specify extensions:
manager.eventGenerator.createEventClass<BuyEvent>(extensions = listOf(ExtensionSpecification(
residence = Unit, // Normally @Extension annotated element, but does not applies to this case
extensionClass = null,
implement = BusinessEvent::class.java
)))To provide implementation to functions that does not have a default implementation, or to override other functions or to override properties, you need an extension class. An extension class must have a single parameter constructor that receives an event, this event can be a sub-type of event to apply extension or the exact event type:
class AmountTenExtension(val event: Event) { // In this case, we will use a sub-type
val amount: Int = 10
}This will override amount property of events that have this property and always returns 10. To create a variant we do the same thing as before, but instead of defining implement, we define extensionClass:
interface MyFactory {
fun createBuyEvent(product: Product, amount: Int): BuyEvent
@Extension(implement = BusinessEvent::class)
fun createBuyEvent(product: Product, amount: Int, business: Business): BuyEvent
@Extension(extensionClass = AmountTenExtension::class)
fun createBuyEvent(product: Product): BuyEvent
}Note that there is no amount property in factory function, this is because we overwritten the property in AmountTenExtension, if you add amount parameter to factory function it will count as additional property and cause a function duplication, which EventSys will detect and fail to create event class.
Also extension classes can override functions and properties of @Extension.implement specified interface.
You can specify a default extension for an event before it is generated, this is useful when the event does not have a default implementation for a function.
interface TransactionEvent : Event {
var amount: Double
fun apply(func: (amount: Double) -> Double)
}
EventSys will normally generate a class for this event but will warn (in red) about the abstract method:
Following methods was not implemented for event TransactionEvent:
public abstract void com.github.projectsandstone.eventsys.test.wiki.TransactionEvent.apply(kotlin.jvm.functions.Function1)
Provide an extension which implement them.
If you try to invoke this method, a java.lang.AbstractMethodError will be throw by the JVM.
To provide an extension we use EventGenerator.registerExtension before event class generation (and before factory generation).
First write the extension:
class ApplyExt(val transactionEvent: TransactionEvent) {
fun apply(f: (amount: Double) -> Double) {
this.transactionEvent.amount = f(this.transactionEvent.amount)
}
}Now register it:
manager.eventGenerator.registerExtension(TransactionEvent::class.java, ExtensionSpecification(
residence = Unit,
extensionClass = ApplyExt::class.java,
implement = null
))Because of this nature, you can hide the implementation of the function (in modular projects for example).
If you're a crazy people like me, you can annotate TransactionEvent with Extension:
@Extension(extensionClass = ApplyExt::class)
interface TransactionEvent : Event {
var amount: Double
fun apply(f: (amount: Double) -> Double)
}Also you can use default implementations too, like a normal people:
interface TransactionEvent : Event {
var amount: Double
fun apply(f: (amount: Double) -> Double) = f(this.amount).also { this.amount = it }
}