Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Optimized Selector Variant #53

Merged
merged 1 commit into from

2 participants

@josharnold52

As of #51, custom selectors can no longer leverage the bloom filter. I'd like to try and restore that ability in a more (hopefully) palatable way:

trait OptimizingSelector[+A] extends Selector[A] {
  /***
   * Provides a hint as to whether the selector can any children or their
   * descendants in the specified group.  Note that this is merely a hint,
   * `isDefinedAt` is the authoritative determinant of whether a selector matches.
   */
  def canMatchIn(group: Group[Node]): Boolean
} 

Basically, canMatchIn takes the role of the old matches method, but with (hopefully) cleaner semantics. Of course, implementations can call Group.matches(String) to reproduce the old functionality.

For some concrete examples, here are some searches that I'd like to be able to do while leveraging the bloom filter optimization:

  1. Find all elements, e that have a given name and a given attribute value
  2. Find all elements, e with a given name and return f(e) for some transform f.
  3. Find all elements, e that contain a child element with a given name.
@djspiewak
Owner

Ok, yeah, that is a lot more general than just matching on ElemSelector…and you provided tests! Merged!

@djspiewak djspiewak merged commit 669fd62 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 23, 2011
  1. @josharnold52

    Optimizing selector idea

    josharnold52 authored
This page is out of date. Refresh to see the latest.
View
3  src/main/scala/com/codecommit/antixml/PathCreator.scala
@@ -98,9 +98,10 @@ private[antixml] object PathCreator {
/** Returns true if there is a chance that applying the given selector on the group
* would yield some results. */
- private def dispatchSelector(s: Selector[_], g: Group[_]) = {
+ private def dispatchSelector(s: Selector[_], g: Group[Node]) = {
s match {
case e: ElemSelector => g matches e.elementName
+ case opt: OptimizingSelector[_] => opt.canMatchIn(g)
case _ => true // no info about the selector, should proceed
}
}
View
9 src/main/scala/com/codecommit/antixml/Selector.scala
@@ -33,6 +33,15 @@ import scala.collection.immutable.Seq
trait Selector[+A] extends PartialFunction[Node, A]
+trait OptimizingSelector[+A] extends Selector[A] {
+ /***
+ * Provides a hint as to whether the selector can any children or their
+ * descendants in the specified group. Note that this is mearly a hint,
+ * `isDefinedAt` is the authoritative determinant of whether a selector matches.
+ */
+ def canMatchIn(group: Group[Node]): Boolean
+}
+
/** A selector that selects an element by name. */
private[antixml] class ElemSelector(val elementName: String) extends Selector[Elem] {
// not using a case class to allow inheritance
View
44 src/test/scala/com/codecommit/antixml/SelectorSpecs.scala
@@ -55,4 +55,48 @@ class SelectorSpecs extends Specification {
<parent><foo/><bar/>Baz<foo/></parent>.convert \ 'foo mustEqual Group(<foo/>.convert, <foo/>.convert)
}
}
+
+
+
+ "Optimizing selectors" should {
+ val bookstore = new StAXParser().fromString {
+ "<bookstore>" +
+ "<book>" +
+ "<title>For Whom the Bell Tolls</title>" +
+ "<author>Hemmingway</author>" +
+ "</book>" +
+ "<book>" +
+ "<title>I, Robot</title>" +
+ "<author>Isaac Asimov</author>" +
+ "</book>" +
+ "<book>" +
+ "<title>Programming Scala</title>" +
+ "<author>Dean Wampler</author>" +
+ "<author>Alex Payne</author>" +
+ "</book>" +
+ "<book>" +
+ "<title>An anonymous transcript</title>" +
+ "</book>" +
+ "</bookstore>"
+ }
+
+ "work using a non-trivial canMatchIn and mapping" in {
+ val titlesOfBooksWithAuthors = new OptimizingSelector[String]() {
+ private val pf: PartialFunction[Node, String] = {
+ case e:Elem if (e \ 'author).nonEmpty => (e \ 'title \ text).mkString
+ }
+
+ override def isDefinedAt(e:Node) = pf.isDefinedAt(e)
+ override def apply(sel: Node):String = pf(sel)
+ override def canMatchIn(g: Group[Node]) = {
+ g.matches("author") && g.matches("title")
+ }
+ }
+
+ val result = bookstore \\ titlesOfBooksWithAuthors
+ result mustEqual Vector("For Whom the Bell Tolls","I, Robot","Programming Scala")
+
+ }
+ }
+
}
Something went wrong with that request. Please try again.