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

overflowdb.traversal.PathAwareTraversal.scala Maven / Gradle / Ivy

There is a newer version: 1.193
Show newest version
package overflowdb.traversal

import scala.annotation.tailrec
import scala.collection.{IterableOnce, Iterator}

class PathAwareTraversal[A](val wrapped: Iterator[(A, Vector[Any])]) extends Iterator[A] {
  type Traversal[A] = Iterator[A]

  override def hasNext: Boolean = wrapped.hasNext

  override def next(): A = wrapped.next()._1

  override def map[B](f: A => B): PathAwareTraversal[B] = new PathAwareTraversal[B](wrapped.map { case (a, p) =>
    (f(a), p.appended(a))
  })

  override def flatMap[B](f: A => IterableOnce[B]): PathAwareTraversal[B] =
    new PathAwareTraversal[B](wrapped.flatMap { case (a, p) =>
      val ap = p.appended(a)
      f(a).iterator.map {
        (_, ap)
      }
    })

  override def distinctBy[B](f: A => B): PathAwareTraversal[A] = new PathAwareTraversal[A](wrapped.distinctBy {
    case (a, p) => f(a)
  })

  override def collect[B](pf: PartialFunction[A, B]): PathAwareTraversal[B] = flatMap(pf.lift)

  override def filter(p: A => Boolean): PathAwareTraversal[A] = new PathAwareTraversal(wrapped.filter(ap => p(ap._1)))

  override def filterNot(p: A => Boolean): PathAwareTraversal[A] = new PathAwareTraversal(
    wrapped.filterNot(ap => p(ap._1))
  )

  override def duplicate: (Iterator[A], Iterator[A]) = {
    val tmp = wrapped.duplicate
    (new PathAwareTraversal(tmp._1), new PathAwareTraversal(tmp._2))
  }

  private[traversal] def _union[B](traversals: (Traversal[A] => Traversal[B])*): Traversal[B] =
    new PathAwareTraversal(wrapped.flatMap { case (a, p) =>
      traversals.iterator.flatMap { inner =>
        inner(new PathAwareTraversal(Iterator.single((a, p)))) match {
          case stillPathAware: PathAwareTraversal[B] => stillPathAware.wrapped
          // do we really want to allow the following, or is it an error?
          case notPathAware => notPathAware.iterator.map { (b: B) => (b, p.appended(a)) }
        }
      }
    })

  private[traversal] def _choose[BranchOn >: Null, NewEnd](on: Traversal[A] => Traversal[BranchOn])(
      options: PartialFunction[BranchOn, Traversal[A] => Traversal[NewEnd]]
  ): Traversal[NewEnd] =
    new PathAwareTraversal(wrapped.flatMap { case (a, p) =>
      val branchOnValue: BranchOn = on(Iterator.single(a)).nextOption().getOrElse(null)
      options
        .applyOrElse(branchOnValue, (failState: BranchOn) => ((unused: Traversal[A]) => Iterator.empty[NewEnd]))
        .apply(new PathAwareTraversal(Iterator.single((a, p)))) match {
        case stillPathAware: PathAwareTraversal[NewEnd] => stillPathAware.wrapped
        // do we really want to allow the following, or is it an error?
        case notPathAware => notPathAware.iterator.map { (b: NewEnd) => (b, p.appended(a)) }
      }
    })

  private[traversal] def _coalesce[NewEnd](options: (Traversal[A] => Traversal[NewEnd])*): Traversal[NewEnd] =
    new PathAwareTraversal(wrapped.flatMap { case (a, p) =>
      options.iterator
        .map { inner =>
          inner(new PathAwareTraversal(Iterator.single((a, p)))) match {
            case stillPathAware: PathAwareTraversal[NewEnd] => stillPathAware.wrapped
            // do we really want to allow the following, or is it an error?
            case notPathAware => notPathAware.iterator.map { (b: NewEnd) => (b, p.appended(a)) }
          }
        }
        .find(_.nonEmpty)
        .getOrElse(Iterator.empty)
    })

  private[traversal] def _sideEffect(f: A => _): PathAwareTraversal[A] = new PathAwareTraversal(wrapped.map {
    case (a, p) => f(a); (a, p)
  })

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy