SAMSON uses serialization, i.e. the conversion of data structures to and from serialized streams, in order to achieve several essential tasks. For example copying, pasting, saving and loading, etc. are all performed through serialization.
All data graph nodes defined by the SAMSON API implement a serialize and an unserialize function.
Serialization is performed via a serializer class passed to the serialize and unserialize functions.
If your SAMSON Element contains new classes derived from data graph nodes types (typically, visual models, interaction models, property models, controllers, labels or state updaters), you might need to re-implement their serialize and unserialize functions, and the isSerializable function to indicate to SAMSON that whether the custom class is serializable or not.
In the re-implementation of the serialize function it is necessary to call first the serialize function of a parent class, which in turn calls the serialize function of its parents and so on all the way up to SBNode itself. The parent functions are needed for correct saving and loading of node properties. This allows to save the node's name, visibility flag, etc. The same is for the unserialize function.
When SAMSON serializes a group of nodes, it proceeds in two passes:
serialize
function of each node is called. This function receives the node indexer.During unserialization, SAMSON also proceeds in two steps:
unserialize
function of each node is called. This function receives the node indexer.Note: Saving of the document leads to the serialization of every node that can be serialized, while copying leads to the serialization only of copied nodes. Thus, while serializing, it is necessary to check whether the referenced node is present in the node indexer. If a node that is referenced by a serialized node is also serialized then during the serialization it is necessary to indicate the index in the node indexer of the referenced node, else it is necessary to indicate an address of the referenced node.
Please, see the Basic rules of serialization and example below for more information.
nodeIndexer
(see the serialize function definition). If a node referenced by the serialized node is not to be serialized (e.g. it is a case when copying a node), then serialize the reference node's address. And serialize a boolean flag for each referenced node indicating whether it was serialized via its index or address.Let's consider how to serialize a custom class derived from data graph nodes types on an example of a custom visual model which references data graph nodes.
First, it is necessary to indicate to SAMSON that the custom visual model is serializable. For that, we re-implement the isSerializable function to return true
:
Now, we need to re-implement both serialize
and unserialize
functions.
The serialize
function allows for serialization of a node (a visual model in this case).
First we invoke the serialization function of the parent class. Then we save information on a custom node itself: custom node's parameters, number of nodes which are referenced by the custom node (e.g. nodes to which the visual model is applied), and the indices of these nodes in the nodeIndexer
or their addresses. We check whether the atom itself was serialized or not. Basically, saving leads to the serialization of every node that can be serialized, while copying leads to the serialization only of nodes which are being copied. If atom was serialized we save its index in the nodeIndexer
, else we save the atom's address.
The unserialize
function allows for unserialization of a node (a visual model in this case).
First, we invoke the unserialization function of the parent class. This will create the node in the data graph. Then we read information on a custom node itself: custom node's parameters, number of nodes referenced by the custom node (e.g. nodes to which the visual model is applied), and the indices of these nodes in the nodeIndexer
or their addresses. We check whether the referenced node itself was serialized or not. If the referenced node was serialized we read its index in the nodeIndexer
, else we read the referenced node's address.