Skip to content

Commit

Permalink
Dot exporter initial code
Browse files Browse the repository at this point in the history
  • Loading branch information
hovsep committed Oct 9, 2024
1 parent a97373f commit 22d0555
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 22 deletions.
72 changes: 51 additions & 21 deletions export/dot.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,71 +10,101 @@ import (
type dotExporter struct {
}

const nodeIDLabel = "export/dot/id"

func NewDotExporter() Exporter {
return &dotExporter{}
}

// Export returns the f-mesh represented as digraph in DOT language
func (d *dotExporter) Export(fm *fmesh.FMesh) []byte {
// Setup graph
func (d *dotExporter) Export(fm *fmesh.FMesh) ([]byte, error) {
// Setup main graph
graph := dot.NewGraph(dot.Directed)
graph.
Attr("layout", "dot").
Attr("splines", "ortho")

for componentName, c := range fm.Components() {
for _, component := range fm.Components() {
// Component subgraph (wrapper)
componentSubgraph := graph.NewSubgraph()
componentSubgraph.
NodeBaseAttrs().
Attr("width", "1.0").Attr("height", "1.0")
componentSubgraph.
Attr("label", componentName).
Attr("label", component.Name()).
Attr("cluster", "true").
Attr("style", "rounded").
Attr("color", "black").
Attr("bgcolor", "lightgrey").
Attr("margin", "20")

// Component node
// Create component node and subgraph (cluster)
componentNode := componentSubgraph.Node()
componentNode.Attr("label", "𝑓")
if c.Description() != "" {
componentNode.Attr("label", c.Description())
if component.Description() != "" {
componentNode.Attr("label", component.Description())
}
componentNode.
Attr("color", "blue").
Attr("shape", "rect").
Attr("group", componentName)
Attr("group", component.Name())

// Create nodes for input ports
for _, port := range component.Inputs() {
portID := getPortID(component.Name(), "input", port.Name())

// Input ports
for portName := range c.Inputs() {
portNode := componentSubgraph.NodeWithID(fmt.Sprintf("%s.inputs.%s", componentName, portName))
//Mark input ports to be able to find their respective nodes later when adding pipes
port.AddLabel(nodeIDLabel, portID)

portNode := componentSubgraph.NodeWithID(portID)
portNode.
Attr("label", portName).
Attr("label", port.Name()).
Attr("shape", "circle").
Attr("group", componentName)
Attr("group", component.Name())

componentSubgraph.Edge(portNode, componentNode)
}

// Output ports
for portName, port := range c.Outputs() {
portNode := componentSubgraph.NodeWithID(fmt.Sprintf("%s.inputs.%s", componentName, portName))
// Create nodes for output ports
for _, port := range component.Outputs() {
portID := getPortID(component.Name(), "output", port.Name())
portNode := componentSubgraph.NodeWithID(portID)
portNode.
Attr("label", portName).
Attr("label", port.Name()).
Attr("shape", "circle").
Attr("group", componentName)
Attr("group", component.Name())

componentSubgraph.Edge(componentNode, portNode)
}
}

// Create edges representing pipes (all ports must exist at this point)
for _, component := range fm.Components() {
for _, srcPort := range component.Outputs() {
for _, destPort := range srcPort.Pipes() {
// Any destination port in any pipe is input port, but we do not know in which component
// so we use the label we added earlier
destPortID, err := destPort.Label(nodeIDLabel)
if err != nil {
return nil, err
}
// Clean up and leave the f-mesh as it was before export
destPort.DeleteLabel(nodeIDLabel)

// Pipes
//@TODO
// Any source port in any pipe is always output port, so we can build its node ID
srcPortNode := graph.FindNodeByID(getPortID(component.Name(), "output", srcPort.Name()))
destPortNode := graph.FindNodeByID(destPortID)
graph.Edge(srcPortNode, destPortNode)
}
}
}

buf := new(bytes.Buffer)
graph.Write(buf)

return buf.Bytes()
return buf.Bytes(), nil
}

func getPortID(componentName string, portKind string, portName string) string {
return fmt.Sprintf("component/%s/%s/%s", componentName, portKind, portName)
}
3 changes: 2 additions & 1 deletion export/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package export

import "github.com/hovsep/fmesh"

// Exporter is the common interface for all formats
type Exporter interface {
Export(fm *fmesh.FMesh) []byte
Export(fm *fmesh.FMesh) ([]byte, error)
}

0 comments on commit 22d0555

Please sign in to comment.