Fixing Blueprint Typo's and docs
[ccsdk/cds.git] / ms / blueprintsprocessor / modules / blueprints / blueprint-core / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / core / data / BluePrintGraph.kt
1 /*
2  *  Copyright © 2019 IBM.
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16
17 package org.onap.ccsdk.cds.controllerblueprints.core.data
18
19 enum class EdgeLabel(val id: String) {
20     SUCCESS("success"),
21     FAILURE("failure"),
22     DEFAULT("*")
23 }
24
25 enum class EdgeStatus(val id: String) {
26     NOT_STARTED("not_started"),
27     EXECUTED("executed"),
28     SKIPPED("skipped")
29 }
30
31 enum class NodeStatus(val id: String) {
32     NOT_STARTED("not_started"),
33     READY("ready"),
34     EXECUTING("executing"),
35     EXECUTED("executed"),
36     SKIPPED("skipped"),
37     TERMINATED("terminated")
38 }
39
40 class Graph {
41
42     val nodes: MutableMap<String, Node> = hashMapOf()
43     val edges: MutableSet<Edge> = mutableSetOf()
44
45     fun addNode(value: String): Node {
46         val node = Node(value)
47         nodes[value] = node
48         return node
49     }
50
51     fun addEdge(source: String, destination: String, label: EdgeLabel) {
52         if (!nodes.containsKey(source)) {
53             addNode(source)
54         }
55         if (!nodes.containsKey(destination)) {
56             addNode(destination)
57         }
58         val edge = Edge(nodes[source]!!, nodes[destination]!!, label)
59         if (!edges.contains(edge)) {
60             edges.add(edge)
61             nodes[source]!!.edges.add(edge)
62         }
63     }
64
65     override fun toString(): String {
66         val standaloneNodes = nodes.values.filter { node -> edges.all { it.source != node && it.target != node } }
67         val s = (edges.map { it.toString() } + standaloneNodes.map { it.toString() }).joinToString()
68         return "[$s]"
69     }
70
71     fun print(): String {
72         val buffer = StringBuffer("Nodes :")
73         nodes.values.forEach {
74             buffer.append("\n\t$it")
75         }
76         buffer.append("\nEdges :")
77         edges.forEach {
78             buffer.append("\n\t$it")
79         }
80         return buffer.toString()
81     }
82
83     override fun equals(other: Any?): Boolean {
84         if (this === other) return true
85         if (other?.javaClass != javaClass) return false
86         other as Graph
87         return nodes == other.nodes && edges == other.edges
88     }
89
90     override fun hashCode() = 31 * nodes.hashCode() + edges.hashCode()
91
92     fun equivalentTo(other: Graph): Boolean {
93         return nodes == other.nodes && edges.all { edge -> other.edges.any { it.equivalentTo(edge) } }
94     }
95
96     data class Node(val id: String, var status: NodeStatus = NodeStatus.NOT_STARTED) {
97
98         val edges: MutableList<Edge> = ArrayList()
99
100         fun neighbors(): List<Node> = edges.map { edge -> edge.target(this) }
101
102         fun neighbors(label: EdgeLabel): List<Node> = edges.filter { it.label == label }
103             .map { edge -> edge.target(this) }
104
105         fun labelEdges(label: EdgeLabel): List<Edge> = edges.filter { it.label == label }
106
107         override fun toString() = "$id, Status($status)"
108     }
109
110     data class Edge(
111         val source: Node,
112         val target: Node,
113         val label: EdgeLabel,
114         var status: EdgeStatus = EdgeStatus.NOT_STARTED
115     ) {
116
117         fun target(node: Node): Node = target
118
119         fun equivalentTo(other: Edge) =
120             (source == other.source && target == other.target) ||
121                 (source == other.target && target == other.source)
122
123         override fun toString() =
124             "${source.id}>${target.id}/$label($status)"
125     }
126
127     data class TermForm(val nodes: Collection<String>, val edges: List<Term>) {
128
129         data class Term(val source: String, val target: String, val label: EdgeLabel) {
130
131             override fun toString() = "Term($source, $target, $label)"
132         }
133     }
134
135     data class AdjacencyList<String, out EdgeLabel>(val entries: List<Entry<String, EdgeLabel>>) {
136         constructor(vararg entries: Entry<String, EdgeLabel>) : this(entries.asList())
137
138         override fun toString() = "AdjacencyList(${entries.joinToString()})"
139
140         data class Entry<out String, out EdgeLabel>(val node: String, val links: List<Link<String, EdgeLabel>> = emptyList<Nothing>()) {
141             constructor(node: String, vararg links: Link<String, EdgeLabel>) : this(node, links.asList())
142
143             override fun toString() = "Entry($node, links[${links.joinToString()}])"
144         }
145
146         data class Link<out String, out EdgeLabel>(val node: String, val label: EdgeLabel) {
147
148             override fun toString() = if (label == null) "$node" else "$node/$label"
149         }
150     }
151
152     companion object {
153
154         fun labeledDirectedTerms(termForm: TermForm): Graph =
155             createFromTerms(termForm) { graph, n1, n2, value -> graph.addEdge(n1, n2, value) }
156
157         fun labeledDirectedAdjacent(adjacencyList: AdjacencyList<String, EdgeLabel>): Graph =
158             fromAdjacencyList(adjacencyList) { graph, n1, n2, value ->
159                 graph.addEdge(n1, n2, value)
160             }
161
162         private fun createFromTerms(
163             termForm: TermForm,
164             addFunction: (Graph, String, String, EdgeLabel) -> Unit
165         ): Graph {
166             val graph = Graph()
167             termForm.nodes.forEach { graph.addNode(it) }
168             termForm.edges.forEach { addFunction(graph, it.source, it.target, it.label) }
169             return graph
170         }
171
172         private fun fromAdjacencyList(
173             adjacencyList: AdjacencyList<String, EdgeLabel>,
174             addFunction: (Graph, String, String, EdgeLabel) -> Unit
175         ): Graph {
176             val graph = Graph()
177             adjacencyList.entries.forEach { graph.addNode(it.node) }
178             adjacencyList.entries.forEach { (node, links) ->
179                 links.forEach { addFunction(graph, node, it.node, it.label) }
180             }
181             return graph
182         }
183     }
184 }