2  *  Copyright © 2017-2018 AT&T Intellectual Property.
 
   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.apps.controllerblueprints.resource.dict.service
 
  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
 
  29  * ResourceAssignmentValidationService.
 
  31  * @author Brinda Santh
 
  33 interface ResourceAssignmentValidationService : Serializable {
 
  35     @Throws(BluePrintException::class)
 
  36     fun validate(resourceAssignments: List<ResourceAssignment>): Boolean
 
  40  * ResourceAssignmentValidationDefaultService.
 
  42  * @author Brinda Santh
 
  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()
 
  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())
 
  61     open fun validateSources(resourceAssignments: List<ResourceAssignment>) {
 
  62         log.info("validating resource assignment sources")
 
  65     open fun validateDuplicateDictionaryKeys() {
 
  66         val uniqueDictionaryKeys = hashSetOf<String>()
 
  68         this.resourceAssignments.forEach { resourceAssignment ->
 
  69             // Check Duplicate Names
 
  70             if (!resourceAssignmentMap.containsKey(resourceAssignment.name)) {
 
  71                 resourceAssignmentMap[resourceAssignment.name] = resourceAssignment
 
  73                 validationMessage.appendln(String.format("Duplicate Assignment Template Key (%s) is Present",
 
  74                         resourceAssignment.name))
 
  76             // Check duplicate Dictionary Keys
 
  77             if (!uniqueDictionaryKeys.contains(resourceAssignment.dictionaryName!!)) {
 
  78                 uniqueDictionaryKeys.add(resourceAssignment.dictionaryName!!)
 
  80                 validationMessage.appendln(
 
  81                         String.format("Duplicate Assignment Dictionary Key (%s) present with Template Key (%s)",
 
  82                                 resourceAssignment.dictionaryName, resourceAssignment.name))
 
  87     open fun validateCyclicDependency() {
 
  88         val startResourceAssignment = ResourceAssignment()
 
  89         startResourceAssignment.name = "*"
 
  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)
 
  98                 topologySorting.add(startResourceAssignment, assignment)
 
 102         if (!topologySorting.isDag) {
 
 103             val graph = getTopologicalGraph(topologySorting)
 
 104             validationMessage.appendln("Cyclic Dependency :$graph")
 
 108     open fun getTopologicalGraph(topologySorting: TopologicalSortingUtils<ResourceAssignment>): String {
 
 109         val s = StringBuilder()
 
 110         val neighbors = topologySorting.getNeighbors()
 
 112         neighbors.forEach { v, vs ->
 
 114                 s.append("\n    * -> [")
 
 115                 for (resourceAssignment in vs) {
 
 116                     s.append("(" + resourceAssignment.dictionaryName + ":" + resourceAssignment.name
 
 121                 s.append("\n    (" + v.dictionaryName + ":" + v.name + ") -> [")
 
 122                 for (resourceAssignment in vs) {
 
 123                     s.append("(" + resourceAssignment.dictionaryName + ":" + resourceAssignment.name