AtuinStand.Node (atuin_stand v0.2.0)
View SourceA node in an AtuinStand.Tree
.
You can access the node's ID via the id
property, and the tree it belongs to
via the tree
property.
Since Node
structs only hold a reference to their containing tree, nodes
might be invalidated if the tree is manipulated such that the node is removed.
In this case, the Node
functions will return {:error, :not_found}
.
For a more detailed overview of the API, see AtuinStand
.
Raising API
Every function that can return an error tuple has a raising version that raises an error instead of returning an error tuple, and returns the result instead of an ok tuple if successful.
Each error tuple maps to a specific exception:
{:error, :not_found}
->AtuinStand.Error.NodeNotFound
{:error, :duplicate_id}
->AtuinStand.Error.DuplicateNode
{:error, :invalid_operation}
->AtuinStand.Error.InvalidOperation
{:error, :invalid_data}
->AtuinStand.Error.InvalidData
{:error, :has_children}
->AtuinStand.Error.HasChildren
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> AtuinStand.Node.create_child(root, "node1")
{:ok, %AtuinStand.Node{id: "node1", tree: tree}}
iex> AtuinStand.Node.create_child!(root, "node2")
%AtuinStand.Node{id: "node2", tree: tree}
iex> AtuinStand.Node.create_child!(root, "node1")
** (AtuinStand.Error.DuplicateNode) Node with id "node1" already exists
Summary
Functions
Returns a list of all ancestors of the given node, starting at the node's parent and ending at the root node (inclusive).
A raising version of ancestors/1
.
Returns a list of all children of the given node.
A raising version of children/1
.
Creates a new child node with the given ID.
A raising version of create_child/2
.
Deletes the node from the tree.
A raising version of delete/2
.
Returns the depth of the given node.
A raising version of depth/1
.
Returns a list of all descendants of the given node.
A raising version of descendants/2
.
Returns the user-defined data associated with the node.
A raising version of get_data/1
.
Moves the node after the given node.
A raising version of move_after/2
.
Moves the node before the given node.
A raising version of move_before/2
.
Moves the node to a new parent node.
A raising version of move_to/3
.
Returns the parent of the given node.
A raising version of parent/1
.
Moves the node to a new position amongst its siblings.
A raising version of reposition/2
.
Sets the user-defined data associated with the node. Returns the node.
A raising version of set_data/2
.
Returns a list of all siblings (other nodes with the same parent) of the given node.
A raising version of siblings/1
.
Types
@type t() :: %AtuinStand.Node{id: atom() | String.t(), tree: AtuinStand.Tree.t()}
Functions
Returns a list of all ancestors of the given node, starting at the node's parent and ending at the root node (inclusive).
Returns {:error, :not_found}
if the node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(node1, "node2")
iex> {:ok, node3} = AtuinStand.Node.create_child(node2, "node3")
iex> AtuinStand.Node.ancestors(node3)
{:ok, [node2, node1, root]}
A raising version of ancestors/1
.
Returns a list of all children of the given node.
Returns {:error, :not_found}
if the node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(root, "node2")
iex> AtuinStand.Node.children(root)
{:ok, [node1, node2]}
iex> AtuinStand.Node.children(node1)
{:ok, []}
A raising version of children/1
.
Creates a new child node with the given ID.
User-created nodes must have unique, string IDs. Returns {:error, :duplicate_id}
if a node with the given ID already exists in the tree. Returns {:error, :not_found}
if the parent node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> AtuinStand.Node.create_child(root, "node1")
{:ok, %AtuinStand.Node{id: "node1", tree: tree}}
iex> AtuinStand.Node.create_child(root, "node1")
{:error, :duplicate_id}
A raising version of create_child/2
.
@spec delete(node :: t(), strategy :: :refuse | :cascade | :reattach) :: {:ok, t()} | {:error, atom()}
Deletes the node from the tree.
Returns {:error, :invalid_operation}
if the node is the root node. Returns
{:error, :not_found}
if the node is not found in the tree.
Provide a strategy
to specify what to do with the node's children:
:refuse
- return{:error, :has_children}
if the node being deleted has children:cascade
- recursively delete the node and all of its children:reattach
- move the node's children to the node's parent before deleting it
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(node1, "node2")
iex> {:ok, node3} = AtuinStand.Node.create_child(node2, "node3")
iex> AtuinStand.Node.delete(node1, :refuse)
{:error, :has_children}
iex> AtuinStand.Node.delete(node1, :reattach)
iex> AtuinStand.Node.descendants(root)
{:ok, [node2, node3]}
iex> AtuinStand.Node.delete(node2, :cascade)
iex> AtuinStand.Node.descendants(root)
{:ok, []}
A raising version of delete/2
.
@spec depth(node :: t()) :: {:ok, non_neg_integer()} | {:error, atom()}
Returns the depth of the given node.
For any node, the depth is the number of edges on the path to the root node. The root node has a depth of 0, and every other node has a depth of 1 + its parent's depth.
Equivalent to length(AtuinStand.Node.ancestors(node))
.
Returns {:error, :not_found}
if the node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> AtuinStand.Node.depth(root)
{:ok, 0}
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> AtuinStand.Node.depth(node1)
{:ok, 1}
iex> {:ok, node2} = AtuinStand.Node.create_child(node1, "node2")
iex> AtuinStand.Node.depth(node2)
{:ok, 2}
@spec depth!(node :: t()) :: non_neg_integer()
A raising version of depth/1
.
Returns a list of all descendants of the given node.
Provide :dfs
or :bfs
as an optional argument to return the results in
depth-first or breadth-first order, respectively. Defaults to :dfs
.
Returns {:error, :not_found}
if the node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(node1, "node2")
iex> {:ok, node3} = AtuinStand.Node.create_child(node2, "node3")
iex> {:ok, node4} = AtuinStand.Node.create_child(root, "node4")
iex> AtuinStand.Node.descendants(node1, :dfs)
{:ok, [node2, node3]}
iex> AtuinStand.Node.descendants(root, :bfs)
{:ok, [node1, node4, node2, node3]}
A raising version of descendants/2
.
Returns the user-defined data associated with the node.
If the node is not found, returns {:error, :not_found}
.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> AtuinStand.Node.set_data(node1, %{"name" => "Node 1"})
iex> AtuinStand.Node.get_data(node1)
{:ok, %{"name" => "Node 1"}}
A raising version of get_data/1
.
Moves the node after the given node.
Returns {:error, :invalid_operation}
if the node is the root node or if the move would create
a cycle in the tree. Returns {:error, :not_found}
if either node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(root, "node2")
iex> {:ok, node3} = AtuinStand.Node.create_child(root, "node3")
iex> AtuinStand.Node.move_after(node1, node3)
iex> AtuinStand.Node.children(root)
{:ok, [node2, node3, node1]}
A raising version of move_after/2
.
Moves the node before the given node.
Returns {:error, :invalid_operation}
if the node is the root node or if the move would create
a cycle in the tree. Returns {:error, :not_found}
if either node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(root, "node2")
iex> {:ok, node3} = AtuinStand.Node.create_child(root, "node3")
iex> AtuinStand.Node.move_before(node3, node1)
iex> AtuinStand.Node.children(root)
{:ok, [node3, node1, node2]}
A raising version of move_before/2
.
@spec move_to(node :: t(), new_parent :: t(), index :: non_neg_integer() | nil) :: {:ok, t()} | {:error, atom()}
Moves the node to a new parent node.
Returns {:error, :invalid_operation}
if the node is the root node or if the move
would create a cycle in the tree. Returns {:error, :not_found}
if the either node
is not found in the tree.
Provide an optional index
to specify the position of the node in the new parent's
child list. The node will be inserted at the end if no index is provided.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(node1, "node2")
iex> {:ok, node3} = AtuinStand.Node.create_child(node2, "node3")
iex> AtuinStand.Node.move_to(node1, node3)
{:error, :invalid_operation}
iex> AtuinStand.Node.move_to(node2, root)
iex> AtuinStand.Node.children(root)
{:ok, [node1, node2]}
iex> AtuinStand.Node.move_to(node3, root, 1)
iex> AtuinStand.Node.children(root)
{:ok, [node1, node3, node2]}
iex> AtuinStand.Node.move_to(node2, root, 1)
iex> AtuinStand.Node.children(root)
{:ok, [node1, node2, node3]}
@spec move_to!(node :: t(), new_parent :: t(), index :: non_neg_integer() | nil) :: t()
A raising version of move_to/3
.
Returns the parent of the given node.
Returns {:error, :not_found}
if the node is not found in the tree.
Returns {:error, :invalid_operation}
if the node is the root node.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> AtuinStand.Node.parent(root)
{:error, :invalid_operation}
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> AtuinStand.Node.parent(node1)
{:ok, %AtuinStand.Node{id: :root, tree: tree}}
iex> fake_node = %AtuinStand.Node{id: "fake", tree: tree}
iex> AtuinStand.Node.parent(fake_node)
{:error, :not_found}
A raising version of parent/1
.
@spec reposition(node :: t(), index :: non_neg_integer()) :: {:ok, t()} | {:error, atom()}
Moves the node to a new position amongst its siblings.
Returns {:error, :invalid_operation}
if the node is the root node. Returns
{:error, :not_found}
if the node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(root, "node2")
iex> {:ok, node3} = AtuinStand.Node.create_child(root, "node3")
iex> AtuinStand.Node.reposition(node2, 0)
iex> AtuinStand.Node.children(root)
{:ok, [node2, node1, node3]}
iex> AtuinStand.Node.reposition(node2, 2)
iex> AtuinStand.Node.children(root)
{:ok, [node1, node3, node2]}
@spec reposition!(node :: t(), index :: non_neg_integer()) :: t()
A raising version of reposition/2
.
Sets the user-defined data associated with the node. Returns the node.
The data must be a map, otherwise returns {:error, :invalid_data}
. When the
tree is serialized to JSON, the data is serialized as well, so any atom keys
will be converted to strings.
If the node is not found, returns {:error, :not_found}
.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node1} = AtuinStand.Tree.node(tree, "node1")
iex> AtuinStand.Node.set_data(node1, %{"name" => "Node 1"})
iex> AtuinStand.Node.get_data(node1)
{:ok, %{"name" => "Node 1"}}
A raising version of set_data/2
.
Returns a list of all siblings (other nodes with the same parent) of the given node.
Returns {:error, :not_found}
if the node is not found in the tree.
Examples
iex> tree = AtuinStand.Tree.new()
iex> root = AtuinStand.Tree.root(tree)
iex> {:ok, node1} = AtuinStand.Node.create_child(root, "node1")
iex> {:ok, node2} = AtuinStand.Node.create_child(root, "node2")
iex> {:ok, node3} = AtuinStand.Node.create_child(root, "node3")
iex> AtuinStand.Node.siblings(node1)
{:ok, [node2, node3]}
A raising version of siblings/1
.