Maintain Node Tree first, then Required Flag
The LionWeb C# framework always keep the nodes in a tree. This means that every node has zero or one parents, and this parent contains the node. As a consequence, simple assignments of containments can have side effects.
This only concerns containments. We can freely assign LionWeb references without side effects.
class Person {
...
public IReadOnlyList<Toe> Toes { get; }
public Person AddToes(IEnumerable<Toe> nodes);
public Person InsertToes(int index, IEnumerable<Toe> nodes);
public Person RemoveToes(IEnumerable<Toe> nodes);
public Appendix App { get; set; }
public Person SetApp(Appendix value);
}
...
Toe toe1 = new Toe("t1");
Toe toe2 = new Toe("t2");
Appendix worm = new Appendix("a");
Person john = new Person("g1_X") { Toes = [toe1, toe2], App = worm };
Person sid = new Person("-12");
sid.App = john.App ; <1>
john.App; // throws UnsetFeatureException
Toe firstToe = john.Toes.First(); <2>
Toe lastToe = john.Toes.Last();
sid.AddToes([firstToe, lastToe]); <3>
joh.Toes; // throws UnsetFeatureException
We assign John's App to Sid.
For C#, that's just a C# reference -- several places can refer to the same C# object.
But for LionWeb, that's a containment, and we must not have two parents for worm
!
Thus, we detach worm
from John, and attach it to Sid:
Now, John's App is null
, even though it's required.
Consequently, we'd get a UnsetFeatureException
in the next line if we tried to get John's App.
We get John's first Toe, i.e. toe1
.
That's ok, as we only store it in a local variable -- no effect on the tree.
We add several of John's Toes to Sid. Again, we must not have two parents for the same toe, so we detach them from John, and attach them to Sid:
Now, John's Toes are empty, even though the link is required.
Consequently, we'd get a UnsetFeatureException
in the next line if we tried to get John's Toes.
To summarize, the LionWeb framework always keeps the tree, even if it has to violate required constraints.
It helps the developer to adhere to required flags by throwing specializations of LionWebExceptionBase
on direct attempts to violate the constraints.