backend/app/model/frontend/Resource.scala (165 lines of code) (raw):

package model.frontend import extraction.EnrichedMetadata import model._ import model.annotations.Comment import model.index.{Document, IndexedResource} import org.neo4j.driver.v1.Value import play.api.libs.json._ import services.previewing.{PreviewService, PreviewStatus} import scala.jdk.CollectionConverters._ case class RelatedResource(uri: String, `type`: String, display: Option[String], isExpandable: Boolean) object RelatedResource { implicit val relatedResourceFormat = Json.format[RelatedResource] def fromNeo4jValue(v: Value) = RelatedResource( v.get("uri").asString(), BasicResource.getLabelFromValue(v), v.get("display").optionally(_.asString()), v.get("isExpandable").optionally(_.asBoolean()).getOrElse(false) ) } trait Resource { def uri: String def display: Option[String] def `type`: String def isBasic: Boolean def isExpandable: Boolean def previewStatus: PreviewStatus def parents: List[RelatedResource] def children: List[RelatedResource] } object Resource { private val emailResourceFormat = Json.format[EmailResource] private val documentResourceFormat = Json.format[DocumentResource] def mergeResources(indexable: IndexedResource, basic: BasicResource, comments: List[Comment]): Resource = indexable match { case d: Document => DocumentResource.fromDocument(d, basic, comments: List[Comment]) case e: Email => EmailResource.fromEmail(e, basic, comments: List[Comment]) case _ => basic } implicit val format = new Format[Resource] { override def writes(resource: Resource): JsValue = resource match { case r: BasicResource => BasicResource.format.writes(r) case r: EmailResource => emailResourceFormat.writes(r) case r: DocumentResource => documentResourceFormat.writes(r) } override def reads(json: JsValue): JsResult[Resource] = (json \ "isBasic").get match { case JsTrue => BasicResource.format.reads(json) case _ => (json \ "type").get match { case JsString("email") => emailResourceFormat.reads(json) case JsString("document") => documentResourceFormat.reads(json) case JsString(other) => JsError(s"Unexpected type value: '$other'") case _ => JsError("Unexpected value for resource type") } } } } // Basic resource is used when you don't want to have all the information about a particular resource - for example when you're // exploring a file tree you don't want to pull in all the Blob information case class BasicResource( uri: String, display: Option[String], `type`: String, parents: List[RelatedResource] = Nil, children: List[RelatedResource] = Nil, isBasic: Boolean = true, isExpandable: Boolean, previewStatus: PreviewStatus = PreviewStatus.Disabled ) extends Resource object BasicResource { implicit val format: Format[BasicResource] = Json.format[BasicResource] def getLabelFromValue(v: Value): String = { v.asNode().labels().asScala.toList.filterNot(_ == "Resource").head.toLowerCase } def fromNeo4jValues(resource: Value, parentValues: List[Value], childValues: List[Value]): BasicResource = { BasicResource( uri = resource.get("uri").asString(), display = resource.get("display").optionally(_.asString()), `type` = getLabelFromValue(resource), isExpandable = resource.get("isExpandable").optionally(_.asBoolean()).getOrElse(false), parents = parentValues.map(p => RelatedResource.fromNeo4jValue(p)), children = childValues.map(c => RelatedResource.fromNeo4jValue(c)) ) } } case class EmailResource( uri: String, display: Option[String], parents: List[RelatedResource], children: List[RelatedResource], from: Option[Recipient], recipients: List[Recipient], sentAt: Option[String], sensitivity: Option[Sensitivity], priority: Option[String], subject: String, text: HighlightableText, inReplyTo: List[String], references: List[String], previewStatus: PreviewStatus, flag: Option[String], extracted: Boolean = true, `type`: String = "email", isBasic: Boolean = false, isExpandable: Boolean, comments: List[Comment] ) extends Resource object EmailResource { def fromEmail(email: Email, basic: BasicResource, comments: List[Comment]): EmailResource = EmailResource( uri = email.uri.value, display = Some(email.subject), parents = basic.parents, children = basic.children, from = email.from, recipients = email.recipients, sentAt = email.sentAt, sensitivity = email.sensitivity, priority = email.priority, subject = email.subject, text = HighlightableText.fromString(email.body, page = None), inReplyTo = email.inReplyTo, references = email.references, previewStatus = if (email.html.isDefined) PreviewStatus.PdfGenerated else PreviewStatus.Disabled, flag = email.flag, isExpandable = basic.isExpandable, comments = comments ) } case class DocumentResource private ( uri: String, display: Option[String], parents: List[RelatedResource], children: List[RelatedResource], text: HighlightableText, ocr: Option[Map[String, HighlightableText]], transcript: Option[Map[String, HighlightableText]], metadata: Map[String, Seq[String]], enrichedMetadata: Option[EnrichedMetadata], previewStatus: PreviewStatus, flag: Option[String], extracted: Boolean, fileSize: Long, mimeTypes: Set[String], `type`: String = "blob", isBasic: Boolean = false, isExpandable: Boolean, comments: List[Comment] ) extends Resource object DocumentResource { def fromDocument(document: Document, basic: BasicResource, comments: List[Comment]): DocumentResource = { DocumentResource( uri = document.uri.value, display = None, // Documents shouldn't be shown directly in the resource browser so don't need display text parents = basic.parents, children = basic.children, text = HighlightableText.fromString(document.text, page = None), ocr = document.ocr.map(ocrMap => ocrMap.view.mapValues { v => HighlightableText.fromString(v, page = None) }.toMap), transcript = document.transcript.map(ocrMap => ocrMap.view.mapValues { v => HighlightableText.fromString(v, page = None) }.toMap), metadata = document.metadata, enrichedMetadata = document.enrichedMetadata, previewStatus = PreviewService.previewStatus(document.mimeTypes), flag = document.flag, extracted = document.extracted, fileSize = document.fileSize, mimeTypes = document.mimeTypes, isExpandable = basic.isExpandable, comments = comments ) } }