Class ModelTransaction

java.lang.Object
org.apache.commons.configuration2.tree.ModelTransaction

final class ModelTransaction extends Object

An internal helper class for a atomic updates of an InMemoryNodeModel.

This class performs updates on the node structure of a node model consisting of ImmutableNode objects. Because the nodes themselves cannot be changed updates are achieved by replacing parts of the structure with new nodes; the new nodes are copies of original nodes with the corresponding manipulations applied. Therefore, each update of a node in the structure results in a new structure in which the affected node is replaced by a new one, and this change bubbles up to the root node (because all parent nodes have to be replaced by instances with an updated child reference).

A single update of a model may consist of multiple changes on nodes. For instance, a remove property operation can include many nodes. There are some reasons why such updates should be handled in a single "transaction" rather than executing them on altered node structures one by one:

  • An operation is typically executed on a set of source nodes from the original node hierarchy. While manipulating nodes, nodes of this set may be replaced by new ones. The handling of these replacements complicates things a lot.
  • Performing all updates one after the other may cause more updates of nodes than necessary. Nodes near to the root node always have to be replaced when a child of them gets manipulated. If all these updates are deferred and handled in a single transaction, the resulting operation is more efficient.

  • Field Details

    • MAX_REPLACEMENTS

      private static final int MAX_REPLACEMENTS
      Constant for the maximum number of entries in the replacement mapping. If this number is exceeded, the parent mapping is reconstructed. The number is a bit arbitrary. If it is too low, updates - especially on large node structures - are expensive because the parent mapping is often rebuild. If it is too big, read access to the model is slowed down because looking up the parent of a node is more complicated.
      See Also:
    • LEVEL_UNKNOWN

      private static final int LEVEL_UNKNOWN
      Constant for an unknown level.
      See Also:
    • currentData

      private final TreeData currentData
      Stores the current tree data of the calling node model.
    • queryRoot

      private final ImmutableNode queryRoot
      The root node for query operations.
    • rootNodeSelector

      private final NodeSelector rootNodeSelector
      The selector to the root node of this transaction.
    • resolver

      private final NodeKeyResolver<ImmutableNode> resolver
      The NodeKeyResolver to be used for this transaction.
    • replacementMapping

      private final Map<ImmutableNode,ImmutableNode> replacementMapping
      A new replacement mapping.
    • replacedNodes

      private final Map<ImmutableNode,ImmutableNode> replacedNodes
      The nodes replaced in this transaction.
    • parentMapping

      private final Map<ImmutableNode,ImmutableNode> parentMapping
      A new parent mapping.
    • addedNodes

      private final Collection<ImmutableNode> addedNodes
      A collection with nodes which have been added.
    • removedNodes

      private final Collection<ImmutableNode> removedNodes
      A collection with nodes which have been removed.
    • allRemovedNodes

      private final Collection<ImmutableNode> allRemovedNodes
      Stores all nodes which have been removed in this transaction (not only the root nodes of removed trees).
    • operations

      Stores the operations to be executed during this transaction. The map is sorted by the levels of the nodes to be manipulated: Operations on nodes down in the hierarchy are executed first because they affect the nodes closer to the root.
    • newReferences

      private Map<ImmutableNode,Object> newReferences
      A map with reference objects to be added during this transaction.
    • newRoot

      private ImmutableNode newRoot
      The new root node.
  • Constructor Details

    • ModelTransaction

      public ModelTransaction(TreeData treeData, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver)
      Creates a new instance of ModelTransaction for the current tree data.
      Parameters:
      treeData - the current TreeData structure to operate on
      selector - an optional NodeSelector defining the target root node for this transaction; this can be used to perform operations on tracked nodes
      resolver - the NodeKeyResolver
  • Method Details

    • append

      private static <E> Collection<E> append(Collection<E> col, E node)
      Appends a single element to a collection. The collection may be null, then it is created.
      Type Parameters:
      E - the type of elements involved
      Parameters:
      col - the collection
      node - the element to be added
      Returns:
      the resulting collection
    • append

      private static <K, V> Map<K,V> append(Map<K,V> map, K key, V value)
      Adds a single key-value pair to a map. The map may be null, then it is created.
      Type Parameters:
      K - the type of the key
      V - the type of the value
      Parameters:
      map - the map
      key - the key
      value - the value
      Returns:
      the resulting map
    • append

      private static <E> Set<E> append(Set<E> col, E elem)
      Appends a single element to a set. The set may be null then it is created.
      Type Parameters:
      E - the type of the elements involved
      Parameters:
      col - the set
      elem - the element to be added
      Returns:
      the resulting set
    • concatenate

      private static <E> Collection<E> concatenate(Collection<E> col1, Collection<? extends E> col2)
      Constructs the concatenation of two collections. Both can be null.
      Type Parameters:
      E - the type of the elements involved
      Parameters:
      col1 - the first collection
      col2 - the second collection
      Returns:
      the resulting collection
    • concatenate

      private static <K, V> Map<K,V> concatenate(Map<K,V> map1, Map<? extends K,? extends V> map2)
      Constructs the concatenation of two maps. Both can be null.
      Type Parameters:
      K - the type of the keys
      V - the type of the values
      Parameters:
      map1 - the first map
      map2 - the second map
      Returns:
      the resulting map
    • concatenate

      private static <E> Set<E> concatenate(Set<E> set1, Set<? extends E> set2)
      Constructs the concatenation of two sets. Both can be null.
      Type Parameters:
      E - the type of the elements involved
      Parameters:
      set1 - the first set
      set2 - the second set
      Returns:
      the resulting set
    • addAddNodeOperation

      public void addAddNodeOperation(ImmutableNode parent, ImmutableNode newChild)
      Adds an operation for adding a new child to a given parent node.
      Parameters:
      parent - the parent node
      newChild - the new child to be added
    • addAddNodesOperation

      public void addAddNodesOperation(ImmutableNode parent, Collection<? extends ImmutableNode> newNodes)
      Adds an operation for adding a number of new children to a given parent node.
      Parameters:
      parent - the parent node
      newNodes - the collection of new child nodes
    • addAttributeOperation

      public void addAttributeOperation(ImmutableNode target, String name, Object value)
      Adds an operation for adding an attribute to a target node.
      Parameters:
      target - the target node
      name - the name of the attribute
      value - the value of the attribute
    • addAttributesOperation

      public void addAttributesOperation(ImmutableNode target, Map<String,Object> attributes)
      Adds an operation for adding multiple attributes to a target node.
      Parameters:
      target - the target node
      attributes - the map with attributes to be set
    • addChangeNodeNameOperation

      public void addChangeNodeNameOperation(ImmutableNode target, String newName)
      Adds an operation for changing the name of a target node.
      Parameters:
      target - the target node
      newName - the new name for this node
    • addChangeNodeValueOperation

      public void addChangeNodeValueOperation(ImmutableNode target, Object newValue)
      Adds an operation for changing the value of a target node.
      Parameters:
      target - the target node
      newValue - the new value for this node
    • addClearNodeValueOperation

      public void addClearNodeValueOperation(ImmutableNode target)
      Adds an operation for clearing the value of a target node.
      Parameters:
      target - the target node
    • addNewReference

      public void addNewReference(ImmutableNode node, Object ref)
      Adds a new reference object for the given node.
      Parameters:
      node - the affected node
      ref - the reference object for this node
    • addNewReferences

      public void addNewReferences(Map<ImmutableNode,?> refs)
      Adds a map with new reference objects. The entries in this map are passed to the ReferenceTracker during execution of this transaction.
      Parameters:
      refs - the map with new reference objects
    • addRemoveAttributeOperation

      public void addRemoveAttributeOperation(ImmutableNode target, String name)
      Adds an operation for removing an attribute from a target node.
      Parameters:
      target - the target node
      name - the name of the attribute
    • addRemoveNodeOperation

      public void addRemoveNodeOperation(ImmutableNode parent, ImmutableNode node)
      Adds an operation for removing a child node of a given node.
      Parameters:
      parent - the parent node
      node - the child node to be removed
    • execute

      public TreeData execute()
      Executes this transaction resulting in a new TreeData object. The object returned by this method serves as the definition of a new node structure for the calling model.
      Returns:
      the updated TreeData
    • executeOperations

      private void executeOperations()
      Executes all operations in this transaction.
    • fetchOperations

      ModelTransaction.Operations fetchOperations(ImmutableNode target, int level)
      Obtains the Operations object for manipulating the specified node. If no such object exists yet, it is created. The level can be undefined, then it is determined based on the target node.
      Parameters:
      target - the target node
      level - the level of the target node (may be undefined)
      Returns:
      the Operations object for this node
    • fetchReferenceMap

      private Map<ImmutableNode,Object> fetchReferenceMap()
      Returns the map with new reference objects. It is created if necessary.
      Returns:
      the map with reference objects
    • getCurrentData

      public TreeData getCurrentData()
      Gets the current TreeData object this transaction operates on.
      Returns:
      the associated TreeData object
    • getParent

      ImmutableNode getParent(ImmutableNode node)
      Gets the parent node of the given node.
      Parameters:
      node - the node in question
      Returns:
      the parent of this node
    • getQueryRoot

      public ImmutableNode getQueryRoot()
      Gets the root node to be used within queries. This is not necessarily the current root node of the model. If the operation is executed on a tracked node, this node has to be passed as root nodes to the expression engine.
      Returns:
      the root node for queries and calls to the expression engine
    • getResolver

      public NodeKeyResolver<ImmutableNode> getResolver()
      Gets the NodeKeyResolver used by this transaction.
      Returns:
      the NodeKeyResolver
    • initQueryRoot

      private ImmutableNode initQueryRoot(TreeData treeData, NodeSelector selector)
      Initializes the root node to be used within queries. If a tracked node selector is provided, this node becomes the root node. Otherwise, the actual root node is used.
      Parameters:
      treeData - the current data of the model
      selector - an optional NodeSelector defining the target root
      Returns:
      the query root node for this transaction
    • level

      private int level(ImmutableNode node)
      Determines the level of the specified node in the current hierarchy. The level of the root node is 0, the children of the root have level 1 and so on.
      Parameters:
      node - the node in question
      Returns:
      the level of this node
    • rebuildParentMapping

      private void rebuildParentMapping()
      Rebuilds the parent mapping from scratch. This method is called if the replacement mapping exceeds its maximum size. In this case, it is cleared, and a new parent mapping is constructed for the new root node.
    • removeNodeFromReplacementMapping

      private void removeNodeFromReplacementMapping(ImmutableNode node)
      Removes the specified node completely from the replacement mapping. This also includes the nodes that replace the given one.
      Parameters:
      node - the node to be removed
    • removeNodesFromParentAndReplacementMapping

      private void removeNodesFromParentAndReplacementMapping(ImmutableNode root)
      Removes a node and its children (recursively) from the parent and the replacement mappings.
      Parameters:
      root - the root of the subtree to be removed
    • updateParentMapping

      private void updateParentMapping()
      Updates the parent mapping for the resulting TreeData instance. This method is called after all update operations have been executed. It ensures that the parent mapping is updated for the changes on the nodes structure.
    • updateParentMappingForAddedNodes

      private void updateParentMappingForAddedNodes()
      Adds newly added nodes and their children to the parent mapping.
    • updateParentMappingForRemovedNodes

      private void updateParentMappingForRemovedNodes()
      Removes nodes that have been removed during this transaction from the parent and replacement mappings.
    • updateReferenceTracker

      private ReferenceTracker updateReferenceTracker()
      Returns an updated ReferenceTracker instance. The changes performed during this transaction are applied to the tracker.
      Returns:
      the updated tracker instance