scala.xml.factory.NodeFactory.scala Maven / Gradle / Ivy
The newest version!
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala
package xml
package factory
import scala.collection.Seq
trait NodeFactory[A <: Node] {
val ignoreComments: Boolean = false
val ignoreProcInstr: Boolean = false
/* default behaviour is to use hash-consing */
val cache: scala.collection.mutable.HashMap[Int, List[A]] = new scala.collection.mutable.HashMap[Int, List[A]]
protected def create(pre: String, name: String, attrs: MetaData, scope: NamespaceBinding, children: Seq[Node]): A
protected def construct(hash: Int, old: List[A], pre: String, name: String, attrSeq: MetaData, scope: NamespaceBinding, children: Seq[Node]): A = {
val el: A = create(pre, name, attrSeq, scope, children)
cache.update(hash, el :: old)
el
}
def eqElements(ch1: Seq[Node], ch2: Seq[Node]): Boolean =
ch1.view.zipAll(ch2.view, null, null).forall { case (x, y) => x.eq(y) }
def nodeEquals(n: Node, pre: String, name: String, attrSeq: MetaData, scope: NamespaceBinding, children: Seq[Node]): Boolean =
n.prefix == pre &&
n.label == name &&
n.attributes == attrSeq &&
// scope?
eqElements(n.child, children)
def makeNode(pre: String, name: String, attrSeq: MetaData, scope: NamespaceBinding, children: Seq[Node]): A = {
val hash: Int = Utility.hashCode(pre, name, attrSeq.##, scope.##, children)
def cons(old: List[A]): A = construct(hash, old, pre, name, attrSeq, scope, children)
cache.get(hash) match {
case Some(list) => // find structurally equal
list.find(nodeEquals(_, pre, name, attrSeq, scope, children)) match {
case Some(x) => x
case _ => cons(list)
}
case None => cons(Nil)
}
}
def makeText(s: String): Text = Text(s)
def makePCData(s: String): PCData =
PCData(s)
def makeComment(s: String): Seq[Comment] =
if (ignoreComments) Nil else List(Comment(s))
def makeProcInstr(t: String, s: String): Seq[ProcInstr] =
if (ignoreProcInstr) Nil else List(ProcInstr(t, s))
}