XYOracleNetwork/sdk-core-kotlin

View on GitHub
core-android-library/src/main/kotlin/network/xyo/sdkcorekotlin/persist/repositories/XyoStorageBridgeQueueRepository.kt

Summary

Maintainability
A
30 mins
Test Coverage
package network.xyo.sdkcorekotlin.persist.repositories

import android.annotation.SuppressLint
import network.xyo.sdkcorekotlin.node.XyoBridgeQueueItem
import network.xyo.sdkcorekotlin.persist.XyoKeyValueStore
import network.xyo.sdkcorekotlin.repositories.XyoBridgeQueueRepository
import network.xyo.sdkcorekotlin.schemas.XyoSchemas
import network.xyo.sdkobjectmodelkotlin.structure.XyoIterableStructure
import network.xyo.sdkobjectmodelkotlin.structure.XyoObjectStructure
import java.lang.Math.min
import java.nio.ByteBuffer

class XyoStorageBridgeQueueRepository (private val store: XyoKeyValueStore) : XyoBridgeQueueRepository {
    private var queueCache = ArrayList<XyoBridgeQueueItem>()

    override fun getQueue (): Array<XyoBridgeQueueItem> {
        return queueCache.toTypedArray()
    }

    override fun setQueue (queue:  Array<XyoBridgeQueueItem>) {
        queueCache = ArrayList(queue.asList())
    }

    override fun addQueueItem (item: XyoBridgeQueueItem) {
        val insertIndex = getInsertIndex(item.weight)
        queueCache.add(insertIndex, item)
    }

    @SuppressLint("NewApi")
    override fun removeQueueItems (items: Array<XyoObjectStructure>) {
        for (item in items) {
            queueCache.removeIf { cachedItem ->
                return@removeIf item.bytesCopy.contentEquals(cachedItem.hash.bytesCopy)
            }
        }
    }

    override fun getLowestWeight (n: Int): Array<XyoBridgeQueueItem> {
        if (queueCache.size == 0 || n == 0) {
            return arrayOf()
        }

        val itemsToReturn = ArrayList<XyoBridgeQueueItem>()

        for (i in 0..min(n - 1, queueCache.size - 1)) {
            itemsToReturn.add(queueCache[i])
        }

        return itemsToReturn.toTypedArray()
    }

    override fun incrementWeights (hashes: Array<XyoObjectStructure>) {
        for (hash in hashes) {
            val indexToAdd = queueCache.indexOfFirst { cachedItem ->
                return@indexOfFirst cachedItem.hash.bytesCopy.contentEquals(hash.bytesCopy)
            }

            queueCache[indexToAdd].weight += 1
        }
    }

    override suspend fun commit () {
        val encodedQueueItems: Array<XyoObjectStructure> = Array(queueCache.size) { i ->
            return@Array this@XyoStorageBridgeQueueRepository.queueCache[i].encode()
        }

        val encodedMaster = XyoIterableStructure.createUntypedIterableObject(XyoSchemas.ARRAY_UNTYPED, encodedQueueItems)
        store.write(STORE_QUEUE_KEY, encodedMaster.bytesCopy)
    }

    @Suppress("unused")
    suspend fun restore () {
        val encodedItems = store.read(STORE_QUEUE_KEY) ?: return
        val restoredQueueCache = ArrayList<XyoBridgeQueueItem>()
        val it = XyoIterableStructure(encodedItems, 0).iterator

        while (it.hasNext()) {
            val item = it.next() as? XyoIterableStructure

            if (item != null) {
                restoredQueueCache.add(decodeBridgeItem(item))
            }
        }

        queueCache = restoredQueueCache
    }

    private fun getInsertIndex (weight: Int): Int {
        if (queueCache.size == 0) {
            return 0
        }

        for (i in 0..queueCache.size) {
            if (queueCache[i].weight >= weight) {
                return i
            }
        }

        return 0

    }

    private fun XyoBridgeQueueItem.encode() : XyoIterableStructure {
        val hashStructure = this.hash
        val weightStructure = XyoObjectStructure.newInstance(XyoSchemas.BLOB, ByteBuffer.allocate(4).putInt(this.weight).array())

        return XyoIterableStructure.createUntypedIterableObject(XyoSchemas.ARRAY_UNTYPED, arrayOf(hashStructure, weightStructure))
    }

    private fun decodeBridgeItem (item : XyoIterableStructure): XyoBridgeQueueItem {
        val hash = item[0]
        val weight = ByteBuffer.wrap(item[1].valueCopy).int

        return XyoBridgeQueueItem(weight, hash)
    }

    companion object {
        private val STORE_QUEUE_KEY = "STORE_QUEUE_KEY".toByteArray()
    }
}