6809831f90ba3db2288a6736cbab0048aad4e46e
[ccsdk/cds.git] /
1 /*
2  *  Copyright © 2017-2018 AT&T Intellectual Property.
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.apps.controllerblueprints.resource.dict.service
18
19 import org.apache.commons.lang3.text.StrBuilder
20 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException
21 import org.onap.ccsdk.apps.controllerblueprints.core.utils.TopologicalSortingUtils
22 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.ResourceAssignment
23 import org.onap.ccsdk.apps.controllerblueprints.resource.dict.validator.ResourceAssignmentValidator
24 import org.slf4j.LoggerFactory
25 import org.apache.commons.collections.CollectionUtils
26 import org.apache.commons.lang3.StringUtils
27 import java.io.Serializable
28 /**
29  * ResourceAssignmentValidationService.
30  *
31  * @author Brinda Santh
32  */
33 interface ResourceAssignmentValidationService : Serializable {
34
35     @Throws(BluePrintException::class)
36     fun validate(resourceAssignments: List<ResourceAssignment>): Boolean
37 }
38
39 /**
40  * ResourceAssignmentValidationDefaultService.
41  *
42  * @author Brinda Santh
43  */
44 open class ResourceAssignmentValidationDefaultService : ResourceAssignmentValidationService {
45     private val log = LoggerFactory.getLogger(ResourceAssignmentValidator::class.java)
46     open var resourceAssignments: List<ResourceAssignment> = arrayListOf()
47     open var resourceAssignmentMap: MutableMap<String, ResourceAssignment> = hashMapOf()
48     open val validationMessage = StrBuilder()
49
50     override fun validate(resourceAssignments: List<ResourceAssignment>): Boolean {
51         this.resourceAssignments = resourceAssignments
52         validateSources(resourceAssignments)
53         validateDuplicateDictionaryKeys()
54         validateCyclicDependency()
55         if (StringUtils.isNotBlank(validationMessage)) {
56             throw BluePrintException("Resource Assignment Validation :" + validationMessage.toString())
57         }
58         return true
59     }
60
61     open fun validateSources(resourceAssignments: List<ResourceAssignment>) {
62         log.info("validating resource assignment sources")
63     }
64
65     open fun validateDuplicateDictionaryKeys() {
66         val uniqueDictionaryKeys = hashSetOf<String>()
67
68         this.resourceAssignments.forEach { resourceAssignment ->
69             // Check Duplicate Names
70             if (!resourceAssignmentMap.containsKey(resourceAssignment.name)) {
71                 resourceAssignmentMap[resourceAssignment.name] = resourceAssignment
72             } else {
73                 validationMessage.appendln(String.format("Duplicate Assignment Template Key (%s) is Present",
74                         resourceAssignment.name))
75             }
76             // Check duplicate Dictionary Keys
77             if (!uniqueDictionaryKeys.contains(resourceAssignment.dictionaryName!!)) {
78                 uniqueDictionaryKeys.add(resourceAssignment.dictionaryName!!)
79             } else {
80                 validationMessage.appendln(
81                         String.format("Duplicate Assignment Dictionary Key (%s) present with Template Key (%s)",
82                                 resourceAssignment.dictionaryName, resourceAssignment.name))
83             }
84         }
85     }
86
87     open fun validateCyclicDependency() {
88         val startResourceAssignment = ResourceAssignment()
89         startResourceAssignment.name = "*"
90
91         val topologySorting = TopologicalSortingUtils<ResourceAssignment>()
92         this.resourceAssignmentMap.forEach { assignmentKey, assignment ->
93             if (CollectionUtils.isNotEmpty(assignment.dependencies)) {
94                 for (dependency in assignment.dependencies!!) {
95                     topologySorting.add(resourceAssignmentMap[dependency]!!, assignment)
96                 }
97             } else {
98                 topologySorting.add(startResourceAssignment, assignment)
99             }
100         }
101
102         if (!topologySorting.isDag) {
103             val graph = getTopologicalGraph(topologySorting)
104             validationMessage.appendln("Cyclic Dependency :$graph")
105         }
106     }
107
108     open fun getTopologicalGraph(topologySorting: TopologicalSortingUtils<ResourceAssignment>): String {
109         val s = StringBuilder()
110         val neighbors = topologySorting.getNeighbors()
111
112         neighbors.forEach { v, vs ->
113             if (v.name == "*") {
114                 s.append("\n    * -> [")
115                 for (resourceAssignment in vs) {
116                     s.append("(" + resourceAssignment.dictionaryName + ":" + resourceAssignment.name
117                             + "),")
118                 }
119                 s.append("]")
120             } else {
121                 s.append("\n    (" + v.dictionaryName + ":" + v.name + ") -> [")
122                 for (resourceAssignment in vs) {
123                     s.append("(" + resourceAssignment.dictionaryName + ":" + resourceAssignment.name
124                             + "),")
125                 }
126                 s.append("]")
127             }
128         }
129         return s.toString()
130     }
131
132
133 }