/* * Copyright © 2019 IBM. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onap.ccsdk.cds.controllerblueprints.core.data enum class EdgeLabel(val id: String) { SUCCESS("success"), FAILURE("failure"), DEFAULT("*") } enum class EdgeStatus(val id: String) { NOT_STARTED("not_started"), EXECUTED("executed"), SKIPPED("skipped") } enum class NodeStatus(val id: String) { NOT_STARTED("not_started"), READY("ready"), EXECUTING("executing"), EXECUTED("executed"), SKIPPED("skipped"), TERMINATED("terminated") } class Graph { val nodes: MutableMap = hashMapOf() val edges: MutableSet = mutableSetOf() fun addNode(value: String): Node { val node = Node(value) nodes[value] = node return node } fun addEdge(source: String, destination: String, label: EdgeLabel) { if (!nodes.containsKey(source)) { addNode(source) } if (!nodes.containsKey(destination)) { addNode(destination) } val edge = Edge(nodes[source]!!, nodes[destination]!!, label) if (!edges.contains(edge)) { edges.add(edge) nodes[source]!!.edges.add(edge) } } override fun toString(): String { val standaloneNodes = nodes.values.filter { node -> edges.all { it.source != node && it.target != node } } val s = (edges.map { it.toString() } + standaloneNodes.map { it.toString() }).joinToString() return "[$s]" } fun print(): String { val buffer = StringBuffer("Nodes :") nodes.values.forEach { buffer.append("\n\t$it") } buffer.append("\nEdges :") edges.forEach { buffer.append("\n\t$it") } return buffer.toString() } override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false other as Graph return nodes == other.nodes && edges == other.edges } override fun hashCode() = 31 * nodes.hashCode() + edges.hashCode() fun equivalentTo(other: Graph): Boolean { return nodes == other.nodes && edges.all { edge -> other.edges.any { it.equivalentTo(edge) } } } data class Node(val id: String, var status: NodeStatus = NodeStatus.NOT_STARTED) { val edges: MutableList = ArrayList() fun neighbors(): List = edges.map { it.target } fun neighbors(label: EdgeLabel): List = edges.filter { it.label == label } .map { it.target } fun labelEdges(label: EdgeLabel): List = edges.filter { it.label == label } override fun toString() = "$id, Status($status)" } data class Edge( val source: Node, val target: Node, val label: EdgeLabel, var status: EdgeStatus = EdgeStatus.NOT_STARTED ) { fun equivalentTo(other: Edge) = (source == other.source && target == other.target) || (source == other.target && target == other.source) override fun toString() = "${source.id}>${target.id}/$label($status)" } data class TermForm(val nodes: Collection, val edges: List) { data class Term(val source: String, val target: String, val label: EdgeLabel) { override fun toString() = "Term($source, $target, $label)" } } data class AdjacencyList(val entries: List>) { constructor(vararg entries: Entry) : this(entries.asList()) override fun toString() = "AdjacencyList(${entries.joinToString()})" data class Entry(val node: String, val links: List> = emptyList()) { constructor(node: String, vararg links: Link) : this(node, links.asList()) override fun toString() = "Entry($node, links[${links.joinToString()}])" } data class Link(val node: String, val label: EdgeLabel) { override fun toString() = if (label == null) "$node" else "$node/$label" } } companion object { fun labeledDirectedTerms(termForm: TermForm): Graph = createFromTerms(termForm) { graph, n1, n2, value -> graph.addEdge(n1, n2, value) } fun labeledDirectedAdjacent(adjacencyList: AdjacencyList): Graph = fromAdjacencyList(adjacencyList) { graph, n1, n2, value -> graph.addEdge(n1, n2, value) } private fun createFromTerms( termForm: TermForm, addFunction: (Graph, String, String, EdgeLabel) -> Unit ): Graph { val graph = Graph() termForm.nodes.forEach { graph.addNode(it) } termForm.edges.forEach { addFunction(graph, it.source, it.target, it.label) } return graph } private fun fromAdjacencyList( adjacencyList: AdjacencyList, addFunction: (Graph, String, String, EdgeLabel) -> Unit ): Graph { val graph = Graph() adjacencyList.entries.forEach { graph.addNode(it.node) } adjacencyList.entries.forEach { (node, links) -> links.forEach { addFunction(graph, node, it.node, it.label) } } return graph } } }