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

geotrellis.process.History.scala Maven / Gradle / Ivy

The newest version!
package geotrellis.process

import scala.collection.mutable

import geotrellis._

object TreeChars {
  val DOWN_OUT = "├"
  val OUT_DOWN = "┬"
  val TOP_OUT = "└"
  val IN_BOTTOM = "¬"
  val OUT_BOTTOM = "┌"
  val OUT = "─"
  val DOWN = "│"
}

object History {
  def apply(op:Op[_]) =
    new History(op.opId,Nil,None,System.currentTimeMillis,0)

  def apply(op:Op[_],system:String) =
    new History(op.opId,Nil,None,System.currentTimeMillis,0,system)

  def literal[T](v:T,system:String) =
    new History("Literal",Nil,None,System.currentTimeMillis,0,system).withResult(v)

  implicit def historyToString(h:History) = h.toString
}

abstract sealed trait HistoryResult { 
  def toJson:String
}

case class SuccessHistory(value:String) extends HistoryResult {
  def toJson() = {
    val escapedVal = value.replace(""""""","""\"""")
    s"""{ "type" : "success", "value" : "$escapedVal" }"""
  }
}
case class FailureHistory(msg:String,trace:String) extends HistoryResult {
  def toJson() = {
    val escapedMsg = msg.replace(""""""","""\"""")
    val escapedTrace = msg.replace(""""""","""\"""")
    s"""{ "type" : "failure", "msg" : "$escapedMsg", "trace" : "$escapedTrace" }"""
  }
}

case class History(id:String,
                   steps:List[StepHistory],
                   result:Option[HistoryResult],
                   startTime:Long,
                   endTime:Long,
                   system:String = "unknown") {
  val elapsedTime = endTime - startTime

  def withResult[T](value:T,forced:Boolean = false) = {
    val now = System.currentTimeMillis
    val resultString = 
      value match {
        case null => "null"
        case s:String => s""""$s""""
        case i:Int => s"""$i"""
        case d:Double => s"""$d"""
        case v:Vector[_] => 
          val sb = new StringBuilder
          sb.append("Vector(")
          val len = v.length
          for(i <- 0 until len) {
            sb.append(v(i).getClass.getSimpleName)
            if(i != len - 1) { sb.append(",") }
          }
          sb.append(")")
          sb.toString
        case l:List[_] => 
          val sb = new StringBuilder
          sb.append("List(")
          val len = l.length
          for(i <- 0 until len) {
            sb.append(l(i).getClass.getSimpleName)
            if(i != len - 1) { sb.append(",") }
          }
          sb.append(")")
          sb.toString
        case _ => value.getClass.getSimpleName
      }

    val s = 
      if(forced) { resultString + " [Forced]" }
      else { resultString }

    new History(id,steps,Some(SuccessHistory(s)),startTime,now,system)
  }

  def withError(msg:String,trace:String) = {
    val now = System.currentTimeMillis
    new History(id,steps,Some(FailureHistory(msg,trace)),startTime,now,system)
  }

  def withStep(step:StepHistory) =
    new History(id,step :: steps,result,startTime,endTime,system)

  def withStep(stepHistorys:List[History]) =
    new History(id,StepHistory(stepHistorys) :: steps,result,startTime,endTime,system)

  override
  def toString:String = 
    toString("",false)

  def toString(indentString:String,initialIndent:Boolean,includeSystem:Boolean=true):String = {
    val halfLen = id.length/2
    val sb = new StringBuilder
    if(initialIndent) {
      sb.append(indentString)
    }
    sb.append(s"$id\n")
    val stepIndentString = indentString + (" " * halfLen) + TreeChars.DOWN + (" " * halfLen)
    val stepOpIndentString = indentString + (" " * halfLen) + TreeChars.DOWN_OUT + (TreeChars.OUT * halfLen)
    for(step <- steps.reverse) {
      sb.append(step.toString(stepIndentString, stepOpIndentString))
    }
    sb.append(indentString)
    sb.append(" " * halfLen)
    sb.append(TreeChars.TOP_OUT)
    sb.append(TreeChars.OUT * halfLen)
    sb.append("Result: ")
    sb.append(result match {
      case Some(SuccessHistory(s)) => s"$s (in ${endTime - startTime} ms)"
      case Some(FailureHistory(msg,trace)) => 
        s"ERROR: $msg (in $elapsedTime ms): \n" + trace + "\n"
      case None => "No Result"
    })
    if (includeSystem && system != "") {
      sb.append("[" + system + "]")
    }
    sb.append("\n")
    sb.toString
  }

  def toJson():String = {
    val r = result match {
      case Some(r) => r.toJson
      case None => """{ "type" : "none" }"""
    }
    val orderedSteps = steps.reverse.toList
    val stepsJson = 
      (for(i <- 0 until orderedSteps.length) yield {
        orderedSteps(i).toJson(i)
      }).mkString(",")

    s"""{ "id" : "$id",
          "elapsedTime" : "$elapsedTime",
          "result" : $r,
          "steps" : [ $stepsJson ]
        }"""
  }
}

case class StepHistory(opHistories:List[History]) {
  override
  def toString:String =
    toString("","")

  def toString(indentString:String,opIndentString:String):String = {
    val sb = new StringBuilder
    val len = opHistories.length

    val firstOpIndentString = opIndentString + TreeChars.OUT_DOWN + TreeChars.OUT
    val otherOpIndentString = indentString + TreeChars.DOWN_OUT + TreeChars.OUT
    val lastOpIndentString = indentString + TreeChars.TOP_OUT + TreeChars.OUT
    val betweenIndentString = indentString + TreeChars.DOWN + " "

    for(i <- 0 until len) {
      if(i == 0 && len == 1) {
        sb.append(opIndentString + (TreeChars.OUT * 2))
      } else if(i == len - 1) { 
        sb.append(lastOpIndentString)
      } else if(i == 0) {
        sb.append(firstOpIndentString) 
      } else { 
        sb.append(otherOpIndentString) 
      }
      val ins = 
        if(i == len - 1) { indentString + (" " * 2) }
        else { betweenIndentString }
      sb.append(opHistories(i).toString(ins,false))
    }
    sb.toString
  }

  def toJson(pos:Int = 0) = {
    val opsJson = opHistories.map(_.toJson).mkString(",")
    s"""{ "seq" : $pos,
          "ops" : [ $opsJson ] }"""
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy