From 5832f63b84d7388441d1200f2442dc1e9de0225c Mon Sep 17 00:00:00 2001 From: vlad Date: Tue, 27 Jun 2017 17:13:02 -0700 Subject: All PDS UI domain models, API case classes, service traits and necessary utils moved to pdsui-common --- .../json/extracteddata/ApiExtractedData.scala | 44 ++++++++++++ .../extracteddata/ApiPartialExtractedData.scala | 80 ++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala create mode 100644 src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala (limited to 'src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata') diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala new file mode 100644 index 0000000..dad7a1e --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiExtractedData.scala @@ -0,0 +1,44 @@ +package xyz.driver.pdsuidomain.formats.json.extracteddata + +import xyz.driver.pdsuidomain.formats.json.label.ApiExtractedDataLabel +import play.api.libs.json._ +import play.api.data.validation._ +import play.api.libs.functional.syntax._ +import xyz.driver.pdsuicommon.json.JsonSerializer +import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData + +// The specification: https://driverinc.atlassian.net/wiki/pages/viewpage.action?pageId=33423387 +// Note, that there is "Extracted data object or Temporary extracted data object" in specification +// ApiExtractedData represents both types +final case class ApiExtractedData(id: Long, + documentId: Long, + keywordId: Option[Long], + evidence: Option[String], + meta: Option[String], + // An empty list and no-existent list are different cases + labels: Option[List[ApiExtractedDataLabel]]) + +object ApiExtractedData { + + implicit val format: Format[ApiExtractedData] = ( + (JsPath \ "id").format[Long] and + (JsPath \ "documentId").format[Long] and + (JsPath \ "keywordId").formatNullable[Long] and + (JsPath \ "evidence").formatNullable[String] and + (JsPath \ "meta").formatNullable[String] and + (JsPath \ "labels").formatNullable[List[ApiExtractedDataLabel]](Format( + Reads.of[List[ApiExtractedDataLabel]].filter(ValidationError("empty labels"))({ + case x if x.nonEmpty => true + case _ => false + }), Writes.of[List[ApiExtractedDataLabel]])) + ) (ApiExtractedData.apply, unlift(ApiExtractedData.unapply)) + + def fromDomain(extractedDataWithLabels: RichExtractedData) = ApiExtractedData( + id = extractedDataWithLabels.extractedData.id.id, + documentId = extractedDataWithLabels.extractedData.documentId.id, + keywordId = extractedDataWithLabels.extractedData.keywordId.map(_.id), + evidence = extractedDataWithLabels.extractedData.evidenceText, + meta = extractedDataWithLabels.extractedData.meta.map(x => JsonSerializer.serialize(x.content)), + labels = Option(extractedDataWithLabels.labels.map(ApiExtractedDataLabel.fromDomain)) + ) +} diff --git a/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala new file mode 100644 index 0000000..69b5627 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuidomain/formats/json/extracteddata/ApiPartialExtractedData.scala @@ -0,0 +1,80 @@ +package xyz.driver.pdsuidomain.formats.json.extracteddata + +import xyz.driver.pdsuicommon.domain.{LongId, TextJson} +import xyz.driver.pdsuidomain.entities.ExtractedData.Meta +import xyz.driver.pdsuidomain.entities._ +import org.davidbild.tristate.Tristate +import org.davidbild.tristate.contrib.play.ToJsPathOpsFromJsPath +import play.api.data.validation._ +import play.api.libs.functional.syntax._ +import play.api.libs.json._ +import xyz.driver.pdsuicommon.json.{JsonSerializer, JsonValidationException} +import xyz.driver.pdsuicommon.validation.{AdditionalConstraints, JsonValidationErrors} +import xyz.driver.pdsuidomain.formats.json.label.ApiExtractedDataLabel +import xyz.driver.pdsuidomain.services.ExtractedDataService.RichExtractedData + +import scala.collection._ + +final case class ApiPartialExtractedData(documentId: Option[Long], + keywordId: Option[Long], + evidence: Tristate[String], + meta: Tristate[String], + labels: Tristate[List[ApiExtractedDataLabel]]) { + + def applyTo(orig: RichExtractedData): RichExtractedData = RichExtractedData( + extractedData = applyTo(orig.extractedData), + labels = labels.cata(_.map(_.toDomain(orig.extractedData.id)), List.empty, orig.labels) + ) + + private def applyTo(orig: ExtractedData): ExtractedData = ExtractedData( + id = orig.id, + documentId = orig.documentId, + keywordId = keywordId.map(LongId[Keyword]).orElse(orig.keywordId), + evidenceText = evidence.cata(Some(_), None, orig.evidenceText), + meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).cata(Some(_), None, orig.meta) + ) + + def toDomain: RichExtractedData = { + val validation = Map( + JsPath \ "documentId" -> AdditionalConstraints.optionNonEmptyConstraint(documentId) + ) + + val validationErrors: JsonValidationErrors = validation.collect({ + case (fieldName, e: Invalid) => (fieldName, e.errors) + })(breakOut) + + if (validationErrors.isEmpty) { + val extractedData = ExtractedData( + documentId = documentId.map(LongId[Document]).get, + keywordId = keywordId.map(LongId[Keyword]), + evidenceText = evidence.toOption, + meta = meta.map(x => TextJson(JsonSerializer.deserialize[Meta](x))).toOption + ) + val labelList = labels.map(_.map(_.toDomain())) + RichExtractedData(extractedData, labelList.getOrElse(List.empty)) + } else { + throw new JsonValidationException(validationErrors) + } + } +} + +object ApiPartialExtractedData { + + private val reads: Reads[ApiPartialExtractedData] = ( + (JsPath \ "documentId").readNullable[Long] and + (JsPath \ "keywordId").readNullable[Long] and + (JsPath \ "evidence").readTristate[String] and + (JsPath \ "meta").readTristate[String] and + (JsPath \ "labels").readTristate[List[ApiExtractedDataLabel]] + ) (ApiPartialExtractedData.apply _) + + private val writes: Writes[ApiPartialExtractedData] = ( + (JsPath \ "documentId").writeNullable[Long] and + (JsPath \ "keywordId").writeNullable[Long] and + (JsPath \ "evidence").writeTristate[String] and + (JsPath \ "meta").writeTristate[String] and + (JsPath \ "labels").writeTristate[List[ApiExtractedDataLabel]] + ) (unlift(ApiPartialExtractedData.unapply)) + + implicit val format: Format[ApiPartialExtractedData] = Format(reads, writes) +} -- cgit v1.2.3