org.modeshape.jcr.cache.document

## Class LazyCachedNode

- java.lang.Object
- - org.modeshape.jcr.cache.document.LazyCachedNode

- All Implemented Interfaces:
    Serializable, CachedNode

      @ThreadSafe
      public class LazyCachedNode
      extends Object
      implements CachedNode, Serializable

  This is a (mostly) immutable `CachedNode` implementation that lazily loads its content. Technically each instance modifies its internal state, but most of the state is based upon a single Document that is read-in only once and never changed again. And thus externally each instance appears to be immutable and invariant, except anything that has to do with this node's `getName(NodeCache)` (e.g., `segment`, and the `path` { `methods`). That's because the name of this node is actually stored on the parent in the parent's `child references`, and this node's name, SNS index, and thus the path can all change even though none of the information stored in this node's document will actually change.

  This class is marked `Serializable` so instances can be placed within an Infinispan cache, though this class is never intended to actually be persisted. Instead, it is kept within ModeShape's `WorkspaceCache` that uses a purely in-memory Infinispan cache containing a configurable number of the most-recently-used `CachedNode` instances. As soon as `CachedNode` instances are evicted, they are GCed and no longer used. (Note that they can be easily reconstructed from the entries stored in the repository's main cache.

  The `WorkspaceCache` that keeps these `LazyCachedNode` instances is intended to be a cache of the persisted nodes, and thus are accessed by all sessions for that workspace. When a persisted node is changed, the corresponding `CachedNode` is purged from the `WorkspaceCache`. Therefore, these LazyCachedNode's must be able to be accessed concurrently from multiple threads; this is the reason why all of the lazily-populated fields are either atomic references or volatile. (Since all of these lazily-populated members are idempotent, the implementations do this properly without synchronization or blocking. The exception is the `parentRefToSelf` field, which can change but is done so in an atomic fashion (see `parentReferenceToSelf(WorkspaceCache)` for details).

  See Also:
    Serialized Form

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `protected static class` | `LazyCachedNode.NonRootParentReferenceToSelf` A `LazyCachedNode.ParentReferenceToSelf` implementation that caches the `ChildReference` from the parent plus the actual parent (via a weak reference to the `CachedNode`.
    `protected static interface` | `LazyCachedNode.ParentReferenceToSelf` A single object used to cache the parent's `ChildReference` that points to this node and methods that determine whether this cached information is still valid.
    `protected static class` | `LazyCachedNode.RootParentReferenceToSelf` A `LazyCachedNode.ParentReferenceToSelf` implementation used only for the root node.

    - ### Nested classes/interfaces inherited from interface org.modeshape.jcr.cache.CachedNode

      `CachedNode.Properties, CachedNode.ReferenceType`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `LazyCachedNode(NodeKey key, Document document)`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `protected Document` | `document(WorkspaceCache cache)` Get the `Document` that represents this node.
    `boolean` | `equals(Object obj)`
    `Set<NodeKey>` | `getAdditionalParentKeys(NodeCache cache)` Get the keys for all of the nodes (other than the `primary parent`) under which this node appears.
    `ChildReferences` | `getChildReferences(NodeCache cache)` Get the set of child references for this node.
    `int` | `getDepth(NodeCache cache)` Get the depth of this node.
    `NodeKey` | `getKey()` Get the key for the node.
    `Set<Name>` | `getMixinTypes(NodeCache cache)` Get the set of mixin types for this node.
    `Name` | `getName(NodeCache cache)` Get the name for this node, without any same-name-sibiling (SNS) index.
    `NodeKey` | `getParentKey(NodeCache cache)` Get the node key for this node's primary parent within this workspace.
    `NodeKey` | `getParentKeyInAnyWorkspace(NodeCache cache)` Get the node key for this node's primary parent in any workspace.
    `Path` | `getPath(NodeCache cache)` Get the path to this node.
    `Path` | `getPath(PathCache pathCache)` Get the path to this node.
    `Map<String,Set<String>>` | `getPermissions(NodeCache cache)` Gets the map of privileges by principal name which are in effect for this node.
    `Name` | `getPrimaryType(NodeCache cache)` Get the primary type for this node.
    `Iterator<Property>` | `getProperties(Collection<?> namePatterns, NodeCache cache)` Get an iterator over all of the properties of this node that have names matching at least one of the supplied patterns.
    `Iterator<Property>` | `getProperties(NodeCache cache)` Get an iterator over all of the node's properties.
    `CachedNode.Properties` | `getPropertiesByName(NodeCache cache)` Get the properties collection.
    `Property` | `getProperty(Name name, NodeCache cache)` Get the property with the given name.
    `int` | `getPropertyCount(NodeCache cache)` Determine the number of properties that this node contains.
    `Set<NodeKey>` | `getReferrers(NodeCache cache, CachedNode.ReferenceType type)` Get the keys of the nodes that have JCR REFERENCE and/or WEAK_REFERENCE properties pointing to this node.
    `Path.Segment` | `getSegment(NodeCache cache)` Get the path segment for this node.
    `protected Path.Segment` | `getSegment(WorkspaceCache cache)` Get the name for this node, without any same-name-sibiling (SNS) index.
    `String` | `getString(NamespaceRegistry registry)`
    `boolean` | `hasACL(NodeCache cache)` Determine if there is an access control list for this node only, not taking into account any possible parents.
    `int` | `hashCode()`
    `boolean` | `hasProperties(NodeCache cache)` Determine if the node contains one or more properties.
    `boolean` | `hasProperty(Name name, NodeCache cache)` Determine if the node contains a property with the specified name.
    `boolean` | `isAtOrBelow(NodeCache cache, Path path)` Determine if this node is effectively at or below the supplied path.
    `boolean` | `isExternal(NodeCache cache)` Determine if this node belongs to an external source (via federation) or is local to the repository.
    `boolean` | `isQueryable(NodeCache cache)` Determine if this node should be indexed and therefore available for querying.
    `protected CachedNode` | `parent(WorkspaceCache cache)`
    `protected ChildReference` | `parentReferenceToSelf(WorkspaceCache cache)` Get the parent node's child reference to this node.
    `protected Map<Name,Property>` | `properties()`
    `String` | `toString()`
    `protected WorkspaceCache` | `workspaceCache(NodeCache cache)`

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

      `clone, finalize, getClass, notify, notifyAll, wait, wait, wait`

- - ### Constructor Detail

    - #### LazyCachedNode

          public LazyCachedNode(NodeKey key,
                        Document document)

  - ### Method Detail

    - #### workspaceCache

          protected final WorkspaceCache workspaceCache(NodeCache cache)

    - #### document

          protected Document document(WorkspaceCache cache)

      Get the `Document` that represents this node.
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the document; never null
      Throws:
        `NodeNotFoundException` - if this node no longer exists

    - #### getParentKey

          public NodeKey getParentKey(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the node key for this node's primary parent within this workspace.
      Specified by:
        `getParentKey` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the parent's key; null if this is the root node or it has been removed from the document by someone else

    - #### getParentKeyInAnyWorkspace

          public NodeKey getParentKeyInAnyWorkspace(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the node key for this node's primary parent in any workspace.
      Specified by:
        `getParentKeyInAnyWorkspace` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the parent's key; null if this is the root node or it has been removed from the document by someone else

    - #### getAdditionalParentKeys

          public Set<NodeKey> getAdditionalParentKeys(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the keys for all of the nodes (other than the `primary parent`) under which this node appears.
      Specified by:
        `getAdditionalParentKeys` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the immutable set of keys to the additional parents, excluding the primary parent

    - #### isAtOrBelow

          public boolean isAtOrBelow(NodeCache cache,
                            Path path)

      Description copied from interface: `CachedNode`
      Determine if this node is effectively at or below the supplied path. Note that because of `additional parents`, a node has multiple effective paths.
      Specified by:
        `isAtOrBelow` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
        `path` - the path to be used for comparison; may not be null
      Returns:
        true if this node can be considered at or below the supplied path; or false otherwise

    - #### parent

          protected CachedNode parent(WorkspaceCache cache)

    - #### parentReferenceToSelf

          protected ChildReference parentReferenceToSelf(WorkspaceCache cache)

      Get the parent node's child reference to this node. This method atomically determines if the `parentRefToSelf` object is still up-to-date with the parent node's cached representation. If it is not still valid, then it will be recomputed.

      This method is carefully written to always return an atomically-consistent result without requiring any locking or synchronization. Generally speaking, at any given moment the cached information is idempotent, so we rely upon that and use an AtomicReference to ensure that the reference is updated atomically. The method implementation also reads the AtomicReference only once before deciding what to do; this means that multiple threads can concurrently call this method and it will always return the correct information.

      Parameters:
        `cache` - the cache
      Returns:
        the child reference; never null (even for the root node)
      Throws:
        `NodeNotFoundInParentException` - if this node is no longer referenced by its parent as a child of the parent node (which can happen if this node is used while in the midst of being (re)moved.

    - #### properties

          protected Map<Name,Property> properties()

    - #### getKey

          public NodeKey getKey()

      Description copied from interface: `CachedNode`
      Get the key for the node.
      Specified by:
        `getKey` in interface `CachedNode`
      Returns:
        the node's key; never null

    - #### getName

          public Name getName(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the name for this node, without any same-name-sibiling (SNS) index.
      Specified by:
        `getName` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the name; never null, but the root node will have a zero-length name
      See Also:
        `CachedNode.getSegment(NodeCache)`, `CachedNode.getPath(NodeCache)`

    - #### getSegment

          public Path.Segment getSegment(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the path segment for this node. The segment consists of a name and a same-name-sibling (SNS) index.
      Specified by:
        `getSegment` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the segment; never null, but the root node will have a zero-length name
      See Also:
        `CachedNode.getName(NodeCache)`, `CachedNode.getPath(NodeCache)`

    - #### getSegment

          protected Path.Segment getSegment(WorkspaceCache cache)

      Get the name for this node, without any same-name-sibiling (SNS) index.
      Parameters:
        `cache` - the workspace cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the name; never null, but the root node will have a zero-length name
      Throws:
        `NodeNotFoundInParentException` - if this node no longer exists
      See Also:
        `getSegment(NodeCache)`, `getPath(NodeCache)`

    - #### getPath

          public Path getPath(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the path to this node.
      Specified by:
        `getPath` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the node's path; never null with at least one segment for all nodes except the root node
      See Also:
        `CachedNode.getName(NodeCache)`, `CachedNode.getSegment(NodeCache)`

    - #### getPath

          public Path getPath(PathCache pathCache)
                       throws NodeNotFoundException

      Description copied from interface: `CachedNode`
      Get the path to this node.
      Specified by:
        `getPath` in interface `CachedNode`
      Parameters:
        `pathCache` - the cache of paths that can be used to compute the path for any node; may not be null
      Returns:
        the node's path; never null with at least one segment for all nodes except the root node
      Throws:
        `NodeNotFoundInParentException` - if this node no longer exists inside the parent node (and perhaps in no other parent)
        `NodeNotFoundException` - if this node no longer exists
      See Also:
        `CachedNode.getName(NodeCache)`, `CachedNode.getSegment(NodeCache)`

    - #### getDepth

          public int getDepth(NodeCache cache)
                       throws NodeNotFoundException

      Description copied from interface: `CachedNode`
      Get the depth of this node. The depth is equivalent to the number of segments in the node's path (0 for the root node, 1 for "`/foo`", 2 for "`/foo/bar`", etc.), although this method will likely compute the depth more efficiently that finding the path and asking for the number of segments.

      The depth is calculated based upon the primary parent (and `primary path`). This is, although shared nodes are accessible at multiple paths, only the primary path is used to determine the depth of the node.

      Specified by:
        `getDepth` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the depth of this node; 0 for the root, or a positive number for all other nodes
      Throws:
        `NodeNotFoundException` - if this node no longer exists

    - #### getPrimaryType

          public Name getPrimaryType(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the primary type for this node.
      Specified by:
        `getPrimaryType` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the primary type name; never null

    - #### getMixinTypes

          public Set<Name> getMixinTypes(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the set of mixin types for this node.
      Specified by:
        `getMixinTypes` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the immutable list of mixin type names; never null but possibly empty

    - #### getPropertyCount

          public int getPropertyCount(NodeCache cache)

      Description copied from interface: `CachedNode`
      Determine the number of properties that this node contains.
      Specified by:
        `getPropertyCount` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the number of properties; never negative

    - #### hasProperties

          public boolean hasProperties(NodeCache cache)

      Description copied from interface: `CachedNode`
      Determine if the node contains one or more properties.
      Specified by:
        `hasProperties` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        true if the node has at least one property, or false otherwise

    - #### hasProperty

          public boolean hasProperty(Name name,
                            NodeCache cache)

      Description copied from interface: `CachedNode`
      Determine if the node contains a property with the specified name.
      Specified by:
        `hasProperty` in interface `CachedNode`
      Parameters:
        `name` - the name of the property
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        true if the node has the named property, or false otherwise

    - #### getProperty

          public Property getProperty(Name name,
                             NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the property with the given name.
      Specified by:
        `getProperty` in interface `CachedNode`
      Parameters:
        `name` - the name of the property
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the property, or null if the property does not exist on this node

    - #### getPropertiesByName

          public CachedNode.Properties getPropertiesByName(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the properties collection.
      Specified by:
        `getPropertiesByName` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the properties; never null but possibly empty

    - #### getProperties

          public Iterator<Property> getProperties(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get an iterator over all of the node's properties.
      Specified by:
        `getProperties` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the property iterator; never null but possibly empty

    - #### getProperties

          public Iterator<Property> getProperties(Collection<?> namePatterns,
                                         NodeCache cache)

      Description copied from interface: `CachedNode`
      Get an iterator over all of the properties of this node that have names matching at least one of the supplied patterns.
      Specified by:
        `getProperties` in interface `CachedNode`
      Parameters:
        `namePatterns` - the regex patterns or string literals describing the names
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the property iterator; never null but possibly empty

    - #### getChildReferences

          public ChildReferences getChildReferences(NodeCache cache)

      Description copied from interface: `CachedNode`
      Get the set of child references for this node. Note that each child reference will need to be resolved by the caller.
      Specified by:
        `getChildReferences` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        the representation of the children of this node; never null but possibly empty

    - #### getReferrers

          public Set<NodeKey> getReferrers(NodeCache cache,
                                  CachedNode.ReferenceType type)

      Description copied from interface: `CachedNode`
      Get the keys of the nodes that have JCR REFERENCE and/or WEAK_REFERENCE properties pointing to this node.
      Specified by:
        `getReferrers` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
        `type` - the flag specifying whether nodes with REFERENCE properties and/or WEAK reference properties should be included in the result; may not be null
      Returns:
        the set of keys to the nodes that have a reference to this node; never null but possibly empty

    - #### isQueryable

          public boolean isQueryable(NodeCache cache)

      Description copied from interface: `CachedNode`
      Determine if this node should be indexed and therefore available for querying. By default, every node is queryable, so only in certain cases can a node be made non-queryable.
      Specified by:
        `isQueryable` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        `true` if the node should be indexed, `false` otherwise

    - #### hasACL

          public boolean hasACL(NodeCache cache)

      Description copied from interface: `CachedNode`
      Determine if there is an access control list for this node only, not taking into account any possible parents.
      Specified by:
        `hasACL` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        `true` if this node has an ACL, `false` otherwise

    - #### getPermissions

          public Map<String,Set<String>> getPermissions(NodeCache cache)

      Description copied from interface: `CachedNode`
      Gets the map of privileges by principal name which are in effect for this node. This will not look at any of the parent nodes.
      Specified by:
        `getPermissions` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        a `Map` which contains a set of permission names keyed by principal name or `null` if no privileges are in effect for this node(i.e. this node does not have an ACL). An empty `Map` means a node which has an ACL, but does not have any permissions.

    - #### isExternal

          public boolean isExternal(NodeCache cache)

      Description copied from interface: `CachedNode`
      Determine if this node belongs to an external source (via federation) or is local to the repository.
      Specified by:
        `isExternal` in interface `CachedNode`
      Parameters:
        `cache` - the cache to which this node belongs, required in case this node needs to use the cache; may not be null
      Returns:
        `true` if the node is local, `false` otherwise.

    - #### hashCode

          public int hashCode()

      Overrides:
        `hashCode` in class `Object`

    - #### equals

          public boolean equals(Object obj)

      Overrides:
        `equals` in class `Object`

    - #### toString

          public String toString()

      Overrides:
        `toString` in class `Object`

    - #### getString

          public String getString(NamespaceRegistry registry)

Copyright © 2008-2014 JBoss, a division of Red Hat. All Rights Reserved.