Class InMemoryNodeModel
java.lang.Object
org.apache.commons.configuration2.tree.InMemoryNodeModel
- All Implemented Interfaces:
NodeModel<ImmutableNode>
A specialized node model implementation which operates on ImmutableNode
structures.
This NodeModel
implementation keeps all its data as a tree of ImmutableNode
objects in memory. The
managed structure can be manipulated in a thread-safe, non-blocking way. This is achieved by using atomic variables:
The root of the tree is stored in an atomic reference variable. Each update operation causes a new structure to be
constructed (which reuses as much from the original structure as possible). The old root node is then replaced by the
new one using an atomic compare-and-set operation. If this fails, the manipulation has to be done anew on the updated
structure.
- Since:
- 2.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static interface
An interface used internally for handling concurrent updates. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final NodeHandler
<ImmutableNode> A dummy node handler instance used in operations which require only a limited functionality.private final AtomicReference
<TreeData> Stores information about the current nodes structure. -
Constructor Summary
ConstructorsConstructorDescriptionCreates a new instance ofInMemoryNodeModel
which is initialized with an empty root node.Creates a new instance ofInMemoryNodeModel
and initializes it from the given root node. -
Method Summary
Modifier and TypeMethodDescriptionprivate static void
addAttributeProperty
(ModelTransaction tx, NodeAddData<ImmutableNode> addData, Iterable<?> values) Handles an add property operation if the property to be added is an attribute.private static void
addNodeProperty
(ModelTransaction tx, NodeAddData<ImmutableNode> addData, Iterable<?> values) Handles an add property operation if the property to be added is a node.void
addNodes
(String key, Collection<? extends ImmutableNode> nodes, NodeKeyResolver<ImmutableNode> resolver) Adds a collection of new nodes to this model.void
addNodes
(String key, NodeSelector selector, Collection<? extends ImmutableNode> nodes, NodeKeyResolver<ImmutableNode> resolver) Adds new nodes using a tracked node as root node.private static void
addNodesByAddData
(ModelTransaction tx, NodeAddData<ImmutableNode> addData, Collection<ImmutableNode> newNodes) Initializes a transaction to add a collection of nodes as described by aNodeAddData
object.void
addProperty
(String key, Iterable<?> values, NodeKeyResolver<ImmutableNode> resolver) Adds a new property to this node model consisting of an arbitrary number of values.void
addProperty
(String key, NodeSelector selector, Iterable<?> values, NodeKeyResolver<ImmutableNode> resolver) Adds new property values using a tracked node as root node.private static IllegalArgumentException
Creates an exception referring to an invalid key for adding properties.(package private) static boolean
Checks if the passed in node is defined.void
clear
(NodeKeyResolver<ImmutableNode> resolver) Removes all data from this model.void
clearProperty
(String key, NodeKeyResolver<ImmutableNode> resolver) Clears the value of a property.void
clearProperty
(String key, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Clears a property using a tracked node as root node.clearTree
(String key, NodeKeyResolver<ImmutableNode> resolver) Removes the sub trees defined by the given key from this model.clearTree
(String key, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Clears a whole sub tree using a tracked node as root node.private static TreeData
createDataWithTrackedChildNode
(TreeData current, ImmutableNode parent, String childName, NodeKeyResolver<ImmutableNode> resolver, org.apache.commons.lang3.mutable.MutableObject<NodeSelector> refSelector) Creates a new data object with a tracked child node of the given parent node.private static ImmutableNode
createNodeOnPath
(Iterator<String> it, Collection<ImmutableNode> newNodes) Recursive helper method for creating a path node for an add operation.private static Collection
<ImmutableNode> createNodesToAdd
(String newNodeName, Iterable<?> values) Creates a collection with new nodes with a given name and a value from a given collection.private static ImmutableNode
createNodeToAddWithPath
(NodeAddData<ImmutableNode> addData, Collection<ImmutableNode> newNodes) Creates a node structure consisting of the path nodes defined by the passed inNodeAddData
instance and all new child nodes.private Map
<ImmutableNode, ImmutableNode> Creates the mapping to parent nodes for the nodes structured represented by the passed in root node.private static TreeData
createSelectorsForTrackedNodes
(org.apache.commons.lang3.mutable.Mutable<Collection<NodeSelector>> refSelectors, List<ImmutableNode> nodes, TreeData current, NodeKeyResolver<ImmutableNode> resolver) Creates tracked node entries for the specified nodes and creates the corresponding selectors.private TreeData
createTreeData
(ImmutableNode root, TreeData current) Creates aTreeData
object for the specified root node.private TreeData
createTreeDataForRootAndTracker
(ImmutableNode root, NodeTracker newTracker) Creates aTreeData
object for the specified root node andNodeTracker
.private static String
determineRootName
(ImmutableNode rootNode, ImmutableNode node, String rootName) Determines the name of the root node for a merge operation.private boolean
executeTransactionOnCurrentStructure
(InMemoryNodeModel.TransactionInitializer txInit, NodeSelector selector, TreeData currentData, NodeKeyResolver<ImmutableNode> resolver) Executes a transaction on the current data of this model.private boolean
executeTransactionOnDetachedTrackedNode
(InMemoryNodeModel.TransactionInitializer txInit, NodeSelector selector, TreeData currentData, NodeKeyResolver<ImmutableNode> resolver) Tries to execute a transaction on the model of a detached tracked node.Gets a representation of the data stored in this model in form of a nodes hierarchy ofImmutableNode
objects.Gets aNodeHandler
for dealing with the nodes managed by this model.Gets aReferenceNodeHandler
object for this model.Gets the root node of this mode.getTrackedNode
(NodeSelector selector) Gets the currentImmutableNode
instance associated with the givenNodeSelector
.getTrackedNodeHandler
(NodeSelector selector) Gets aNodeHandler
for a tracked node.(package private) TreeData
Gets the currentTreeData
object.private void
initializeAddTransaction
(ModelTransaction tx, String key, Iterable<?> values, NodeKeyResolver<ImmutableNode> resolver) Initializes a transaction for an add operation.private static boolean
initializeClearTransaction
(ModelTransaction tx, Collection<QueryResult<ImmutableNode>> results) Initializes a transaction to clear the values of a property based on the passed in collection of affected results.private static boolean
initializeUpdateTransaction
(ModelTransaction tx, Map<QueryResult<ImmutableNode>, Object> changedValues) Initializes a transaction to change the values of some query results based on the passed in map.private static ImmutableNode
initialRootNode
(ImmutableNode providedRoot) Determines the initial root node of this model.boolean
isTrackedNodeDetached
(NodeSelector selector) Returns a flag whether the specified tracked node is detached.void
mergeRoot
(ImmutableNode node, String rootName, Map<ImmutableNode, ?> references, Object rootRef, NodeKeyResolver<ImmutableNode> resolver) Merges the root node of this model with the specified node.private boolean
replaceActiveTrackedNode
(TreeData currentData, NodeSelector selector, ImmutableNode newNode) Replaces an active tracked node.private boolean
replaceDetachedTrackedNode
(TreeData currentData, NodeSelector selector, ImmutableNode newNode) Replaces a tracked node if it is already detached.void
replaceRoot
(ImmutableNode newRoot, NodeKeyResolver<ImmutableNode> resolver) Replaces the root node of this model.void
replaceTrackedNode
(NodeSelector selector, ImmutableNode newNode) Replaces a tracked node by another node.selectAndTrackNodes
(String key, NodeKeyResolver<ImmutableNode> resolver) Allows tracking all nodes selected by a key.void
setProperty
(String key, Object value, NodeKeyResolver<ImmutableNode> resolver) Changes the value of a property.void
setProperty
(String key, NodeSelector selector, Object value, NodeKeyResolver<ImmutableNode> resolver) Sets the value of a property using a tracked node as root node.void
setRootNode
(ImmutableNode newRoot) Sets a new root node for this model.trackChildNodes
(String key, NodeKeyResolver<ImmutableNode> resolver) Tracks all nodes which are children of the node selected by the passed in key.trackChildNodeWithCreation
(String key, String childName, NodeKeyResolver<ImmutableNode> resolver) Tracks a node which is a child of another node selected by the passed in key.void
trackNode
(NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Adds a node to be tracked.void
untrackNode
(NodeSelector selector) Removes a tracked node.private static TreeData
updateDataWithNewTrackedNode
(TreeData current, ImmutableNode node, NodeKeyResolver<ImmutableNode> resolver, org.apache.commons.lang3.mutable.MutableObject<NodeSelector> refSelector) Adds a tracked node that has already been resolved to the specified data object.private void
updateModel
(InMemoryNodeModel.TransactionInitializer txInit, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Performs a non-blocking, thread-safe update of this model based on a transaction initialized by the passed in initializer.(package private) static void
updateParentMapping
(Map<ImmutableNode, ImmutableNode> parents, ImmutableNode root) Updates the mapping from nodes to their parents for the passed in hierarchy of nodes.private static boolean
valuesNotEmpty
(Iterable<?> values) Checks whether the specified collection with values is not empty.
-
Field Details
-
DUMMY_HANDLER
A dummy node handler instance used in operations which require only a limited functionality. -
structure
Stores information about the current nodes structure.
-
-
Constructor Details
-
InMemoryNodeModel
public InMemoryNodeModel()Creates a new instance ofInMemoryNodeModel
which is initialized with an empty root node. -
InMemoryNodeModel
Creates a new instance ofInMemoryNodeModel
and initializes it from the given root node. If the passed in node is null, a new, empty root node is created.- Parameters:
root
- the new root node for this model
-
-
Method Details
-
addAttributeProperty
private static void addAttributeProperty(ModelTransaction tx, NodeAddData<ImmutableNode> addData, Iterable<?> values) Handles an add property operation if the property to be added is an attribute.- Parameters:
tx
- the transactionaddData
- theNodeAddData
values
- the collection with node values
-
addNodeProperty
private static void addNodeProperty(ModelTransaction tx, NodeAddData<ImmutableNode> addData, Iterable<?> values) Handles an add property operation if the property to be added is a node.- Parameters:
tx
- the transactionaddData
- theNodeAddData
values
- the collection with node values
-
addNodesByAddData
private static void addNodesByAddData(ModelTransaction tx, NodeAddData<ImmutableNode> addData, Collection<ImmutableNode> newNodes) Initializes a transaction to add a collection of nodes as described by aNodeAddData
object. If necessary, new path nodes are created. Eventually, the new nodes are added as children to the specified target node.- Parameters:
tx
- the transactionaddData
- theNodeAddData
newNodes
- the collection of new child nodes
-
attributeKeyException
Creates an exception referring to an invalid key for adding properties. Such an exception is thrown when an operation tries to add something to an attribute.- Parameters:
key
- the invalid key causing this exception- Returns:
- the exception
-
checkIfNodeDefined
Checks if the passed in node is defined. Result is true if the node contains any data.- Parameters:
node
- the node in question- Returns:
- true if the node is defined, false otherwise
-
createDataWithTrackedChildNode
private static TreeData createDataWithTrackedChildNode(TreeData current, ImmutableNode parent, String childName, NodeKeyResolver<ImmutableNode> resolver, org.apache.commons.lang3.mutable.MutableObject<NodeSelector> refSelector) Creates a new data object with a tracked child node of the given parent node. If such a child node already exists, it is used. Otherwise, a new one is created.- Parameters:
current
- the currentTreeData
objectparent
- the parent nodechildName
- the name of the child noderesolver
- theNodeKeyResolver
refSelector
- here the newly createdNodeSelector
is returned- Returns:
- the new
TreeData
instance
-
createNodeOnPath
private static ImmutableNode createNodeOnPath(Iterator<String> it, Collection<ImmutableNode> newNodes) Recursive helper method for creating a path node for an add operation. All path nodes except for the last have a single child. The last path node has the new nodes as children.- Parameters:
it
- the iterator over the names of the path nodesnewNodes
- the collection of new child nodes- Returns:
- the newly created path node
-
createNodesToAdd
Creates a collection with new nodes with a given name and a value from a given collection.- Parameters:
newNodeName
- the name of the new nodesvalues
- the collection with node values- Returns:
- the newly created collection
-
createNodeToAddWithPath
private static ImmutableNode createNodeToAddWithPath(NodeAddData<ImmutableNode> addData, Collection<ImmutableNode> newNodes) Creates a node structure consisting of the path nodes defined by the passed inNodeAddData
instance and all new child nodes.- Parameters:
addData
- theNodeAddData
newNodes
- the collection of new child nodes- Returns:
- the parent node of the newly created hierarchy
-
createSelectorsForTrackedNodes
private static TreeData createSelectorsForTrackedNodes(org.apache.commons.lang3.mutable.Mutable<Collection<NodeSelector>> refSelectors, List<ImmutableNode> nodes, TreeData current, NodeKeyResolver<ImmutableNode> resolver) Creates tracked node entries for the specified nodes and creates the corresponding selectors.- Parameters:
refSelectors
- the reference where to store the selectorsnodes
- the nodes to be trackedcurrent
- the currentTreeData
objectresolver
- theNodeKeyResolver
- Returns:
- the updated
TreeData
object
-
determineRootName
private static String determineRootName(ImmutableNode rootNode, ImmutableNode node, String rootName) Determines the name of the root node for a merge operation. If a root name is provided, it is used. Otherwise, if the current root node has no name, the name of the node to be merged is used. A result of null means that no node name has to be set.- Parameters:
rootNode
- the current root nodenode
- the node to be merged with the root noderootName
- the name of the resulting node- Returns:
- the new name of the root node
-
initializeClearTransaction
private static boolean initializeClearTransaction(ModelTransaction tx, Collection<QueryResult<ImmutableNode>> results) Initializes a transaction to clear the values of a property based on the passed in collection of affected results.- Parameters:
tx
- the transaction to be initializedresults
- a collection with results pointing to the nodes to be cleared- Returns:
- a flag whether there are elements to be cleared
-
initializeUpdateTransaction
private static boolean initializeUpdateTransaction(ModelTransaction tx, Map<QueryResult<ImmutableNode>, Object> changedValues) Initializes a transaction to change the values of some query results based on the passed in map.- Parameters:
tx
- the transaction to be initializedchangedValues
- the map defining the elements to be changed- Returns:
- a flag whether there are elements to be updated
-
initialRootNode
Determines the initial root node of this model. If a root node has been provided, it is used. Otherwise, an empty dummy root node is created.- Parameters:
providedRoot
- the passed in root node- Returns:
- the root node to be used
-
updateDataWithNewTrackedNode
private static TreeData updateDataWithNewTrackedNode(TreeData current, ImmutableNode node, NodeKeyResolver<ImmutableNode> resolver, org.apache.commons.lang3.mutable.MutableObject<NodeSelector> refSelector) Adds a tracked node that has already been resolved to the specified data object.- Parameters:
current
- the currentTreeData
objectnode
- the node in questionresolver
- theNodeKeyResolver
refSelector
- here the newly createdNodeSelector
is returned- Returns:
- the new
TreeData
instance
-
updateParentMapping
Updates the mapping from nodes to their parents for the passed in hierarchy of nodes. This method traverses all children and grand-children of the passed in root node. For each node in the subtree the parent relation is added to the map.- Parameters:
parents
- the map with parent nodesroot
- the root node of the current tree
-
valuesNotEmpty
Checks whether the specified collection with values is not empty.- Parameters:
values
- the collection with node values- Returns:
- true if values are provided, false otherwise
-
addNodes
public void addNodes(String key, Collection<? extends ImmutableNode> nodes, NodeKeyResolver<ImmutableNode> resolver) Description copied from interface:NodeModel
Adds a collection of new nodes to this model. This operation corresponds to theaddNodes()
method of theHierarchicalConfiguration
interface. The new nodes are either added to an existing node (if the passed in key selects exactly one node) or to a newly created node. The passed inNodeKeyResolver
is used to interpret the given key.- Specified by:
addNodes
in interfaceNodeModel<ImmutableNode>
- Parameters:
key
- the keynodes
- the collection of nodes to be added (may be null)resolver
- theNodeKeyResolver
-
addNodes
public void addNodes(String key, NodeSelector selector, Collection<? extends ImmutableNode> nodes, NodeKeyResolver<ImmutableNode> resolver) Adds new nodes using a tracked node as root node. This method works like the normaladdNodes()
method, but the origin of the operation (also for the interpretation of the passed in key) is a tracked node identified by the passed inNodeSelector
. The selector can be null, then the root node is assumed.- Parameters:
key
- the keyselector
- theNodeSelector
defining the root node (or null)nodes
- the collection of new nodes to be addedresolver
- theNodeKeyResolver
- Throws:
ConfigurationRuntimeException
- if the selector cannot be resolved
-
addProperty
Description copied from interface:NodeModel
Adds a new property to this node model consisting of an arbitrary number of values. The key for the add operation is provided. For each value a new node has to be added. The passed in resolver is queried for aNodeAddData
object defining the add operation to be performed.- Specified by:
addProperty
in interfaceNodeModel<ImmutableNode>
- Parameters:
key
- the keyvalues
- the values to be added at the position defined by the keyresolver
- theNodeKeyResolver
-
addProperty
public void addProperty(String key, NodeSelector selector, Iterable<?> values, NodeKeyResolver<ImmutableNode> resolver) Adds new property values using a tracked node as root node. This method works like the normaladdProperty()
method, but the origin of the operation (also for the interpretation of the passed in key) is a tracked node identified by the passed inNodeSelector
. The selector can be null, then the root node is assumed.- Parameters:
key
- the keyselector
- theNodeSelector
defining the root node (or null)values
- the values to be addedresolver
- theNodeKeyResolver
- Throws:
ConfigurationRuntimeException
- if the selector cannot be resolved
-
clear
Removes all data from this model. A new empty root node is created with the same name as the current root node. Implementation note: Because this is a hard reset the usual dance for dealing with concurrent updates is not required here.- Specified by:
clear
in interfaceNodeModel<ImmutableNode>
- Parameters:
resolver
- theNodeKeyResolver
-
clearProperty
Clears the value of a property. This method is similar toNodeModel.clearTree(String, NodeKeyResolver)
: However, the nodes referenced by the passed in key are not removed completely, but only their value is set to null. If this operation leaves an affected node in an undefined state, it is removed from the model.- Specified by:
clearProperty
in interfaceNodeModel<ImmutableNode>
- Parameters:
key
- the key selecting the properties to be clearedresolver
- theNodeKeyResolver
-
clearProperty
public void clearProperty(String key, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Clears a property using a tracked node as root node. This method works like the normalclearProperty()
method, but the origin of the operation (also for the interpretation of the passed in key) is a tracked node identified by the passed inNodeSelector
. The selector can be null, then the root node is assumed.- Parameters:
key
- the keyselector
- theNodeSelector
defining the root node (or null)resolver
- theNodeKeyResolver
- Throws:
ConfigurationRuntimeException
- if the selector cannot be resolved
-
clearTree
public List<QueryResult<ImmutableNode>> clearTree(String key, NodeKeyResolver<ImmutableNode> resolver) Removes the sub trees defined by the given key from this model. All nodes selected by this key are retrieved from the specifiedNodeKeyResolver
and removed from the model. This implementation checks whether nodes become undefined after subtrees have been removed. If this is the case, such nodes are removed, too. Return value is a collection withQueryResult
objects for the elements to be removed from the model.- Specified by:
clearTree
in interfaceNodeModel<ImmutableNode>
- Parameters:
key
- the key selecting the properties to be removedresolver
- theNodeKeyResolver
- Returns:
- an object with information about the data removed
-
clearTree
public List<QueryResult<ImmutableNode>> clearTree(String key, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Clears a whole sub tree using a tracked node as root node. This method works like the normalclearTree()
method, but the origin of the operation (also for the interpretation of the passed in key) is a tracked node identified by the passed inNodeSelector
. The selector can be null, then the root node is assumed.- Parameters:
key
- the keyselector
- theNodeSelector
defining the root node (or null)resolver
- theNodeKeyResolver
- Returns:
- a list with the results to be removed
- Throws:
ConfigurationRuntimeException
- if the selector cannot be resolved
-
createParentMapping
Creates the mapping to parent nodes for the nodes structured represented by the passed in root node. Each node is assigned its parent node. Here an iterative algorithm is used rather than a recursive one to avoid stack overflow for huge structures.- Parameters:
root
- the root node of the structure- Returns:
- the parent node mapping
-
createTreeData
Creates aTreeData
object for the specified root node.- Parameters:
root
- the root node of the current treecurrent
- the currentTreeData
object (may be null)- Returns:
- the
TreeData
describing the current tree
-
createTreeDataForRootAndTracker
Creates aTreeData
object for the specified root node andNodeTracker
. Other parameters are set to default values.- Parameters:
root
- the new root node for this modelnewTracker
- the newNodeTracker
- Returns:
- the new
TreeData
object
-
executeTransactionOnCurrentStructure
private boolean executeTransactionOnCurrentStructure(InMemoryNodeModel.TransactionInitializer txInit, NodeSelector selector, TreeData currentData, NodeKeyResolver<ImmutableNode> resolver) Executes a transaction on the current data of this model. This method is called if an operation is to be executed on the model's root node or a tracked node which is not yet detached.- Parameters:
txInit
- theTransactionInitializer
selector
- an optionalNodeSelector
defining the target nodecurrentData
- the current data of the modelresolver
- theNodeKeyResolver
- Returns:
- a flag whether the operation has been completed successfully
-
executeTransactionOnDetachedTrackedNode
private boolean executeTransactionOnDetachedTrackedNode(InMemoryNodeModel.TransactionInitializer txInit, NodeSelector selector, TreeData currentData, NodeKeyResolver<ImmutableNode> resolver) Tries to execute a transaction on the model of a detached tracked node. This method checks whether the target node of the transaction is a tracked node and if this node is already detached. If this is the case, the update operation is independent on this model and has to be executed on the specific model for the detached node.- Parameters:
txInit
- theTransactionInitializer
selector
- an optionalNodeSelector
defining the target nodecurrentData
- the current data of the modelresolver
- theNodeKeyResolver
@return a flag whether the transaction could be executed- Throws:
ConfigurationRuntimeException
- if the selector cannot be resolved
-
getInMemoryRepresentation
Gets a representation of the data stored in this model in form of a nodes hierarchy ofImmutableNode
objects. A concrete model implementation can use an arbitrary means to store its data. When a model's data is to be used together with other functionality of the Configuration library (e.g. when combining multiple configuration sources) it has to be transformed into a common format. This is done by this method.ImmutableNode
is a generic representation of a hierarchical structure. Thus, it should be possible to generate a corresponding structure from arbitrary model data. This implementation simply returns the current root node of this model.- Specified by:
getInMemoryRepresentation
in interfaceNodeModel<ImmutableNode>
- Returns:
- the root node of an in-memory hierarchy representing the data stored in this model
-
getNodeHandler
Gets aNodeHandler
for dealing with the nodes managed by this model.InMemoryNodeModel
implements theNodeHandler
interface itself. So this implementation just returns the this reference.- Specified by:
getNodeHandler
in interfaceNodeModel<ImmutableNode>
- Returns:
- the
NodeHandler
-
getReferenceNodeHandler
Gets aReferenceNodeHandler
object for this model. This extended node handler can be used to query references objects stored for this model.- Returns:
- the
ReferenceNodeHandler
-
getRootNode
Gets the root node of this mode. Note: This method should be used with care. The model may be updated concurrently which causes the root node to be replaced. If the root node is to be processed further (e.g. by executing queries on it), the model should be asked for itsNodeHandler
, and the root node should be obtained from there. The connection between a node handler and its root node remain constant because an update of the model causes the whole node handler to be replaced.- Returns:
- the current root node
-
getTrackedNode
Gets the currentImmutableNode
instance associated with the givenNodeSelector
. The node must be a tracked node, i.e.trackNode(NodeSelector, NodeKeyResolver)
must have been called before with the given selector.- Parameters:
selector
- theNodeSelector
defining the desired node- Returns:
- the current
ImmutableNode
associated with this selector - Throws:
ConfigurationRuntimeException
- if the selector is unknown
-
getTrackedNodeHandler
Gets aNodeHandler
for a tracked node. Such a handler may be required for operations on a sub tree of the model. The handler to be returned depends on the current state of the tracked node. If it is still active, a handler is used which shares some data (especially the parent mapping) with this model. Detached track nodes in contrast have their own separate model; in this case a handler associated with this model is returned.- Parameters:
selector
- theNodeSelector
defining the tracked node- Returns:
- a
NodeHandler
for this tracked node - Throws:
ConfigurationRuntimeException
- if the selector is unknown
-
getTreeData
TreeData getTreeData()Gets the currentTreeData
object. This object contains all information about the current node structure.- Returns:
- the current
TreeData
object
-
initializeAddTransaction
private void initializeAddTransaction(ModelTransaction tx, String key, Iterable<?> values, NodeKeyResolver<ImmutableNode> resolver) Initializes a transaction for an add operation.- Parameters:
tx
- the transaction to be initializedkey
- the keyvalues
- the collection with node valuesresolver
- theNodeKeyResolver
-
isTrackedNodeDetached
Returns a flag whether the specified tracked node is detached. As long as theNodeSelector
associated with that node returns a single instance, the tracked node is said to be life. If now an update of the model happens which invalidates the selector (maybe the target node was removed), the tracked node becomes detached. It is still possible to query the node; here the latest valid instance is returned. But further changes on the node model are no longer tracked for this node. So even if there are further changes which would make theNodeSelector
valid again, the tracked node stays in detached state.- Parameters:
selector
- theNodeSelector
defining the desired node- Returns:
- a flag whether this tracked node is in detached state
- Throws:
ConfigurationRuntimeException
- if the selector is unknown
-
mergeRoot
public void mergeRoot(ImmutableNode node, String rootName, Map<ImmutableNode, ?> references, Object rootRef, NodeKeyResolver<ImmutableNode> resolver) Merges the root node of this model with the specified node. This method is typically caused by configuration implementations when a configuration source is loaded, and its data has to be added to the model. It is possible to define the new name of the root node and to pass in a map with reference objects.- Parameters:
node
- the node to be merged with the root noderootName
- the new name of the root node; can be null, then the name of the root node is not changed unless it is nullreferences
- an optional map with reference objectsrootRef
- an optional reference object for the new root noderesolver
- theNodeKeyResolver
-
replaceActiveTrackedNode
private boolean replaceActiveTrackedNode(TreeData currentData, NodeSelector selector, ImmutableNode newNode) Replaces an active tracked node. The node then becomes detached.- Parameters:
currentData
- the current data of the modelselector
- theNodeSelector
defining the tracked nodenewNode
- the node replacing the tracked node- Returns:
- a flag whether the operation was successful
-
replaceDetachedTrackedNode
private boolean replaceDetachedTrackedNode(TreeData currentData, NodeSelector selector, ImmutableNode newNode) Replaces a tracked node if it is already detached.- Parameters:
currentData
- the current data of the modelselector
- theNodeSelector
defining the tracked nodenewNode
- the node replacing the tracked node- Returns:
- a flag whether the operation was successful
-
replaceRoot
Replaces the root node of this model. This method is similar tosetRootNode(ImmutableNode)
; however, tracked nodes will not get lost. The model applies the selectors of all tracked nodes on the new nodes hierarchy, so that corresponding nodes are selected (this may cause nodes to become detached if a select operation fails). This operation is useful if the new nodes hierarchy to be set is known to be similar to the old one. Note that reference objects are lost; there is no way to automatically match nodes between the old and the new nodes hierarchy.- Parameters:
newRoot
- the new root node to be set (must not be null)resolver
- theNodeKeyResolver
- Throws:
IllegalArgumentException
- if the new root node is null
-
replaceTrackedNode
Replaces a tracked node by another node. If the tracked node is not yet detached, it becomes now detached. The passed in node (which must not be null) becomes the new root node of an independent model for this tracked node. Further updates of this model do not affect the tracked node's model and vice versa.- Parameters:
selector
- theNodeSelector
defining the tracked nodenewNode
- the node replacing the tracked node (must not be null)- Throws:
ConfigurationRuntimeException
- if the selector cannot be resolvedIllegalArgumentException
- if the replacement node is null
-
selectAndTrackNodes
public Collection<NodeSelector> selectAndTrackNodes(String key, NodeKeyResolver<ImmutableNode> resolver) Allows tracking all nodes selected by a key. This method evaluates the specified key on the current nodes structure. For all selected nodes correspondingNodeSelector
objects are created, and they are tracked. The returned collection ofNodeSelector
objects can be used for interacting with the selected nodes.- Parameters:
key
- the key for selecting the nodes to trackresolver
- theNodeKeyResolver
- Returns:
- a collection with the
NodeSelector
objects for the new tracked nodes
-
setProperty
public void setProperty(String key, NodeSelector selector, Object value, NodeKeyResolver<ImmutableNode> resolver) Sets the value of a property using a tracked node as root node. This method works like the normalsetProperty()
method, but the origin of the operation (also for the interpretation of the passed in key) is a tracked node identified by the passed inNodeSelector
. The selector can be null, then the root node is assumed.- Parameters:
key
- the keyselector
- theNodeSelector
defining the root node (or null)value
- the new value for this propertyresolver
- theNodeKeyResolver
- Throws:
ConfigurationRuntimeException
- if the selector cannot be resolved
-
setProperty
Description copied from interface:NodeModel
Changes the value of a property. This is a more complex operation as it might involve adding, updating, or deleting nodes and attributes from the model. The object representing the new value is passed to theNodeKeyResolver
which will produce a correspondingNodeUpdateData
object. Based on the content of this object, update operations are performed.- Specified by:
setProperty
in interfaceNodeModel<ImmutableNode>
- Parameters:
key
- the keyvalue
- the new value for this property (to be evaluated by theNodeKeyResolver
)resolver
- theNodeKeyResolver
-
setRootNode
Sets a new root node for this model. The whole structure is replaced by the new node and its children. All tracked nodes and reference objects managed by this model are cleared.Care has to be taken when this method is used and the model is accessed by multiple threads. It is not deterministic which concurrent operations see the old root and which see the new root node.- Specified by:
setRootNode
in interfaceNodeModel<ImmutableNode>
- Parameters:
newRoot
- the new root node to be set (can be null, then an empty root node is set)
-
trackChildNodes
public Collection<NodeSelector> trackChildNodes(String key, NodeKeyResolver<ImmutableNode> resolver) Tracks all nodes which are children of the node selected by the passed in key. If the key selects exactly one node, for all children of this nodeNodeSelector
objects are created, and they become tracked nodes. The returned collection ofNodeSelector
objects can be used for interacting with the selected nodes.- Parameters:
key
- the key for selecting the parent node whose children are to be trackedresolver
- theNodeKeyResolver
- Returns:
- a collection with the
NodeSelector
objects for the new tracked nodes
-
trackChildNodeWithCreation
public NodeSelector trackChildNodeWithCreation(String key, String childName, NodeKeyResolver<ImmutableNode> resolver) Tracks a node which is a child of another node selected by the passed in key. If the selected node has a child node with this name, it is tracked and its selector is returned. Otherwise, a new child node with this name is created first.- Parameters:
key
- the key for selecting the parent nodechildName
- the name of the child noderesolver
- theNodeKeyResolver
- Returns:
- the
NodeSelector
for the tracked child node - Throws:
ConfigurationRuntimeException
- if the passed in key does not select a single node
-
trackNode
Adds a node to be tracked. After this method has been called with a specificNodeSelector
, the node associated with this key can be always obtained usinggetTrackedNode(NodeSelector)
with the same selector. This is useful because during updates of a model parts of the structure are replaced. Therefore, it is not a good idea to simply hold a reference to a node; this might become outdated soon. Rather, the node should be tracked. This mechanism ensures that always the correct node reference can be obtained.- Parameters:
selector
- theNodeSelector
defining the desired noderesolver
- theNodeKeyResolver
- Throws:
ConfigurationRuntimeException
- if the selector does not select a single node
-
untrackNode
Removes a tracked node. This method is the opposite oftrackNode()
. It has to be called if there is no longer the need to track a specific node. Note that for each call oftrackNode()
there has to be a correspondinguntrackNode()
call. This ensures that multiple observers can track the same node.- Parameters:
selector
- theNodeSelector
defining the desired node- Throws:
ConfigurationRuntimeException
- if the specified node is not tracked
-
updateModel
private void updateModel(InMemoryNodeModel.TransactionInitializer txInit, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver) Performs a non-blocking, thread-safe update of this model based on a transaction initialized by the passed in initializer. This method uses the atomic reference for the model's current data to ensure that an update was successful even if the model is concurrently accessed.- Parameters:
txInit
- theTransactionInitializer
selector
- an optionalNodeSelector
defining the target node of the transactionresolver
- theNodeKeyResolver
-