Permalink
Browse files

Merge branch 'master' into attrapi

  • Loading branch information...
2 parents 09b1450 + bf30b77 commit 6803a507fbc096db64fe7301afc66dfa1b86d488 @josharnold52 josharnold52 committed Oct 1, 2011
Showing with 1,836 additions and 2,377 deletions.
  1. +15 −6 CHANGELOG.rst
  2. +1 −1 build.sbt
  3. +0 −36 src/main/scala/com/codecommit/antixml/CanBuildFromWithDeepZipper.scala
  4. +84 −111 src/main/scala/com/codecommit/antixml/CanBuildFromWithZipper.scala
  5. +0 −49 src/main/scala/com/codecommit/antixml/CanProduceZipper.scala
  6. +0 −776 src/main/scala/com/codecommit/antixml/DeepZipper.scala
  7. +17 −80 src/main/scala/com/codecommit/antixml/Group.scala
  8. +169 −0 src/main/scala/com/codecommit/antixml/PathCreator.scala
  9. +74 −104 src/main/scala/com/codecommit/antixml/Selectable.scala
  10. +21 −7 src/main/scala/com/codecommit/antixml/Selector.scala
  11. +9 −2 src/main/scala/com/codecommit/antixml/XMLSerializer.scala
  12. +275 −162 src/main/scala/com/codecommit/antixml/Zipper.scala
  13. +26 −0 src/main/scala/com/codecommit/antixml/ZipperMergeContext.scala
  14. +133 −0 src/main/scala/com/codecommit/antixml/ZipperMergeStrategy.scala
  15. +11 −2 src/main/scala/com/codecommit/antixml/node.scala
  16. +0 −17 src/main/scala/com/codecommit/antixml/package.scala
  17. +3 −4 src/test/scala/com/codecommit/antixml/ConversionSpecs.scala
  18. +0 −679 src/test/scala/com/codecommit/antixml/DeepZipperSpecs.scala
  19. +90 −17 src/test/scala/com/codecommit/antixml/GroupSpecs.scala
  20. +163 −0 src/test/scala/com/codecommit/antixml/PathCreatorSpecs.scala
  21. +44 −0 src/test/scala/com/codecommit/antixml/SelectorSpecs.scala
  22. +128 −0 src/test/scala/com/codecommit/antixml/ZipperMergeStrategySpecs.scala
  23. +573 −324 src/test/scala/com/codecommit/antixml/ZipperSpecs.scala
View
@@ -2,9 +2,21 @@
CHANGELOG
=========
+0.4
+===
+
0.3
===
+* New selection methods
+
+ * ``\\!`` – Performs a deep selection, but stops the recursion once a match is
+ reached (thus, if a parent and its child both match, only the parent will be
+ returned). The results are guaranteed to have a zipper with an non-conflicting
+ ``unselect`` on all operations
+ * ``select`` – Performs a selection at the *current* level, without descent
+
+* Deep selection (``\\``) is now depth-first, rather than breadth-first
* Zipper now works for both ``\`` and ``\\`` methods
* New utility methods supported by Zipper
@@ -13,8 +25,6 @@ CHANGELOG
* ``splitAt``
* ``take``
-* Deep-select now returns a ``Group`` rather than a ``Zipper`` with an invalid
- context
* Implicit conversions from ``String`` and ``Symbol`` to ``Selector`` are now
hidden in the ``Selector`` companion object
* Explicit converters now use ``convert`` instead of ``anti``
@@ -28,10 +38,9 @@ CHANGELOG
results have been dropped
* ``Zipper#unselect`` on empty selection results no functions appropriately
* `Issue 12`_ – Utility Operations on Group Return an Invalid Zipper
-
- * Utility methods on ``Group`` now return ``Group`` when possible, rather
- than ``Zipper``. This also changes the ``CanBuildFromWithZipper`` API
- by splitting it entirely from ``CanBuildFrom``.
+ * Utility methods on ``Group`` now return ``Group`` when possible, rather
+ than ``Zipper``. This also changes the ``CanBuildFromWithZipper`` API
+ by splitting it entirely from ``CanBuildFrom``.
.. _Issue #40: https://github.com/djspiewak/anti-xml/issues/40
View
@@ -2,7 +2,7 @@ name := "anti-xml"
organization := "com.codecommit"
-version := "0.3-SNAPSHOT"
+version := "0.4-SNAPSHOT"
crossScalaVersions := Seq("2.9.1", "2.9.0-1", "2.9.0")
@@ -1,36 +0,0 @@
-package com.codecommit.antixml
-
-import scala.collection.mutable.Builder
-import scala.collection.generic.CanBuildFrom
-import DeepZipper._
-
-/** A factory for [[DeepZipper]] instances.
- * @tparam N The type of nodes to be contained in the [[DeepZipper]] (if any).
- */
-trait CanBuildFromWithDeepZipper[-From, -Elem, To] {
- /** Creates a new builder.
- *
- * @param parent The parent of the zipper
- * @param contexts The contexts from which the zipper should be composed.
- * The contexts will be merged to the builder's input to produce a zipper.
- * @parent emptiesSet A set of empty locations in the zipper. */
- def apply(parent: Option[From], contexts: Vector[LocationContext], emptiesSet: EmptiesSet): Builder[Elem, To]
-}
-
-/** A marker interface for [[CanBuildFrom]] instances that can be lifted into
- * [[CanBuildFromWithDeepZipper]] instances which operate on [[Node]] types. */
-trait CanProduceDeepZipper[-From, A <: Node, To] { this: CanBuildFrom[From, A, _ >: To] =>
- def lift: CanBuildFromWithDeepZipper[From, A, To]
-}
-
-/** Different implicit implementations of [[CanBuildFromWithDeepZipper]]. */
-object CanBuildFromWithDeepZipper {
-
- /** Implicitly lifts [[CanBuildFrom]] instances into instances of [[CanBuildFromWithDeepZipper]]. */
- implicit def identityCanBuildFrom[From, Elem, To](implicit cbf: CanBuildFrom[From, Elem, To]) = {
- new CanBuildFromWithDeepZipper[From, Elem, To] {
- /** Creates a builder that just ignores anything [[DeepZipper]] related. */
- def apply(parent: Option[From], contexts: Vector[LocationContext], emptiesSet: EmptiesSet) = cbf()
- }
- }
-}
@@ -1,111 +1,84 @@
-/*
- * Copyright (c) 2011, Daniel Spiewak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- * - Neither the name of "Anti-XML" nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.codecommit.antixml
-
-import scala.collection.generic.CanBuildFrom
-import scala.collection.immutable.Vector
-import scala.collection.mutable.Builder
-
-/**
- * An implicit factory creator for use in selection in the style
- * of [[scala.collection.generic.CanBuildFrom]] with functionality required to
- * generate zippers. In addition to providing the standard CanBuildFrom
- * functionality (producing an instanceof [[scala.collection.mutable.Builder]])
- * with respect to a provided zipper context, this typeclass also provides a
- * monoidal append method on the `To` type. This is required for deep-select on
- * [[com.codecommit.antixml.Group]].
- *
- * A default implicit "lifting" is provided from [[scala.collection.generic.CanBuildFrom]] to
- * an instances of [[com.codecommit.antixml.CanBuildFromWithZipper]] for all target
- * types which are implicitly convertable to [[scala.collection.Traversable]].
- * (the reason for this restriction is to allow a default implementation of the
- * aforementioned monoidal append) This implicit lifting is defined in the
- * companion object for this trait, giving it lower priority in the implicit
- * resolution, but still accessible without requiring an explicit import.
- */
-trait CanBuildFromWithZipper[-From, -Elem, To] { self =>
- def apply(parent: From, map: =>Vector[Option[ZContext]]): Builder[Elem, To]
- def apply(map: =>Vector[Option[ZContext]]): Builder[Elem, To]
-
- /**
- */
- def append(left: To, right: To): To
-
- /**
- * Equivalent to `(left /: rest)(append)`. Subclasses may provide a more efficient
- * implementation.
- */
- def appendAll(left: To, rest: TraversableOnce[To]): To = {
- (left /: rest)(append)
- }
-
- def lift[CC >: To]: CanBuildFrom[From, Elem, CC] = new CanBuildFrom[From, Elem, CC] {
- def apply(from: From) = apply()
- def apply() = self(Vector())
- }
-}
-
-/**
- * Serves as a simple container for the implicit lifting
- * of [[scala.collection.generic.CanBuildFrom]] to [[com.codecommit.antixml.CanBuildFromWithZipper]].
- */
-object CanBuildFromWithZipper {
-
- /**
- * Implicitly "lifts" an existing instance of [[scala.collection.generic.CanBuildFrom]] into
- * an instance of [[com.codecommit.antixml.CanBuildFromWithZipper]], provided
- * that the result type of the builder is implicitly convertable (potentially
- * via `identity`) to [[scala.collection.Traversable]]. In practice, this
- * should be effectively all conceivable instances of [[scala.collection.generic.CanBuildFrom]],
- * so this should not be a problematic restriction.
- *
- * This implicit lifting makes it possible to define instances
- * of [[com.codecommit.antixml.Selector]] which produce
- * non-[[com.codecommit.antixml.Node]] result types. More precisely, it allows
- * such selectors to be ''used'' with the `\` and `\\` methods
- * on [[com.codecommit.antixml.Group]].
- */
- implicit def identityCanBuildFrom[From, Elem, To](implicit cbf: CanBuildFrom[From, Elem, To], coerce: To => Traversable[Elem]): CanBuildFromWithZipper[From, Elem, To] = new CanBuildFromWithZipper[From, Elem, To] {
- def apply(parent: From, map: =>Vector[Option[ZContext]]) = cbf()
- def apply(map: =>Vector[Option[ZContext]]) = cbf()
-
- def append(left: To, right: To) = {
- val builder = cbf()
- builder ++= left
- builder ++= right
- builder.result()
- }
-
- override def appendAll(left: To, rest: TraversableOnce[To]): To = {
- val builder = cbf() ++= left
- rest foreach {builder ++= _}
- builder.result()
- }
- }
-}
+package com.codecommit.antixml
+
+import scala.collection.GenTraversableOnce
+import scala.collection.mutable.Builder
+import scala.collection.generic.CanBuildFrom
+
+/** A factory for [[com.codecommit.antixml.Zipper]] instances.
+ * This trait is similar to [[scala.collection.mutable.CanBuildFrom]], however its builders accept instances
+ * of `ElemsWithContext[Elem]` rather than `Elem` instances. In addition, its `apply`
+ * methods accept an optional reference to the zipper's parent.
+ *
+ * @tparam From The type of collection that is producing the zipper.
+ * @tparam Elem The type of nodes to be contained in the result (if any).
+ * @tparam To the type of collection being produced.
+ */
+trait CanBuildFromWithZipper[-From, -Elem, To] {
+ import CanBuildFromWithZipper.ElemsWithContext
+
+ /** Creates a new builder.
+ *
+ * @param parent The parent of the zipper. If `None`, the zipper will
+ * still function as an IndexedSeq, but zipper unselection will fail.
+ */
+ def apply(parent: Option[Zipper[Node]]): Builder[ElemsWithContext[Elem], To]
+
+ /** Creates a new builder.
+ * @param parent The parent of the zipper. If `None`, the zipper will
+ * still function as an IndexedSeq, but zipper unselection will fail.
+ * @param from The collection producing the zipper
+ */
+ def apply(parent: Option[Zipper[Node]], from: From): Builder[ElemsWithContext[Elem], To] = this(parent)
+
+}
+
+/** A marker interface for [[scala.collection.mutable.CanBuildFrom]] instances that can be lifted into
+ * [[com.codecommit.antixml.CanBuildFromWithZipper]] instances that operate on [[com.codecommit.antixml.Node]] types. */
+trait CanProduceZipper[-From, A <: Node, To] { this: CanBuildFrom[From, A, _ >: To] =>
+ def lift: CanBuildFromWithZipper[From, A, To]
+}
+
+/** Different implicit implementations of [[com.codecommit.antixml.CanBuildFromWithZipper]]. */
+object CanBuildFromWithZipper {
+
+ /**
+ * Decorates a sequence of zipper elements with a zipper context and an update time. This is the
+ * basic unit of information used to construct zippers.
+ *
+ * @tparam Elem the type of node that will be contained in the zipper.
+ * @param path Identifies a location in the zipper's parent. The path order is from top to bottom
+ * (the first item specifies the index of a top-level node within the parent). When building a zipper,
+ * it is legal for multiple ElemsWithContexts to specify the same path; In such cases, all of the
+ * corresponding Elems will be added to the zipper and they will all be associated with that path.
+ * @param updateTime the update time associated with these elements. One context is considered to have
+ * been updated later than another if its updateTime is greater.
+ * @param elements the actual elements to be added to the zipper. Note that this sequence may be
+ * empty. This would happen, for example, if `flatMap` operation removed all items for a given path.
+ */
+ case class ElemsWithContext[+Elem](path: Seq[Int], updateTime: Int, elements: GenTraversableOnce[Elem])
+
+ /** Implicitly lifts [[scala.collection.mutable.CanBuildFrom]] instances into instances of [[com.codecommit.antixml.CanBuildFromWithZipper]]. The resulting builders simply ignore
+ * the extra information in `ElemsWithContext` and produce their collections as usual.
+ */
+ implicit def identityCanBuildFrom[From, Elem, To](implicit cbf: CanBuildFrom[From, Elem, To]): CanBuildFromWithZipper[From, Elem, To] = {
+ new CanBuildFromWithZipper[From, Elem, To] {
+
+ /** Creates a builder that just ignores anything [[com.codecommit.antixml.Zipper]] related. */
+ override def apply(parent: Option[Zipper[Node]], from: From) = liftBuilder(cbf(from))
+
+ /** Creates a builder that just ignores anything [[com.codecommit.antixml.Zipper]] related. */
+ override def apply(parent: Option[Zipper[Node]]) = liftBuilder(cbf())
+
+ private def liftBuilder(b: Builder[Elem,To]) = new Builder[ElemsWithContext[Elem], To]() {
+ override def += (x: ElemsWithContext[Elem]) = {
+ b ++= x.elements.seq
+ this
+ }
+ override def clear() {
+ b.clear()
+ }
+ override def result() = b.result()
+ }
+ }
+ }
+}
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2011, Daniel Spiewak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- * - Neither the name of "Anti-XML" nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.codecommit.antixml
-
-import scala.collection.generic.CanBuildFrom
-
-/**
- * Trait which signifies a special type of [[scala.collection.generic.CanBuildFrom]],
- * capable of lifting itself into an instance of [[com.codecommit.antixml.CanBuildFromWithZipper]].
- * Note that even though all CanBuildFrom instances for Traversable targets are
- * implicitly liftable into [[com.codecommit.antixml.CanBuildFromWithZipper]],
- * this lifting is generic and often different from the results of the `lift`
- * method defined by this trait.
- *
- * In practice, this trait is used as a marker trait by the utility methods
- * on [[com.codecommit.antixml.Zipper]] (particularly `map` and `flatMap`).
- * Without this trait, it would be impossible to distinguish zippable collection
- * types from non-zippable collection types while preserving the override of
- * these methods.
- */
-trait CanProduceZipper[-From, -Elem, To] { this: CanBuildFrom[From, Elem, _ >: To] =>
- def lift: CanBuildFromWithZipper[From, Elem, To]
-}
Oops, something went wrong.

0 comments on commit 6803a50

Please sign in to comment.