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

indigoplugin.generators.PathTree.scala Maven / Gradle / Ivy

The newest version!
package indigoplugin.generators

sealed trait PathTree {
  def name: String

  def combine(other: PathTree): PathTree =
    PathTree.combine(this, other)
  def |+|(other: PathTree): PathTree =
    combine(other)

  def sorted: PathTree =
    this match {
      case PathTree.Root(children) =>
        PathTree.Root(children.map(_.sorted).sortBy(_.name))

      case PathTree.Folder(n, children) =>
        PathTree.Folder(n, children.map(_.sorted).sortBy(_.name))

      case f @ PathTree.File(_, _, _) =>
        f
    }
}

object PathTree {

  def empty: PathTree =
    PathTree.Root(Nil)

  private def combineChildren(a: List[PathTree], b: List[PathTree]): List[PathTree] =
    b.flatMap {
      case PathTree.Root(children) =>
        combineChildren(a, children)

      case f @ PathTree.Folder(name, children) =>
        a.find {
          case PathTree.Folder(n, _) => n == name
          case _                     => false
        } match {
          case None =>
            a ++ List(f)

          case Some(fdlr @ PathTree.Folder(n, c)) =>
            a.filterNot(_ == fdlr) ++ List(PathTree.Folder(n, combineChildren(c, children)))

          case Some(_) =>
            a ++ List(f) // Shouldn't happen
        }

      case f: PathTree.File =>
        if (a.contains(f)) a else a ++ List(f)
    }

  def combine(a: PathTree, b: PathTree): PathTree =
    (a, b) match {
      case (PathTree.Root(Nil), PathTree.Root(Nil)) =>
        a

      case (PathTree.Root(csA), PathTree.Root(csB)) =>
        PathTree.Root(
          combineChildren(csA, csB)
        )

      case (PathTree.Root(csA), f @ PathTree.Folder(_, _)) =>
        PathTree.Root(combineChildren(csA, List(f)))

      case (PathTree.Folder(n, csA), PathTree.Root(csB)) =>
        PathTree.Folder(n, combineChildren(csA, csB))

      case (PathTree.Root(cs), f @ PathTree.File(_, _, _)) =>
        PathTree.Root(combineChildren(cs, List(f)))

      case (f @ PathTree.File(_, _, _), PathTree.Root(cs)) =>
        PathTree.Root(combineChildren(cs, List(f)))

      case (PathTree.Folder(nA, _), PathTree.Folder(nB, _)) if nA != nB =>
        throw new Exception(
          s"Something has gone wrong merging asset trees. Found two folders with different names: $nA and $nB"
        )

      case (PathTree.Folder(nA, csA), PathTree.Folder(_, csB)) =>
        PathTree.Folder(nA, combineChildren(csA, csB))

      case (PathTree.File(nA, _, _), PathTree.File(nB, _, _)) if nA != nB =>
        throw new Exception(
          s"Something has gone wrong merging asset trees. Found two file with different names: $nA and $nB"
        )

      case (f @ PathTree.File(_, _, _), PathTree.File(_, _, _)) =>
        f

      case (PathTree.Folder(nA, csA), f @ PathTree.File(_, _, _)) =>
        PathTree.Folder(nA, combineChildren(csA, List(f)))

      case (f @ PathTree.File(_, _, _), PathTree.Folder(nB, csB)) =>
        PathTree.Folder(nB, combineChildren(csB, List(f)))
    }

  def combineAll(pathTrees: List[PathTree]): PathTree =
    pathTrees.foldLeft(empty)(_ |+| _)

  def pathToPathTree(remaining: os.RelPath, original: os.RelPath): Option[PathTree] = {
    val result =
      remaining.segments.toList match {
        case Nil =>
          Option(
            PathTree.Root(Nil)
          )

        case p :: _ if p.isEmpty =>
          None

        case p :: Nil =>
          p.split('.').toList match {
            case Nil =>
              None

            case n :: ext :: Nil =>
              Option(
                PathTree.File(n, ext, original)
              )

            case n :: exts =>
              Option(
                PathTree.File(n, exts.mkString("."), original)
              )
          }

        case p :: ps =>
          Option(
            PathTree.Folder(
              p,
              pathToPathTree(os.RelPath(ps.toIndexedSeq, 0), original).toList
            )
          )
      }

    if (remaining == original) {
      Option(PathTree.Root(result.toList))
    } else {
      result
    }
  }
  def pathToPathTree(path: os.RelPath): Option[PathTree] =
    pathToPathTree(path, path)

  final case class Root(children: List[PathTree]) extends PathTree {
    val name: String = ""
  }
  final case class Folder(name: String, children: List[PathTree]) extends PathTree
  final case class File(name: String, extension: String, path: os.RelPath) extends PathTree {
    val fullName: String = name + "." + extension
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy