2 * Copyright © 2019 IBM.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.onap.ccsdk.cds.controllerblueprints.core.data
19 enum class EdgeLabel(val id: String) {
25 enum class EdgeStatus(val id: String) {
26 NOT_STARTED("not_started"),
31 enum class NodeStatus(val id: String) {
32 NOT_STARTED("not_started"),
34 EXECUTING("executing"),
37 TERMINATED("terminated")
41 val nodes: MutableMap<String, Node> = hashMapOf()
42 val edges: MutableSet<Edge> = mutableSetOf()
44 fun addNode(value: String): Node {
45 val node = Node(value)
50 fun addEdge(source: String, destination: String, label: EdgeLabel) {
51 if (!nodes.containsKey(source)) {
54 if (!nodes.containsKey(destination)) {
57 val edge = Edge(nodes[source]!!, nodes[destination]!!, label)
58 if (!edges.contains(edge)) {
60 nodes[source]!!.edges.add(edge)
64 override fun toString(): String {
65 val standaloneNodes = nodes.values.filter { node -> edges.all { it.source != node && it.target != node } }
66 val s = (edges.map { it.toString() } + standaloneNodes.map { it.toString() }).joinToString()
71 val buffer = StringBuffer("Nodes :")
72 nodes.values.forEach {
73 buffer.append("\n\t$it")
75 buffer.append("\nEdges :")
77 buffer.append("\n\t$it")
79 return buffer.toString()
82 override fun equals(other: Any?): Boolean {
83 if (this === other) return true
84 if (other?.javaClass != javaClass) return false
86 return nodes == other.nodes && edges == other.edges
89 override fun hashCode() = 31 * nodes.hashCode() + edges.hashCode()
91 fun equivalentTo(other: Graph): Boolean {
92 return nodes == other.nodes && edges.all { edge -> other.edges.any { it.equivalentTo(edge) } }
95 data class Node(val id: String, var status: NodeStatus = NodeStatus.NOT_STARTED) {
96 val edges: MutableList<Edge> = ArrayList()
98 fun neighbors(): List<Node> = edges.map { edge -> edge.target(this) }
100 fun neighbors(label: EdgeLabel): List<Node> = edges.filter { it.label == label }
101 .map { edge -> edge.target(this) }
103 fun labelEdges(label: EdgeLabel): List<Edge> = edges.filter { it.label == label }
105 override fun toString() = "$id, Status($status)"
111 val label: EdgeLabel,
112 var status: EdgeStatus = EdgeStatus.NOT_STARTED) {
114 fun target(node: Node): Node = target
116 fun equivalentTo(other: Edge) =
117 (source == other.source && target == other.target)
118 || (source == other.target && target == other.source)
120 override fun toString() =
121 "${source.id}>${target.id}/$label($status)"
124 data class TermForm(val nodes: Collection<String>, val edges: List<Term>) {
126 data class Term(val source: String, val target: String, val label: EdgeLabel) {
127 override fun toString() = "Term($source, $target, $label)"
131 data class AdjacencyList<String, out EdgeLabel>(val entries: List<Entry<String, EdgeLabel>>) {
132 constructor(vararg entries: Entry<String, EdgeLabel>) : this(entries.asList())
134 override fun toString() = "AdjacencyList(${entries.joinToString()})"
136 data class Entry<out String, out EdgeLabel>(val node: String, val links: List<Link<String, EdgeLabel>> = emptyList<Nothing>()) {
137 constructor(node: String, vararg links: Link<String, EdgeLabel>) : this(node, links.asList())
139 override fun toString() = "Entry($node, links[${links.joinToString()}])"
142 data class Link<out String, out EdgeLabel>(val node: String, val label: EdgeLabel) {
143 override fun toString() = if (label == null) "$node" else "$node/$label"
149 fun labeledDirectedTerms(termForm: TermForm): Graph =
150 createFromTerms(termForm) { graph, n1, n2, value -> graph.addEdge(n1, n2, value) }
152 fun labeledDirectedAdjacent(adjacencyList: AdjacencyList<String, EdgeLabel>): Graph =
153 fromAdjacencyList(adjacencyList) { graph, n1, n2, value ->
154 graph.addEdge(n1, n2, value)
157 private fun createFromTerms(termForm: TermForm,
158 addFunction: (Graph, String, String, EdgeLabel) -> Unit): Graph {
160 termForm.nodes.forEach { graph.addNode(it) }
161 termForm.edges.forEach { addFunction(graph, it.source, it.target, it.label) }
165 private fun fromAdjacencyList(adjacencyList: AdjacencyList<String, EdgeLabel>,
166 addFunction: (Graph, String, String, EdgeLabel) -> Unit): Graph {
168 adjacencyList.entries.forEach { graph.addNode(it.node) }
169 adjacencyList.entries.forEach { (node, links) ->
170 links.forEach { addFunction(graph, node, it.node, it.label) }