-
Notifications
You must be signed in to change notification settings - Fork 3
/
write.go
95 lines (81 loc) · 2.23 KB
/
write.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package graphml
import (
"bytes"
"encoding/xml"
"io"
"github.com/loov/layout"
)
func Write(out io.Writer, graphs ...*layout.Graph) error {
file := NewFile()
for _, graph := range graphs {
file.Graphs = append(file.Graphs, Convert(graph))
}
file.Key = []Key{
Key{For: "node", ID: "label", AttrName: "label", AttrType: "string"},
Key{For: "node", ID: "shape", AttrName: "shape", AttrType: "string"},
Key{For: "edge", ID: "label", AttrName: "label", AttrType: "string"},
Key{For: "node", ID: "ynodelabel", YFilesType: "nodegraphics"},
Key{For: "edge", ID: "yedgelabel", YFilesType: "edgegraphics"},
}
enc := xml.NewEncoder(out)
enc.Indent("", "\t")
return enc.Encode(file)
}
func Convert(graph *layout.Graph) *Graph {
out := &Graph{}
out.ID = graph.ID
if graph.Directed {
out.EdgeDefault = Directed
} else {
out.EdgeDefault = Undirected
}
for _, node := range graph.Nodes {
outnode := Node{}
outnode.ID = node.ID
addAttr(&outnode.Attrs, "label", node.DefaultLabel())
addAttr(&outnode.Attrs, "shape", string(node.Shape))
addAttr(&outnode.Attrs, "tooltip", node.Tooltip)
addYedLabelAttr(&outnode.Attrs, "ynodelabel", node.DefaultLabel())
out.Node = append(out.Node, outnode)
}
for _, edge := range graph.Edges {
outedge := Edge{}
outedge.Source = edge.From.ID
outedge.Target = edge.To.ID
addAttr(&outedge.Attrs, "label", edge.Label)
addAttr(&outedge.Attrs, "tooltip", edge.Tooltip)
addYedLabelAttr(&outedge.Attrs, "yedgelabel", edge.Label)
out.Edge = append(out.Edge, outedge)
}
return out
}
func addAttr(attrs *[]Attr, key, value string) {
if value == "" {
return
}
*attrs = append(*attrs, Attr{key, escapeText(value)})
}
func addYedLabelAttr(attrs *[]Attr, key, value string) {
if value == "" {
return
}
var buf bytes.Buffer
buf.WriteString(`<y:ShapeNode><y:NodeLabel>`)
if err := xml.EscapeText(&buf, []byte(value)); err != nil {
// this shouldn't ever happen
panic(err)
}
buf.WriteString(`</y:NodeLabel></y:ShapeNode>`)
*attrs = append(*attrs, Attr{key, buf.Bytes()})
}
func escapeText(s string) []byte {
if s == "" {
return []byte{}
}
var buf bytes.Buffer
if err := xml.EscapeText(&buf, []byte(s)); err != nil {
// this shouldn't ever happen
panic(err)
}
return buf.Bytes()
}