calaxb_2.12.1.12.1.source-code.visitor.scala.template Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scalaxb_2.12 Show documentation
Show all versions of scalaxb_2.12 Show documentation
scalaxb is an XML data-binding tool for Scala that supports W3C XML Schema (xsd) and wsdl.
The newest version!
package scalaxb
import scala.reflect.ClassTag
/**
* Visitor utility for ScalaXB structures.
*
* Apparently these structures are not always simply trees;
* they may contain cycles, against which this visitor has protection
* by maintaining a `visited` collection.
*
*
* These cycles were found after processing MS Office Open XML schemata
* ECMA-376 4th edition Part 4
* http://www.ecma-international.org/publications/standards/Ecma-376.htm
*/
trait VisitorTrait {
import Visitor._
val tree: Any
var parents : List[Any] = Nil
var visited : List[Any] = Nil
var doSkipChildren: Boolean = false
/**
* Runs `f` on each node of the `tree`.
*/
def visit(f: PartialFunction[Any, Unit]): Unit = {
parents = Nil
visited = Nil
doSkipChildren = false
visitBody(tree, f)
}
/**
* This method brings `visitor` object into scope, in case
* you need access to the visitor variables like `parents` from
* the visiting function. Allows for the following syntax:
*
* Visitor(tree) {visitor =>
* {case _ => println(visitor.parents)}
* }
*
* instead of:
*
* val visitor = Visitor(tree)
* visitor {case _ => println(visitor.parents)}
*
* i.e. allows you to define the `visitor` variable and call the visitor
* function at the same time.
*/
def apply(fGenerator: VisitorTrait => PartialFunction[Any, Unit]): Unit =
visit(fGenerator(this))
/**
* Finds all the nodes matching a given `predicate` and
* returns them in a Seq in order of encounter.
*/
def collect(predicate: Any => Boolean): Seq[Any] = {
var collected: List[Any] = Nil
visit {case x if predicate(x) => collected :+= x}
collected
}
/**
* Collects all the nodes of a given class.
*/
def collect[T](implicit m: ClassTag[T]): Seq[T] =
collect(m.runtimeClass.isInstance(_)).asInstanceOf[Seq[T]]
/**
* Don't traverse the children of the given node.
*/
def skipChildren: Unit = doSkipChildren = true
protected def visitBody(node: Any, f: PartialFunction[Any, Unit]): Unit = {
visited :+= node
doSkipChildren = false
if (f isDefinedAt node) f(node)
if (!doSkipChildren) {
parents ::= node
children(node).filter {
case n: AnyRef => !visited.exists {case m: AnyRef => n eq m case _ => false}
case n => !visited.contains(n)
}.foreach(visitBody(_, f))
parents = parents.tail
}
}
/** Extracts the children of the given node. */
def children(node: Any): Seq[Any] = node match {
case x: Option[_] => x.map(Seq(_)).getOrElse(Nil)
case x: Seq[_] => x
case x: DataRecord[_] => Seq(x.value)
case x: Product => x.productIterator.toSeq
case _ => Nil
}
}
case class Visitor(tree: Any) extends VisitorTrait
© 2015 - 2025 Weber Informatics LLC | Privacy Policy