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

com.gu.vidispineakka.vidispine.VSShape.scala Maven / Gradle / Ivy

package com.gu.vidispineakka.vidispine

import akka.event.DiagnosticLoggingAdapter
import akka.stream.Materializer
import com.softwaremill.sttp.Uri
import com.gu.vidispineakka.models.HttpError
import org.slf4j.LoggerFactory
import VSCommunicator.OperationType

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Failure, Success, Try}
import scala.xml.{NodeSeq, XML}

case class VSShape (vsid:String,essenceVersion:Int,tag:String,mimeType:String, files:Seq[VSFile])

object VSShape {
  private val logger = LoggerFactory.getLogger(getClass)

  def vsIdForShapeTag(itemId:String, shapeTag:String)(implicit vsCommunicator:VSCommunicator,mat:Materializer) = {
    val uri = s"/API/item/$itemId/shape?tag=$shapeTag"
    vsCommunicator.request(OperationType.GET, uri, None, Map("Accept"->"application/xml"))
      .map({
        case Right(stringData)=>UriListDocument.fromXmlString(stringData) match {
          case Success(uriListDocument)=>
            Right(uriListDocument.uri.headOption)
          case Failure(err)=>
            Left(HttpError(err.toString, -1))
        }
        case Left(err)=>
          Left(err)
      })
  }

  def forItemWithId(itemId:String, shapeId:String)(implicit vsCommunicator:VSCommunicator,mat:Materializer) = {
    val uri = s"/API/item/$itemId/shape/$shapeId"
    logger.debug(s"VSShape.forItemWithId: URI is $uri")
    vsCommunicator.request(OperationType.GET, uri,None, headers=Map("Accept" -> "application/xml"))
      .map({
        case Right(stringData) => VSShape.fromXmlString(stringData) match {
          case Success(vsShape) =>
            logger.debug(s"VSShape.forItemWithID: Converted XML to domain object")
            Right(vsShape)
          case Failure(err) =>
            logger.warn(s"VSShape.forItemWithID: Could not interpret returned XML: ", err)
            Left(HttpError(err.toString, -1))
        }
        case Left(err) =>
          logger.warn(s"VSShape.forItemWithID: Got HTTP error $err")
          Left(err)
      })
  }

  def forItemWithTag(itemId:String, shapeTag:String)(implicit vsCommunicator:VSCommunicator,mat:Materializer) = {
    vsIdForShapeTag(itemId, shapeTag).flatMap({
      case Left(err) => Future(Left(err))
      case Right(None) => Future(Left(HttpError(s"No shape exists for tag $shapeTag", 404)))
      case Right(Some(shapeId)) => forItemWithId(itemId, shapeId)
    })
  }


  def fromXmlString(xmlString:String):Try[VSShape] = Try {
    val xmlNodes = XML.loadString(xmlString)
    fromXml(xmlNodes)
  }

  def fromXml(xmlNodes:NodeSeq):VSShape = {
    //see http://apidoc.vidispine.com/latest/ref/xml-schema.html?highlight=shapedocument#schema-element-ShapeDocument for a list of all the possible components
    val containerNodesList = (xmlNodes \ "containerComponent" \ "file") ++ (xmlNodes \ "binaryComponent" \ "file") ++ (xmlNodes \ "descriptorComponent" \ "file") ++ (xmlNodes \ "audioComponent" \ "file") ++ (xmlNodes \ "videoComponent" \ "file") ++ (xmlNodes \ "subtitleComponent" \ "file")
    new VSShape(
      (xmlNodes \ "id").text,
      (xmlNodes \ "essenceVersion").text.toInt,
      (xmlNodes \ "tag").text,
      (xmlNodes \ "mimeType").text,
      containerNodesList.map(fileNode => VSFile.fromXml(fileNode) match {
        case Success(Some(vsFile)) => vsFile
        case Success(None) =>
          logger.error(s"Recceived shape document with empty file nodes, this should not happen")
          logger.error(xmlNodes.toString)
          throw new RuntimeException("Recceived shape document with empty file nodes, this should not happen")
        case Failure(err) => throw err //this is picked up immediately by the containing Try and returned as a Failure
      })
    )
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy