A reference to a data tree node.

Selectors are used to access data in a data tree:

		// Get the settings selector
		Selector settings = dataTree.root.child("settings");

		// Write the settings
		settings.child("display text").setText("SALE SALE");

		// Read the settings
		boolean enabled = settings.child("enabled").booleanValue();
		long speed = settings.child("speed").integerValue();
		String displayText = settings.child("display text").textValue();

Using records, nodes can contain structured data:

		// Set a new background
		Record background = new Record();
		Record gradient = background.add("gradient");
		gradient.add("start color").add(0xcc3300);
		gradient.add("end color").add(0x996600);

		// Read the background
		Record background = settings.child("background").record();
		Record value = background.firstChild();
		if (value.asText().equals("gradient")) {
			long startColor = value.child("start color").integerValue();
			long endColor = value.child("end color").integerValue();
			long angle = value.child("angle").integerValue();
		} else {

Note that child labels are byte sequences.


Selector rootSelector = dataTree.root;
var rootSelector = dataTree.root
my $rootSelector = $dataTree->root

The root node of a data tree.

		Bytes settingsLabel = Bytes.fromText("settings");
		Selector settingsSelector = selector.child(settingsLabel);
		var settingsLabel = cn.bytesFromText('settings');
		var settingsSelector = selector.child(settingsLabel);
my $settingsSelector = $selector->child('settings');

Retrieves to the subnode with the label settings. Note that all labels are byte sequences.

		for (Selector child : selector.children()) {
		var children = selector.children();
		for (var i = 0; i < children.length; i++) {
			var child = children[i];
		for my $child ($selector->children) {

Iterates over all children of a selector.

Selector parent = selector.parent();
var parent = selector.parent();
my $parent = $selector->parent;

Navigates to the parent of a selector. For the root node, this returns nullundef.

Querying data

		Record record = selector.record();
		var record = selector.record();
		my $record = $selector->record;

Retrieves the node's raw value. This is always a record with zero or more children.

boolean isSet = selector.isSet();
var isSet = selector.isSet();
my $isSet = $selector->isSet;

Returns true if the node has a value (i.e., a record with at least one child), and false otherwise.

		Record record = selector.firstValue();
		boolean value = selector.booleanValue();
		long value = selector.integerValue();
		long value = selector.unsignedValue();
		String text = selector.textValue();
		Bytes bytes = selector.bytesValue();
		Hash hash = selector.hashValue();
		Reference reference = selector.referenceValue();
		var record = selector.firstValue();
		var value = selector.booleanValue();
		var value = selector.integerValue();
		var value = selector.unsignedValue();
		var text = selector.textValue();
		var bytes = selector.bytesValue();
		var hash = selector.hashValue();
		var reference = selector.referenceValue();
		my $record = $selector->firstValue;
		my $value = $selector->booleanValue;
		my $value = $selector->integerValue;
		my $value = $selector->unsignedValue;
		my $text = $selector->textValue;
		my $bytes = $selector->bytesValue;
		my $hash = $selector->hashValue;
		my $reference = $selector->referenceValue;

Returns the first value of the node in the requested format.

Empty nodes are treated as nodes with an empty byte sequence, which will translate into boolean false, number 0, or an empty text. Use isSet to check if the node is empty.

Signed integers are supported up to a size of 52 bits. Unsigned integers are discouraged, as they are easily confused with signed integers, which may lead to errors that go unnoticed for a long time.

Note that nodes and records do not store any data types. The application (implicitly or explicitly) defines the structure of a data tree, and the data type of each node. However, dynamic type information can – if needed – easily be stored as a record with two children: one holding the type, and one holding the data.

If the node's record holds multiple values, the above functions only return the first value. The complete list of values can be retrieved by traversing the record's children, e.g.

		for (Record child: selector.record().children) {
			String text = child.asText();
		var record = selector.record();
		for (var i = 0; i < record.children.length; i++) {
			var text = record.children[i].asText();
		for my $child ($selector->record->children) {
			my $text = child->asText;
ancestorOf isAncestorOf any() -> SelectorRange

Modifying data


Sets a new value for this node.

The node's revision is increased to the current timestamp. In case the node's revision is larger (e.g. due to badly synchronized clocks), the revision is simply incremented by 1. This is not ideal, but good enough for most practical cases.

selector.merge(revision, record);
selector.merge(revision, record);
$selector->merge($revision, $record);

Merges a value with a revision.

Merging only keeps the value with the newer revision. Hence, if the value currently stored in the node has a newer revision, it is not modified.


Clears the value. This is a shortcut for :

selector.set(new Record());
selector.set(new cn.Record());

Querying metadata

Bytes label = selector.label;
var label = selector.label;
my $label = $selector->label;

Retrieves the node's label.

long revision = selector.revision();
var revision = selector.revision();
my $revision = $selector->revision;

Retrieves the node's revision. This is the timestamp of the last node modification. When merging two versions of the data tree, only the value with the larger revision value is kept.

Broom management

long broom = selector.broom();
var broom = selector.broom();
my $broom = $selector->broom;

Retrieves the node's broom.

Change notification