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

net.fwbrasil.activate.storage.prevalent.PrevalentTransactionSerializer.scala Maven / Gradle / Ivy

The newest version!
package net.fwbrasil.activate.storage.prevalent

import net.fwbrasil.activate.storage.marshalling.StorageValue
import net.fwbrasil.activate.storage.marshalling.BooleanStorageValue
import net.fwbrasil.activate.storage.marshalling.DoubleStorageValue
import net.fwbrasil.activate.storage.marshalling.IntStorageValue
import net.fwbrasil.activate.storage.marshalling.BigDecimalStorageValue
import net.fwbrasil.activate.storage.marshalling.LongStorageValue
import net.fwbrasil.activate.storage.marshalling.StringStorageValue
import net.fwbrasil.activate.storage.marshalling.DateStorageValue
import net.fwbrasil.activate.storage.marshalling.FloatStorageValue
import net.fwbrasil.activate.storage.marshalling.ReferenceStorageValue
import net.fwbrasil.activate.storage.marshalling.ByteArrayStorageValue
import java.nio.ByteBuffer
import java.nio.charset.Charset
import scala.collection.mutable.ListBuffer
import java.util.Date
import java.nio.BufferUnderflowException
import net.fwbrasil.activate.storage.marshalling.ListStorageValue
import net.fwbrasil.activate.storage.marshalling.ListStorageValue
import net.fwbrasil.activate.entity.BaseEntity
import net.fwbrasil.activate.serialization.javaSerializer
import java.io.ByteArrayOutputStream
import java.io.ObjectOutputStream
import java.io.ObjectInputStream
import java.io.ByteArrayInputStream
import net.fwbrasil.activate.storage.marshalling.StorageOptionalValue
import net.fwbrasil.activate.storage.memory.BasePrevalentTransaction
import net.fwbrasil.activate.ActivateContext

object PrevalentTransactionSerializer {

    def write(transaction: BasePrevalentTransaction)(implicit buffer: ByteBuffer) = {
        writeBoolean(true)
        writeValuesArray(transaction.insertList)
        writeValuesArray(transaction.updateList)
        writeIdsArray(transaction.deleteList)
    }

    def read(implicit buffer: ByteBuffer, context: ActivateContext) =
        if (hasTrue) {
            Some(
                new BasePrevalentTransaction(
                        context,
                    insertList = readValuesArray,
                    updateList = readValuesArray,
                    deleteList = readIdsArray))
        } else
            None

    private def hasTrue(implicit buffer: ByteBuffer) =
        try {
            buffer.mark
            if (!readBoolean) {
                buffer.reset
                false
            } else
                true
        } catch {
            case e: BufferUnderflowException =>
                buffer.reset
                false
        }

    private def writeIdsArray(array: Array[(BaseEntity#ID, Class[BaseEntity])])(implicit buffer: ByteBuffer) = {
        buffer.putInt(array.length)
        array.foreach(tuple => writeId(tuple._1, tuple._2))
    }

    private def readIdsArray(implicit buffer: ByteBuffer) = {
        val length = buffer.getInt
        val ids = new Array[(BaseEntity#ID, Class[BaseEntity])](length)
        for (i <- 0 until length)
            ids(i) = readId
        ids
    }

    private def writeId(entityId: BaseEntity#ID, entityClass: Class[BaseEntity])(implicit buffer: ByteBuffer) = {
        val baos = new ByteArrayOutputStream()
        val oos = new ObjectOutputStream(baos)
        oos.writeObject(entityId)
        oos.writeObject(entityClass)
        writeByteArray(baos.toByteArray)
    }

    private def readId(implicit buffer: ByteBuffer) = {
        val bytes = readByteArray
        val bios = new ByteArrayInputStream(bytes)
        val ois = new ObjectInputStream(bios)
        val entityId = ois.readObject.asInstanceOf[BaseEntity#ID]
        val entityClass = ois.readObject.asInstanceOf[Class[BaseEntity]]
        (entityId, entityClass)
    }

    private def readStringArray(implicit buffer: ByteBuffer) = {
        val length = buffer.getInt
        val array = new Array[String](length)
        for (i <- 0 until length)
            array(i) = readString
        array
    }

    private def writeValuesArray(array: Array[((BaseEntity#ID, Class[BaseEntity]), Map[String, StorageValue])])(implicit buffer: ByteBuffer) = {
        buffer.putInt(array.size)
        array.foreach(writeTuple)
    }

    private def readValuesArray(implicit buffer: ByteBuffer) = {
        val length = buffer.getInt
        val array = new Array[((BaseEntity#ID, Class[BaseEntity]), Map[String, StorageValue])](length)
        for (i <- 0 until length)
            array(i) = readTuple
        array
    }

    private def writeTuple(tuple: ((BaseEntity#ID, Class[BaseEntity]), Map[String, StorageValue]))(implicit buffer: ByteBuffer) = {
        writeId(tuple._1._1, tuple._1._2)
        writeMap(tuple._2)
    }

    private def readTuple(implicit buffer: ByteBuffer) =
        (readId, readMap)

    private def writeString(string: String)(implicit buffer: ByteBuffer) = {
        val bytes = string.getBytes
        buffer.putInt(bytes.length)
        buffer.put(bytes)
    }

    private def readString(implicit buffer: ByteBuffer) = {
        val length = buffer.getInt
        val bytes = new Array[Byte](length)
        buffer.get(bytes)
        new String(bytes)
    }

    private def writeMap(map: Map[String, StorageValue])(implicit buffer: ByteBuffer) = {
        buffer.putInt(map.size)
        for ((name, value) <- map)
            writeProperty(name, value)
    }

    private def readMap(implicit buffer: ByteBuffer) = {
        val length = buffer.getInt
        val array = new Array[(String, StorageValue)](length)
        for (i <- 0 until length)
            array(i) = readProperty
        array.toMap
    }

    private def writeProperty(name: String, value: StorageValue)(implicit buffer: ByteBuffer) = {
        writeString(name)
        writeValue(value)
    }

    private def readProperty(implicit buffer: ByteBuffer) =
        (readString, readValue)

    private def writeBoolean(value: Boolean)(implicit buffer: ByteBuffer) =
        if (value)
            buffer.put(4: Byte)
        else
            buffer.put(1: Byte)

    private def readBoolean(implicit buffer: ByteBuffer) =
        buffer.get == (4: Byte)

    private def writeValue(value: StorageValue)(implicit buffer: ByteBuffer): Unit =
        value match {
            case value: IntStorageValue =>
                writeValue[Int](0, value.value, buffer.putInt(_))
            case value: LongStorageValue =>
                writeValue[Long](1, value.value, buffer.putLong(_))
            case value: BooleanStorageValue =>
                writeValue[Boolean](2, value.value, writeBoolean(_))
            case value: StringStorageValue =>
                writeValue[String](3, value.value, writeString(_))
            case value: FloatStorageValue =>
                writeValue[Float](4, value.value, buffer.putFloat(_))
            case value: DateStorageValue =>
                writeValue[Long](5, value.value.map(_.getTime), buffer.putLong(_))
            case value: DoubleStorageValue =>
                writeValue[Double](6, value.value, buffer.putDouble(_))
            case value: BigDecimalStorageValue =>
                writeValue[Double](7, value.value.map(_.doubleValue), buffer.putDouble(_))
            case value: ByteArrayStorageValue =>
                writeValue[Array[Byte]](8, value.value, writeByteArray(_))
            case value: ListStorageValue =>
                writeValue[List[StorageValue]](9, value.value, writeList(_))
                writeValue(value.emptyStorageValue)
            case value: ReferenceStorageValue =>
                writeValue[StorageValue](10, Some(value.value), writeValue(_))
        }

    private def readValue(implicit buffer: ByteBuffer): StorageValue =
        buffer.get.intValue match {
            case 0 =>
                IntStorageValue(readValue(buffer.getInt))
            case 1 =>
                LongStorageValue(readValue(buffer.getLong))
            case 2 =>
                BooleanStorageValue(readValue(readBoolean))
            case 3 =>
                StringStorageValue(readValue(readString))
            case 4 =>
                FloatStorageValue(readValue(buffer.getFloat))
            case 5 =>
                DateStorageValue(readValue(new Date(buffer.getLong)))
            case 6 =>
                DoubleStorageValue(readValue(buffer.getDouble))
            case 7 =>
                BigDecimalStorageValue(readValue(buffer.getDouble))
            case 8 =>
                ByteArrayStorageValue(readValue(readByteArray))
            case 9 =>
                ListStorageValue(readValue(readList), readValue)
            case 10 =>
                ReferenceStorageValue(readValue(readValue).get.asInstanceOf[StorageOptionalValue])
        }

    private def writeList(list: List[StorageValue])(implicit buffer: ByteBuffer) = {
        buffer.putInt(list.length)
        list.foreach(writeValue)
    }

    private def readList(implicit buffer: ByteBuffer) = {
        val length = buffer.getInt
        val array = new Array[StorageValue](length)
        for (i <- 0 until length)
            array(i) = readValue
        array.toList
    }

    private def writeByteArray(array: Array[Byte])(implicit buffer: ByteBuffer) = {
        buffer.putInt(array.length)
        buffer.put(array)
    }
    private def readByteArray(implicit buffer: ByteBuffer) = {
        val length = buffer.getInt
        val array = new Array[Byte](length)
        buffer.get(array)
        array
    }

    private def writeValue[V](identifier: Byte, option: Option[V], writeValue: (V) => Unit)(implicit buffer: ByteBuffer): Unit = {
        buffer.put(identifier)
        option.map { value =>
            writeBoolean(true)
            writeValue(value)
        }.getOrElse {
            writeBoolean(false)
        }
    }

    private def readValue[V](readValue: => V)(implicit buffer: ByteBuffer) =
        if (readBoolean)
            Some(readValue)
        else
            None

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy