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 eu.cdevreeze.yaidom.Scope is to resolve eu.cdevreeze.yaidom.QNames as eu.cdevreeze.yaidom.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.minimize(declarations)

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

scope.minimize(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.minimize(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. Scope
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. Immutable
  7. AnyRef
  8. Any
  1. Hide All
  2. Show all
Learn more about member selection
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 clone(): AnyRef

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

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

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

    Definition Classes
    AnyRef
  12. def filter(p: ((String, String)) ⇒ Boolean): Scope

    Returns Scope.from(this.map.filter(p)).

  13. def filterKeys(p: (String) ⇒ Boolean): Scope

    Returns Scope.from(this.map.filterKeys(p)).

  14. def finalize(): Unit

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

    Definition Classes
    AnyRef → Any
  16. 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.

  17. 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.

  18. final def isInstanceOf[T0]: Boolean

    Definition Classes
    Any
  19. 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.

  20. def keySet: Set[String]

    Returns this.map.keySet.

  21. val map: Map[String, String]

  22. def minimize(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. final def notify(): Unit

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

    Definition Classes
    AnyRef
  26. 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.

  27. 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.

  28. 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.

  29. 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)
  30. def retainingDefaultNamespace: Scope

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

  31. 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.

  32. 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.

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

    Definition Classes
    AnyRef
  34. def toStringInXml: String

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

  35. final def wait(): Unit

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

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

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

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

Inherited from Serializable

Inherited from Serializable

Inherited from Product

Inherited from Equals

Inherited from Immutable

Inherited from AnyRef

Inherited from Any

Ungrouped