
scales.xml.parser.strategies.TreeOptimisations.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scales-xml_2.11 Show documentation
Show all versions of scales-xml_2.11 Show documentation
An alternate Scala Xml processing library
The newest version!
package scales.xml.parser.strategies
import scales.xml._
import scales.utils.collection.{ImmutableArrayProxy, SeqLikeThing, Tree}
import scales.xml.impl.{FromParser, IsFromParser, NotFromParser}
import ImmutableArrayProxy.one
import impl.TreeProxies
import scales.utils.ItemOrTree
/**
* Allows replacing a tree for memory optimisations
*/
trait TreeOptimisation[TOKEN <: OptimisationToken] extends PathOptimisationStrategy[TOKEN] {
def newTree( elem : Elem, children : XmlChildren, token : TOKEN )(implicit seqLikeThing: SeqLikeThing[XCC[_], ItemOrTree[XmlItem, Elem, XCC], XCC]): XmlTree
final override def elementEnd( xml : TreeProxies, token : TOKEN ) {
val l = xml.current
val nt = newTree(l.elem, l.builder.result, token)
val d = xml.depth
val nd = d - 1
if (d > 0) {
xml.depth = nd
val c = xml.proxy( nd )
xml.current = c
c.builder.+=(nt)
} else {
xml.rootTree = nt
xml.depth = nd
}
}
}
/**
* An elem with no attributes, namespaces and only one text value.
*
*/
abstract class NameValue(val name : QName, val text : String) extends Tree[XmlItem, Elem, XCC] {
def section : Elem
def children : XmlChildren = one(Text(text))
def copy( section : Elem = section, children : XmlChildren = children) : Tree[XmlItem, Elem, XCC] = {
// if we are copying we are no longer in a parse
import ScalesXml.fromParserDefault
LazyOptimisedTree(section, children)
}
}
/**
* An elem with attributes or namespaces and only one text value.
*
*/
class ElemValue(val section : Elem, val text : String)(implicit val seqLikeThing: SeqLikeThing[XCC[_], ItemOrTree[XmlItem, Elem, XCC], XCC]) extends Tree[XmlItem, Elem, XCC] {
def children : XmlChildren = one(Text(text))
def copy( section : Elem = section, children : XmlChildren = children) : Tree[XmlItem, Elem, XCC] = {
// if we are copying we are no longer in a parse
import ScalesXml.fromParserDefault
LazyOptimisedTree(section, children)
}
}
/**
* Collection of optimisations that reduce memory significantly at the cost of parsing performance, and later non-lazy creation of correct objects for accessing the tree.
*
* This can have confusing runtime evaluation of XPaths etc. These optimisations are appropriate for trees that are seldom read, repeated reads may generate too much garbage.
*/
object LazyOptimisedTree {
/**
* Returns an optimised Tree if Possible
*/
def apply( section : Elem, children : XmlChildren ) ( implicit fromParser : FromParser ) : XmlTree =
if (children.isEmpty)
Tree(section, children)
else {
val head = children.head
if (head.isLeft) {
val left = head.getLeft
if (left.isInstanceOf[Text] && children.size == 1) {
if (section.attributes.isEmpty && section.namespaces.isEmpty)
newNameValue(section.name, left.value)
else
new ElemValue(section, left.value)
} else Tree(section, children)
} else Tree(section, children)
}
def newNameValue( iname : QName, itext : String ) ( implicit fromParser : FromParser, iseqLikeThing: SeqLikeThing[XCC[_], ItemOrTree[XmlItem, Elem, XCC], XCC] ) : NameValue =
if (fromParser eq NotFromParser)
new NameValue(iname, itext) {
def section : Elem = Elem(name)(NotFromParser) // have to recheck that the qname is ok
override implicit val seqLikeThing: SeqLikeThing[XCC[_], ItemOrTree[XmlItem, Elem, XCC], XCC] = iseqLikeThing
}
else
new NameValue(iname, itext) {
def section : Elem = Elem(name)(IsFromParser) // don't have to recheck
override implicit val seqLikeThing: SeqLikeThing[XCC[_], ItemOrTree[XmlItem, Elem, XCC], XCC] = iseqLikeThing
}
}
/**
* Optimises QNames and Trees according to LazyOptimisedTree
*/
object QNameTreeOptimisation extends TreeOptimisation[QNameToken] with QNameOptimisationT[QNameToken] with QNameTokenF {
def newTree( elem : Elem, children : XmlChildren, token : QNameToken )(implicit seqLikeThing: SeqLikeThing[XCC[_], ItemOrTree[XmlItem, Elem, XCC], XCC]) : XmlTree =
LazyOptimisedTree( elem, children )(IsFromParser)
}
/**
* Optimised QNames, Elems and Tree, heavily reduced memory consumption with LazyOptimisedTree.
*/
object QNameElemTreeOptimisation extends PathOptimisationStrategy[ElemToken] with ElemQNameOptimisationT[ElemToken] with TreeOptimisation[ElemToken] with ElemTokenF {
def newTree( elem : Elem, children : XmlChildren, token : ElemToken )(implicit seqLikeThing: SeqLikeThing[XCC[_], ItemOrTree[XmlItem, Elem, XCC], XCC]) : XmlTree =
LazyOptimisedTree( elem, children )(IsFromParser)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy