summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-02-26 22:24:46 +0000
committerPaul Phillips <paulp@improving.org>2010-02-26 22:24:46 +0000
commit64fd0c1346dcd43cb814e4f99638321c159108fd (patch)
treea9cc92f5756442698813bc4d97bdf191b85b0680 /src
parent462e27a358fc466d51aaeec28c994c6667d320eb (diff)
downloadscala-64fd0c1346dcd43cb814e4f99638321c159108fd.tar.gz
scala-64fd0c1346dcd43cb814e4f99638321c159108fd.tar.bz2
scala-64fd0c1346dcd43cb814e4f99638321c159108fd.zip
Quite a lot more work on XML equality than I ca...
Quite a lot more work on XML equality than I can properly justify spending time on, but you know how it is once you get started on something. This commit will likely break some code out there in the world but this is impossible to avoid if we are to achieve sane equality in trunk. For anyone who was relying upon the 2.7 equality behavior for scala.xml.* classes, using "xml_==" instead of "==" for comparisons will restore the old behavior. The standard == on xml elements now attempts to behave in such a way that symmetry and hashCode contracts will be preserved. It's probably not 100% there yet, but I can tell you this: it is closer today than it was yesterday. Review by community.
Diffstat (limited to 'src')
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala6
-rw-r--r--src/library/scala/testing/SUnit.scala20
-rw-r--r--src/library/scala/xml/Atom.scala18
-rw-r--r--src/library/scala/xml/Attribute.scala46
-rw-r--r--src/library/scala/xml/Comment.scala2
-rw-r--r--src/library/scala/xml/Document.scala4
-rw-r--r--src/library/scala/xml/Elem.scala18
-rw-r--r--src/library/scala/xml/EntityRef.scala2
-rw-r--r--src/library/scala/xml/Equality.scala115
-rw-r--r--src/library/scala/xml/Group.scala58
-rw-r--r--src/library/scala/xml/MetaData.scala47
-rw-r--r--src/library/scala/xml/NamespaceBinding.scala13
-rw-r--r--src/library/scala/xml/Node.scala56
-rw-r--r--src/library/scala/xml/NodeBuffer.scala3
-rw-r--r--src/library/scala/xml/NodeSeq.scala35
-rw-r--r--src/library/scala/xml/Null.scala57
-rw-r--r--src/library/scala/xml/PCData.scala7
-rw-r--r--src/library/scala/xml/PrefixedAttribute.scala52
-rw-r--r--src/library/scala/xml/PrettyPrinter.scala3
-rw-r--r--src/library/scala/xml/ProcInstr.scala1
-rw-r--r--src/library/scala/xml/SpecialNode.scala4
-rw-r--r--src/library/scala/xml/Text.scala10
-rw-r--r--src/library/scala/xml/TextBuffer.scala4
-rw-r--r--src/library/scala/xml/TopScope.scala2
-rw-r--r--src/library/scala/xml/Unparsed.scala7
-rw-r--r--src/library/scala/xml/UnprefixedAttribute.scala36
-rw-r--r--src/library/scala/xml/Utility.scala8
-rw-r--r--src/library/scala/xml/XML.scala10
-rw-r--r--src/library/scala/xml/dtd/ContentModel.scala5
-rw-r--r--src/library/scala/xml/dtd/ContentModelParser.scala3
-rw-r--r--src/library/scala/xml/dtd/DTD.scala22
-rw-r--r--src/library/scala/xml/dtd/Decl.scala4
-rw-r--r--src/library/scala/xml/dtd/DocType.scala3
-rw-r--r--src/library/scala/xml/dtd/ExternalID.scala5
-rw-r--r--src/library/scala/xml/dtd/Scanner.scala4
-rw-r--r--src/library/scala/xml/factory/Binder.scala2
-rw-r--r--src/library/scala/xml/factory/NodeFactory.scala4
-rw-r--r--src/library/scala/xml/factory/XMLLoader.scala4
-rw-r--r--src/library/scala/xml/include/sax/Main.scala5
-rw-r--r--src/library/scala/xml/include/sax/XIncludeFilter.scala93
-rw-r--r--src/library/scala/xml/include/sax/XIncluder.scala24
-rw-r--r--src/library/scala/xml/package.scala18
-rw-r--r--src/library/scala/xml/parsing/FactoryAdapter.scala11
-rw-r--r--src/library/scala/xml/parsing/MarkupHandler.scala5
-rw-r--r--src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala4
-rw-r--r--src/library/scala/xml/parsing/TokenTests.scala2
-rw-r--r--src/library/scala/xml/parsing/XhtmlEntities.scala3
47 files changed, 402 insertions, 463 deletions
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 9a61f38be2..ca8549bffa 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -15,7 +15,7 @@ import scala.reflect.ClassManifest
import scala.collection.{ Seq, IndexedSeq }
import scala.collection.mutable.WrappedArray
import scala.collection.immutable.{ List, Stream, Nil, :: }
-import scala.xml.Node
+import scala.xml.{ Node, MetaData }
import scala.util.control.ControlException
/* The object <code>ScalaRunTime</code> provides ...
@@ -192,12 +192,14 @@ object ScalaRunTime {
case null => "null"
// Node extends NodeSeq extends Seq[Node] strikes again
case x: Node => x toString
+ // Not to mention MetaData extends Iterable[MetaData]
+ case x: MetaData => x toString
case x: AnyRef if isArray(x) => WrappedArray make x map inner mkString ("Array(", ", ", ")")
case x: Traversable[_] if !x.hasDefiniteSize => x.toString
case x: Traversable[_] =>
// Some subclasses of AbstractFile implement Iterable, then throw an
// exception if you call iterator. What a world.
- // And they can't be infinite either.
+ // And they can't be infinite either.
if (x.getClass.getName startsWith "scala.tools.nsc.io") x.toString
else (x map inner) mkString (x.stringPrefix + "(", ", ", ")")
case x => x toString
diff --git a/src/library/scala/testing/SUnit.scala b/src/library/scala/testing/SUnit.scala
index cf43bd1b06..d5d845cb98 100644
--- a/src/library/scala/testing/SUnit.scala
+++ b/src/library/scala/testing/SUnit.scala
@@ -12,6 +12,7 @@
package scala.testing
import scala.collection.mutable.ArrayBuffer
+import xml.{ Node, NodeSeq }
/**
* <p>
@@ -237,6 +238,25 @@ object SUnit {
assertTrue("(no message)", actual)
}
+ /** Temporary patchwork trying to nurse xml forward. */
+ def assertEqualsXML(msg: String, expected: NodeSeq, actual: NodeSeq) {
+ if (!expected.xml_==(actual))
+ fail(msg, expected, actual)
+ }
+ def assertEqualsXML(msg: String, expected: Seq[Node], actual: Seq[Node]) {
+ assertEqualsXML(msg, expected: NodeSeq, actual: NodeSeq)
+ }
+
+ def assertEqualsXML(expected: NodeSeq, actual: NodeSeq) {
+ assertEqualsXML("(no message)", expected, actual)
+ }
+
+ def assertSameElementsXML(actual: Seq[Node], expected: Seq[Node]) {
+ val res = (actual: NodeSeq) xml_sameElements expected
+
+ assert(res, "\nassertSameElementsXML:\n actual = %s\n expected = %s".format(actual, expected))
+ }
+
/** throws <code>AssertFailed</code> with given message <code>msg</code>.
*/
def fail(msg: String) {
diff --git a/src/library/scala/xml/Atom.scala b/src/library/scala/xml/Atom.scala
index 129a0803d2..7c66995573 100644
--- a/src/library/scala/xml/Atom.scala
+++ b/src/library/scala/xml/Atom.scala
@@ -8,9 +8,7 @@
// $Id$
-
package scala.xml
-import collection.mutable.StringBuilder
/** The class <code>Atom</code> provides an XML node for text (PCDATA).
* It is used in both non-bound and bound XML representations.
@@ -24,17 +22,21 @@ class Atom[+A](val data: A) extends SpecialNode
if (data == null)
throw new IllegalArgumentException("cannot construct Atom(null)")
+ override def basisForHashCode: Seq[Any] = Seq(data)
+ override def strict_==(other: Equality) = other match {
+ case x: Atom[_] => data == x.data
+ case _ => false
+ }
+ override def canEqual(other: Any) = other match {
+ case _: Atom[_] => true
+ case _ => false
+ }
+
final override def doCollectNamespaces = false
final override def doTransform = false
def label = "#PCDATA"
- override def equals(x: Any) = x match {
- case s:Atom[_] => data == s.data
- case _ => false
- }
- override def hashCode() = data.hashCode()
-
/** Returns text, with some characters escaped according to the XML
* specification.
*
diff --git a/src/library/scala/xml/Attribute.scala b/src/library/scala/xml/Attribute.scala
index 8ff9fb2ed7..3259526d98 100644
--- a/src/library/scala/xml/Attribute.scala
+++ b/src/library/scala/xml/Attribute.scala
@@ -10,9 +10,6 @@
package scala.xml
-import collection.Seq
-import collection.mutable.StringBuilder
-
/** Attribute defines the interface shared by both
* PrefixedAttribute and UnprefixedAttribute
*/
@@ -45,6 +42,7 @@ object Attribute {
abstract trait Attribute extends MetaData
{
+ def pre: String // will be null if unprefixed
val key: String
val value: Seq[Node]
val next: MetaData
@@ -52,13 +50,43 @@ abstract trait Attribute extends MetaData
def apply(key: String): Seq[Node]
def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node]
def copy(next: MetaData): Attribute
- def remove(key: String): MetaData
- def remove(namespace: String, scope: NamespaceBinding, key: String): MetaData
- def isPrefixed: Boolean
+ def remove(key: String) =
+ if (!isPrefixed && this.key == key) next
+ else copy(next remove key)
+
+ def remove(namespace: String, scope: NamespaceBinding, key: String) =
+ if (isPrefixed && this.key == key && (scope getURI pre) == namespace) next
+ else next.remove(namespace, scope, key)
+
+ def isPrefixed: Boolean = pre != null
def getNamespace(owner: Node): String
- def wellformed(scope: NamespaceBinding): Boolean
+ def wellformed(scope: NamespaceBinding): Boolean = {
+ val arg = if (isPrefixed) scope getURI pre else null
+ (next(arg, scope, key) == null) && (next wellformed scope)
+ }
- def equals1(m: MetaData): Boolean
- def toString1(sb: StringBuilder): Unit
+ override def canEqual(other: Any) = other match {
+ case _: Attribute => true
+ case _ => false
+ }
+ override def strict_==(other: Equality) = other match {
+ case x: Attribute => (pre == x.pre) && (key == x.key) && (value sameElements x.value)
+ case _ => false
+ }
+ override def basisForHashCode = List(pre, key, value)
+
+ /** Appends string representation of only this attribute to stringbuffer.
+ */
+ def toString1(sb: StringBuilder) {
+ if (value == null)
+ return
+ if (isPrefixed)
+ sb append pre append ':'
+
+ sb append key append '='
+ val sb2 = new StringBuilder()
+ Utility.sequenceToXML(value, TopScope, sb2, true)
+ Utility.appendQuoted(sb2.toString(), sb)
+ }
}
diff --git a/src/library/scala/xml/Comment.scala b/src/library/scala/xml/Comment.scala
index 4e8cff8d75..9608748601 100644
--- a/src/library/scala/xml/Comment.scala
+++ b/src/library/scala/xml/Comment.scala
@@ -10,7 +10,7 @@
package scala.xml
-import collection.mutable.StringBuilder
+
/** The class <code>Comment</code> implements an XML node for comments.
*
diff --git a/src/library/scala/xml/Document.scala b/src/library/scala/xml/Document.scala
index 3ac50b80b7..6c73252a37 100644
--- a/src/library/scala/xml/Document.scala
+++ b/src/library/scala/xml/Document.scala
@@ -87,4 +87,8 @@ class Document extends NodeSeq with pull.XMLEvent {
def theSeq: Seq[Node] = this.docElem
+ override def canEqual(other: Any) = other match {
+ case _: Document => true
+ case _ => false
+ }
}
diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala
index 18b513527c..9c58177417 100644
--- a/src/library/scala/xml/Elem.scala
+++ b/src/library/scala/xml/Elem.scala
@@ -8,11 +8,8 @@
// $Id$
-
package scala.xml
-import collection.Seq
-
/** This singleton object contains the apply and unapplySeq methods for convenient construction and
* deconstruction. It is possible to deconstruct any Node instance (that is not a SpecialNode or
* a Group) using the syntax
@@ -26,8 +23,10 @@ object Elem
def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) =
new Elem(prefix,label,attributes,scope,child:_*)
- def unapplySeq(n:Node) = if (n.isInstanceOf[SpecialNode] || n.isInstanceOf[Group]) None else
- Some((n.prefix, n.label, n.attributes, n.scope, n.child))
+ def unapplySeq(n: Node) = n match {
+ case _: SpecialNode | _: Group => None
+ case _ => Some((n.prefix, n.label, n.attributes, n.scope, n.child))
+ }
}
/** The case class <code>Elem</code> extends the <code>Node</code> class,
@@ -54,18 +53,17 @@ extends Node
final override def doCollectNamespaces = true
final override def doTransform = true
- if ((null != prefix) && 0 == prefix.length())
+ if (prefix == "")
throw new IllegalArgumentException("prefix of zero length, use null instead")
- if (null == scope)
- throw new IllegalArgumentException("scope is null, try xml.TopScope for empty scope")
+ if (scope == null)
+ throw new IllegalArgumentException("scope is null, use xml.TopScope for empty scope")
//@todo: copy the children,
// setting namespace scope if necessary
// cleaning adjacent text nodes if necessary
- override def hashCode(): Int =
- Utility.hashCode(prefix, label, attributes.hashCode(), scope.hashCode(), child)
+ override def basisForHashCode: Seq[Any] = prefix :: label :: attributes :: child.toList
/** Returns a new element with updated attributes, resolving namespace uris from this element's scope.
* See MetaData.update for details.
diff --git a/src/library/scala/xml/EntityRef.scala b/src/library/scala/xml/EntityRef.scala
index 0806b8fa68..fbc1f351cf 100644
--- a/src/library/scala/xml/EntityRef.scala
+++ b/src/library/scala/xml/EntityRef.scala
@@ -10,7 +10,7 @@
package scala.xml
-import collection.mutable.StringBuilder
+
/** The class <code>EntityRef</code> implements an XML node for entity
diff --git a/src/library/scala/xml/Equality.scala b/src/library/scala/xml/Equality.scala
new file mode 100644
index 0000000000..d09ae10b2d
--- /dev/null
+++ b/src/library/scala/xml/Equality.scala
@@ -0,0 +1,115 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.xml
+
+/** In an attempt to contain the damage being inflicted on
+ * consistency by the ad hoc equals methods spread around
+ * xml, the logic is centralized and all the xml classes
+ * go through the xml.Equality trait. There are two forms
+ * of xml comparison.
+ *
+ * 1) def strict_==(other: xml.Equality)
+ *
+ * This one tries to honor the little things like symmetry
+ * and hashCode contracts. The equals method routes all
+ * comparisons through this.
+ *
+ * 2) xml_==(other: Any)
+ *
+ * This one picks up where strict_== leaves off. It might
+ * declare any two things equal.
+ *
+ * As things stood, the logic not only made a mockery of
+ * the collections equals contract, but also laid waste to
+ * that of case classes.
+ *
+ * Among the obstacles to sanity are/were:
+ *
+ * Node extends NodeSeq extends Seq[Node]
+ * MetaData extends Iterable[MetaData]
+ * The hacky "Group" xml node which throws exceptions
+ * with wild abandon, so don't get too close
+ * Rampant asymmetry and impossible hashCodes
+ * Most classes claiming to be equal to "String" if
+ * some specific stringification of it was the same.
+ * String was never going to return the favor.
+ */
+
+object Equality {
+ def asRef(x: Any): AnyRef = x.asInstanceOf[AnyRef]
+
+ /** Note - these functions assume strict equality has already failed.
+ */
+ def compareBlithely(x1: AnyRef, x2: String): Boolean = x1 match {
+ case x: Atom[_] => x.data == x2
+ case x: NodeSeq => x.text == x2
+ case _ => false
+ }
+ def compareBlithely(x1: AnyRef, x2: Node): Boolean = x1 match {
+ case x: NodeSeq if x.length == 1 => x2 == x(0)
+ case _ => false
+ }
+ def compareBlithely(x1: AnyRef, x2: AnyRef): Boolean = {
+ if (x1 == null || x2 == null)
+ return (x1 eq x2)
+
+ x2 match {
+ case s: String => compareBlithely(x1, s)
+ case n: Node => compareBlithely(x1, n)
+ case _ => false
+ }
+ }
+}
+import Equality._
+
+private[xml]
+trait Equality extends scala.Equals {
+ def basisForHashCode: Seq[Any]
+ def strict_==(other: Equality): Boolean
+ def strict_!=(other: Equality) = !strict_==(other)
+
+ private def hashOf(x: Any) = if (x == null) 1 else x.hashCode()
+
+ /** We insist we're only equal to other xml.Equality implementors,
+ * which heads off a lot of inconsistency up front.
+ */
+ override def canEqual(other: Any): Boolean = other match {
+ case x: Equality => true
+ case _ => false
+ }
+
+ /** It's be nice to make these final, but there are probably
+ * people out there subclassing the XML types, especially when
+ * it comes to equals. However WE at least can pretend they
+ * are final since clearly individual classes cannot be trusted
+ * to maintain a semblance of order.
+ */
+ override def hashCode() = basisForHashCode match {
+ case Nil => 0
+ case x :: xs => hashOf(x) * 41 + (xs map hashOf).foldLeft(0)(_ * 7 + _)
+ }
+ override def equals(other: Any) = doComparison(other, false)
+ final def xml_==(other: Any) = doComparison(other, true)
+ final def xml_!=(other: Any) = !xml_==(other)
+
+ /** The "blithe" parameter expresses the caller's unconcerned attitude
+ * regarding the usual constraints on equals. The method is thereby
+ * given carte blanche to declare any two things equal.
+ */
+ private def doComparison(other: Any, blithe: Boolean) = {
+ val strictlyEqual = other match {
+ case x: AnyRef if this eq x => true
+ case x: Equality => (x canEqual this) && (this strict_== x)
+ case _ => false
+ }
+
+ strictlyEqual || (blithe && compareBlithely(this, asRef(other)))
+ }
+}
+
diff --git a/src/library/scala/xml/Group.scala b/src/library/scala/xml/Group.scala
index 91ddba6ce6..8b714d2813 100644
--- a/src/library/scala/xml/Group.scala
+++ b/src/library/scala/xml/Group.scala
@@ -8,9 +8,7 @@
// $Id$
-
package scala.xml
-import collection.Seq
/** A hack to group XML nodes in one node for output.
*
@@ -18,49 +16,27 @@ import collection.Seq
* @version 1.0
*/
@serializable
-case class Group(val nodes: Seq[Node]) extends Node {
- // final override def doTransform = false
+final case class Group(val nodes: Seq[Node]) extends Node {
override def theSeq = nodes
- /** XXX this is ridiculous, we can't do equality like this. */
- override def equals(x: Any) = x match {
- case z:Group => (length == z.length) && sameElements(z)
- case z:Node => (length == 1) && z == apply(0)
- case z:Seq[_] => sameElements(z)
- case z:String => text == z
- case _ => false
+ override def canEqual(other: Any) = other match {
+ case x: Group => true
+ case _ => false
}
- /* As if there were a hashCode which could back up the above implementation! */
- override def hashCode = nodes.hashCode
-
- /**
- * @throws Predef.UnsupportedOperationException (always)
- */
- final def label =
- throw new UnsupportedOperationException("class Group does not support method 'label'")
-
- /**
- * @throws Predef.UnsupportedOperationException (always)
- */
- final override def attributes =
- throw new UnsupportedOperationException("class Group does not support method 'attributes'")
-
- /**
- * @throws Predef.UnsupportedOperationException (always)
- */
- final override def namespace =
- throw new UnsupportedOperationException("class Group does not support method 'namespace'")
+ override def strict_==(other: Equality) = other match {
+ case Group(xs) => nodes sameElements xs
+ case _ => false
+ }
+ override def basisForHashCode = nodes
- /**
- * @throws Predef.UnsupportedOperationException (always)
+ /** Since Group is very much a hack it throws an exception if you
+ * try to do anything with it.
*/
- final override def child =
- throw new UnsupportedOperationException("class Group does not support method 'child'")
+ private def fail(msg: String) = throw new UnsupportedOperationException("class Group does not support method '%s'" format msg)
- /**
- * @throws Predef.UnsupportedOperationException (always)
- */
- def buildString(sb: StringBuilder) =
- throw new UnsupportedOperationException(
- "class Group does not support method toString(StringBuilder)")
+ def label = fail("label")
+ override def attributes = fail("attributes")
+ override def namespace = fail("namespace")
+ override def child = fail("child")
+ def buildString(sb: StringBuilder) = fail("toString(StringBuilder)")
}
diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala
index 01b1cbc1d9..744b662fb8 100644
--- a/src/library/scala/xml/MetaData.scala
+++ b/src/library/scala/xml/MetaData.scala
@@ -8,14 +8,10 @@
// $Id$
-
package scala.xml
import Utility.sbToString
import annotation.tailrec
-import collection.immutable.List
-import collection.{Seq, Iterator, Iterable}
-import collection.mutable.StringBuilder
/**
@@ -77,7 +73,7 @@ object MetaData {
* @author Burak Emir <bqe@google.com>
*/
@serializable
-abstract class MetaData extends Iterable[MetaData]
+abstract class MetaData extends Iterable[MetaData] with Equality
{
/** Updates this MetaData with the MetaData given as argument. All attributes that occur in updates
* are part of the resulting MetaData. If an attribute occurs in both this instance and
@@ -118,13 +114,6 @@ abstract class MetaData extends Iterable[MetaData]
*/
def apply(namespace_uri:String, scp:NamespaceBinding, k:String): Seq[Node]
- /**
- * @param m ...
- * @return <code>true</code> iff ...
- */
- def containedIn1(m: MetaData): Boolean =
- m != null && (m.equals1(this) || containedIn1(m.next))
-
/** returns a copy of this MetaData item with next field set to argument.
*
* @param next ...
@@ -143,22 +132,20 @@ abstract class MetaData extends Iterable[MetaData]
def isPrefixed: Boolean
- /** deep equals method - XXX */
- override def equals(that: Any) = that match {
- case m: MetaData =>
- (this.length == m.length) &&
- (this.hashCode == m.hashCode) &&
- (this forall (_ containedIn1 m))
+ override def canEqual(other: Any) = other match {
+ case _: MetaData => true
+ case _ => false
+ }
+ override def strict_==(other: Equality) = other match {
+ case m: MetaData => this.toSet == m.toSet
case _ => false
}
+ def basisForHashCode: Seq[Any] = List(this.toSet)
/** Returns an iterator on attributes */
- def iterator: Iterator[MetaData] = Iterator.iterate(this)(_.next) takeWhile (_ != Null)
+ def iterator: Iterator[MetaData] = Iterator.single(this) ++ next.iterator
override def size: Int = 1 + iterator.length
- /** shallow equals method */
- def equals1(that: MetaData): Boolean
-
/** filters this sequence of meta data */
override def filter(f: MetaData => Boolean): MetaData =
if (f(this)) copy(next filter f)
@@ -170,8 +157,18 @@ abstract class MetaData extends Iterable[MetaData]
/** returns value of this MetaData item */
def value: Seq[Node]
- /** maps this sequence of meta data */
- def map(f: MetaData => Text): List[Text] = (iterator map f).toList
+ /** Returns a String containing "prefix:key" if the first key is
+ * prefixed, and "key" otherwise.
+ */
+ def prefixedKey = this match {
+ case x: Attribute if x.isPrefixed => x.pre + ":" + key
+ case _ => key
+ }
+
+ /** Returns a Map containing the attributes stored as key/value pairs.
+ */
+ def asAttrMap: Map[String, String] =
+ iterator map (x => (x.prefixedKey, x.value.text)) toMap
/** returns Null or the next MetaData item */
def next: MetaData
@@ -198,8 +195,6 @@ abstract class MetaData extends Iterable[MetaData]
final def get(uri: String, scope: NamespaceBinding, key: String): Option[Seq[Node]] =
Option(apply(uri, scope, key))
- override def hashCode(): Int
-
def toString1(): String = sbToString(toString1)
// appends string representations of single attribute to StringBuilder
diff --git a/src/library/scala/xml/NamespaceBinding.scala b/src/library/scala/xml/NamespaceBinding.scala
index 7381f0129b..47ca8fed87 100644
--- a/src/library/scala/xml/NamespaceBinding.scala
+++ b/src/library/scala/xml/NamespaceBinding.scala
@@ -12,7 +12,7 @@
package scala.xml
import Utility.sbToString
-import collection.mutable.StringBuilder
+
/** The class <code>NamespaceBinding</code> represents namespace bindings
* and scopes. The binding for the default namespace is treated as a null
@@ -23,7 +23,7 @@ import collection.mutable.StringBuilder
* @version 1.0
*/
@SerialVersionUID(0 - 2518644165573446725L)
-case class NamespaceBinding(prefix: String, uri: String, parent: NamespaceBinding) extends AnyRef
+case class NamespaceBinding(prefix: String, uri: String, parent: NamespaceBinding) extends AnyRef with Equality
{
if (prefix == "")
throw new IllegalArgumentException("zero length prefix not allowed")
@@ -41,6 +41,15 @@ case class NamespaceBinding(prefix: String, uri: String, parent: NamespaceBindin
if (_uri == uri) prefix else parent getPrefix _uri
override def toString(): String = sbToString(buildString(_, TopScope))
+ override def canEqual(other: Any) = other match {
+ case _: NamespaceBinding => true
+ case _ => false
+ }
+ override def strict_==(other: Equality) = other match {
+ case x: NamespaceBinding => (prefix == x.prefix) && (uri == x.uri) && (parent == x.parent)
+ case _ => false
+ }
+ def basisForHashCode: Seq[Any] = List(prefix, uri, parent)
def buildString(stop: NamespaceBinding): String = sbToString(buildString(_, stop))
def buildString(sb: StringBuilder, stop: NamespaceBinding): Unit = {
diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala
index 500c11e41d..5117bb9282 100644
--- a/src/library/scala/xml/Node.scala
+++ b/src/library/scala/xml/Node.scala
@@ -8,13 +8,8 @@
// $Id$
-
package scala.xml
-import collection.Seq
-import collection.immutable.{List, Nil}
-import collection.mutable.StringBuilder
-
/**
* This object provides methods ...
*
@@ -22,7 +17,6 @@ import collection.mutable.StringBuilder
* @version 1.0
*/
object Node {
-
/** the constant empty attribute sequence */
final def NoAttributes: MetaData = Null
@@ -30,7 +24,6 @@ object Node {
val EmptyNamespace = ""
def unapplySeq(n: Node) = Some((n.label, n.attributes, n.child))
-
}
/**
@@ -116,6 +109,10 @@ abstract class Node extends NodeSeq {
*/
def child: Seq[Node]
+ /** Children which do not stringify to "" (needed for equality)
+ */
+ def nonEmptyChildren: Seq[Node] = child filterNot (_.toString == "")
+
/**
* Descendant axis (all descendants of this node, not including node itself)
* includes all text nodes, element nodes, comments and processing instructions.
@@ -129,41 +126,24 @@ abstract class Node extends NodeSeq {
*/
def descendant_or_self: List[Node] = this :: descendant
- /**
- * Returns true if x is structurally equal to this node. Compares prefix,
- * label, attributes and children.
- *
- * @param x ...
- * @return <code>true</code> if ..
- */
- override def equals(x: Any): Boolean = x match {
- case g: Group => false
- case that: Node =>
- this.prefix == that.prefix &&
- this.label == that.label &&
- this.attributes == that.attributes &&
- this.scope == that.scope &&
- equalChildren(that)
+ override def canEqual(other: Any) = other match {
+ case x: Group => false
+ case x: Node => true
case _ => false
}
-
- // children comparison has to be done carefully - see bug #1773.
- // It would conceivably be a better idea for a scala block which
- // generates the empty string not to generate a child rather than
- // our having to filter it later, but that approach would be more
- // delicate to implement.
- private def equalChildren(that: Node) = {
- def noEmpties(xs: Seq[Node]) = xs filter (_.toString() != "")
- noEmpties(this.child) sameElements noEmpties(that.child)
+ override def basisForHashCode: Seq[Any] = prefix :: label :: attributes :: nonEmptyChildren.toList
+ override def strict_==(other: Equality) = other match {
+ case _: Group => false
+ case x: Node =>
+ (prefix == x.prefix) &&
+ (label == x.label) &&
+ (attributes == x.attributes) &&
+ // (scope == x.scope) // note - original code didn't compare scopes so I left it as is.
+ (nonEmptyChildren sameElements x.nonEmptyChildren)
+ case _ =>
+ false
}
- /** <p>
- * Returns a hashcode.
- * </p>
- */
- override def hashCode(): Int =
- Utility.hashCode(prefix, label, attributes.hashCode(), scope.hashCode(), child)
-
// implementations of NodeSeq methods
/**
diff --git a/src/library/scala/xml/NodeBuffer.scala b/src/library/scala/xml/NodeBuffer.scala
index 49efe0a5ca..2cf999e8a4 100644
--- a/src/library/scala/xml/NodeBuffer.scala
+++ b/src/library/scala/xml/NodeBuffer.scala
@@ -8,11 +8,8 @@
// $Id$
-
package scala.xml
-import collection.{Iterator, Seq, Iterable}
-
/**
* <p>
* This class acts as a Buffer for nodes. If it is used as a sequence
diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala
index 02c1b6ece8..3b56ba25e4 100644
--- a/src/library/scala/xml/NodeSeq.scala
+++ b/src/library/scala/xml/NodeSeq.scala
@@ -11,11 +11,9 @@
package scala.xml
-import collection.immutable
-import collection.immutable.{List, Nil, ::}
-import collection.{Seq, SeqLike}
-import collection.mutable.{Builder, ListBuffer}
-import collection.generic.CanBuildFrom
+import collection.{ mutable, immutable, generic, SeqLike }
+import mutable.{ Builder, ListBuffer }
+import generic.{ CanBuildFrom }
/** This object ...
*
@@ -43,7 +41,7 @@ object NodeSeq {
* @author Burak Emir
* @version 1.0
*/
-abstract class NodeSeq extends immutable.Seq[Node] with SeqLike[Node, NodeSeq] {
+abstract class NodeSeq extends immutable.Seq[Node] with SeqLike[Node, NodeSeq] with Equality {
import NodeSeq.seqToNodeSeq // import view magic for NodeSeq wrappers
/** Creates a list buffer as builder for this class */
@@ -56,12 +54,23 @@ abstract class NodeSeq extends immutable.Seq[Node] with SeqLike[Node, NodeSeq] {
def apply(i: Int): Node = theSeq(i)
def apply(f: Node => Boolean): NodeSeq = filter(f)
- /** structural equality (XXX - this shatters any hope of hashCode equality) */
- override def equals(x: Any): Boolean = x match {
- case z:Node => (length == 1) && z == apply(0)
- case z:Seq[_] => sameElements(z)
- case z:String => text == z
- case _ => false
+ def xml_sameElements[A](that: Iterable[A]): Boolean = {
+ val these = this.iterator
+ val those = that.iterator
+ while (these.hasNext && those.hasNext)
+ if (these.next xml_!= those.next)
+ return false
+
+ !these.hasNext && !those.hasNext
+ }
+ def basisForHashCode: Seq[Any] = theSeq
+ override def canEqual(other: Any) = other match {
+ case _: NodeSeq => true
+ case _ => false
+ }
+ override def strict_==(other: Equality) = other match {
+ case x: NodeSeq => (length == x.length) && (theSeq sameElements x.theSeq)
+ case _ => false
}
/** Projection function. Similar to XPath, use <code>this \ "foo"</code>
@@ -92,7 +101,7 @@ abstract class NodeSeq extends immutable.Seq[Node] with SeqLike[Node, NodeSeq] {
if (uri == "" || key == "") fail
else y.attribute(uri, key)
}
- else y.attribute(that.substring(1))
+ else y.attribute(that drop 1)
attr match {
case Some(x) => Group(x)
diff --git a/src/library/scala/xml/Null.scala b/src/library/scala/xml/Null.scala
index a3246d4b57..d6f06fc3cd 100644
--- a/src/library/scala/xml/Null.scala
+++ b/src/library/scala/xml/Null.scala
@@ -12,70 +12,49 @@
package scala.xml
import Utility.{ isNameStart }
-import collection.Iterator
-import collection.immutable.{Nil, List}
-import collection.mutable.StringBuilder
+/** Essentially, every method in here is a dummy, returning Zero[T].
+ * It provides a backstop for the unusual collection defined by MetaData,
+ * sort of a linked list of tails.
+ */
case object Null extends MetaData {
-
- /** appends given MetaData items to this MetaData list */
- override def append(m: MetaData, scope: NamespaceBinding = TopScope): MetaData = m
-
- override def containedIn1(m: MetaData): Boolean = false
-
- /** returns its argument */
- def copy(next: MetaData) = next
-
override def iterator = Iterator.empty
-
+ override def append(m: MetaData, scope: NamespaceBinding = TopScope): MetaData = m
override def filter(f: MetaData => Boolean): MetaData = this
+ def copy(next: MetaData) = next
def getNamespace(owner: Node) = null
- final override def hasNext = false
+ override def hasNext = false
def next = null
def key = null
def value = null
-
- final override def length = 0
- final override def length(i: Int) = i
-
def isPrefixed = false
- /** deep equals method - XXX */
- override def equals(that: Any) = that match {
- case m: MetaData => m.length == 0
- case _ => false
- }
+ override def length = 0
+ override def length(i: Int) = i
- def equals1(that:MetaData) = that.length == 0
-
- override def map(f: MetaData => Text): List[Text] = Nil
+ override def strict_==(other: Equality) = other match {
+ case x: MetaData => x.length == 0
+ case _ => false
+ }
+ override def basisForHashCode: Seq[Any] = Nil
- /** null */
+ def apply(namespace: String, scope: NamespaceBinding, key: String) = null
def apply(key: String) = {
- if(!isNameStart(key charAt 0))
+ if (!isNameStart(key.head))
throw new IllegalArgumentException("not a valid attribute name '"+key+"', so can never match !")
+
null
}
- /** gets value of qualified (prefixed) attribute with given key */
- def apply(namespace: String, scope: NamespaceBinding, key: String) = null
-
- override def hashCode(): Int = 0
-
+ def toString1(sb: StringBuilder) = ()
override def toString1(): String = ""
-
- //appends string representations of single attribute to StringBuilder
- def toString1(sb:StringBuilder) = {}
-
override def toString(): String = ""
override def buildString(sb: StringBuilder): StringBuilder = sb
-
override def wellformed(scope: NamespaceBinding) = true
def remove(key: String) = this
-
def remove(namespace: String, scope: NamespaceBinding, key: String) = this
}
diff --git a/src/library/scala/xml/PCData.scala b/src/library/scala/xml/PCData.scala
index 5cf4bda070..fa44591496 100644
--- a/src/library/scala/xml/PCData.scala
+++ b/src/library/scala/xml/PCData.scala
@@ -7,16 +7,9 @@ package scala.xml
* and is to be preserved as CDATA section in the output.
*/
case class PCData(_data: String) extends Atom[String](_data) {
- /* The following code is a derivative work of scala.xml.Text */
if (null == data)
throw new IllegalArgumentException("tried to construct PCData with null")
- final override def equals(x: Any) = x match {
- case s: String => s.equals(data)
- case s: Atom[_] => data == s.data
- case _ => false
- }
-
/** Returns text, with some characters escaped according to the XML
* specification.
*
diff --git a/src/library/scala/xml/PrefixedAttribute.scala b/src/library/scala/xml/PrefixedAttribute.scala
index a465e61ba3..d7c04ab6ad 100644
--- a/src/library/scala/xml/PrefixedAttribute.scala
+++ b/src/library/scala/xml/PrefixedAttribute.scala
@@ -8,13 +8,8 @@
// $Id$
-
package scala.xml
-import collection.Seq
-import collection.mutable.StringBuilder
-
-
/** prefixed attributes always have a non-null namespace.
*
* @param pre ...
@@ -36,24 +31,12 @@ extends Attribute
def this(pre: String, key: String, value: String, next: MetaData) =
this(pre, key, Text(value), next)
- /*
- // the problem here is the fact that we cannot remove the proper attribute from
- // next, and thus cannot guarantee that hashcodes are computed properly
- def this(pre: String, key: String, value: scala.AllRef, next: MetaData) =
- throw new UnsupportedOperationException("can't construct prefixed nil attributes")
- */
-
/** Returns a copy of this unprefixed attribute with the given
* next field.
*/
def copy(next: MetaData) =
new PrefixedAttribute(pre, key, value, next)
- def equals1(m: MetaData) =
- (m.isPrefixed &&
- (m.asInstanceOf[PrefixedAttribute].pre == pre) &&
- (m.key == key) && (m.value sameElements value))
-
def getNamespace(owner: Node) =
owner.getNamespace(pre)
@@ -68,41 +51,8 @@ extends Attribute
else
next(namespace, scope, key)
}
-
- /** returns true */
- final def isPrefixed = true
-
- /** returns the hashcode.
- */
- override def hashCode() =
- pre.hashCode() * 41 + key.hashCode() * 7 + next.hashCode()
-
-
- /** appends string representation of only this attribute to stringbuffer */
- def toString1(sb:StringBuilder): Unit = if(value ne null) {
- sb.append(pre)
- sb.append(':')
- sb.append(key)
- sb.append('=')
- val sb2 = new StringBuilder()
- Utility.sequenceToXML(value, TopScope, sb2, true)
- Utility.appendQuoted(sb2.toString(), sb)
- }
-
- def wellformed(scope: NamespaceBinding): Boolean =
- (null == next(scope.getURI(pre), scope, key) &&
- next.wellformed(scope))
-
- def remove(key: String) =
- copy(next.remove(key))
-
- def remove(namespace: String, scope: NamespaceBinding, key: String): MetaData =
- if (key == this.key && scope.getURI(pre) == namespace)
- next
- else
- next.remove(namespace, scope, key)
-
}
+
object PrefixedAttribute {
def unapply(x: PrefixedAttribute) = Some(x.pre, x.key, x.value, x.next)
}
diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala
index 17e7db679a..77199ca367 100644
--- a/src/library/scala/xml/PrettyPrinter.scala
+++ b/src/library/scala/xml/PrettyPrinter.scala
@@ -8,10 +8,8 @@
// $Id$
-
package scala.xml
-import scala.collection.Map
import Utility.sbToString
/** Class for pretty printing. After instantiating, you can use the
@@ -39,7 +37,6 @@ class PrettyPrinter(width: Int, step: Int) {
protected var items: List[Item] = Nil
protected var cur = 0
- //protected var pmap:Map[String,String] = _
protected def reset() = {
cur = 0
diff --git a/src/library/scala/xml/ProcInstr.scala b/src/library/scala/xml/ProcInstr.scala
index 5a4e67e647..051fd499f4 100644
--- a/src/library/scala/xml/ProcInstr.scala
+++ b/src/library/scala/xml/ProcInstr.scala
@@ -9,7 +9,6 @@
// $Id$
package scala.xml
-import collection.mutable.StringBuilder
/** an XML node for processing instructions (PI)
*
diff --git a/src/library/scala/xml/SpecialNode.scala b/src/library/scala/xml/SpecialNode.scala
index d40d829c4b..1688cd1e15 100644
--- a/src/library/scala/xml/SpecialNode.scala
+++ b/src/library/scala/xml/SpecialNode.scala
@@ -8,12 +8,8 @@
// $Id$
-
package scala.xml
-import collection.immutable.{List, Nil, ::}
-import collection.mutable.StringBuilder
-
/** <p>
* <code>SpecialNode</code> is a special XML node which
* represents either text (PCDATA), a comment, a PI, or an entity ref.
diff --git a/src/library/scala/xml/Text.scala b/src/library/scala/xml/Text.scala
index 3090883bb8..5f0b010c9f 100644
--- a/src/library/scala/xml/Text.scala
+++ b/src/library/scala/xml/Text.scala
@@ -8,11 +8,8 @@
// $Id$
-
package scala.xml
-import collection.mutable.StringBuilder
-
// XXX This attempt to make Text not a case class revealed a bug in the pattern
// matcher (see ticket #2883) so I've put the case back. (It was/is desirable that
// it not be a case class because it is using the antipattern of passing constructor
@@ -42,13 +39,6 @@ case class Text(_data: String) extends Atom[String](_data)
if (_data == null)
throw new IllegalArgumentException("tried to construct Text with null")
- /** XXX More hashCode flailing. */
- final override def equals(x: Any) = x match {
- case s:String => s == data
- case s:Atom[_] => data == s.data
- case _ => false
- }
-
/** Returns text, with some characters escaped according to the XML
* specification.
*
diff --git a/src/library/scala/xml/TextBuffer.scala b/src/library/scala/xml/TextBuffer.scala
index 17c40aad2f..84c6c24146 100644
--- a/src/library/scala/xml/TextBuffer.scala
+++ b/src/library/scala/xml/TextBuffer.scala
@@ -8,12 +8,8 @@
// $Id$
-
package scala.xml
-import collection.Seq
-import collection.mutable.StringBuilder
-import collection.immutable.{List, Nil, ::}
import Utility.isSpace
object TextBuffer {
diff --git a/src/library/scala/xml/TopScope.scala b/src/library/scala/xml/TopScope.scala
index c638b80b2d..8b3c1383c9 100644
--- a/src/library/scala/xml/TopScope.scala
+++ b/src/library/scala/xml/TopScope.scala
@@ -10,8 +10,6 @@
package scala.xml
-import collection.mutable.StringBuilder
-
/** top level namespace scope. only contains the predefined binding
* for the &quot;xml&quot; prefix which is bound to
* &quot;http://www.w3.org/XML/1998/namespace&quot;
diff --git a/src/library/scala/xml/Unparsed.scala b/src/library/scala/xml/Unparsed.scala
index a570b83fb5..d3c63172e8 100644
--- a/src/library/scala/xml/Unparsed.scala
+++ b/src/library/scala/xml/Unparsed.scala
@@ -22,13 +22,6 @@ class Unparsed(data: String) extends Atom[String](data)
if (null == data)
throw new IllegalArgumentException("tried to construct Unparsed with null")
- /** XXX another hashCode fail */
- final override def equals(x: Any) = x match {
- case s:String => s == data
- case s:Atom[_] => data == s.data
- case _ => false
- }
-
/** returns text, with some characters escaped according to XML spec */
override def buildString(sb: StringBuilder) = sb append data
}
diff --git a/src/library/scala/xml/UnprefixedAttribute.scala b/src/library/scala/xml/UnprefixedAttribute.scala
index 283cc3a1d0..a8720f13e1 100644
--- a/src/library/scala/xml/UnprefixedAttribute.scala
+++ b/src/library/scala/xml/UnprefixedAttribute.scala
@@ -8,13 +8,8 @@
// $Id$
-
package scala.xml
-import collection.Seq
-import collection.mutable.StringBuilder
-
-
/** Unprefixed attributes have the null namespace, and no prefix field
*
* @author Burak Emir
@@ -25,6 +20,7 @@ class UnprefixedAttribute(
next1: MetaData)
extends Attribute
{
+ final val pre = null
val next = if (value ne null) next1 else next1.remove(key)
/** same as this(key, Text(value), next) */
@@ -38,9 +34,6 @@ extends Attribute
/** returns a copy of this unprefixed attribute with the given next field*/
def copy(next: MetaData) = new UnprefixedAttribute(key, value, next)
- def equals1(m: MetaData) =
- !m.isPrefixed && (m.key == key) && (m.value sameElements value)
-
final def getNamespace(owner: Node): String = null
/**
@@ -62,33 +55,6 @@ extends Attribute
*/
def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] =
next(namespace, scope, key)
-
- override def hashCode() =
- key.hashCode() * 7 + { if(value ne null) value.hashCode() * 53 else 0 } + next.hashCode()
-
- final def isPrefixed = false
-
- /** appends string representation of only this attribute to stringbuffer.
- *
- * @param sb ..
- */
- def toString1(sb: StringBuilder): Unit = if (value ne null) {
- sb.append(key)
- sb.append('=')
- val sb2 = new StringBuilder()
- Utility.sequenceToXML(value, TopScope, sb2, true)
- Utility.appendQuoted(sb2.toString(), sb)
- }
-
- def wellformed(scope: NamespaceBinding): Boolean =
- (null == next(null, scope, key)) && next.wellformed(scope)
-
- def remove(key: String) =
- if (this.key == key) next else copy(next.remove(key))
-
- def remove(namespace: String, scope: NamespaceBinding, key: String): MetaData =
- next.remove(namespace, scope, key)
-
}
object UnprefixedAttribute {
def unapply(x: UnprefixedAttribute) = Some(x.key, x.value, x.next)
diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala
index 138a704957..48a23dc389 100644
--- a/src/library/scala/xml/Utility.scala
+++ b/src/library/scala/xml/Utility.scala
@@ -11,8 +11,8 @@
package scala.xml
-import collection.mutable.{Set, HashSet, StringBuilder}
-import collection.Seq
+import collection.mutable
+import mutable.{ Set, HashSet }
import parsing.XhtmlEntities
/**
@@ -149,7 +149,7 @@ object Utility extends AnyRef with parsing.TokenTests
* @param nodes ...
* @return ...
*/
- def collectNamespaces(nodes: Seq[Node]): Set[String] =
+ def collectNamespaces(nodes: Seq[Node]): mutable.Set[String] =
nodes.foldLeft(new HashSet[String]) { (set, x) => collectNamespaces(x, set) ; set }
/**
@@ -158,7 +158,7 @@ object Utility extends AnyRef with parsing.TokenTests
* @param n ...
* @param set ...
*/
- def collectNamespaces(n: Node, set: Set[String]) {
+ def collectNamespaces(n: Node, set: mutable.Set[String]) {
if (n.doCollectNamespaces) {
set += n.namespace
for (a <- n.attributes) a match {
diff --git a/src/library/scala/xml/XML.scala b/src/library/scala/xml/XML.scala
index 1e85d4ae06..1395f7426f 100644
--- a/src/library/scala/xml/XML.scala
+++ b/src/library/scala/xml/XML.scala
@@ -11,12 +11,10 @@
package scala.xml
-import scala.xml.parsing.NoBindingFactoryAdapter
-import scala.xml.factory.XMLLoader
-import org.xml.sax.InputSource
-import javax.xml.parsers.{ SAXParser, SAXParserFactory }
-import java.io.{File, FileDescriptor, FileInputStream, FileOutputStream}
-import java.io.{InputStream, Reader, StringReader, Writer}
+import parsing.NoBindingFactoryAdapter
+import factory.XMLLoader
+import java.io.{ File, FileDescriptor, FileInputStream, FileOutputStream }
+import java.io.{ InputStream, Reader, StringReader, Writer }
import java.nio.channels.Channels
import scala.util.control.Exception.ultimately
diff --git a/src/library/scala/xml/dtd/ContentModel.scala b/src/library/scala/xml/dtd/ContentModel.scala
index d5d4b95cce..772d8ec599 100644
--- a/src/library/scala/xml/dtd/ContentModel.scala
+++ b/src/library/scala/xml/dtd/ContentModel.scala
@@ -13,10 +13,7 @@ package scala.xml
package dtd
import util.regexp.WordExp
-import util.automata.{DetWordAutom, SubsetConstruction, WordBerrySethi}
-import collection.mutable.{HashSet, StringBuilder}
-import collection.immutable.{List, Nil}
-import collection.Seq
+import util.automata._
import Utility.sbToString
import PartialFunction._
diff --git a/src/library/scala/xml/dtd/ContentModelParser.scala b/src/library/scala/xml/dtd/ContentModelParser.scala
index c260a9fc46..2b0df3f6a5 100644
--- a/src/library/scala/xml/dtd/ContentModelParser.scala
+++ b/src/library/scala/xml/dtd/ContentModelParser.scala
@@ -8,12 +8,9 @@
// $Id$
-
package scala.xml
package dtd
-import collection.immutable.List
-
/** Parser for regexps (content models in DTD element declarations) */
object ContentModelParser extends Scanner { // a bit too permissive concerning #PCDATA
diff --git a/src/library/scala/xml/dtd/DTD.scala b/src/library/scala/xml/dtd/DTD.scala
index 14c16f8489..0fde1188f3 100644
--- a/src/library/scala/xml/dtd/DTD.scala
+++ b/src/library/scala/xml/dtd/DTD.scala
@@ -8,31 +8,25 @@
// $Id$
-
package scala.xml
package dtd
-import scala.collection.mutable.{HashMap, Map}
+import collection.mutable
+import mutable.HashMap
/** A document type declaration.
*
* @author Burak Emir
*/
abstract class DTD {
-
- var externalID: ExternalID = null
-
- def notations: Seq[NotationDecl] = Nil
-
+ var externalID: ExternalID = null
+ var decls: List[Decl] = Nil
+ def notations: Seq[NotationDecl] = Nil
def unparsedEntities: Seq[EntityDecl] = Nil
- var elem: Map[String, ElemDecl] = new HashMap[String, ElemDecl]()
-
- var attr: Map[String, AttListDecl] = new HashMap[String, AttListDecl]()
-
- var ent: Map[String, EntityDecl] = new HashMap[String, EntityDecl]()
-
- var decls: List[Decl] = Nil
+ var elem: mutable.Map[String, ElemDecl] = new HashMap[String, ElemDecl]()
+ var attr: mutable.Map[String, AttListDecl] = new HashMap[String, AttListDecl]()
+ var ent: mutable.Map[String, EntityDecl] = new HashMap[String, EntityDecl]()
override def toString() =
"DTD [\n%s%s]".format(
diff --git a/src/library/scala/xml/dtd/Decl.scala b/src/library/scala/xml/dtd/Decl.scala
index 25ee30b356..ddc179b69f 100644
--- a/src/library/scala/xml/dtd/Decl.scala
+++ b/src/library/scala/xml/dtd/Decl.scala
@@ -8,14 +8,10 @@
// $Id$
-
package scala.xml
package dtd
import Utility.sbToString
-import collection.immutable.List
-import collection.mutable.StringBuilder
-
abstract class Decl
diff --git a/src/library/scala/xml/dtd/DocType.scala b/src/library/scala/xml/dtd/DocType.scala
index dab1d9ff6b..7da38b3e73 100644
--- a/src/library/scala/xml/dtd/DocType.scala
+++ b/src/library/scala/xml/dtd/DocType.scala
@@ -8,12 +8,9 @@
// $Id$
-
package scala.xml
package dtd
-import collection.Seq
-
/** An XML node for document type declaration.
*
* @author Burak Emir
diff --git a/src/library/scala/xml/dtd/ExternalID.scala b/src/library/scala/xml/dtd/ExternalID.scala
index 784273083a..b0d311e54a 100644
--- a/src/library/scala/xml/dtd/ExternalID.scala
+++ b/src/library/scala/xml/dtd/ExternalID.scala
@@ -8,14 +8,9 @@
// $Id$
-
package scala.xml
package dtd
-import collection.immutable.{List, Nil}
-import collection.mutable.StringBuilder
-
-
/** an ExternalIDs - either PublicID or SystemID
*
* @author Burak Emir
diff --git a/src/library/scala/xml/dtd/Scanner.scala b/src/library/scala/xml/dtd/Scanner.scala
index 1a45a186a0..7b3e2acfe0 100644
--- a/src/library/scala/xml/dtd/Scanner.scala
+++ b/src/library/scala/xml/dtd/Scanner.scala
@@ -8,13 +8,9 @@
// $Id$
-
package scala.xml
package dtd
-import collection.{Seq, Iterator}
-import collection.immutable.{List, Nil}
-
/** Scanner for regexps (content models in DTD element declarations)
* todo: cleanup
*/
diff --git a/src/library/scala/xml/factory/Binder.scala b/src/library/scala/xml/factory/Binder.scala
index caad009b9b..3996ef2d36 100644
--- a/src/library/scala/xml/factory/Binder.scala
+++ b/src/library/scala/xml/factory/Binder.scala
@@ -12,7 +12,7 @@
package scala.xml
package factory
-import scala.xml.parsing.ValidatingMarkupHandler
+import parsing.ValidatingMarkupHandler
/**
* @author Burak Emir
diff --git a/src/library/scala/xml/factory/NodeFactory.scala b/src/library/scala/xml/factory/NodeFactory.scala
index 45dac6ccda..2dd52242db 100644
--- a/src/library/scala/xml/factory/NodeFactory.scala
+++ b/src/library/scala/xml/factory/NodeFactory.scala
@@ -12,11 +12,7 @@ package scala.xml
package factory
import parsing.{ FactoryAdapter, NoBindingFactoryAdapter }
-import collection.Seq
-import collection.immutable.{List, Nil}
-import org.xml.sax.InputSource
import java.io.{ InputStream, Reader, StringReader, File, FileDescriptor, FileInputStream }
-import javax.xml.parsers.{ SAXParser, SAXParserFactory }
trait NodeFactory[A <: Node]
{
diff --git a/src/library/scala/xml/factory/XMLLoader.scala b/src/library/scala/xml/factory/XMLLoader.scala
index a1bca21b40..8bb0cf4188 100644
--- a/src/library/scala/xml/factory/XMLLoader.scala
+++ b/src/library/scala/xml/factory/XMLLoader.scala
@@ -11,11 +11,9 @@
package scala.xml
package factory
+import javax.xml.parsers.SAXParserFactory
import parsing.{ FactoryAdapter, NoBindingFactoryAdapter }
-import org.xml.sax.InputSource
import java.io.{ InputStream, Reader, StringReader, File, FileDescriptor, FileInputStream }
-import javax.xml.parsers.{ SAXParser, SAXParserFactory }
-import java.net.URL
/** Presents collection of XML loading methods which use the parser
* created by "def parser".
diff --git a/src/library/scala/xml/include/sax/Main.scala b/src/library/scala/xml/include/sax/Main.scala
index e7e986e0f8..3aa281451c 100644
--- a/src/library/scala/xml/include/sax/Main.scala
+++ b/src/library/scala/xml/include/sax/Main.scala
@@ -13,11 +13,10 @@ package include.sax
import scala.xml.include._
import scala.util.control.Exception.{ catching, ignoring }
-import org.xml.sax.{ SAXException, SAXParseException, EntityResolver, XMLReader }
+import org.xml.sax.XMLReader
import org.xml.sax.helpers.XMLReaderFactory
object Main {
- private val xercesClass = "org.apache.xerces.parsers.SAXParser"
private val namespacePrefixes = "http://xml.org/sax/features/namespace-prefixes"
private val lexicalHandler = "http://xml.org/sax/properties/lexical-handler"
@@ -35,7 +34,7 @@ object Main {
val parser: XMLReader =
saxe[XMLReader](XMLReaderFactory.createXMLReader()) getOrElse (
- saxe[XMLReader](XMLReaderFactory.createXMLReader(xercesClass)) getOrElse (
+ saxe[XMLReader](XMLReaderFactory.createXMLReader(XercesClassName)) getOrElse (
return error("Could not find an XML parser")
)
)
diff --git a/src/library/scala/xml/include/sax/XIncludeFilter.scala b/src/library/scala/xml/include/sax/XIncludeFilter.scala
index b469086e73..6e64fa9aa5 100644
--- a/src/library/scala/xml/include/sax/XIncludeFilter.scala
+++ b/src/library/scala/xml/include/sax/XIncludeFilter.scala
@@ -12,11 +12,10 @@ package scala.xml
package include.sax
import scala.xml.include._
-import org.xml.sax.{ Attributes, SAXException, XMLReader, EntityResolver, Locator }
+import org.xml.sax.{ Attributes, XMLReader, Locator }
import org.xml.sax.helpers.{ XMLReaderFactory, XMLFilterImpl, NamespaceSupport, AttributesImpl }
-import java.net.{ URL, URLConnection, MalformedURLException }
-import java.io.{ UnsupportedEncodingException, IOException, InputStream, BufferedInputStream, InputStreamReader }
+import java.io.{ InputStream, BufferedInputStream, InputStreamReader }
import java.util.Stack
/**
@@ -351,61 +350,49 @@ class XIncludeFilter extends XMLFilterImpl {
be downloaded from the specified URL.
*/
private def includeXMLDocument(url: String) {
- var source: URL = null
- try {
- val base = bases.peek().asInstanceOf[URL]
- source = new URL(base, url)
- }
- catch {
- case e:MalformedURLException =>
- val ex = new UnavailableResourceException("Unresolvable URL " + url
- + getLocation());
- ex.setRootCause(e)
- throw new SAXException("Unresolvable URL " + url + getLocation(), ex)
- }
+ val source =
+ try new URL(bases.peek(), url)
+ catch {
+ case e: MalformedURLException =>
+ val ex = new UnavailableResourceException("Unresolvable URL " + url + getLocation())
+ ex setRootCause e
+ throw new SAXException("Unresolvable URL " + url + getLocation(), ex)
+ }
try {
- // make this more robust
- var parser: XMLReader = null
- try {
- parser = XMLReaderFactory.createXMLReader()
- } catch {
- case e:SAXException =>
- try {
- parser = XMLReaderFactory.createXMLReader(
- "org.apache.xerces.parsers.SAXParser"
- );
- } catch {
- case e2: SAXException =>
- System.err.println("Could not find an XML parser")
- }
- }
- if(parser != null) {
- parser.setContentHandler(this)
- val resolver = this.getEntityResolver()
- if (resolver != null) parser.setEntityResolver(resolver);
- // save old level and base
- val previousLevel = level
- this.level = 0
- if (bases.contains(source)) {
- val e = new CircularIncludeException(
- "Circular XInclude Reference to " + source + getLocation()
- );
- throw new SAXException("Circular XInclude Reference", e)
+ val parser: XMLReader =
+ try XMLReaderFactory.createXMLReader()
+ catch {
+ case e: SAXException =>
+ try XMLReaderFactory.createXMLReader(XercesClassName)
+ catch { case _: SAXException => return System.err.println("Could not find an XML parser") }
}
- bases.push(source)
- atRoot = true
- parser.parse(source.toExternalForm())
- // restore old level and base
- this.level = previousLevel
- bases.pop()
- }
+
+ parser setContentHandler this
+ val resolver = this.getEntityResolver()
+ if (resolver != null)
+ parser setEntityResolver resolver
+
+ // save old level and base
+ val previousLevel = level
+ this.level = 0
+ if (bases contains source)
+ throw new SAXException(
+ "Circular XInclude Reference",
+ new CircularIncludeException("Circular XInclude Reference to " + source + getLocation())
+ )
+
+ bases push source
+ atRoot = true
+ parser parse source.toExternalForm()
+
+ // restore old level and base
+ this.level = previousLevel
+ bases.pop()
}
catch {
- case e:IOException =>
- throw new SAXException("Document not found: "
- + source.toExternalForm() + getLocation(), e)
+ case e: IOException =>
+ throw new SAXException("Document not found: " + source.toExternalForm() + getLocation(), e)
}
-
}
}
diff --git a/src/library/scala/xml/include/sax/XIncluder.scala b/src/library/scala/xml/include/sax/XIncluder.scala
index 3417dd78f0..bd9da10c59 100644
--- a/src/library/scala/xml/include/sax/XIncluder.scala
+++ b/src/library/scala/xml/include/sax/XIncluder.scala
@@ -10,22 +10,13 @@
package scala.xml
package include.sax
+
import scala.xml.include._
+import collection.mutable.Stack
-import org.xml.sax.SAXException
-import org.xml.sax.SAXParseException
-import org.xml.sax.ContentHandler
-import org.xml.sax.EntityResolver
-import org.xml.sax.helpers.XMLReaderFactory
-import org.xml.sax.XMLReader
-import org.xml.sax.Locator
-import org.xml.sax.Attributes
+import org.xml.sax.{ ContentHandler, XMLReader, Locator, Attributes }
import org.xml.sax.ext.LexicalHandler
-
-import java.io.{File, IOException, OutputStream, OutputStreamWriter,
- UnsupportedEncodingException, Writer}
-import java.net.{MalformedURLException, URL}
-import java.util.Stack
+import java.io.{ File, OutputStream, OutputStreamWriter, Writer }
/** XIncluder is a SAX <code>ContentHandler</code>
* that writes its XML document onto an output stream after resolving
@@ -35,8 +26,7 @@ import java.util.Stack
* based on Eliotte Rusty Harold's SAXXIncluder
* </p>
*/
-class XIncluder(outs:OutputStream, encoding:String) extends Object
-with ContentHandler with LexicalHandler {
+class XIncluder(outs: OutputStream, encoding: String) extends ContentHandler with LexicalHandler {
var out = new OutputStreamWriter(outs, encoding)
@@ -153,7 +143,7 @@ with ContentHandler with LexicalHandler {
def startDTD(name: String, publicID: String, systemID: String) {
inDTD = true
// if this is the source document, output a DOCTYPE declaration
- if (entities.size() == 0) {
+ if (entities.isEmpty) {
var id = ""
if (publicID != null) id = " PUBLIC \"" + publicID + "\" \"" + systemID + '"';
else if (systemID != null) id = " SYSTEM \"" + systemID + '"';
@@ -169,7 +159,7 @@ with ContentHandler with LexicalHandler {
def endDTD() {}
def startEntity(name: String) {
- entities.push(name)
+ entities push name
}
def endEntity(name: String) {
diff --git a/src/library/scala/xml/package.scala b/src/library/scala/xml/package.scala
new file mode 100644
index 0000000000..33639ed978
--- /dev/null
+++ b/src/library/scala/xml/package.scala
@@ -0,0 +1,18 @@
+package scala
+
+package object xml {
+ val XercesClassName = "org.apache.xerces.parsers.SAXParser"
+
+ type SAXException = org.xml.sax.SAXException
+ type SAXParseException = org.xml.sax.SAXParseException
+ type EntityResolver = org.xml.sax.EntityResolver
+ type InputSource = org.xml.sax.InputSource
+
+ type SAXParser = javax.xml.parsers.SAXParser
+
+ type IOException = java.io.IOException
+ type UnsupportedEncodingException = java.io.UnsupportedEncodingException
+
+ type URL = java.net.URL
+ type MalformedURLException = java.net.MalformedURLException
+} \ No newline at end of file
diff --git a/src/library/scala/xml/parsing/FactoryAdapter.scala b/src/library/scala/xml/parsing/FactoryAdapter.scala
index a83f9677a1..6960e05d25 100644
--- a/src/library/scala/xml/parsing/FactoryAdapter.scala
+++ b/src/library/scala/xml/parsing/FactoryAdapter.scala
@@ -12,20 +12,15 @@
package scala.xml
package parsing
-import java.io.{InputStream, Reader, File, FileDescriptor, FileInputStream}
-import collection.mutable.{Stack, StringBuilder}
-import collection.immutable.{List, Nil}
-import collection.{Seq, Iterator}
+import java.io.{ InputStream, Reader, File, FileDescriptor, FileInputStream }
+import collection.mutable.Stack
-import org.xml.sax.{ Attributes, InputSource }
+import org.xml.sax.Attributes
import org.xml.sax.helpers.DefaultHandler
-import javax.xml.parsers.{ SAXParser, SAXParserFactory }
// can be mixed into FactoryAdapter if desired
trait ConsoleErrorHandler extends DefaultHandler
{
- import org.xml.sax.SAXParseException
-
// ignore warning, crimson warns even for entity resolution!
override def warning(ex: SAXParseException): Unit = { }
override def error(ex: SAXParseException): Unit = printError("Error", ex)
diff --git a/src/library/scala/xml/parsing/MarkupHandler.scala b/src/library/scala/xml/parsing/MarkupHandler.scala
index a0058e8bc4..75c7958c38 100644
--- a/src/library/scala/xml/parsing/MarkupHandler.scala
+++ b/src/library/scala/xml/parsing/MarkupHandler.scala
@@ -12,7 +12,8 @@
package scala.xml
package parsing
-import scala.collection.mutable.{HashMap, Map}
+import collection.mutable
+import mutable.HashMap
import scala.io.Source
import scala.util.logging.Logged
import scala.xml.dtd._
@@ -32,7 +33,7 @@ abstract class MarkupHandler extends Logged
val isValidating: Boolean = false
var decls: List[Decl] = Nil
- var ent: Map[String, EntityDecl] = new HashMap[String, EntityDecl]()
+ var ent: mutable.Map[String, EntityDecl] = new HashMap[String, EntityDecl]()
def lookupElemDecl(Label: String): ElemDecl = {
for (z @ ElemDecl(Label, _) <- decls)
diff --git a/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala b/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala
index 05d535155b..083465bc41 100644
--- a/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala
+++ b/src/library/scala/xml/parsing/NoBindingFactoryAdapter.scala
@@ -12,10 +12,6 @@ package scala.xml
package parsing
import factory.NodeFactory
-import collection.Seq
-import collection.immutable.List
-import org.xml.sax.InputSource
-import javax.xml.parsers.{ SAXParser, SAXParserFactory }
/** nobinding adaptor providing callbacks to parser to create elements.
* implements hash-consing
diff --git a/src/library/scala/xml/parsing/TokenTests.scala b/src/library/scala/xml/parsing/TokenTests.scala
index e41cff20a3..13500e8510 100644
--- a/src/library/scala/xml/parsing/TokenTests.scala
+++ b/src/library/scala/xml/parsing/TokenTests.scala
@@ -12,8 +12,6 @@
package scala.xml
package parsing
-import collection.Seq
-import collection.immutable.List
/**
* Helper functions for parsing XML fragments
*/
diff --git a/src/library/scala/xml/parsing/XhtmlEntities.scala b/src/library/scala/xml/parsing/XhtmlEntities.scala
index dbc2ae0621..6e35aa9606 100644
--- a/src/library/scala/xml/parsing/XhtmlEntities.scala
+++ b/src/library/scala/xml/parsing/XhtmlEntities.scala
@@ -8,11 +8,10 @@
// $Id$
-
package scala.xml
package parsing
-import scala.xml.dtd.{IntDef, ParsedEntityDecl}
+import scala.xml.dtd.{ IntDef, ParsedEntityDecl }
/** <p>
* (c) David Pollak 2007 WorldWide Conferencing, LLC.