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