Saving CollapsingRecordNode to XML

Hi Jake,

Im trying to save CollapsingRecordNode to an xml.
I tried to copy what StateCharter example does, but when loading I only see the CollapsingRecordNode headers.

How to I get it to save all the information in the xml, mainly CollapsingRecordNode List info.

Thanks
Ekta

This was from some work we did for a customer a year or so ago...
Jake
The basic problem is that the constructor for CollapsingRecordNodeItemList creates a CollapsingRecordNodeItem as the header.
Since it would write out the whole list of items, reading them all in again would create a duplicate item at the beginning of each list.
The simple solution is not to write out the first item, since that’s the same object as the Header.
There was also a minor problem in the initialization of CollapsingRecordNode.ItemWidth.
It gets written and read OK, but unfortunately it is read too early in the process, because the items haven’t been created yet.
So I made it re-set the ItemWidth property as part of finishing up building the CollapsingRecordNode.

public void SaveXmlCollapsingRecords() {

CollapsingRecordXmlWriter xw = new CollapsingRecordXmlWriter();

xw.Objects = myView.Document;

using (StreamWriter file = new StreamWriter(@"C:\GoDiagram3\records.xml")) {

xw.Generate(file);

}

}

public void LoadXmlCollapsingRecords() {

myView.StartTransaction();

myView.Document.Clear();

CollapsingRecordXmlReader r = new CollapsingRecordXmlReader();

r.RootObject = myView.Document;

using (StreamReader file = new StreamReader(@"C:\GoDiagram3\records.xml")) {

r.Consume(file);

}

myView.FinishTransaction("loaded XML");

}

public class CollapsingRecordXmlReader : GoXmlReader {

public CollapsingRecordXmlReader() {

}

public override void RegisterTransformers() {

CollapsingRecordXmlWriter.RegisterTransformers(this);

}

}

public class CollapsingRecordXmlWriter : GoXmlWriter {

public CollapsingRecordXmlWriter() {

this.RootElementName = "doc";

}

public override void RegisterTransformers() {

RegisterTransformers(this);

}

internal static void RegisterTransformers(GoXmlReaderWriterBase rw) {

// create a prototype document

GoDocument doc = new GoDocument();

GoXmlBindingTransformer bt = new GoXmlBindingTransformer("doc", doc);

rw.AddTransformer(bt);

CollapsingRecordNode crn = new CollapsingRecordNode();

bt = new CollapsingRecordNodeTransformer(crn);

bt.IdAttributeUsedForSharedObjects = true;

bt.HandlesNamedPorts = true;

bt.HandlesChildren = true; // generates and consumes child objects

bt.ChildrenCollectionPath = "List"; // collection of children is held in this property

bt.AddBinding("Location", "Location");

bt.AddBinding("ItemWidth", "ItemWidth"); // is read too early, need to reset it to finish up

bt.AddBinding("Text", "Text");

rw.AddTransformer(bt);

CollapsingRecordNodeItemList crnil = new CollapsingRecordNodeItemList();

bt = new CollapsingRecordNodeItemListTransformer(crnil);

bt.HandlesNamedPorts = true;

bt.HandlesChildren = true; // generates and consumes child objects

bt.AddBinding("Text", "Text");

rw.AddTransformer(bt);

CollapsingRecordNodeItem crni = new CollapsingRecordNodeItem();

crni.Init("", "", false); // create a GoImage, so we can set the Name

bt = new GoXmlBindingTransformer(crni);

bt.HandlesNamedPorts = true;

bt.AddBinding("Text", "Text");

bt.AddBinding("Image", "Image.Name");

rw.AddTransformer(bt);

GoLink link = new GoLink();

bt = new GoXmlBindingTransformer(link);

bt.AddBinding("From", "FromPort");

bt.AddBinding("To", "ToPort");

rw.AddTransformer(bt);

}

}

public class CollapsingRecordNodeTransformer : GoXmlBindingTransformer {

public CollapsingRecordNodeTransformer(Object proto) : base(proto) { }

public override void GenerateBody(object obj) {

CollapsingRecordNode crn = (CollapsingRecordNode)obj;

bool first = true;

foreach (GoObject c in crn.List) {

if (first) {

first = false; // skip first CollapsingRecordNodeItem, which is the Header

} else {

this.Writer.GenerateObject(c);

}

}

}

protected override void GeneratePortReferences(object obj) {

CollapsingRecordNode crn = (CollapsingRecordNode)obj;

base.GeneratePortReferences(crn.List.Header);

}

protected override void ConsumePortReferences(object obj) {

CollapsingRecordNode crn = (CollapsingRecordNode)obj;

base.ConsumePortReferences(crn.List.Header);

}

public override void ConsumeObjectFinish(object obj) {

CollapsingRecordNode crn = (CollapsingRecordNode)obj;

crn.ItemWidth = crn.ItemWidth; // reset it now that the items are present

}

}

public class CollapsingRecordNodeItemListTransformer : GoXmlBindingTransformer {

public CollapsingRecordNodeItemListTransformer(Object proto) : base(proto) {}

public override void GenerateBody(object obj) {

CollapsingRecordNodeItemList list = (CollapsingRecordNodeItemList)obj;

bool first = true;

foreach (GoObject c in list) {

if (first) {

first = false; // skip first CollapsingRecordNodeItem, which is the Header

} else {

this.Writer.GenerateObject(c);

}

}

}

protected override void GeneratePortReferences(object obj) {

CollapsingRecordNodeItemList list = (CollapsingRecordNodeItemList)obj;

base.GeneratePortReferences(list.Header);

}

protected override void ConsumePortReferences(object obj) {

CollapsingRecordNodeItemList list = (CollapsingRecordNodeItemList)obj;

base.ConsumePortReferences(list.Header);

}

}

Since we’re duplicating the “item” information for the “headers” of the CollapsingRecordNode and CollapsingRecordNodeItemList,

we need to do the same for the ports on each item.

That’s why I overrode the ...PortReferences methods to operate on the Header instead of on the object (...Node or ...NodeItemList) itself.

In retrospect, it might have been clearer and simpler to just change the definition of the CollapsingRecord... classes,

instead of complicating the implementation of the XML transformers by overriding all those methods to treat the Header specially.

But the advantage of this is that you don’t need to write out brush and font and size information for each item.

Those properties are determined entirely by the implementation in code.

On the other hand, moving some of the visual customizations into the XML gives you more flexibility to control the appearance of each item.

Those are policy decisions that you need to make for your applications.

Thanks, will try this out.

Worked for me Thanks!!