[VOL-4023] openonuAdapterGo - Ani side configuration fails while waiting for FlowDeletion, and upgrade looplab/fsm

Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I9053d2ee774ff46c6d3a9cff5743a141bf14ad58
diff --git a/vendor/github.com/looplab/fsm/graphviz_visualizer.go b/vendor/github.com/looplab/fsm/graphviz_visualizer.go
new file mode 100644
index 0000000..4163529
--- /dev/null
+++ b/vendor/github.com/looplab/fsm/graphviz_visualizer.go
@@ -0,0 +1,58 @@
+package fsm
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// Visualize outputs a visualization of a FSM in Graphviz format.
+func Visualize(fsm *FSM) string {
+	var buf bytes.Buffer
+
+	// we sort the key alphabetically to have a reproducible graph output
+	sortedEKeys := getSortedTransitionKeys(fsm.transitions)
+	sortedStateKeys, _ := getSortedStates(fsm.transitions)
+
+	writeHeaderLine(&buf)
+	writeTransitions(&buf, fsm.current, sortedEKeys, fsm.transitions)
+	writeStates(&buf, sortedStateKeys)
+	writeFooter(&buf)
+
+	return buf.String()
+}
+
+func writeHeaderLine(buf *bytes.Buffer) {
+	buf.WriteString(fmt.Sprintf(`digraph fsm {`))
+	buf.WriteString("\n")
+}
+
+func writeTransitions(buf *bytes.Buffer, current string, sortedEKeys []eKey, transitions map[eKey]string) {
+	// make sure the current state is at top
+	for _, k := range sortedEKeys {
+		if k.src == current {
+			v := transitions[k]
+			buf.WriteString(fmt.Sprintf(`    "%s" -> "%s" [ label = "%s" ];`, k.src, v, k.event))
+			buf.WriteString("\n")
+		}
+	}
+	for _, k := range sortedEKeys {
+		if k.src != current {
+			v := transitions[k]
+			buf.WriteString(fmt.Sprintf(`    "%s" -> "%s" [ label = "%s" ];`, k.src, v, k.event))
+			buf.WriteString("\n")
+		}
+	}
+
+	buf.WriteString("\n")
+}
+
+func writeStates(buf *bytes.Buffer, sortedStateKeys []string) {
+	for _, k := range sortedStateKeys {
+		buf.WriteString(fmt.Sprintf(`    "%s";`, k))
+		buf.WriteString("\n")
+	}
+}
+
+func writeFooter(buf *bytes.Buffer) {
+	buf.WriteString(fmt.Sprintln("}"))
+}