public class InMemoryNodeModel extends Object implements 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.
Constructor and Description |
---|
InMemoryNodeModel()
Creates a new instance of
InMemoryNodeModel which is initialized with an empty root node. |
InMemoryNodeModel(ImmutableNode root)
Creates a new instance of
InMemoryNodeModel and initializes it from the given root node. |
Modifier and Type | Method and Description |
---|---|
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.
|
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.
|
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.
|
List<QueryResult<ImmutableNode>> |
clearTree(String key,
NodeKeyResolver<ImmutableNode> resolver)
Removes the sub trees defined by the given key from this model.
|
List<QueryResult<ImmutableNode>> |
clearTree(String key,
NodeSelector selector,
NodeKeyResolver<ImmutableNode> resolver)
Clears a whole sub tree using a tracked node as root node.
|
ImmutableNode |
getInMemoryRepresentation()
Returns a representation of the data stored in this model in form of a nodes hierarchy of
ImmutableNode
objects. |
NodeHandler<ImmutableNode> |
getNodeHandler()
Returns a
NodeHandler for dealing with the nodes managed by this model. |
ReferenceNodeHandler |
getReferenceNodeHandler()
Returns a
ReferenceNodeHandler object for this model. |
ImmutableNode |
getRootNode()
Returns the root node of this mode.
|
ImmutableNode |
getTrackedNode(NodeSelector selector)
Returns the current
ImmutableNode instance associated with the given NodeSelector . |
NodeHandler<ImmutableNode> |
getTrackedNodeHandler(NodeSelector selector)
Returns a
NodeHandler for a tracked node. |
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.
|
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.
|
Collection<NodeSelector> |
selectAndTrackNodes(String key,
NodeKeyResolver<ImmutableNode> resolver)
Allows tracking all nodes selected by a key.
|
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 |
setProperty(String key,
Object value,
NodeKeyResolver<ImmutableNode> resolver)
Changes the value of a property.
|
void |
setRootNode(ImmutableNode newRoot)
Sets a new root node for this model.
|
Collection<NodeSelector> |
trackChildNodes(String key,
NodeKeyResolver<ImmutableNode> resolver)
Tracks all nodes which are children of the node selected by the passed in key.
|
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.
|
void |
trackNode(NodeSelector selector,
NodeKeyResolver<ImmutableNode> resolver)
Adds a node to be tracked.
|
void |
untrackNode(NodeSelector selector)
Removes a tracked node.
|
public InMemoryNodeModel()
InMemoryNodeModel
which is initialized with an empty root node.public InMemoryNodeModel(ImmutableNode root)
InMemoryNodeModel
and initializes it from the given root node. If the passed in
node is null, a new, empty root node is created.root
- the new root node for this modelpublic ImmutableNode getRootNode()
NodeHandler
, 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.public NodeHandler<ImmutableNode> getNodeHandler()
NodeHandler
for dealing with the nodes managed by this model. InMemoryNodeModel
implements the NodeHandler
interface itself. So this implementation
just returns the this reference.getNodeHandler
in interface NodeModel<ImmutableNode>
NodeHandler
public void addProperty(String key, Iterable<?> values, NodeKeyResolver<ImmutableNode> resolver)
NodeModel
NodeAddData
object defining the add operation to be performed.addProperty
in interface NodeModel<ImmutableNode>
key
- the keyvalues
- the values to be added at the position defined by the keyresolver
- the NodeKeyResolver
public void addProperty(String key, NodeSelector selector, Iterable<?> values, NodeKeyResolver<ImmutableNode> resolver)
addProperty()
method, but the origin of the operation (also for the interpretation of the passed in key) is a tracked node
identified by the passed in NodeSelector
. The selector can be null, then the root node is assumed.key
- the keyselector
- the NodeSelector
defining the root node (or null)values
- the values to be addedresolver
- the NodeKeyResolver
ConfigurationRuntimeException
- if the selector cannot be resolvedpublic void addNodes(String key, Collection<? extends ImmutableNode> nodes, NodeKeyResolver<ImmutableNode> resolver)
NodeModel
addNodes()
method of the
HierarchicalConfiguration
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 in NodeKeyResolver
is used to interpret the
given key.addNodes
in interface NodeModel<ImmutableNode>
key
- the keynodes
- the collection of nodes to be added (may be null)resolver
- the NodeKeyResolver
public void addNodes(String key, NodeSelector selector, Collection<? extends ImmutableNode> nodes, NodeKeyResolver<ImmutableNode> resolver)
addNodes()
method, but
the origin of the operation (also for the interpretation of the passed in key) is a tracked node identified by the
passed in NodeSelector
. The selector can be null, then the root node is assumed.key
- the keyselector
- the NodeSelector
defining the root node (or null)nodes
- the collection of new nodes to be addedresolver
- the NodeKeyResolver
ConfigurationRuntimeException
- if the selector cannot be resolvedpublic void setProperty(String key, Object value, NodeKeyResolver<ImmutableNode> resolver)
NodeModel
NodeKeyResolver
which will produce a corresponding NodeUpdateData
object. Based on the content of this object, update
operations are performed.setProperty
in interface NodeModel<ImmutableNode>
key
- the keyvalue
- the new value for this property (to be evaluated by the NodeKeyResolver
)resolver
- the NodeKeyResolver
public void setProperty(String key, NodeSelector selector, Object value, NodeKeyResolver<ImmutableNode> resolver)
setProperty()
method, but the origin of the operation (also for the interpretation of the passed in key) is a
tracked node identified by the passed in NodeSelector
. The selector can be null, then the root node is
assumed.key
- the keyselector
- the NodeSelector
defining the root node (or null)value
- the new value for this propertyresolver
- the NodeKeyResolver
ConfigurationRuntimeException
- if the selector cannot be resolvedpublic List<QueryResult<ImmutableNode>> clearTree(String key, NodeKeyResolver<ImmutableNode> resolver)
NodeKeyResolver
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 with QueryResult
objects for the elements
to be removed from the model.clearTree
in interface NodeModel<ImmutableNode>
key
- the key selecting the properties to be removedresolver
- the NodeKeyResolver
public List<QueryResult<ImmutableNode>> clearTree(String key, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver)
clearTree()
method, but the origin of the operation (also for the interpretation of the passed in key) is a tracked node
identified by the passed in NodeSelector
. The selector can be null, then the root node is assumed.key
- the keyselector
- the NodeSelector
defining the root node (or null)resolver
- the NodeKeyResolver
ConfigurationRuntimeException
- if the selector cannot be resolvedpublic void clearProperty(String key, NodeKeyResolver<ImmutableNode> resolver)
NodeModel.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.clearProperty
in interface NodeModel<ImmutableNode>
key
- the key selecting the properties to be clearedresolver
- the NodeKeyResolver
public void clearProperty(String key, NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver)
clearProperty()
method, but the origin of the operation (also for the interpretation of the passed in key) is a tracked node
identified by the passed in NodeSelector
. The selector can be null, then the root node is assumed.key
- the keyselector
- the NodeSelector
defining the root node (or null)resolver
- the NodeKeyResolver
ConfigurationRuntimeException
- if the selector cannot be resolvedpublic void clear(NodeKeyResolver<ImmutableNode> resolver)
clear
in interface NodeModel<ImmutableNode>
resolver
- the NodeKeyResolver
public ImmutableNode getInMemoryRepresentation()
ImmutableNode
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.getInMemoryRepresentation
in interface NodeModel<ImmutableNode>
public void setRootNode(ImmutableNode newRoot)
setRootNode
in interface NodeModel<ImmutableNode>
newRoot
- the new root node to be set (can be null, then an empty root node is set)public void replaceRoot(ImmutableNode newRoot, NodeKeyResolver<ImmutableNode> resolver)
setRootNode(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.newRoot
- the new root node to be set (must not be null)resolver
- the NodeKeyResolver
IllegalArgumentException
- if the new root node is nullpublic void mergeRoot(ImmutableNode node, String rootName, Map<ImmutableNode,?> references, Object rootRef, NodeKeyResolver<ImmutableNode> resolver)
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
- the NodeKeyResolver
public void trackNode(NodeSelector selector, NodeKeyResolver<ImmutableNode> resolver)
NodeSelector
, the node
associated with this key can be always obtained using getTrackedNode(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.selector
- the NodeSelector
defining the desired noderesolver
- the NodeKeyResolver
ConfigurationRuntimeException
- if the selector does not select a single nodepublic Collection<NodeSelector> selectAndTrackNodes(String key, NodeKeyResolver<ImmutableNode> resolver)
NodeSelector
objects are created, and they are tracked. The returned
collection of NodeSelector
objects can be used for interacting with the selected nodes.key
- the key for selecting the nodes to trackresolver
- the NodeKeyResolver
NodeSelector
objects for the new tracked nodespublic Collection<NodeSelector> trackChildNodes(String key, NodeKeyResolver<ImmutableNode> resolver)
NodeSelector
objects are created, and they become tracked nodes. The returned
collection of NodeSelector
objects can be used for interacting with the selected nodes.key
- the key for selecting the parent node whose children are to be trackedresolver
- the NodeKeyResolver
NodeSelector
objects for the new tracked nodespublic NodeSelector trackChildNodeWithCreation(String key, String childName, NodeKeyResolver<ImmutableNode> resolver)
key
- the key for selecting the parent nodechildName
- the name of the child noderesolver
- the NodeKeyResolver
NodeSelector
for the tracked child nodeConfigurationRuntimeException
- if the passed in key does not select a single nodepublic ImmutableNode getTrackedNode(NodeSelector selector)
ImmutableNode
instance associated with the given NodeSelector
. The node must be a
tracked node, i.e. trackNode(NodeSelector, NodeKeyResolver)
must have been called before with the given
selector.selector
- the NodeSelector
defining the desired nodeImmutableNode
associated with this selectorConfigurationRuntimeException
- if the selector is unknownpublic void replaceTrackedNode(NodeSelector selector, ImmutableNode newNode)
selector
- the NodeSelector
defining the tracked nodenewNode
- the node replacing the tracked node (must not be null)ConfigurationRuntimeException
- if the selector cannot be resolvedIllegalArgumentException
- if the replacement node is nullpublic NodeHandler<ImmutableNode> getTrackedNodeHandler(NodeSelector selector)
NodeHandler
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.selector
- the NodeSelector
defining the tracked nodeNodeHandler
for this tracked nodeConfigurationRuntimeException
- if the selector is unknownpublic boolean isTrackedNodeDetached(NodeSelector selector)
NodeSelector
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 the NodeSelector
valid again, the tracked node stays in detached state.selector
- the NodeSelector
defining the desired nodeConfigurationRuntimeException
- if the selector is unknownpublic void untrackNode(NodeSelector selector)
trackNode()
. It has to be called if there is no longer
the need to track a specific node. Note that for each call of trackNode()
there has to be a corresponding
untrackNode()
call. This ensures that multiple observers can track the same node.selector
- the NodeSelector
defining the desired nodeConfigurationRuntimeException
- if the specified node is not trackedpublic ReferenceNodeHandler getReferenceNodeHandler()
ReferenceNodeHandler
object for this model. This extended node handler can be used to query
references objects stored for this model.ReferenceNodeHandler
Copyright © 2001–2022 The Apache Software Foundation. All rights reserved.