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

tech.ytsaurus.spyt.fs.path.YPathEnriched.scala Maven / Gradle / Ivy

The newest version!
package tech.ytsaurus.spyt.fs.path

import org.apache.hadoop.fs.Path
import tech.ytsaurus.client.CompoundClient
import tech.ytsaurus.core.GUID
import tech.ytsaurus.core.cypress.{RichYPath, YPath}
import tech.ytsaurus.spyt.fs.path.YPathEnriched._
import tech.ytsaurus.spyt.wrapper.YtWrapper
import tech.ytsaurus.ysontree.YTreeBuilder

import scala.annotation.tailrec
import scala.collection.immutable.ListMap
import scala.collection.mutable

case class YPathEnriched(path: Path, attributes: Map[String, String] = Map.empty) extends Serializable {
  implicit class RichPath(val path: Path) {
    def child(name: String): Path = {
      new Path(path.toString + Path.SEPARATOR + name)
    }
  }

  def toPath: Path = attributes.foldLeft(path) { case (p, (k, v)) => p.child(s"@${k}_$v") }

  def toStringPath: String = toPath.toString

  def toYPath: YPath = {
    import scala.collection.JavaConverters._

    val yPath = node.map(n => YPath.objectRoot(GUID.valueOf(n))).getOrElse(YPath.simple(YtWrapper.formatPath(path.toString)))
    val tsYPath = timestamp.filter(_ != -1).map(yPath.withTimestamp).getOrElse(yPath)
    val attrs = attributes.filterKeys(!RESERVED_ATTRIBUTES.contains(_)).mapValues(new YTreeBuilder().value(_).build())
    tsYPath.withAdditionalAttributes(attrs.asJava)
  }

  def toStringYPath: String = toYPath.toStableString

  def cluster: Option[String] = attributes.get(CLUSTER_KEY)

  def transaction: Option[String] = attributes.get(TRANSACTION_KEY)

  def timestamp: Option[Long] = attributes.get(TIMESTAMP_KEY).map(_.toLong)

  def node: Option[String] = attributes.get(NODE_KEY)

  def parent: YPathEnriched = YPathEnriched(path.getParent, attributes)

  def name: String = path.getName

  def withName(newName: String): YPathEnriched = parent.child(newName)

  def child(name: String): YPathEnriched = YPathEnriched(path.child(name), attributes)

  def withAttr(key: String, value: String): YPathEnriched = YPathEnriched(path, attributes + (key -> value))

  def withTransaction(transactionId: String): YPathEnriched = withAttr(TRANSACTION_KEY, transactionId)

  def withTransaction(transactionId: Option[String]): YPathEnriched = transactionId.map(withTransaction).getOrElse(this)

  def withTimestamp(timestamp: Long): YPathEnriched = withAttr(TIMESTAMP_KEY, timestamp.toString)

  def withLatestVersion: YPathEnriched = withTimestamp(-1)

  def dropTimestamp(): YPathEnriched = YPathEnriched(path, attributes - TIMESTAMP_KEY)

  def lock()(implicit yt: CompoundClient): YPathEnriched = transaction match {
    case Some(tId) if node.isEmpty => withAttr(NODE_KEY, YtWrapper.lockNode(toYPath, tId))
    case _ => this
  }

  override def equals(obj: Any): Boolean = obj match {
    case value: YPathEnriched => path.equals(value.path) && attributes.equals(value.attributes)
    case _ => false
  }

  override def toString: String = toStringPath
}

object YPathEnriched {
  private val NODE_KEY = "node"
  private val TIMESTAMP_KEY = "timestamp"
  private val TRANSACTION_KEY = "transaction"
  private val CLUSTER_KEY = "cluster"
  private val RESERVED_ATTRIBUTES: Set[String] = Set(NODE_KEY, TIMESTAMP_KEY, TRANSACTION_KEY, CLUSTER_KEY)

  @tailrec
  def fromPath(path: Path, attrs: Seq[(String, String)] = Seq.empty): YPathEnriched = {
    if (path.getName.startsWith("@")) {
      val attr = path.getName.drop(1).split("_", 2)
      fromPath(path.getParent, attrs :+ (attr.head -> attr.last))
    } else {
      // NB: It's important to save order of attributes
      YPathEnriched(path, ListMap(attrs.reverse: _*))
    }
  }

  def fromString(p: String): YPathEnriched = {
    // It can be taken from path, but now ytTable is the only right schema
    val scheme = "ytTable"
    val path = if (p.contains(":/")) p.split(":/", 2).last else p
    val richP = RichYPath.fromString(path)
    val strP = YtWrapper.correctSlashes(richP.justPath().toStableString, 1)
    val attrs = mutable.ListMap[String, String]()
    val cluster = richP.getAdditionalAttribute("cluster")
    if (cluster.isPresent) {
      attrs("cluster") = cluster.get().stringValue()
    }
    YPathEnriched(new Path(scheme, null, strP), attrs.toMap)
  }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy