eu.cdevreeze.yaidom

Scope

final case class Scope(map: Map[String, String]) extends Immutable with Product with Serializable

Scope mapping prefixes to namespace URIs, as well as holding an optional default namespace. In other words, in-scope namespaces.

The purpose of a Scope is to resolve QNames as ENames.

A Scope must not contain prefix "xmlns" and must not contain namespace URI "http://www.w3.org/2000/xmlns/". Moreover, a Scope must not contain the XML namespace (prefix "xml", namespace URI "http://www.w3.org/XML/1998/namespace").

The Scope is backed by a map from prefixes (or the empty string for the default namespace) to (non-empty) namespace URIs.

This class depends on Declarations, but not the other way around.

Scope more formally

Method resolve resolves a Declarations against this Scope, returning a new Scope. It could be defined by the following equality:

scope.resolve(declarations) == {
  val m = (scope.map ++ declarations.withoutUndeclarations.map) -- declarations.retainingUndeclarations.map.keySet
  Scope(m)
}

The actual implementation may be more efficient than that, but it is consistent with this definition.

Method relativize relativizes a Scope against this Scope, returning a Declarations. It could be defined by the following equality:

scope1.relativize(scope2) == {
  val declared = scope2.map filter { case (pref, ns) => scope1.map.getOrElse(pref, "") != ns }
  val undeclared = scope1.map.keySet -- scope2.map.keySet
  Declarations(declared) ++ Declarations.undeclaring(undeclared)
}

Again, the actual implementation may be more efficient than that, but it is consistent with this definition.

1. Property about relativize and resolve, and its proof

Methods relativize and resolve obey the following equality:

scope1.resolve(scope1.relativize(scope2)) == scope2

This property can be proven easily. After all, for arbitrary Declarations decl, we have:

scope1.resolve(decl).map == { (scope1.map ++ decl.withoutUndeclarations.map) -- decl.retainingUndeclarations.map.keySet }

Here, decl stands for scope1.relativize(scope2), so:

scope1.resolve(decl).map == {
  val properDeclarations = scope1.relativize(scope2).withoutUndeclarations.map
  val undeclared = scope1.relativize(scope2).retainingUndeclarations.map.keySet
  (scope1.map ++ properDeclarations) -- undeclared
}

so:

scope1.resolve(decl).map == {
  val properDeclarations = scope2.map filter { case (pref, ns) => scope1.map.getOrElse(pref, "") != ns }
  val undeclared = scope1.map.keySet -- scope2.map.keySet

  assert((scope1.map ++ properDeclarations).keySet == scope1.map.keySet.union(scope2.map.keySet))
  (scope1.map ++ properDeclarations) -- undeclared
}

so (visualising with Venn diagrams for prefix sets):

scope1.resolve(decl).map == {
  val properDeclarations = scope2.map filter { case (pref, ns) => scope1.map.getOrElse(pref, "") != ns }
  (scope1.map ++ properDeclarations) filterKeys (scope2.map.keySet)
}

The RHS clearly has as keys the keys of scope2.map and the mapped values (per key) are also those found in scope2.map. Hence,

scope1.resolve(scope1.relativize(scope2)).map == scope2.map

so:

scope1.resolve(scope1.relativize(scope2)) == scope2
2. Another property about relativize and resolve, and its proof

Methods relativize and resolve also obey the following equality:

scope.relativize(scope.resolve(declarations)) == scope.minimized(declarations)

where scope.minimized(declarations) is defined by the following equality:

scope.minimized(declarations) == {
  val declared = declarations.withoutUndeclarations.map filter { case (pref, ns) => scope.map.getOrElse(pref, "") != ns }
  val undeclared = declarations.retainingUndeclarations.map.keySet.intersect(scope.map.keySet)
  Declarations(declared) ++ Declarations.undeclaring(undeclared)
}

Below follows a proof of this property. For arbitrary Scope sc, we have:

scope.relativize(sc) == {
  val declared = sc.map filter { case (pref, ns) => scope.map.getOrElse(pref, "") != ns }
  val undeclared = scope.map.keySet -- sc.map.keySet
  Declarations(declared) ++ Declarations.undeclaring(undeclared)
}

Here, sc stands for scope.resolve(declarations), so:

scope.relativize(sc) == {
  val declared = scope.resolve(declarations).map filter { case (pref, ns) => scope.map.getOrElse(pref, "") != ns }
  val undeclared = scope.map.keySet -- scope.resolve(declarations).map.keySet
  Declarations(declared) ++ Declarations.undeclaring(undeclared)
}

so:

scope.relativize(sc) == {
  val newScope = Scope((scope.map ++ declarations.withoutUndeclarations.map) -- declarations.retainingUndeclarations.map.keySet)
  val declared = newScope.map filter { case (pref, ns) => scope.map.getOrElse(pref, "") != ns }
  val undeclared = scope.map.keySet -- newScope.map.keySet
  Declarations(declared) ++ Declarations.undeclaring(undeclared)
}

so:

scope.relativize(sc) == {
  val declared = declarations.withoutUndeclarations.map filter { case (pref, ns) => scope.map.getOrElse(pref, "") != ns }
  val undeclared = declarations.retainingUndeclarations.map.keySet.intersect(scope.map.keySet)
  Declarations(declared) ++ Declarations.undeclaring(undeclared)
}

so, as a result:

scope.relativize(scope.resolve(declarations)) == scope.minimized(declarations)

This and the preceding (proven) property are analogous to corresponding properties in the URI class.

Linear Supertypes
Serializable, Serializable, Product, Equals, Immutable, AnyRef, Any
Ordering
  1. Alphabetic
  2. By inheritance
Inherited
  1. Hide All
  2. Show all
  1. Scope
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. Immutable
  7. AnyRef
  8. Any
Visibility
  1. Public
  2. All

Instance Constructors

  1. new Scope(map: Map[String, String])

Value Members

  1. final def !=(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  2. final def !=(arg0: Any): Boolean

    Definition Classes
    Any
  3. final def ##(): Int

    Definition Classes
    AnyRef → Any
  4. def ++(scope: Scope): Scope

    Returns Scope(this.map ++ scope.map)

  5. def --(prefixes: Set[String]): Scope

    Returns Scope(this.map -- prefixes)

  6. final def ==(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  7. final def ==(arg0: Any): Boolean

    Definition Classes
    Any
  8. final def asInstanceOf[T0]: T0

    Definition Classes
    Any
  9. def canEqual(arg0: Any): Boolean

    Definition Classes
    Scope → Equals
  10. def clone(): AnyRef

    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws()
  11. def defaultNamespaceOption: Option[String]

    Returns the default namespace, if any, wrapped in an Option

  12. final def eq(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  13. def equals(arg0: Any): Boolean

    Definition Classes
    Scope → Equals → AnyRef → Any
  14. def finalize(): Unit

    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws()
  15. final def getClass(): java.lang.Class[_]

    Definition Classes
    AnyRef → Any
  16. def hashCode(): Int

    Definition Classes
    Scope → AnyRef → Any
  17. def inverse: Map[String, Set[String]]

    Returns the inverse of this Scope, as Map from namespace URIs to collections of prefixes.

    Returns the inverse of this Scope, as Map from namespace URIs to collections of prefixes. These prefixes also include the empty String if this Scope has a default namespace.

  18. def isEmpty: Boolean

    Returns true if this Scope is empty.

    Returns true if this Scope is empty. Faster than comparing this Scope against the empty Scope.

  19. final def isInstanceOf[T0]: Boolean

    Definition Classes
    Any
  20. def isInvertible: Boolean

    Returns true if the inverse exists, that is, each namespace URI has a unique prefix (including the empty prefix for the default namespace, if applicable).

    Returns true if the inverse exists, that is, each namespace URI has a unique prefix (including the empty prefix for the default namespace, if applicable).

    In other words, returns true if the inverse of toMap is also a mathematical function, mapping namespace URIs to unique prefixes.

    Invertible scopes offer a one-to-one correspondence between QNames and ENames. This is needed, for example, for ElemPaths. Only if there is such a one-to-one correspondence, the indexes in ElemPaths and ElemPathBuilders are stable, when converting between the two.

  21. val map: Map[String, String]

  22. def minimized(declarations: Declarations): Declarations

    Returns the smallest sub-declarations decl of declarations such that this.resolve(decl) == this.resolve(declarations)

  23. final def ne(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  24. def notUndeclaring(scope: Scope): Scope

    Returns this.resolve(this.relativize(scope).withoutUndeclarations).

    Returns this.resolve(this.relativize(scope).withoutUndeclarations). In other words, returns the minimal superscope sc of scope such that this.relativize(sc) contains no namespace undeclarations.

    Note that:

    scope.subScopeOf(this.notUndeclaring(scope))
    

    This does not necessarily mean that scope.resolveQNameOption(qname) == this.notUndeclaring(scope).resolveQNameOption(qname). After all, for any unqualified name qname, if this scope has a default namespace but the passed scope does not, the LHS uses no namespace to resolve qname, whereas the RHS uses the default namespace.

  25. def notUndeclaringPrefixes(scope: Scope): Scope

    Returns scope.retainingDefaultNamespace ++ this.withoutDefaultNamespace.notUndeclaring(scope.withoutDefaultNamespace).

    Returns scope.retainingDefaultNamespace ++ this.withoutDefaultNamespace.notUndeclaring(scope.withoutDefaultNamespace).

    Note that for each QName qname for which scope.resolveQNameOption(qname).isDefined, we have:

    scope.resolveQNameOption(qname) == this.notUndeclaringPrefixes(scope).resolveQNameOption(qname)
    

    and that:

    scope.subScopeOf(this.notUndeclaringPrefixes(scope))
    

    This property is handy when adding child elements to a parent Elem. By invoking this method (recursively) for the descendant elements, against the parent Scope, we can create Elem trees without any unnecessary undeclarations (which are implicit, of course, because Elems contain Scopes, not Declarations). There is indeed a corresponding method in class Elem, which does just that.

  26. final def notify(): Unit

    Definition Classes
    AnyRef
  27. final def notifyAll(): Unit

    Definition Classes
    AnyRef
  28. def prefixOption(namespaceUri: String): Option[String]

    Returns a prefix mapping to the given namespace URI, if any, wrapped in an Option.

    Returns a prefix mapping to the given namespace URI, if any, wrapped in an Option. If multiple prefixes map to the given namespace URI, it is undetermined which of the prefixes is returned.

    This method can be handy when "inserting" an "element" into a parent tree, if one wants to reuse prefixes of the parent tree.

  29. def productArity: Int

    Definition Classes
    Scope → Product
  30. def productElement(arg0: Int): Any

    Definition Classes
    Scope → Product
  31. def productIterator: Iterator[Any]

    Definition Classes
    Product
  32. def productPrefix: String

    Definition Classes
    Scope → Product
  33. def relativize(scope: Scope): Declarations

    Relativizes the given Scope against this Scope, returning a Declarations object.

    Relativizes the given Scope against this Scope, returning a Declarations object.

    Inspired by java.net.URI, which has a similar method for URIs.

  34. def resolve(declarations: Declarations): Scope

    Resolves the given declarations against this Scope, returning an "updated" Scope.

    Resolves the given declarations against this Scope, returning an "updated" Scope.

    Inspired by java.net.URI, which has a similar method for URIs.

  35. def resolveQNameOption(qname: QName): Option[EName]

    Tries to resolve the given QName against this Scope, returning None for prefixed names whose prefixes are unknown to this Scope.

    Tries to resolve the given QName against this Scope, returning None for prefixed names whose prefixes are unknown to this Scope.

    Note that the subScopeOf relation keeps the resolveQNameOption result the same, provided there is no default namespace. That is, if scope1.withoutDefaultNamespace.subScopeOf(scope2.withoutDefaultNamespace), then for each QName qname such that scope1.withoutDefaultNamespace.resolveQNameOption(qname).isDefined, we have:

    scope1.withoutDefaultNamespace.resolveQNameOption(qname) == scope2.withoutDefaultNamespace.resolveQNameOption(qname)
    
  36. def retainingDefaultNamespace: Scope

    Returns an adapted copy of this Scope, but retaining only the default namespace, if any

  37. def subScopeOf(scope: Scope): Boolean

    Returns true if this is a subscope of the given parameter Scope.

    Returns true if this is a subscope of the given parameter Scope. A Scope is considered subscope of itself.

  38. def superScopeOf(scope: Scope): Boolean

    Returns true if this is a superscope of the given parameter Scope.

    Returns true if this is a superscope of the given parameter Scope. A Scope is considered superscope of itself.

  39. final def synchronized[T0](arg0: ⇒ T0): T0

    Definition Classes
    AnyRef
  40. def toString(): String

    Definition Classes
    Scope → AnyRef → Any
  41. def toStringInXml: String

    Creates a String representation of this Scope, as it is shown in XML

  42. final def wait(): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws()
  43. final def wait(arg0: Long, arg1: Int): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws()
  44. final def wait(arg0: Long): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws()
  45. def withoutDefaultNamespace: Scope

    Returns an adapted copy of this Scope, but without the default namespace, if any

Deprecated Value Members

  1. def productElements: Iterator[Any]

    Definition Classes
    Product
    Annotations
    @deprecated
    Deprecated

    (Since version 2.8.0) use productIterator instead

Inherited from Serializable

Inherited from Serializable

Inherited from Product

Inherited from Equals

Inherited from Immutable

Inherited from AnyRef

Inherited from Any