Skip to content
This repository has been archived by the owner on May 15, 2019. It is now read-only.

Commit

Permalink
Issue #13 - Introduced the notion of Zipper#hasValidContext to avoid …
Browse files Browse the repository at this point in the history
…some of these issues
  • Loading branch information
djspiewak committed May 13, 2011
1 parent e95566e commit 85ca4e3
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 40 deletions.
4 changes: 4 additions & 0 deletions src/main/scala/com/codecommit/antixml/Group.scala
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ class Group[+A <: Node] private[antixml] (private[antixml] val nodes: VectorCase
new Group(nodes) with Zipper[A] {
val map = Vector()
def parent = error("Attempted to move up at root of the tree")
override val hasValidContext = false
}
}

Expand Down Expand Up @@ -239,6 +240,8 @@ object Group {
case group: Group[Node] => group.toZipper
case _ => error("No zipper context available")
}

override val hasValidContext = from.isInstanceOf[Group[Node]]
}
}
}
Expand All @@ -248,6 +251,7 @@ object Group {
new Group(vec) with Zipper[A] {
lazy val map = baseMap
def parent = error("No zipper context available")
override val hasValidContext = false
}
}
}
Expand Down
85 changes: 45 additions & 40 deletions src/main/scala/com/codecommit/antixml/Zipper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ trait Zipper[+A <: Node] extends Group[A] with ScalaCompat { self =>

protected def map: Vector[Option[ZContext]]
protected def parent: Zipper[Node]
protected val hasValidContext = true

// TODO this *may* be a poor choice of words...
def stripZipper = new Group(toVectorCase)
Expand Down Expand Up @@ -67,52 +68,56 @@ trait Zipper[+A <: Node] extends Group[A] with ScalaCompat { self =>

override def flatMap[B, That](f: A => CompatTraversable[B])(implicit cbf: CanBuildFrom[Group[A], B, That]): That = cbf match {
case cbf: CanBuildFromWithZipper[Group[A], B, That] => {
val result = toVectorCase.toVector map f

val intermedMap = map map {
case Some((from, to, rebuild, childMap)) => {
// get the mapping from *our* indexes to source indexes
val inverseMap = {
val maps = for ((source, targets) <- childMap)
yield (Map[Int, Int]() /: targets) { (acc, t) => acc + (t -> source) }

(Map[Int, Int]() /: maps) { _ ++ _ }
}

val (_, aggregate, childMap2) = result.slice(from, to).zipWithIndex.foldLeft((0, Vector[B](), Map[Int, Set[Int]]())) {
case ((start, acc, childMap2), (chunk, i)) => {
val size = chunk.size
val source = inverseMap(i)

val contrib = Set(start until (start + size): _*)
val set2 = childMap2.getOrElse(source, contrib) ++ contrib
if (!hasValidContext) {
super.flatMap(f)(cbf) // don't try to preserve
} else {
val result = toVectorCase.toVector map f

(start + size, acc ++ chunk, childMap2.updated(source, set2))
val intermedMap = map map {
case Some((from, to, rebuild, childMap)) => {
// get the mapping from *our* indexes to source indexes
val inverseMap = {
val maps = for ((source, targets) <- childMap)
yield (Map[Int, Int]() /: targets) { (acc, t) => acc + (t -> source) }

(Map[Int, Int]() /: maps) { _ ++ _ }
}

val (_, aggregate, childMap2) = result.slice(from, to).zipWithIndex.foldLeft((0, Vector[B](), Map[Int, Set[Int]]())) {
case ((start, acc, childMap2), (chunk, i)) => {
val size = chunk.size
val source = inverseMap(i)

val contrib = Set(start until (start + size): _*)
val set2 = childMap2.getOrElse(source, contrib) ++ contrib

(start + size, acc ++ chunk, childMap2.updated(source, set2))
}
}

val length = aggregate.length
val delta = length - (to - from)
Some((from, to + delta, rebuild, childMap2, aggregate, delta))
}

val length = aggregate.length
val delta = length - (to - from)
Some((from, to + delta, rebuild, childMap2, aggregate, delta))

case None => None
}
case None => None
}

val (_, map2, chunks) = intermedMap.foldLeft((0, Vector[Option[ZContext]](), Vector[Vector[B]]())) {
case ((offset, map2, acc), Some((from, to, rebuild, childMap, aggregate, delta))) => {
val from2 = from + offset
val to2 = to + offset
val offset2 = offset + delta
(offset2, map2 :+ Some((from2, to2, rebuild, childMap)), acc :+ aggregate)

val (_, map2, chunks) = intermedMap.foldLeft((0, Vector[Option[ZContext]](), Vector[Vector[B]]())) {
case ((offset, map2, acc), Some((from, to, rebuild, childMap, aggregate, delta))) => {
val from2 = from + offset
val to2 = to + offset
val offset2 = offset + delta
(offset2, map2 :+ Some((from2, to2, rebuild, childMap)), acc :+ aggregate)
}

case ((offset, map2, acc), None) => (offset, map2 :+ None, acc)
}

case ((offset, map2, acc), None) => (offset, map2 :+ None, acc)

val builder = cbf(parent.asInstanceOf[Group[A]], map2)
chunks foreach (builder ++=)
builder.result
}

val builder = cbf(parent.asInstanceOf[Group[A]], map2)
chunks foreach (builder ++=)
builder.result
}

case _ => super.flatMap(f)(cbf)
Expand Down

0 comments on commit 85ca4e3

Please sign in to comment.