All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.pylons.ipc.IPCLayer.kt Maven / Gradle / Ivy

package tech.pylons.ipc

import java.lang.reflect.Method
import kotlin.random.Random

abstract class IPCLayer(val permitUnboundOperations : Boolean) {
    var clientId : Int = 0
    var walletId : Int = Random.nextInt()
    var messageId : Int = 0

    class NoClientException : Exception() { }
    class ConnectionBrokenException : Exception() { }

    enum class ConnectionState {
        NoClient,
        Connected,
        ConnectionBroken
    }

    annotation class OnGetNext

    protected open fun initIpcChannel() { if (!permitUnboundOperations) establishConnection(); initialized = true }
    protected abstract fun getNextJson(callback: (String) -> Unit)
    protected open fun preprocessResponse(r : Response,
                                          callback: (Response) -> Unit) {callback(r)}
    protected open fun cleanup() {}
    abstract fun establishConnection()
    abstract fun checkConnectionStatus() : ConnectionState
    abstract fun connectionBroken()
    abstract fun submit (r : Response)
    abstract fun reject (json : String)

    var connectionState : ConnectionState = ConnectionState.NoClient
        private set
    protected var initialized = false

    fun onMessage (msg : Message) {
        msg.ui()
    }

    fun onUiConfirmed (uiHook: Message.UiHook) {
        uiHook.response = uiHook.msg.resolve()
        handleResponse(uiHook.response!!)
    }

    fun onUiRejected (uiHook: Message.UiHook) {
        uiHook.response = Response.emit(uiHook.msg, false)
        handleResponse(uiHook.response!!)
    }

    fun onUiReleased (uiHook: Message.UiHook) {
        // Unclear on what if anything needs to be done here rn
    }

    companion object {
        var implementation : IPCLayer? = null
            set(value) { field = value; init() }
        private lateinit var onGetNextList : List

        private fun init () {
            onGetNextList = findAllOnGetNextMethods()
        }

        private fun updateConnectionState() {
            implementation!!.connectionState = implementation!!.checkConnectionStatus()
            if (implementation!!.connectionState == ConnectionState.NoClient && !implementation!!.permitUnboundOperations)
                throw NoClientException()
            else if (implementation!!.connectionState == ConnectionState.ConnectionBroken && !implementation!!.permitUnboundOperations)
                throw ConnectionBrokenException()
        }

        private fun findAllOnGetNextMethods () : List {
            val ls = mutableListOf()
            implementation!!::class.java.declaredMethods.forEach {
                if (it.getAnnotation(OnGetNext::class.java) != null)
                    ls.add(it)
            }
            return ls
        }

        fun getNextMessage(callback : (Message) -> Unit) {
            safelyDoIpcOperation {
                implementation?.getNextJson {
                    println("got: \n$it")
                    val msg = Message.match(it)
                    println("matched!")
                    when (msg) {
                        null -> implementation!!.reject(it)
                        else -> {
                            onGetNextList.forEach { method ->
                                method.invoke(implementation, msg)
                            }
                            implementation!!.onMessage(msg)
                            println("trying to do callback")

                            callback(msg)
                        }
                    }
                }
            }
        }

        fun handleResponse(r : Response) {
            println("handleResponse safelyDoIpcOperation")
            safelyDoIpcOperation {
                println("preprocessResponse")
                implementation!!.preprocessResponse(r) {
                    implementation!!.submit(r)
                    implementation!!.cleanup()
                }
            }
        }

        private fun safelyDoIpcOperation (action : () -> Unit) {
            if (!implementation!!.initialized) implementation!!.initIpcChannel()
            try {
                updateConnectionState()
                action()
            } catch (e : Exception) {
                when (e) {
                    is NoClientException -> {
                        implementation!!.establishConnection()
                    }
                    is ConnectionBrokenException -> {
                        implementation!!.connectionBroken()
                    }
                    else -> throw e // todo: this should do some logging before it dies
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy