aboutsummaryrefslogblamecommitdiff
path: root/src/main/scala/xyz/driver/pdsuidomain/formats/json/sprayformats/extracteddata.scala
blob: ab27b675daf60c85e02040d946fb4a160e293922 (plain) (tree)




















































































































































                                                                                                                      
package xyz.driver.pdsuidomain.formats.json.sprayformats

import spray.json._
import xyz.driver.pdsuicommon.domain.{FuzzyValue, LongId, TextJson}
import xyz.driver.pdsuidomain.entities._
import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData

object extracteddata {
  import DefaultJsonProtocol._
  import common._
  import ExtractedData._

  implicit val metaKeywordFormat: RootJsonFormat[Meta.Keyword] = jsonFormat4(Meta.Keyword)
  implicit val metaTextLayerPositionFormat: RootJsonFormat[Meta.TextLayerPosition] = jsonFormat3(
    Meta.TextLayerPosition)
  implicit val metaEvidenceFormat: RootJsonFormat[Meta.Evidence] = jsonFormat3(Meta.Evidence)

  implicit val extractedDataMetaFormat: RootJsonFormat[Meta] = jsonFormat2(Meta.apply)
  implicit val fullExtractedDataMetaFormat = new RootJsonFormat[TextJson[Meta]] {
    override def write(obj: TextJson[Meta]): JsValue = obj.content.toJson
    override def read(json: JsValue): TextJson[Meta] = TextJson(extractedDataMetaFormat.read(json))
  }

  implicit val extractedDataLabelFormat: RootJsonFormat[ExtractedDataLabel] = new RootJsonFormat[ExtractedDataLabel] {
    override def write(label: ExtractedDataLabel): JsObject = {
      JsObject(
        "id"         -> label.labelId.toJson,
        "categoryId" -> label.categoryId.toJson,
        "value"      -> label.value.toJson
      )
    }

    override def read(json: JsValue): ExtractedDataLabel = json match {
      case JsObject(fields) =>
        val labelId = fields
          .get("id")
          .map(_.convertTo[LongId[Label]])

        val categoryId = fields
          .get("categoryId")
          .map(_.convertTo[LongId[Category]])

        val value = fields
          .get("value")
          .map(_.convertTo[FuzzyValue])

        ExtractedDataLabel(
          id = LongId(0),
          dataId = LongId(0),
          labelId = labelId,
          categoryId = categoryId,
          value = value
        )

      case _ => deserializationError(s"Expected Json Object as ExtractedDataLabel, but got $json")
    }
  }

  def applyUpdateToExtractedData(json: JsValue, orig: RichExtractedData): RichExtractedData = json match {
    case JsObject(fields) =>
      val keywordId = if (fields.contains("keywordId")) {
        fields
          .get("keywordId")
          .map(_.convertTo[LongId[Keyword]])
      } else orig.extractedData.keywordId

      val evidence = if (fields.contains("evidence")) {
        fields
          .get("evidence")
          .map(_.convertTo[String])
      } else orig.extractedData.evidenceText

      val meta = if (fields.contains("meta")) {
        fields
          .get("meta")
          .map(_.convertTo[TextJson[Meta]])
      } else orig.extractedData.meta

      val labels = if (fields.contains("labels")) {
        fields
          .get("labels")
          .map(_.convertTo[List[ExtractedDataLabel]])
          .getOrElse(List.empty[ExtractedDataLabel])
      } else orig.labels

      val extractedData = orig.extractedData.copy(
        keywordId = keywordId,
        evidenceText = evidence,
        meta = meta
      )

      orig.copy(
        extractedData = extractedData,
        labels = labels
      )

    case _ => deserializationError(s"Expected Json Object as partial ExtractedData, but got $json")
  }

  implicit val extractedDataFormat: RootJsonFormat[RichExtractedData] = new RootJsonFormat[RichExtractedData] {
    override def write(richData: RichExtractedData): JsValue =
      JsObject(
        "id"         -> richData.extractedData.id.id.toJson,
        "documentId" -> richData.extractedData.documentId.toJson,
        "keywordId"  -> richData.extractedData.keywordId.toJson,
        "evidence"   -> richData.extractedData.evidenceText.toJson,
        "meta"       -> richData.extractedData.meta.toJson,
        "labels"     -> richData.labels.toJson
      )

    override def read(json: JsValue): RichExtractedData = json match {
      case JsObject(fields) =>
        val documentId = fields
          .get("documentId")
          .map(_.convertTo[LongId[Document]])
          .getOrElse(
            deserializationError(s"ExtractedData create json object does not contain `documentId` field: $json"))

        val keywordId = fields
          .get("keywordId")
          .map(_.convertTo[LongId[Keyword]])

        val evidence = fields
          .get("evidence")
          .map(_.convertTo[String])

        val meta = fields
          .get("meta")
          .map(_.convertTo[TextJson[Meta]])

        val labels = fields
          .get("labels")
          .map(_.convertTo[List[ExtractedDataLabel]])
          .getOrElse(List.empty[ExtractedDataLabel])

        val extractedData = ExtractedData(
          documentId = documentId,
          keywordId = keywordId,
          evidenceText = evidence,
          meta = meta
        )

        RichExtractedData(extractedData, labels)

      case _ => deserializationError(s"Expected Json Object as ExtractedData, but got $json")
    }
  }

}