package netty.handler.context
abstract class AbstractChannelHandlerContext(private val inBound : Boolean, val outBound : Boolean){
lateinit var next : AbstractChannelHandlerContext
lateinit var prev : AbstractChannelHandlerContext
abstract fun handler() : ChannelHandler
fun fireChannelRegistered() {
invokeChannelRegistered(findContextInbound())
}
private fun findContextInbound(): AbstractChannelHandlerContext {
var ctx : AbstractChannelHandlerContext = this
do {
ctx = ctx.next
}while (!ctx.inBound)
return ctx
}
private fun invokeChannelRegistered(next : AbstractChannelHandlerContext) {
(next.handler() as ChannelInBoundHandler).channelRegistered()
}
companion object {
fun invokeChannelRegistered(ctx: AbstractChannelHandlerContext) {
ctx.fireChannelRegistered()
}
}
}
class HeadContext : AbstractChannelHandlerContext(false, true), ChannelOutBoundHandler {
override fun handler(): ChannelHandler = this
}
class TailContext : AbstractChannelHandlerContext(true, false), ChannelOutBoundHandler {
override fun handler(): ChannelHandler = this
}
class DefaultChannelHandlerContext(var handler : ChannelHandler) : AbstractChannelHandlerContext(isInBound(handler), isOutBound(handler)) {
override fun handler() = handler
companion object {
fun isOutBound(handler : ChannelHandler) = handler is ChannelOutBoundHandler
fun isInBound(handler : ChannelHandler) = handler is ChannelInBoundHandler
}
}
interface ChannelInBoundHandler : ChannelHandler{
fun channelRegistered()
}
interface ChannelHandler {
}
class Pipeline(
private val head: AbstractChannelHandlerContext = HeadContext(),
private val tail : AbstractChannelHandlerContext = TailContext()
) {
init {
head.next = tail
tail.prev = head
}
fun addLast(handler : ChannelHandler){
val context = newContext(handler)
addLast(context)
}
private fun addLast(ctx: AbstractChannelHandlerContext) {
val prev = tail.prev
ctx.next = tail
ctx.prev = prev
prev.next = ctx
tail.prev = ctx
}
private fun newContext(handler : ChannelHandler) = DefaultChannelHandlerContext(handler)
fun fireChannelRegistered(){
AbstractChannelHandlerContext.invokeChannelRegistered(head)
}
}