1 package d2oracle
2
3 import (
4 "fmt"
5
6 "oss.terrastruct.com/d2/d2ast"
7 "oss.terrastruct.com/d2/d2format"
8 "oss.terrastruct.com/d2/d2graph"
9 "oss.terrastruct.com/d2/d2parser"
10 )
11
12 func GetBoardGraph(g *d2graph.Graph, boardPath []string) *d2graph.Graph {
13 if len(boardPath) == 0 {
14 return g
15 }
16 for i, b := range g.Layers {
17 if b.Name == boardPath[0] {
18 g2 := GetBoardGraph(g.Layers[i], boardPath[1:])
19 if g2 != nil {
20 g2.FS = g.FS
21 }
22 return g2
23 }
24 }
25 for i, b := range g.Scenarios {
26 if b.Name == boardPath[0] {
27 g2 := GetBoardGraph(g.Scenarios[i], boardPath[1:])
28 if g2 != nil {
29 g2.FS = g.FS
30 }
31 return g2
32 }
33 }
34 for i, b := range g.Steps {
35 if b.Name == boardPath[0] {
36 g2 := GetBoardGraph(g.Steps[i], boardPath[1:])
37 if g2 != nil {
38 g2.FS = g.FS
39 }
40 return g2
41 }
42 }
43 return nil
44 }
45
46 func ReplaceBoardNode(ast, ast2 *d2ast.Map, boardPath []string) bool {
47 if len(boardPath) == 0 {
48 return false
49 }
50
51 findMap := func(root *d2ast.Map, name string) *d2ast.Map {
52 for _, n := range root.Nodes {
53 if n.MapKey != nil && n.MapKey.Key != nil && n.MapKey.Key.Path[0].Unbox().ScalarString() == name {
54 return n.MapKey.Value.Map
55 }
56 }
57 return nil
58 }
59
60 layersMap := findMap(ast, "layers")
61 scenariosMap := findMap(ast, "scenarios")
62 stepsMap := findMap(ast, "steps")
63
64 if layersMap != nil {
65 m := findMap(layersMap, boardPath[0])
66 if m != nil {
67 if len(boardPath) > 1 {
68 return ReplaceBoardNode(m, ast2, boardPath[1:])
69 } else {
70 m.Nodes = ast2.Nodes
71 return true
72 }
73 }
74 }
75
76 if scenariosMap != nil {
77 m := findMap(scenariosMap, boardPath[0])
78 if m != nil {
79 if len(boardPath) > 1 {
80 return ReplaceBoardNode(m, ast2, boardPath[1:])
81 } else {
82 m.Nodes = ast2.Nodes
83 return true
84 }
85 }
86 }
87
88 if stepsMap != nil {
89 m := findMap(stepsMap, boardPath[0])
90 if m != nil {
91 if len(boardPath) > 1 {
92 return ReplaceBoardNode(m, ast2, boardPath[1:])
93 } else {
94 m.Nodes = ast2.Nodes
95 return true
96 }
97 }
98 }
99
100 return false
101 }
102
103 func GetChildrenIDs(g *d2graph.Graph, boardPath []string, absID string) (ids []string, _ error) {
104 g = GetBoardGraph(g, boardPath)
105 if g == nil {
106 return nil, fmt.Errorf("board at path %v not found", boardPath)
107 }
108
109 mk, err := d2parser.ParseMapKey(absID)
110 if err != nil {
111 return nil, err
112 }
113 obj, ok := g.Root.HasChild(d2graph.Key(mk.Key))
114 if !ok {
115 return nil, fmt.Errorf("%v not found", absID)
116 }
117
118 for _, ch := range obj.ChildrenArray {
119 ids = append(ids, ch.AbsID())
120 }
121
122 return ids, nil
123 }
124
125 func GetParentID(g *d2graph.Graph, boardPath []string, absID string) (string, error) {
126 g = GetBoardGraph(g, boardPath)
127 if g == nil {
128 return "", fmt.Errorf("board at path %v not found", boardPath)
129 }
130
131 mk, err := d2parser.ParseMapKey(absID)
132 if err != nil {
133 return "", err
134 }
135 obj, ok := g.Root.HasChild(d2graph.Key(mk.Key))
136 if !ok {
137 return "", fmt.Errorf("%v not found", absID)
138 }
139
140 return obj.Parent.AbsID(), nil
141 }
142
143 func GetObj(g *d2graph.Graph, boardPath []string, absID string) *d2graph.Object {
144 g = GetBoardGraph(g, boardPath)
145 if g == nil {
146 return nil
147 }
148
149 mk, _ := d2parser.ParseMapKey(absID)
150 obj, _ := g.Root.HasChild(d2graph.Key(mk.Key))
151 return obj
152 }
153
154 func GetEdge(g *d2graph.Graph, boardPath []string, absID string) *d2graph.Edge {
155 g = GetBoardGraph(g, boardPath)
156 if g == nil {
157 return nil
158 }
159
160 for _, e := range g.Edges {
161 if e.AbsID() == absID {
162 return e
163 }
164 }
165 return nil
166 }
167
168 func GetObjOrder(g *d2graph.Graph, boardPath []string) ([]string, error) {
169 g = GetBoardGraph(g, boardPath)
170 if g == nil {
171 return nil, fmt.Errorf("board at path %v not found", boardPath)
172 }
173
174 var order []string
175
176 queue := []*d2graph.Object{g.Root}
177 for len(queue) > 0 {
178 curr := queue[0]
179 queue = queue[1:]
180 if curr != g.Root {
181 order = append(order, curr.AbsID())
182 }
183 for _, ch := range curr.ChildrenArray {
184 queue = append(queue, ch)
185 }
186 }
187
188 return order, nil
189 }
190
191 func IsLabelKeyID(key, label string) bool {
192 mk, err := d2parser.ParseMapKey(key)
193 if err != nil {
194 return false
195 }
196 if len(mk.Edges) > 0 {
197 return false
198 }
199 if mk.Key == nil {
200 return false
201 }
202
203 return mk.Key.Path[len(mk.Key.Path)-1].Unbox().ScalarString() == label
204 }
205
206 func GetID(key string) string {
207 mk, err := d2parser.ParseMapKey(key)
208 if err != nil {
209 return ""
210 }
211 if len(mk.Edges) > 0 {
212 return ""
213 }
214 if mk.Key == nil {
215 return ""
216 }
217
218 return d2format.Format(d2ast.RawString(mk.Key.Path[len(mk.Key.Path)-1].Unbox().ScalarString(), true))
219 }
220
View as plain text