From 158e5db28b9a95f54002302f4393b26aa6106e68 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 31 Aug 2009 13:21:58 +0000 Subject: Brushing some of the cobwebs off the denizens o... Brushing some of the cobwebs off the denizens of scala.xml. I am removing bits of XML code which are clearly unfinished and which nothing anywhere in the compiler or library uses. --- .../scala/xml/dtd/DtdTypeSymbol.scala | 1 - .../scala/xml/persistent/IndexedStorage.scala | 1 - src/library/scala/io/File.scala | 2 + src/library/scala/xml/dtd/ContentModel.scala | 108 +++++++-------------- src/library/scala/xml/dtd/DTD.scala | 14 +-- src/library/scala/xml/dtd/Decl.scala | 4 +- src/library/scala/xml/dtd/DtdTypeSymbol.scala | 16 --- src/library/scala/xml/dtd/Scanner.scala | 5 +- .../scala/xml/dtd/ValidationException.scala | 10 +- src/library/scala/xml/path/Expression.scala | 35 ++----- .../scala/xml/persistent/CachedFileStorage.scala | 49 +++++----- .../scala/xml/persistent/IndexedStorage.scala | 49 ---------- src/library/scala/xml/persistent/SetStorage.scala | 25 ++--- 13 files changed, 85 insertions(+), 234 deletions(-) delete mode 100644 src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala delete mode 100644 src/dotnet-library/scala/xml/persistent/IndexedStorage.scala delete mode 100644 src/library/scala/xml/dtd/DtdTypeSymbol.scala delete mode 100644 src/library/scala/xml/persistent/IndexedStorage.scala diff --git a/src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala b/src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala deleted file mode 100644 index afcfeb5200..0000000000 --- a/src/dotnet-library/scala/xml/dtd/DtdTypeSymbol.scala +++ /dev/null @@ -1 +0,0 @@ -/* DtdTypeSymbol.scala does not exist for the dotnet target */ \ No newline at end of file diff --git a/src/dotnet-library/scala/xml/persistent/IndexedStorage.scala b/src/dotnet-library/scala/xml/persistent/IndexedStorage.scala deleted file mode 100644 index 63158b45c0..0000000000 --- a/src/dotnet-library/scala/xml/persistent/IndexedStorage.scala +++ /dev/null @@ -1 +0,0 @@ -/* IndexedStorage.scala does not exist for the dotnet target */ \ No newline at end of file diff --git a/src/library/scala/io/File.scala b/src/library/scala/io/File.scala index 248f8b7176..b10d2360b9 100644 --- a/src/library/scala/io/File.scala +++ b/src/library/scala/io/File.scala @@ -13,6 +13,7 @@ package scala.io import java.io.{ FileInputStream, FileOutputStream, BufferedReader, BufferedWriter, InputStreamReader, OutputStreamWriter, BufferedInputStream, BufferedOutputStream, File => JFile } +import java.nio.channels.FileChannel import collection.Traversable object File @@ -77,6 +78,7 @@ extends Path(jfile) /** Obtains a OutputStream. */ def outputStream(append: Boolean = false) = new FileOutputStream(jfile, append) def bufferedOutput(append: Boolean = false) = new BufferedOutputStream(outputStream(append)) + // def channel(append: Boolean = false) = outputStream(append).getChannel() /** Obtains an InputStreamReader wrapped around a FileInputStream. */ diff --git a/src/library/scala/xml/dtd/ContentModel.scala b/src/library/scala/xml/dtd/ContentModel.scala index 4972ee6eaf..34517843f0 100644 --- a/src/library/scala/xml/dtd/ContentModel.scala +++ b/src/library/scala/xml/dtd/ContentModel.scala @@ -27,24 +27,22 @@ object ContentModel extends WordExp { } case class ElemName(name: String) extends Label { - override def toString() = "ElemName(\""+name+"\")" + override def toString() = """ElemName("%s")""" format name } def isMixed(cm: ContentModel) = cond(cm) { case _: MIXED => true } def containsText(cm: ContentModel) = (cm == PCDATA) || isMixed(cm) def parse(s: String): ContentModel = ContentModelParser.parse(s) - def getLabels(r: RegExp): scala.collection.Set[String] = { - val s = new HashSet[String]() - - def traverse(r: RegExp): Unit = r match { // !!! check for match translation problem - case Letter(ElemName(name)) => s += name + def getLabels(r: RegExp): Set[String] = { + def traverse(r: RegExp): Set[String] = r match { // !!! check for match translation problem + case Letter(ElemName(name)) => Set(name) case Star( x @ _ ) => traverse( x ) // bug if x@_* - case Sequ( xs @ _* ) => xs foreach traverse - case Alt( xs @ _* ) => xs foreach traverse + case Sequ( xs @ _* ) => Set(xs map traverse flatten: _*) + case Alt( xs @ _* ) => Set(xs map traverse flatten: _*) } + traverse(r) - s } def buildString(r: RegExp): String = sbToString(buildString(r, _)) @@ -68,18 +66,19 @@ object ContentModel extends WordExp { case ELEMENTS(_) | MIXED(_) => c buildString sb } - def buildString(r: RegExp, sb:StringBuilder): StringBuilder = r match { // !!! check for match translation problem - case Eps => - sb - case Sequ(rs @ _*) => - sb.append( '(' ); buildString(rs, sb, ','); sb.append( ')' ) - case Alt(rs @ _*) => - sb.append( '(' ); buildString(rs, sb, '|'); sb.append( ')' ) - case Star(r: RegExp) => - sb.append( '(' ); buildString(r, sb); sb.append( ")*" ) - case Letter(ElemName(name)) => - sb.append(name) - } + def buildString(r: RegExp, sb: StringBuilder): StringBuilder = + r match { // !!! check for match translation problem + case Eps => + sb + case Sequ(rs @ _*) => + sb.append( '(' ); buildString(rs, sb, ','); sb.append( ')' ) + case Alt(rs @ _*) => + sb.append( '(' ); buildString(rs, sb, '|'); sb.append( ')' ) + case Star(r: RegExp) => + sb.append( '(' ); buildString(r, sb); sb.append( ")*" ) + case Letter(ElemName(name)) => + sb.append(name) + } } @@ -99,67 +98,28 @@ case object ANY extends ContentModel { override def buildString(sb: StringBuilder): StringBuilder = sb.append("ANY") } sealed abstract class DFAContentModel extends ContentModel { - import ContentModel.ElemName + import ContentModel.{ ElemName, Translator } def r: ContentModel.RegExp - private var _dfa: DetWordAutom[ContentModel.ElemName] = null - def dfa = { - if (null == _dfa) { - val nfa = ContentModel.Translator.automatonFrom(r, 1); - _dfa = new SubsetConstruction(nfa).determinize; - } - _dfa + lazy val dfa: DetWordAutom[ElemName] = { + val nfa = Translator.automatonFrom(r, 1) + new SubsetConstruction(nfa).determinize } } + case class MIXED(r: ContentModel.RegExp) extends DFAContentModel { - import ContentModel.{Alt, Eps, RegExp} - /* - def getIterator(ns:NodeSeq) = new Iterator[String] { - def cond(n:Node) = - !n.isInstanceOf[Text] && !n.isInstanceOf[SpecialNode]; -Console.println("ns = "+ns); - val jt = ns.iterator; - def hasNext = jt.hasNext; - def next = { - var r: Node = jt.next; - while(!cond(r) && jt.hasNext) { - Console.println("skipping "+r); - r = jt.next; - } - Console.println("MIXED, iterator.next, r = "+r); - if(Text("") == r) - null - else - r.label - } - } - */ - override def buildString(sb: StringBuilder): StringBuilder = { - sb.append("(#PCDATA|") - ContentModel.buildString(Alt(r.asInstanceOf[Alt].rs.toList.drop(1):_*):RegExp, sb); - sb.append(")*"); + import ContentModel.{ Alt, RegExp } + + override def buildString(sb: StringBuilder): StringBuilder = { + val newAlt = r match { case Alt(rs @ _*) => Alt(rs drop 1: _*) } + + sb append "(#PCDATA|" + ContentModel.buildString(newAlt: RegExp, sb) + sb append ")*" } } -case class ELEMENTS(r:ContentModel.RegExp) extends DFAContentModel { - /* - def getIterator(ns:NodeSeq) = new Iterator[String] { - val jt = ns.iterator.buffered; - def hasNext = jt.hasNext; - def next = { - var r: Node = jt.next; - while(r.isInstanceOf[SpecialNode] && jt.hasNext) { - r = jt.head; - jt.next; - } - Console.println("MIXED, iterator.next, r = "+r); - if(r.isInstanceOf[Text]) - throw ValidationException("Text not allowed here!") - else - r.label - } - } - */ +case class ELEMENTS(r: ContentModel.RegExp) extends DFAContentModel { override def buildString(sb: StringBuilder): StringBuilder = ContentModel.buildString(r, sb) } diff --git a/src/library/scala/xml/dtd/DTD.scala b/src/library/scala/xml/dtd/DTD.scala index d5654d4ee6..4c1b03bb93 100644 --- a/src/library/scala/xml/dtd/DTD.scala +++ b/src/library/scala/xml/dtd/DTD.scala @@ -34,13 +34,9 @@ abstract class DTD { var decls: List[Decl] = Nil - override def toString() = { - val sb = new StringBuilder("DTD [\n") - if (null != externalID) - sb.append(externalID.toString()).append('\n') - for (d <- decls) - sb.append(d.toString()).append('\n') - sb.append("]").toString() - } - + override def toString() = + "DTD [\n%s%s]".format( + Option(externalID) getOrElse "", + decls.mkString("", "\n", "\n") + ) } diff --git a/src/library/scala/xml/dtd/Decl.scala b/src/library/scala/xml/dtd/Decl.scala index 9f987b4175..fc605f848f 100644 --- a/src/library/scala/xml/dtd/Decl.scala +++ b/src/library/scala/xml/dtd/Decl.scala @@ -23,7 +23,7 @@ abstract class MarkupDecl extends Decl { /** an element declaration */ case class ElemDecl(name: String, contentModel: ContentModel) -extends MarkupDecl with DtdTypeSymbol +extends MarkupDecl { override def buildString(sb: StringBuilder): StringBuilder = { sb @@ -37,7 +37,7 @@ extends MarkupDecl with DtdTypeSymbol } case class AttListDecl(name: String, attrs:List[AttrDecl]) -extends MarkupDecl with DtdTypeSymbol { +extends MarkupDecl { override def buildString(sb: StringBuilder): StringBuilder = { sb .append(" 1) sb.append('s'); - val it = allKeys.iterator - while (it.hasNext) { - sb.append('\'').append(it.next).append('\'') - } + allKeys foreach (k => sb append "'%s'".format(k)) new ValidationException(sb.toString()) } def fromMissingAttribute(key: String, tpe: String) = - new ValidationException("missing value for REQUIRED attribute "+key+" of type "+tpe) - + new ValidationException("missing value for REQUIRED attribute %s of type %s".format(key, tpe)) } diff --git a/src/library/scala/xml/path/Expression.scala b/src/library/scala/xml/path/Expression.scala index 30de790a3c..dce0cd94c2 100644 --- a/src/library/scala/xml/path/Expression.scala +++ b/src/library/scala/xml/path/Expression.scala @@ -14,36 +14,22 @@ package path object Expression { - final def testFromString(x: String): Test = { - x.charAt(0) match { - case '*' if( x.length() == 1 ) => WildcardTest; - case _ => NameTest(x); - } - } + final def testFromString(x: String): Test = if (x == "*") WildcardTest else NameTest(x) + private def emptyNodeSeq = new NodeSeq { val theSeq = Nil } case class FExp(e:Expr, c:Cond) { - def eval(n: Node): NodeSeq = new NodeSeq { val theSeq=Nil}; // @todo + def eval(n: Node): NodeSeq = emptyNodeSeq // @todo } - abstract class GenExp ; - case class Attrib(test: NameTest, e: Expr) extends GenExp; + abstract class GenExp + case class Attrib(test: NameTest, e: Expr) extends GenExp abstract class Expr extends GenExp { - def \ (x: String) = - if( x=="*") - Child(WildcardTest, this) - else - Child(NameTest(x), this); - - def \\ (x: String) = - if( x=="*") - DescOrSelf(WildcardTest, this) - else - DescOrSelf(NameTest(x), this); - - def apply(c: Cond) = FExp(this, c); + def \ (x: String) = Child(testFromString(x), this) + def \\ (x: String) = DescOrSelf(testFromString(x), this) - def eval(n: Node): NodeSeq = new NodeSeq { val theSeq=Nil}; // @todo + def apply(c: Cond) = FExp(this, c) + def eval(n: Node): NodeSeq = emptyNodeSeq // @todo } case object Root extends Expr; @@ -51,16 +37,13 @@ object Expression case class Child(test: Test, e: Expr) extends Expr; case class DescOrSelf(test: Test, e: Expr) extends Expr; - abstract class Test; case object WildcardTest extends Test; // "x \ * " case class NameTest(label: String) extends Test; // "x \ bar" - abstract class Cond; case class Exists(p: GenExp) extends Cond ; // "p [ p ]" case class Equals(p: Expr, c:String) extends Cond ; // "p [ @p == bla ]" - } diff --git a/src/library/scala/xml/persistent/CachedFileStorage.scala b/src/library/scala/xml/persistent/CachedFileStorage.scala index 923e8c2557..17194b4421 100644 --- a/src/library/scala/xml/persistent/CachedFileStorage.scala +++ b/src/library/scala/xml/persistent/CachedFileStorage.scala @@ -11,7 +11,8 @@ package scala.xml package persistent -import java.io.{File, FileOutputStream} +import scala.io.File +import java.io.{ File => JFile, FileOutputStream } import java.nio.ByteBuffer import java.nio.channels.Channels @@ -26,9 +27,9 @@ import java.nio.channels.Channels * @author Burak Emir */ abstract class CachedFileStorage(private val file1: File) -extends java.lang.Thread with scala.util.logging.Logged { - - private val file2 = new File(file1.getParent, file1.getName+"$") +extends java.lang.Thread with scala.util.logging.Logged +{ + private val file2 = (file1.parent.get / (file1.name + "$")).toFile /** either equals file1 or file2, references the next file in which updates will be stored */ @@ -45,19 +46,11 @@ extends java.lang.Thread with scala.util.logging.Logged { /** finds and loads the storage file. subclasses should call this method * prior to any other, but only once, to obtain the initial sequence of nodes. */ - protected def initialNodes: Iterator[Node] = (file1.exists, file2.exists) match { - case (false,false) => - theFile = file1 - Iterator.empty - case (true, true ) if (file1.lastModified < file2.lastModified) => - theFile = file2 - load - case (true, _ ) => - theFile = file1 - load - case _ => - theFile = file2 - load + protected lazy val initialNodes: Iterator[Node] = { + val (e1, e2) = (file1.exists, file2.exists) + + theFile = if (e2 && (file2 isFresher file1)) file2 else file1 + if (!e1 && !e2) Iterator.empty else load } /** returns an iterator over the nodes in this storage */ @@ -73,8 +66,9 @@ extends java.lang.Thread with scala.util.logging.Logged { private def load: Iterator[Node] = { import scala.io.Source import scala.xml.parsing.ConstructingParser + log("[load]\nloading "+theFile) - val src = Source.fromFile(theFile)() + val src = theFile.chars() log("parsing "+theFile) val res = ConstructingParser.fromSource(src,false).document.docElem(0) switch @@ -87,16 +81,16 @@ extends java.lang.Thread with scala.util.logging.Logged { log("[save]\ndeleting "+theFile); theFile.delete(); log("creating new "+theFile); - theFile.createNewFile(); - val fos = new FileOutputStream(theFile) + theFile.createFile(); + val fos = theFile.outputStream() val c = fos.getChannel() // @todo: optimize val storageNode = { nodes.toList } - val w = Channels.newWriter(c, "utf-8") - XML.write(w, storageNode, "utf-8", true, null) + val w = Channels.newWriter(c, "UTF-8") + XML.write(w, storageNode, "UTF-8", true, null) - log("writing to "+theFile); + log("writing to "+theFile) w.close c.close @@ -108,16 +102,17 @@ extends java.lang.Thread with scala.util.logging.Logged { /** run method of the thread. remember to use start() to start a thread, not run. */ override def run = { - log("[run]\nstarting storage thread, checking every "+interval+" ms"); - while(true) { - Thread.sleep( this.interval ); + log("[run]\nstarting storage thread, checking every %d ms" format interval) + + while (true) { + Thread sleep interval save } } /** forces writing of contents to the file, even if there has not been any update. */ def flush = { - this.dirty = true; + this.dirty = true save } } diff --git a/src/library/scala/xml/persistent/IndexedStorage.scala b/src/library/scala/xml/persistent/IndexedStorage.scala deleted file mode 100644 index 0f1200b76c..0000000000 --- a/src/library/scala/xml/persistent/IndexedStorage.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml -package persistent - -import scala.collection.mutable -import java.io.File - -/** indexed multiset of xml trees. The index may be an arbitrary totally - * type, especially one can construct indices by selecting parts of - * xml nodes. - */ -class IndexedStorage[A](file: File, index: Index[A]) //@todo -extends CachedFileStorage(file) { - - private var theMap: mutable.Map[A,Node] = new mutable.HashMap[A,Node]() - - super.initialNodes.foreach { x:Node => this += x } - - this.dirty = false - - def += (e: Node): Unit = synchronized { - log("added element at index '"+index(e)+"'") - dirty = true - theMap(index(e)) = e - } - - def -= (e: Node): Unit = synchronized { - log("removed element at index '"+index(e)+"'") - dirty = true - theMap -= index( e ) - } - - def nodes: Iterator[Node] = synchronized { - theMap.valuesIterator - } - - def lookup(n: A): Option[Node] = theMap.get(n) - -} diff --git a/src/library/scala/xml/persistent/SetStorage.scala b/src/library/scala/xml/persistent/SetStorage.scala index b30e0ee080..ec8bee8f85 100644 --- a/src/library/scala/xml/persistent/SetStorage.scala +++ b/src/library/scala/xml/persistent/SetStorage.scala @@ -12,33 +12,22 @@ package scala.xml package persistent import scala.collection.mutable -import java.io.File +import mutable.HashSet +import scala.io.File /** A persistent store with set semantics. This class allows to add and remove * trees, but never contains two structurally equal trees. * * @author Burak Emir */ -class SetStorage(file: File) extends CachedFileStorage(file) { +class SetStorage(file: File) extends CachedFileStorage(file) +{ + private var theSet: HashSet[Node] = HashSet() ++ initialNodes + dirty = theSet.nonEmpty - private var theSet: mutable.HashSet[Node] = new mutable.HashSet[Node] - - // initialize - - { - val it = super.initialNodes - dirty = it.hasNext - for(x <- it) { - theSet += x; - } - } - - /* forwarding methods to hashset*/ + /* forwarding methods to hashset */ def += (e: Node): Unit = synchronized { this.dirty = true; theSet += e } - def -= (e: Node): Unit = synchronized { this.dirty = true; theSet -= e } - def nodes = synchronized { theSet.iterator } - } -- cgit v1.2.3