Package net.sf.saxon.trans

## Class KeyManager

- java.lang.Object
- - net.sf.saxon.trans.KeyManager

-     public class KeyManager
      extends java.lang.Object

  KeyManager manages the set of key definitions in a stylesheet, and the indexes associated with these key definitions. It handles xsl:sort-key as well as xsl:key definitions.

  The memory management in this class is subtle, with extensive use of weak references. The idea is that an index should continue to exist in memory so long as both the compiled stylesheet and the source document exist in memory: if either is removed, the index should go too. The document itself holds no reference to the index. The compiled stylesheet (which owns the KeyManager) holds a weak reference to the index. The index, of course, holds strong references to the nodes in the document. The Controller holds a strong reference to the list of indexes used for each document, so that indexes remain in memory for the duration of a transformation even if the documents themselves are garbage collected.

  Potentially there is a need for more than one index for a given key name, depending on the primitive type of the value provided to the key() function. An index is built corresponding to the type of the requested value; if subsequently the key() function is called with the same name and a different type of value, then a new index is built.

  For XSLT-defined keys, equality matching follows the rules of the eq operator, which means that untypedAtomic values are treated as strings. In backwards compatibility mode, all values are converted to strings.

  This class is also used for internal indexes constructed (a) to support the idref() function, and (b) (in Saxon-EE only) to support filter expressions of the form /a/b/c[d=e], where the path expression being filtered must be a single-document context-free path rooted at a document node, where exactly one of d and e must be dependent on the focus, and where certain other conditions apply such as the filter predicate not being positional. The operator in this case may be either "=" or "eq". If it is "eq", then the semantics are very similar to xsl:key indexes, except that use of non-comparable types gives an error rather than a non-match. If the operator is "=", however, then the rules for handling untypedAtomic values are different: these must be converted to the type of the other operand. In this situation the following rules apply. Assume that the predicate is [use=value], where use is dependent on the focus (the indexed value), and value is the sought value.

  - If value is a type other than untypedAtomic, say T, then we build an index for type T, in which any untypedAtomic values that arise in evaluating "use" are converted to type T. A conversion failure results in an error. A value of a type that is not comparable to T also results in an error.
  - If value is untypedAtomic, then we build an index for every type actually encountered in evaluating the use expression (treating untypedAtomic as string), and then search each of these indexes. (Note that it is not an error if the use expression returns a mixture of say numbers and dates, provided that the sought value is untypedAtomic).

- - ### Constructor Summary

    Constructors
    Constructor | Description
    --- | ---
    `KeyManager​(Configuration config, PackageData pack)` | Create a KeyManager and initialise variables

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `void` | `addKeyDefinition​(StructuredQName keyName, KeyDefinition keydef, boolean reusable, Configuration config)` | Register a key definition.
    `void` | `clearDocumentIndexes​(TreeInfo doc)` | Clear all the indexes for a given document.
    `void` | `exportKeys​(ExpressionPresenter out, java.util.Map<Component,​java.lang.Integer> componentIdMap)` | Diagnostic output explaining the keys
    `KeyDefinitionSet` | `findKeyDefinition​(Pattern finder, Expression use, java.lang.String collationName)` | Look for a key definition that matches a proposed new key
    `java.util.Collection<KeyDefinitionSet>` | `getAllKeyDefinitionSets()` | Get all the key definition sets
    `KeyDefinitionSet` | `getKeyDefinitionSet​(StructuredQName qName)` | Get all the key definitions that match a particular name
    `int` | `getNumberOfKeyDefinitions()` | Get the number of distinctly-named key definitions
    `KeyIndex` | `obtainIndex​(KeyDefinitionSet keySet, TreeInfo doc, XPathContext context)` | Get the index supporting a particular key definition for a particular document.
    `void` | `preRegisterKeyDefinition​(StructuredQName keyName)` | Pre-register a key definition.
    `SequenceIterator` | `selectByCompositeKey​(KeyDefinitionSet keySet, TreeInfo doc, SequenceIterator soughtValue, XPathContext context)` | Get the nodes with a given composite key value
    `SequenceIterator` | `selectByKey​(KeyDefinitionSet keySet, TreeInfo doc, AtomicValue soughtValue, XPathContext context)` | Get the nodes with a given key value

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### KeyManager

          public KeyManager​(Configuration config,
                            PackageData pack)

      Create a KeyManager and initialise variables
      Parameters:
        `config` - the Saxon configuration
        `pack` - the package in which these keys are available

  - ### Method Detail

    - #### preRegisterKeyDefinition

          public void preRegisterKeyDefinition​(StructuredQName keyName)

      Pre-register a key definition. This simply registers that a key with a given name exists, without providing any details.
      Parameters:
        `keyName` - the name of the key to be pre-registered

    - #### addKeyDefinition

          public void addKeyDefinition​(StructuredQName keyName,
                                       KeyDefinition keydef,
                                       boolean reusable,
                                       Configuration config)
                                throws XPathException

      Register a key definition. Note that multiple key definitions with the same name are allowed
      Parameters:
        `keyName` - Structured QName representing the name of the key
        `keydef` - The details of the key's definition
        `reusable` - Set to true if indexes using this key definition can be used across multiple transformations, false if the indexes need to be rebuilt for each transformation. Indexes are not reusable if the key definition contains references to global variables or parameters, or calls used-defined functions or templates that might contain such references.
        `config` - The configuration
      Throws:
        `XPathException` - if this key definition is inconsistent with existing key definitions having the same name

    - #### getKeyDefinitionSet

          public KeyDefinitionSet getKeyDefinitionSet​(StructuredQName qName)

      Get all the key definitions that match a particular name
      Parameters:
        `qName` - The name of the required key
      Returns:
        The set of key definitions of the named key if there are any, or null otherwise.

    - #### findKeyDefinition

          public KeyDefinitionSet findKeyDefinition​(Pattern finder,
                                                    Expression use,
                                                    java.lang.String collationName)

      Look for a key definition that matches a proposed new key
      Parameters:
        `finder` - matches/selects the nodes to be indexed
        `use` - computes the value on which the nodes are indexed
        `collationName` - collation to be used
      Returns:
        a KeyDefinitionSet containing a key with the required characteristics if there is one, or null otherwise

    - #### selectByKey

          public SequenceIterator selectByKey​(KeyDefinitionSet keySet,
                                              TreeInfo doc,
                                              AtomicValue soughtValue,
                                              XPathContext context)
                                       throws XPathException

      Get the nodes with a given key value
      Parameters:
        `keySet` - The set of key definitions identified by the key name used in the call to the key() function
        `doc` - The source document in question
        `soughtValue` - The required key value
        `context` - The dynamic context, needed only the first time when the key is being built
      Returns:
        an iteration of the selected nodes, always in document order with no duplicates
      Throws:
        `XPathException` - if a dynamic error is encountered

    - #### selectByCompositeKey

          public SequenceIterator selectByCompositeKey​(KeyDefinitionSet keySet,
                                                       TreeInfo doc,
                                                       SequenceIterator soughtValue,
                                                       XPathContext context)
                                                throws XPathException

      Get the nodes with a given composite key value
      Parameters:
        `keySet` - The set of key definitions identified by the key name used in the call to the key() function
        `doc` - The source document in question
        `soughtValue` - The required key value
        `context` - The dynamic context, needed only the first time when the key is being built
      Returns:
        an iteration of the selected nodes, always in document order with no duplicates
      Throws:
        `XPathException` - if a dynamic error is encountered

    - #### obtainIndex

          public KeyIndex obtainIndex​(KeyDefinitionSet keySet,
                                      TreeInfo doc,
                                      XPathContext context)
                               throws XPathException

      Get the index supporting a particular key definition for a particular document. The index is created if it does not already exist.
      Parameters:
        `keySet` - the set of xsl:key definitions making up this key
        `doc` - the document to which the index applies
        `context` - the dynamic evaluation context
      Returns:
        the relevant index
      Throws:
        `XPathException` - if any failure occurs

    - #### clearDocumentIndexes

          public void clearDocumentIndexes​(TreeInfo doc)

      Clear all the indexes for a given document. This is currently done whenever updates are applied to the document, because updates can potentially invalidate the indexes.
      Parameters:
        `doc` - the document whose indexes are to be invalidated

    - #### getAllKeyDefinitionSets

          public java.util.Collection<KeyDefinitionSet> getAllKeyDefinitionSets()

      Get all the key definition sets
      Returns:
        a set containing all the key definition sets

    - #### getNumberOfKeyDefinitions

          public int getNumberOfKeyDefinitions()

      Get the number of distinctly-named key definitions
      Returns:
        the number of key definition sets (where the key definitions in one set share the same name)

    - #### exportKeys

          public void exportKeys​(ExpressionPresenter out,
                                 java.util.Map<Component,​java.lang.Integer> componentIdMap)
                          throws XPathException

      Diagnostic output explaining the keys
      Parameters:
        `out` - the expression presenter that will display the information
      Throws:
        `XPathException`