2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
 
   6  * ================================================================================
 
   7  * Licensed under the Apache License, Version 2.0 (the "License");
 
   8  * you may not use this file except in compliance with the License.
 
   9  * You may obtain a copy of the License at
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  13  * Unless required by applicable law or agreed to in writing, software
 
  14  * distributed under the License is distributed on an "AS IS" BASIS,
 
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  16  * See the License for the specific language governing permissions and
 
  17  * limitations under the License.
 
  18  * ============LICENSE_END=========================================================
 
  21 package org.openecomp.sdc.vendorsoftwareproduct.services.impl.composition;
 
  23 import org.apache.commons.collections4.CollectionUtils;
 
  24 import org.apache.commons.collections4.MapUtils;
 
  25 import org.openecomp.core.utilities.CommonMethods;
 
  26 import org.openecomp.core.utilities.json.JsonSchemaDataGenerator;
 
  27 import org.openecomp.core.utilities.json.JsonUtil;
 
  28 import org.openecomp.sdc.common.errors.CoreException;
 
  29 import org.openecomp.sdc.common.errors.ErrorCategory;
 
  30 import org.openecomp.sdc.common.errors.ErrorCode;
 
  31 import org.openecomp.sdc.logging.api.Logger;
 
  32 import org.openecomp.sdc.logging.api.LoggerFactory;
 
  33 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
 
  34 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDao;
 
  35 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComputeDao;
 
  36 import org.openecomp.sdc.vendorsoftwareproduct.dao.DeploymentFlavorDao;
 
  37 import org.openecomp.sdc.vendorsoftwareproduct.dao.ImageDao;
 
  38 import org.openecomp.sdc.vendorsoftwareproduct.dao.NetworkDao;
 
  39 import org.openecomp.sdc.vendorsoftwareproduct.dao.NicDao;
 
  40 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductDao;
 
  41 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
 
  42 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
 
  43 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.CompositionEntity;
 
  44 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComputeEntity;
 
  45 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.DeploymentFlavorEntity;
 
  46 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ImageEntity;
 
  47 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NetworkEntity;
 
  48 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NicEntity;
 
  49 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
 
  50 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspQuestionnaireEntity;
 
  51 import org.openecomp.sdc.vendorsoftwareproduct.services.composition.CompositionEntityDataManager;
 
  52 import org.openecomp.sdc.vendorsoftwareproduct.services.schemagenerator.SchemaGenerator;
 
  53 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Component;
 
  54 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentComputeAssociation;
 
  55 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentData;
 
  56 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionData;
 
  57 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityId;
 
  58 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityType;
 
  59 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityValidationData;
 
  60 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComputeData;
 
  61 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.DeploymentFlavor;
 
  62 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Image;
 
  63 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Network;
 
  64 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.NetworkType;
 
  65 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
 
  66 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateContext;
 
  67 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateInput;
 
  68 import org.openecomp.sdc.versioning.dao.types.Version;
 
  70 import java.util.ArrayList;
 
  71 import java.util.Collection;
 
  72 import java.util.HashMap;
 
  73 import java.util.HashSet;
 
  74 import java.util.List;
 
  76 import java.util.Objects;
 
  79 public class CompositionEntityDataManagerImpl implements CompositionEntityDataManager {
 
  81   private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR =
 
  82           "COMPOSITION_ENTITY_DATA_MANAGER_ERR";
 
  83   private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG =
 
  84           "Invalid input: %s may not be null";
 
  86   private static final Logger logger =
 
  87           LoggerFactory.getLogger(CompositionEntityDataManagerImpl.class);
 
  88   private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
 
  90   private Map<CompositionEntityId, CompositionEntityData> entities = new HashMap<>();
 
  91   private Map<CompositionEntityType, String> nonDynamicSchemas = new HashMap<>();
 
  92   private List<CompositionEntityValidationData> roots = new ArrayList<>();
 
  94   private VendorSoftwareProductInfoDao vspInfoDao;
 
  95   private ComponentDao componentDao;
 
  96   private NicDao nicDao;
 
  97   private NetworkDao networkDao;
 
  98   private ImageDao imageDao;
 
  99   private ComputeDao computeDao;
 
 100   private DeploymentFlavorDao deploymentFlavorDao;
 
 101   private VendorSoftwareProductDao vendorSoftwareProductDao;
 
 103   public CompositionEntityDataManagerImpl(VendorSoftwareProductInfoDao vspInfoDao,
 
 104                                           ComponentDao componentDao,
 
 105                                           NicDao nicDao, NetworkDao networkDao,
 
 106                                           ImageDao imageDao, ComputeDao computeDao,
 
 107                                           DeploymentFlavorDao deploymentFlavorDao,
 
 108                                           VendorSoftwareProductDao vendorSoftwareProductDao ) {
 
 109     this.vspInfoDao = vspInfoDao;
 
 110     this.componentDao = componentDao;
 
 111     this.nicDao = nicDao;
 
 112     this.networkDao = networkDao;
 
 113     this.imageDao = imageDao;
 
 114     this.computeDao = computeDao;
 
 115     this.deploymentFlavorDao = deploymentFlavorDao;
 
 116     this.vendorSoftwareProductDao = vendorSoftwareProductDao;
 
 120    * Validate entity composition entity validation data.
 
 122    * @param entity                the entity
 
 123    * @param schemaTemplateContext the schema template context
 
 124    * @param schemaTemplateInput   the schema template input
 
 125    * @return the composition entity validation data
 
 128   public CompositionEntityValidationData validateEntity(CompositionEntity entity,
 
 129                                                         SchemaTemplateContext schemaTemplateContext,
 
 130                                                         SchemaTemplateInput schemaTemplateInput) {
 
 131     mdcDataDebugMessage.debugEntryMessage(null);
 
 133     if (entity == null) {
 
 134       throw new CoreException(
 
 135               new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
 
 136                       .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
 
 137                       String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
 
 140     if (schemaTemplateContext == null) {
 
 141       throw new CoreException(
 
 142               new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
 
 143                       .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
 
 144                       String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "schema template context"))
 
 148     CompositionEntityValidationData validationData =
 
 149             new CompositionEntityValidationData(entity.getType(), entity.getId());
 
 151             schemaTemplateContext == SchemaTemplateContext.composition ? entity.getCompositionData()
 
 152                     : entity.getQuestionnaireData();
 
 153     validationData.setErrors(JsonUtil.validate(
 
 154             json == null ? JsonUtil.object2Json(new Object()) : json,
 
 155             generateSchema(schemaTemplateContext, entity.getType(), schemaTemplateInput)));
 
 157     mdcDataDebugMessage.debugExitMessage(null);
 
 158     return validationData;
 
 164    * @param entity              the entity
 
 165    * @param schemaTemplateInput the schema template input
 
 168   public void addEntity(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
 
 169     if (entity == null) {
 
 170       throw new CoreException(
 
 171               new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
 
 172                       .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
 
 173                       String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
 
 176     entities.put(entity.getCompositionEntityId(),
 
 177             new CompositionEntityData(entity, schemaTemplateInput));
 
 181    * Validate entities questionnaire map.
 
 186   public Map<CompositionEntityId, Collection<String>> validateEntitiesQuestionnaire() {
 
 187     mdcDataDebugMessage.debugEntryMessage(null);
 
 189     Map<CompositionEntityId, Collection<String>> errorsByEntityId = new HashMap<>();
 
 190     entities.entrySet().forEach(entry -> {
 
 191       Collection<String> errors = validateQuestionnaire(entry.getValue());
 
 192       if (errors != null) {
 
 193         errorsByEntityId.put(entry.getKey(), errors);
 
 197     mdcDataDebugMessage.debugExitMessage(null);
 
 198     return errorsByEntityId;
 
 205   public void buildTrees() {
 
 206     Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData =
 
 208     entities.entrySet().forEach(
 
 209             entry -> addValidationDataEntity(entitiesValidationData, entry.getKey(),
 
 210                     entry.getValue().entity));
 
 213   public Collection<CompositionEntityValidationData> getTrees() {
 
 218   public void saveCompositionData(String vspId, Version version, CompositionData compositionData) {
 
 219     mdcDataDebugMessage.debugEntryMessage(null);
 
 221     if (Objects.isNull(compositionData)) {
 
 225     Map<String, String> networkIdByName = saveNetworks(vspId, version, compositionData);
 
 226     saveComponents(vspId, version, compositionData, networkIdByName);
 
 228     mdcDataDebugMessage.debugExitMessage(null);
 
 232   public Set<CompositionEntityValidationData> getAllErrorsByVsp(String vspId) {
 
 233     CompositionEntityValidationData matchVsp = null;
 
 234     Set<CompositionEntityValidationData> entitiesWithErrors = new HashSet<>();
 
 235     for (CompositionEntityValidationData root : roots) {
 
 236       if (root.getEntityId().equals(vspId)) {
 
 242     getEntityListWithErrors(matchVsp, entitiesWithErrors);
 
 243     if (CollectionUtils.isNotEmpty(entitiesWithErrors)) {
 
 244       updateValidationCompositionEntityName(entitiesWithErrors);
 
 245       return entitiesWithErrors;
 
 251   private boolean isThereErrorsInSubTree(CompositionEntityValidationData entity) {
 
 252     if (Objects.isNull(entity)) {
 
 256     if (CollectionUtils.isNotEmpty(entity.getErrors())) {
 
 260     Collection<CompositionEntityValidationData> subEntitiesValidationData =
 
 261             entity.getSubEntitiesValidationData();
 
 262     return !CollectionUtils.isEmpty(subEntitiesValidationData) &&
 
 263             checkForErrorsInChildren(subEntitiesValidationData);
 
 267   private boolean checkForErrorsInChildren(
 
 268           Collection<CompositionEntityValidationData> subEntitiesValidationData) {
 
 269     boolean result = false;
 
 270     for (CompositionEntityValidationData subEntity : subEntitiesValidationData) {
 
 271       if (CollectionUtils.isNotEmpty(subEntity.getErrors())) {
 
 275       result = result || isThereErrorsInSubTree(subEntity);
 
 283   public void saveComponents(String vspId, Version version, CompositionData compositionData,
 
 284                              Map<String, String> networkIdByName) {
 
 287     mdcDataDebugMessage.debugEntryMessage(null);
 
 289     if (CollectionUtils.isNotEmpty(compositionData.getComponents())) {
 
 290       for (Component component : compositionData.getComponents()) {
 
 291         ComponentEntity componentEntity = new ComponentEntity(vspId, version, null);
 
 292         componentEntity.setComponentCompositionData(component.getData());
 
 294         String componentId = createComponent(componentEntity).getId();
 
 296         saveImagesByComponent(vspId, version, component, componentId);
 
 297         saveComputesFlavorByComponent(vspId, version, component, componentId);
 
 299         saveNicsByComponent(vspId, version, networkIdByName, component, componentId);
 
 303     mdcDataDebugMessage.debugExitMessage(null);
 
 306   public void saveNicsByComponent(String vspId, Version version,
 
 307                                   Map<String, String> networkIdByName, Component component,
 
 308                                   String componentId) {
 
 309     if (CollectionUtils.isNotEmpty(component.getNics())) {
 
 310       for (Nic nic : component.getNics()) {
 
 311         if (nic.getNetworkName() != null && MapUtils.isNotEmpty(networkIdByName)) {
 
 312           nic.setNetworkId(networkIdByName.get(nic.getNetworkName()));
 
 314         nic.setNetworkName(null);
 
 315         //For heat flow set network type to be internal by default for NIC
 
 316         nic.setNetworkType(NetworkType.Internal);
 
 318         NicEntity nicEntity = new NicEntity(vspId, version, componentId, null);
 
 319         nicEntity.setNicCompositionData(nic);
 
 320         createNic(nicEntity);
 
 325   public Map<String, String> saveNetworks(String vspId, Version version,
 
 326                                           CompositionData compositionData) {
 
 327     mdcDataDebugMessage.debugEntryMessage(null);
 
 329     Map<String, String> networkIdByName = new HashMap<>();
 
 330     if (CollectionUtils.isNotEmpty(compositionData.getNetworks())) {
 
 331       for (Network network : compositionData.getNetworks()) {
 
 333         NetworkEntity networkEntity = new NetworkEntity(vspId, version, null);
 
 334         networkEntity.setNetworkCompositionData(network);
 
 336         if (network.getName() != null) {
 
 337           networkIdByName.put(network.getName(), createNetwork(networkEntity).getId());
 
 342     mdcDataDebugMessage.debugExitMessage(null);
 
 343     return networkIdByName;
 
 347   public NetworkEntity createNetwork(NetworkEntity network) {
 
 348     mdcDataDebugMessage.debugEntryMessage(null);
 
 350     //network.setId(CommonMethods.nextUuId()); will be set by the dao
 
 351     networkDao.create(network);
 
 352     mdcDataDebugMessage.debugExitMessage(null);
 
 357   public ComponentEntity createComponent(ComponentEntity component) {
 
 358     mdcDataDebugMessage.debugEntryMessage(null);
 
 360     //component.setId(CommonMethods.nextUuId()); will be set by the dao
 
 361     component.setQuestionnaireData(
 
 362             new JsonSchemaDataGenerator(
 
 363                     generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.component,
 
 367     componentDao.create(component);
 
 369     mdcDataDebugMessage.debugExitMessage(null);
 
 374   public NicEntity createNic(NicEntity nic) {
 
 375     mdcDataDebugMessage.debugEntryMessage(null);
 
 377     //nic.setId(CommonMethods.nextUuId()); will be set by the dao
 
 378     nic.setQuestionnaireData(
 
 379             new JsonSchemaDataGenerator(
 
 380                     generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.nic, null))
 
 385     mdcDataDebugMessage.debugExitMessage(null);
 
 390   public void addErrorsToTrees(Map<CompositionEntityId, Collection<String>> errors) {
 
 391     roots.forEach(root -> addErrorsToTree(root, null, errors));
 
 395   * get a flat list of all questionnaire entities that have validation errors
 
 397   public Set<CompositionEntityValidationData> getEntityListWithErrors() {
 
 398     mdcDataDebugMessage.debugEntryMessage(null);
 
 399     Set<CompositionEntityValidationData> treeAsList = new HashSet<>();
 
 401     for (CompositionEntityValidationData entity : roots) {
 
 402       if (CollectionUtils.isNotEmpty(entity.getErrors())) {
 
 403         addNodeWithErrors(entity, treeAsList);
 
 405       getEntityListWithErrors(entity, treeAsList);
 
 408     updateValidationCompositionEntityName(treeAsList);
 
 410     mdcDataDebugMessage.debugExitMessage(null);
 
 414   public void getEntityListWithErrors(CompositionEntityValidationData entity,
 
 415                                       Set<CompositionEntityValidationData> compositionSet) {
 
 416     Collection<CompositionEntityValidationData> childNodes =
 
 417             entity.getSubEntitiesValidationData();
 
 419     if (CollectionUtils.isEmpty(childNodes)) {
 
 423     for (CompositionEntityValidationData child : childNodes) {
 
 424       if (CollectionUtils.isNotEmpty(child.getErrors())) {
 
 425         addNodeWithErrors(child, compositionSet);
 
 427       getEntityListWithErrors(child, compositionSet);
 
 432   public void addNodeWithErrors(CompositionEntityValidationData node,
 
 433                                 Set<CompositionEntityValidationData> entitiesWithErrors) {
 
 434     CompositionEntityValidationData compositionNodeToAdd = new CompositionEntityValidationData(node
 
 435             .getEntityType(), node.getEntityId());
 
 436     compositionNodeToAdd.setErrors(node.getErrors());
 
 437     compositionNodeToAdd.setSubEntitiesValidationData(null);
 
 439     entitiesWithErrors.add(compositionNodeToAdd);
 
 442   public void removeNodesWithoutErrors() {
 
 443     roots.forEach(root -> removeNodesWithoutErrors(root, null));
 
 447   private CompositionEntityData getCompositionEntityDataById(CompositionEntityValidationData
 
 449     for (Map.Entry<CompositionEntityId, CompositionEntityData> entityEntry : entities
 
 451       if (entityEntry.getKey().getId().equals(entity.getEntityId())) {
 
 452         return entityEntry.getValue();
 
 459   private void updateValidationCompositionEntityName(Set<CompositionEntityValidationData>
 
 461     for (CompositionEntityValidationData entity : compositionSet) {
 
 462       String compositionData = getCompositionDataAsString(entity);
 
 463       if (entity.getEntityType().equals(CompositionEntityType.vsp) ||
 
 464               Objects.nonNull(compositionData)) {
 
 465         entity.setEntityName(getEntityNameByEntityType(compositionData, entity));
 
 470   private String getCompositionDataAsString(CompositionEntityValidationData entity) {
 
 471     CompositionEntityData compositionEntityData = getCompositionEntityDataById(entity);
 
 472     return compositionEntityData == null ? null : compositionEntityData.entity.getCompositionData();
 
 476   private String getEntityNameByEntityType(String compositionData,
 
 477                                            CompositionEntityValidationData entity) {
 
 478     switch (entity.getEntityType()) {
 
 480         ComponentData component = JsonUtil.json2Object(compositionData, ComponentData.class);
 
 481         return component.getDisplayName();
 
 484         Nic nic = JsonUtil.json2Object(compositionData, Nic.class);
 
 485         return nic.getName();
 
 488         Network network = JsonUtil.json2Object(compositionData, Network.class);
 
 489         return network.getName();
 
 492         Image image = JsonUtil.json2Object(compositionData, Image.class);
 
 493         return image.getFileName();
 
 496         CompositionEntityData vspEntity = getCompositionEntityDataById(entity);
 
 497         VspQuestionnaireEntity vspQuestionnaireEntity = (VspQuestionnaireEntity) vspEntity.entity;
 
 498         VspDetails vspDetails =
 
 499                 vspInfoDao.get(new VspDetails(vspQuestionnaireEntity.getId(),
 
 500                         vspQuestionnaireEntity.getVersion()));
 
 501         return vspDetails.getName();
 
 507   private void removeNodesWithoutErrors(CompositionEntityValidationData node,
 
 508                                         CompositionEntityValidationData parent) {
 
 510     if (Objects.isNull(node)) {
 
 514     if (hasChildren(node)) {
 
 515       Collection<CompositionEntityValidationData> subNodes =
 
 516               new ArrayList<>(node.getSubEntitiesValidationData());
 
 517       subNodes.forEach(subNode -> removeNodesWithoutErrors(subNode, node));
 
 518       node.setSubEntitiesValidationData(subNodes);
 
 520       if (canNodeGetRemovedFromValidationDataTree(node)) {
 
 521         removeNodeFromChildren(parent, node);
 
 523     } else if (canNodeGetRemovedFromValidationDataTree(node)) {
 
 524       removeNodeFromChildren(parent, node);
 
 528   private void removeNodeFromChildren(CompositionEntityValidationData parent,
 
 529                                       CompositionEntityValidationData childToRemove) {
 
 530     if (!Objects.isNull(parent)) {
 
 531       parent.getSubEntitiesValidationData().remove(childToRemove);
 
 535   private boolean hasChildren(CompositionEntityValidationData node) {
 
 536     return !CollectionUtils.isEmpty(node.getSubEntitiesValidationData());
 
 539   private boolean canNodeGetRemovedFromValidationDataTree(CompositionEntityValidationData node) {
 
 540     return !hasChildren(node) && CollectionUtils.isEmpty(node.getErrors());
 
 544   private void addValidationDataEntity(
 
 545           Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData,
 
 546           CompositionEntityId entityId, CompositionEntity entity) {
 
 547     if (entitiesValidationData.containsKey(entityId)) {
 
 551     CompositionEntityValidationData validationData =
 
 552             new CompositionEntityValidationData(entity.getType(), entity.getId());
 
 553     entitiesValidationData.put(entityId, validationData);
 
 555     CompositionEntityId parentEntityId = entityId.getParentId();
 
 556     if (parentEntityId == null) {
 
 557       roots.add(validationData);
 
 559       CompositionEntityData parentEntity = entities.get(parentEntityId);
 
 560       if (parentEntity == null) {
 
 561         roots.add(validationData);
 
 563         addValidationDataEntity(entitiesValidationData, parentEntityId, parentEntity.entity);
 
 564         entitiesValidationData.get(parentEntityId).addSubEntityValidationData(validationData);
 
 569   private void addErrorsToTree(CompositionEntityValidationData node,
 
 570                                CompositionEntityId parentNodeId,
 
 571                                Map<CompositionEntityId, Collection<String>> errors) {
 
 575     CompositionEntityId nodeId = new CompositionEntityId(node.getEntityId(), parentNodeId);
 
 576     node.setErrors(errors.get(nodeId));
 
 578     if (node.getSubEntitiesValidationData() != null) {
 
 579       node.getSubEntitiesValidationData()
 
 580               .forEach(subNode -> addErrorsToTree(subNode, nodeId, errors));
 
 584   private Collection<String> validateQuestionnaire(CompositionEntityData compositionEntityData) {
 
 585     logger.debug(String.format("validateQuestionnaire start:  " +
 
 586                     "[entity.type]=%s, [entity.id]=%s, [entity.questionnaireString]=%s",
 
 587             compositionEntityData.entity.getType().name(),
 
 588             compositionEntityData.entity.getCompositionEntityId().toString(),
 
 589             compositionEntityData.entity.getQuestionnaireData()));
 
 591     if(Objects.isNull(compositionEntityData.entity.getQuestionnaireData()) || !JsonUtil.isValidJson
 
 592             (compositionEntityData.entity.getQuestionnaireData())){
 
 593       List<String> errors = new ArrayList<>();
 
 594       errors.add("Data is missing for the above " + compositionEntityData.entity.getType() +
 
 595               ". Complete the mandatory fields and resubmit.");
 
 599     return JsonUtil.validate(
 
 600             compositionEntityData.entity.getQuestionnaireData() == null
 
 601                     ? JsonUtil.object2Json(new Object())
 
 602                     : compositionEntityData.entity.getQuestionnaireData(),
 
 603             getSchema(compositionEntityData.entity.getType(), SchemaTemplateContext.questionnaire,
 
 604                     compositionEntityData.schemaTemplateInput));
 
 607   private String getSchema(CompositionEntityType compositionEntityType,
 
 608                            SchemaTemplateContext schemaTemplateContext,
 
 609                            SchemaTemplateInput schemaTemplateInput) {
 
 610     return schemaTemplateInput == null
 
 611             ? nonDynamicSchemas.computeIfAbsent(compositionEntityType,
 
 612             k -> generateSchema(schemaTemplateContext, compositionEntityType, null))
 
 613             : generateSchema(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
 
 616   private static class CompositionEntityData {
 
 617     private CompositionEntity entity;
 
 618     private SchemaTemplateInput schemaTemplateInput;
 
 620     CompositionEntityData(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
 
 621       this.entity = entity;
 
 622       this.schemaTemplateInput = schemaTemplateInput;
 
 627   // todo - make SchemaGenerator non static and mock it in UT instead of mocking this method (and
 
 628   // make the method private
 
 630   protected String generateSchema(SchemaTemplateContext schemaTemplateContext,
 
 631                                   CompositionEntityType compositionEntityType,
 
 632                                   SchemaTemplateInput schemaTemplateInput) {
 
 633     return SchemaGenerator
 
 634             .generate(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
 
 638   public DeploymentFlavorEntity createDeploymentFlavor(DeploymentFlavorEntity deploymentFlavor) {
 
 639     mdcDataDebugMessage.debugEntryMessage(null, null);
 
 641     deploymentFlavor.setId(CommonMethods.nextUuId());
 
 642     deploymentFlavorDao.create(deploymentFlavor);
 
 643     return deploymentFlavor;
 
 647   public ImageEntity createImage(ImageEntity image) {
 
 648     mdcDataDebugMessage.debugEntryMessage(null, null);
 
 650     image.setId(CommonMethods.nextUuId());
 
 652     image.setQuestionnaireData(
 
 653             new JsonSchemaDataGenerator(SchemaGenerator
 
 654                     .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.image, null))
 
 657     imageDao.create(image);
 
 658     mdcDataDebugMessage.debugExitMessage(null, null);
 
 663   public ComputeEntity createCompute(ComputeEntity compute) {
 
 664     mdcDataDebugMessage.debugEntryMessage("VSP id, component id", compute.getVspId(),
 
 665             compute.getComponentId());
 
 667     compute.setId(CommonMethods.nextUuId());
 
 668     compute.setQuestionnaireData(
 
 669             new JsonSchemaDataGenerator(SchemaGenerator
 
 670                     .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.compute,
 
 671                             null)).generateData());
 
 673     computeDao.create(compute);
 
 675     mdcDataDebugMessage.debugExitMessage("VSP id, component id", compute.getVspId(),
 
 676             compute.getComponentId());
 
 680   public void saveComputesFlavorByComponent(String vspId, Version version, Component component, String
 
 682     if (CollectionUtils.isNotEmpty(component.getCompute())) {
 
 683       for (ComputeData flavor : component.getCompute()) {
 
 684         ComputeEntity computeEntity = new ComputeEntity(vspId, version, componentId, null);
 
 685         computeEntity.setComputeCompositionData(flavor);
 
 686         createCompute(computeEntity);
 
 691   public void saveImagesByComponent(String vspId, Version version, Component component, String
 
 693     if (CollectionUtils.isNotEmpty(component.getImages())) {
 
 694       for (Image img : component.getImages()) {
 
 695         ImageEntity imageEntity = new ImageEntity(vspId, version, componentId, null);
 
 696         imageEntity.setImageCompositionData(img);
 
 697         createImage(imageEntity);