Class ModelTransaction
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.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static class
A specialized operation class for adding an attribute to a target node.private static class
A specialized operation class for adding multiple attributes to a target node.private static class
A specialized operation class which changes the name of a node.private static class
A specialized operation class which changes the value of a node.private class
A specializedOperation
implementation for replacing the children of a target node.private static class
An abstract base class representing an operation to be performed on a node.private class
A helper class which collects multiple update operations to be executed on a single node.private static class
A specialized operation class for removing an attribute from a target node. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final Collection<ImmutableNode>
A collection with nodes which have been added.private final Collection<ImmutableNode>
Stores all nodes which have been removed in this transaction (not only the root nodes of removed trees).private final TreeData
Stores the current tree data of the calling node model.private static final int
Constant for an unknown level.private static final int
Constant for the maximum number of entries in the replacement mapping.private Map<ImmutableNode,
Object> A map with reference objects to be added during this transaction.private ImmutableNode
The new root node.private final SortedMap<Integer,
Map<ImmutableNode, ModelTransaction.Operations>> Stores the operations to be executed during this transaction.private final Map<ImmutableNode,
ImmutableNode> A new parent mapping.private final ImmutableNode
The root node for query operations.private final Collection<ImmutableNode>
A collection with nodes which have been removed.private final Map<ImmutableNode,
ImmutableNode> The nodes replaced in this transaction.private final Map<ImmutableNode,
ImmutableNode> A new replacement mapping.private final NodeKeyResolver<ImmutableNode>
TheNodeKeyResolver
to be used for this transaction.private final NodeSelector
The selector to the root node of this transaction. -
Constructor Summary
ConstructorsConstructorDescriptionModelTransaction
(TreeData treeData, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Creates a new instance ofModelTransaction
for the current tree data. -
Method Summary
Modifier and TypeMethodDescriptionvoid
addAddNodeOperation
(ImmutableNode parent, ImmutableNode newChild) Adds an operation for adding a new child to a given parent node.void
addAddNodesOperation
(ImmutableNode parent, Collection<? extends ImmutableNode> newNodes) Adds an operation for adding a number of new children to a given parent node.void
addAttributeOperation
(ImmutableNode target, String name, Object value) Adds an operation for adding an attribute to a target node.void
addAttributesOperation
(ImmutableNode target, Map<String, Object> attributes) Adds an operation for adding multiple attributes to a target node.void
addChangeNodeNameOperation
(ImmutableNode target, String newName) Adds an operation for changing the name of a target node.void
addChangeNodeValueOperation
(ImmutableNode target, Object newValue) Adds an operation for changing the value of a target node.void
Adds an operation for clearing the value of a target node.void
addNewReference
(ImmutableNode node, Object ref) Adds a new reference object for the given node.void
addNewReferences
(Map<ImmutableNode, ?> refs) Adds a map with new reference objects.void
addRemoveAttributeOperation
(ImmutableNode target, String name) Adds an operation for removing an attribute from a target node.void
addRemoveNodeOperation
(ImmutableNode parent, ImmutableNode node) Adds an operation for removing a child node of a given node.private static <E> Collection<E>
append
(Collection<E> col, E node) Appends a single element to a collection.private static <K,
V> Map<K, V> Adds a single key-value pair to a map.private static <E> Set<E>
Appends a single element to a set.private static <E> Collection<E>
concatenate
(Collection<E> col1, Collection<? extends E> col2) Constructs the concatenation of two collections.private static <K,
V> Map<K, V> concatenate
(Map<K, V> map1, Map<? extends K, ? extends V> map2) Constructs the concatenation of two maps.private static <E> Set<E>
concatenate
(Set<E> set1, Set<? extends E> set2) Constructs the concatenation of two sets.execute()
Executes this transaction resulting in a newTreeData
object.private void
Executes all operations in this transaction.(package private) ModelTransaction.Operations
fetchOperations
(ImmutableNode target, int level) Obtains theOperations
object for manipulating the specified node.private Map<ImmutableNode,
Object> Returns the map with new reference objects.Gets the currentTreeData
object this transaction operates on.(package private) ImmutableNode
getParent
(ImmutableNode node) Gets the parent node of the given node.Gets the root node to be used within queries.Gets theNodeKeyResolver
used by this transaction.private ImmutableNode
initQueryRoot
(TreeData treeData, NodeSelector selector) Initializes the root node to be used within queries.private int
level
(ImmutableNode node) Determines the level of the specified node in the current hierarchy.private void
Rebuilds the parent mapping from scratch.private void
Removes the specified node completely from the replacement mapping.private void
Removes a node and its children (recursively) from the parent and the replacement mappings.private void
Updates the parent mapping for the resultingTreeData
instance.private void
Adds newly added nodes and their children to the parent mapping.private void
Removes nodes that have been removed during this transaction from the parent and replacement mappings.private ReferenceTracker
Returns an updatedReferenceTracker
instance.
-
Field Details
-
MAX_REPLACEMENTS
private static final int MAX_REPLACEMENTSConstant 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_UNKNOWNConstant for an unknown level.- See Also:
-
currentData
Stores the current tree data of the calling node model. -
queryRoot
The root node for query operations. -
rootNodeSelector
The selector to the root node of this transaction. -
resolver
TheNodeKeyResolver
to be used for this transaction. -
replacementMapping
A new replacement mapping. -
replacedNodes
The nodes replaced in this transaction. -
parentMapping
A new parent mapping. -
addedNodes
A collection with nodes which have been added. -
removedNodes
A collection with nodes which have been removed. -
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
A map with reference objects to be added during this transaction. -
newRoot
The new root node.
-
-
Constructor Details
-
ModelTransaction
public ModelTransaction(TreeData treeData, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Creates a new instance ofModelTransaction
for the current tree data.- Parameters:
treeData
- the currentTreeData
structure to operate onselector
- an optionalNodeSelector
defining the target root node for this transaction; this can be used to perform operations on tracked nodesresolver
- theNodeKeyResolver
-
-
Method Details
-
getResolver
Gets theNodeKeyResolver
used by this transaction.- Returns:
- the
NodeKeyResolver
-
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
-
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 nodenewNodes
- the collection of new child nodes
-
addAddNodeOperation
Adds an operation for adding a new child to a given parent node.- Parameters:
parent
- the parent nodenewChild
- the new child to be added
-
addAttributeOperation
Adds an operation for adding an attribute to a target node.- Parameters:
target
- the target nodename
- the name of the attributevalue
- the value of the attribute
-
addAttributesOperation
Adds an operation for adding multiple attributes to a target node.- Parameters:
target
- the target nodeattributes
- the map with attributes to be set
-
addRemoveNodeOperation
Adds an operation for removing a child node of a given node.- Parameters:
parent
- the parent nodenode
- the child node to be removed
-
addRemoveAttributeOperation
Adds an operation for removing an attribute from a target node.- Parameters:
target
- the target nodename
- the name of the attribute
-
addClearNodeValueOperation
Adds an operation for clearing the value of a target node.- Parameters:
target
- the target node
-
addChangeNodeValueOperation
Adds an operation for changing the value of a target node.- Parameters:
target
- the target nodenewValue
- the new value for this node
-
addChangeNodeNameOperation
Adds an operation for changing the name of a target node.- Parameters:
target
- the target nodenewName
- the new name for this node
-
addNewReferences
Adds a map with new reference objects. The entries in this map are passed to theReferenceTracker
during execution of this transaction.- Parameters:
refs
- the map with new reference objects
-
addNewReference
Adds a new reference object for the given node.- Parameters:
node
- the affected noderef
- the reference object for this node
-
execute
Executes this transaction resulting in a newTreeData
object. The object returned by this method serves as the definition of a new node structure for the calling model.- Returns:
- the updated
TreeData
-
getCurrentData
Gets the currentTreeData
object this transaction operates on.- Returns:
- the associated
TreeData
object
-
getParent
Gets the parent node of the given node.- Parameters:
node
- the node in question- Returns:
- the parent of this node
-
fetchOperations
Obtains theOperations
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 nodelevel
- the level of the target node (may be undefined)- Returns:
- the
Operations
object for this node
-
initQueryRoot
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 modelselector
- an optionalNodeSelector
defining the target root- Returns:
- the query root node for this transaction
-
level
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
-
executeOperations
private void executeOperations()Executes all operations in this transaction. -
updateParentMapping
private void updateParentMapping()Updates the parent mapping for the resultingTreeData
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. -
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. -
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. -
removeNodesFromParentAndReplacementMapping
Removes a node and its children (recursively) from the parent and the replacement mappings.- Parameters:
root
- the root of the subtree to be removed
-
removeNodeFromReplacementMapping
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
-
updateReferenceTracker
Returns an updatedReferenceTracker
instance. The changes performed during this transaction are applied to the tracker.- Returns:
- the updated tracker instance
-
fetchReferenceMap
Returns the map with new reference objects. It is created if necessary.- Returns:
- the map with reference objects
-
concatenate
Constructs the concatenation of two collections. Both can be null.- Type Parameters:
E
- the type of the elements involved- Parameters:
col1
- the first collectioncol2
- the second collection- Returns:
- the resulting collection
-
concatenate
Constructs the concatenation of two sets. Both can be null.- Type Parameters:
E
- the type of the elements involved- Parameters:
set1
- the first setset2
- the second set- Returns:
- the resulting set
-
concatenate
Constructs the concatenation of two maps. Both can be null.- Type Parameters:
K
- the type of the keysV
- the type of the values- Parameters:
map1
- the first mapmap2
- the second map- Returns:
- the resulting map
-
append
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 collectionnode
- the element to be added- Returns:
- the resulting collection
-
append
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 setelem
- the element to be added- Returns:
- the resulting set
-
append
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 keyV
- the type of the value- Parameters:
map
- the mapkey
- the keyvalue
- the value- Returns:
- the resulting map
-