7.4.4. Class Node

A node represents an entity of the source code (e. g. a function, a variable, a file) or a concept in the imagination of the analyst or an analysis (e. g. a cluster, an architectural entity).

7.4.4.1. Obtaining a Node

class Node(node_type)
class Node(graph, node_type_name)

The constructor of class Node returns either a new node of type node_type or the type in graph named node_type_name respectively. A node type can be acquired from the graph by using instance method node_type, see Section Node and Edge Types.

The new node is not contained in any view but it is already part of the graph. You have to insert it into a view. A node as part of the RFG graph is automatically garbage collected when it is removed from the last view that contains it.

Caution

If you remove a node from the last view it has been contained in, the node is automatically garbage collected immediately. So make sure you first add a node to a target view before removing it from a source view if you intend to transfer the node between two views.

Note

If you created a new node and want to get rid of it, you have to insert it into a view and remove it from that view. The node will be garbage collected after the removal.

Caution

Nodes contained in sets are not removed from the sets once they are garbage collected from an RFG.

All methods of the RFG interface that return nodes return values of class Node.

7.4.4.2. General Operations

graph()

Instance method graph returns the graph the node is part of.

__str__()

Instance method __str__ returns a textual representation of the node (only for debugging purposes). For user output, use the general attribute handling methods.

__eq__(other)
__ne__(other)

The two instance methods __eq__ and __ne__ check for equality respectively inequality of two nodes.

Ordinarily, both functions are called by way of the == and != operators.

7.4.4.3. Hashing of Nodes

__hash__()

The hash function is used for dictionaries. Hash values change between multiple runs of a script. They cannot be used for persistence.

The code fragment in Listing Mapping the linkage name onto the nodes hashes the value of the attribute Linkage.Name for all nodes of a view.

Mapping the linkage name onto the nodes
#!/usr/bin/env rfgscript
# Copyright (C) 2025 Axivion GmbH
# Copyright (C) 2025 The Qt Company GmbH, a subsidiary of The Qt Group
# https://www.qt.io

import sys

from bauhaus import rfg

if len(sys.argv) < 2:
    print("usage: %s <rfgfile>" % (sys.argv[0]))
    sys.exit(1)

my_graph = rfg.Graph(sys.argv[1])

my_view = my_graph.view(rfg.code_facts_view_name())

# an empty dictionary
get_node_of_name = {}

# let us fill the table
for n in my_view.xnodes():
    get_node_of_name[n["Linkage.Name"]] = n

# from here on, we have random access to the nodes
# of the code facts view by link name
# example:
# somenode = get_node_of_name["somename"]

7.4.4.4. Type of a Node

node_type()
is_of_type(descriptor)
is_of_subtype(descriptor)
mutate(descriptor)

The node_type instance method returns the type of the node which is represented as NodeType. The instance method is_of_type takes a type descriptor or a string representing the name of the type as argument and checks whether the node is of the given type (and not of a subtype). Instance method is_of_subtype includes subtypes (children) of the given type in the check. Instance method mutate changes the type of a node.

The script shown in Listing Counting how many nodes are present in a view per node type counts how many nodes of each node type show up in the Code Facts view of the RFG you give as command line parameter.

Counting how many nodes are present in a view per node type
#!/usr/bin/env rfgscript
# Copyright (C) 2025 Axivion GmbH
# Copyright (C) 2025 The Qt Company GmbH, a subsidiary of The Qt Group
# https://www.qt.io

import sys
import typing

from bauhaus import rfg

if len(sys.argv) < 3:
    print("usage: %s <rfgfile> <viewname>" % (sys.argv[0]))
    sys.exit(1)

myrfg = rfg.Graph(sys.argv[1])

# summary contains the count of each node type contained in myrfg
summary: typing.Dict[str, int] = {}
if myrfg.is_view_name(sys.argv[2]):
    for node in myrfg.view(sys.argv[2]).xnodes():
        type_of_node = node.node_type().name()
        summary[type_of_node] = summary.get(type_of_node, 0) + 1

    # printout the result table
    print("\n".join("%s %s" % (atype, summary[atype]) for atype in summary))
else:
    print("Argument %s is not a view in the loaded RFG." % sys.argv[2])

7.4.4.5. Value Handling for Attributes

For a full explanation of the attribute handling, see Section Attributes.

Caution

A node has to be inserted in at least one view of a graph before one can set values of attributes at that node.

has_key(key)
__getitem__(key)
__setitem__(key, value)
__delitem__(key)
__iter__()
next()
keys()
items()
get_string_list(key)
set_string_list(key, value)
append_to_string_list(key, value)
These instance methods query and manipulate the attribute at a node. has_key checks whether attribute key is set, __getitem__ gets the stored value for attribute key, __setitem__ sets a new value for the attribute. __iter__ and next implement the iterator interface. keys returns a list of the names of all set attributes. items returns the list of all set pairs of keys (as strings) and values. get_string_list interprets the string attribute as list and returns the list. set_string_list stores a string representing the given string list. append_to_string_list appends the given string to the string list stored in the string attribute.

7.4.4.6. Membership in the View

insert(view)
add(view)
remove(view)

Instance methods insert and add make the node to be contained in the argument view. Instance method remove removes the node from a view.

Caution

If you remove a node from the last view it has been contained in, the node is automatically garbage collected immediately. So make sure you first add a node to a target view before removing it from a source view if you intend to transfer the node between two views.

The class View features a __contains__ method that can be used for checking whether a node is contained in a view.

7.4.4.7. Predicates for the Neighborhood of Nodes

is_neighbor(view, node)
is_predecessor(view, node)
is_successor(view, node)
Instance method is_neighbor checks whether self is a neighbor of node in view. Instance method is_predecessor checks whether self is a predecessor of node in view. Instance method is_successor checks whether self is a successor of node in view.

7.4.4.8. Querying the Neighborhood of Nodes

These instance methods are performing the operations described in section Section Querying the Neighborhood of Nodes and Edges.

incomings(view[, edge_matcher])
outgoings(view[, edge_matcher])
attached(view[, edge_matcher])

The instance methods incomings, outgoings, and attached return edge sets.

successors(view[, edge_matcher])
predecessors(view[, edge_matcher])
neighbors(view[, edge_matcher])

The instance methods successors, predecessors, and neighbors return node sets.

Note

Because edges can be contained in a view and not contained in another view, the argument view is crucial for the neighborhood relations.