c76b15d2219a53f7b17770918589166cb673e4d1
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.openecomp.sdc.vendorsoftwareproduct.services.impl.composition;
22
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;
69
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;
75 import java.util.Map;
76 import java.util.Objects;
77 import java.util.Set;
78
79 public class CompositionEntityDataManagerImpl implements CompositionEntityDataManager {
80
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";
85
86   private static final Logger logger =
87           LoggerFactory.getLogger(CompositionEntityDataManagerImpl.class);
88   private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
89
90   private Map<CompositionEntityId, CompositionEntityData> entities = new HashMap<>();
91   private Map<CompositionEntityType, String> nonDynamicSchemas = new HashMap<>();
92   private List<CompositionEntityValidationData> roots = new ArrayList<>();
93
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;
102
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;
117   }
118
119   /**
120    * Validate entity composition entity validation data.
121    *
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
126    */
127   @Override
128   public CompositionEntityValidationData validateEntity(CompositionEntity entity,
129                                                         SchemaTemplateContext schemaTemplateContext,
130                                                         SchemaTemplateInput schemaTemplateInput) {
131     mdcDataDebugMessage.debugEntryMessage(null);
132
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"))
138                       .build());
139     }
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"))
145                       .build());
146     }
147
148     CompositionEntityValidationData validationData =
149             new CompositionEntityValidationData(entity.getType(), entity.getId());
150     String json =
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)));
156
157     mdcDataDebugMessage.debugExitMessage(null);
158     return validationData;
159   }
160
161   /**
162    * Add entity.
163    *
164    * @param entity              the entity
165    * @param schemaTemplateInput the schema template input
166    */
167   @Override
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"))
174                       .build());
175     }
176     entities.put(entity.getCompositionEntityId(),
177             new CompositionEntityData(entity, schemaTemplateInput));
178   }
179
180   /**
181    * Validate entities questionnaire map.
182    *
183    * @return the map
184    */
185   @Override
186   public Map<CompositionEntityId, Collection<String>> validateEntitiesQuestionnaire() {
187     mdcDataDebugMessage.debugEntryMessage(null);
188
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);
194       }
195     });
196
197     mdcDataDebugMessage.debugExitMessage(null);
198     return errorsByEntityId;
199   }
200
201   /**
202    * Build trees.
203    */
204   @Override
205   public void buildTrees() {
206     Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData =
207             new HashMap<>();
208     entities.entrySet().forEach(
209             entry -> addValidationDataEntity(entitiesValidationData, entry.getKey(),
210                     entry.getValue().entity));
211   }
212
213   public Collection<CompositionEntityValidationData> getTrees() {
214     return roots;
215   }
216
217   @Override
218   public void saveCompositionData(String vspId, Version version, CompositionData compositionData) {
219     mdcDataDebugMessage.debugEntryMessage(null);
220
221     if (Objects.isNull(compositionData)) {
222       return;
223     }
224
225     Map<String, String> networkIdByName = saveNetworks(vspId, version, compositionData);
226     saveComponents(vspId, version, compositionData, networkIdByName);
227
228     mdcDataDebugMessage.debugExitMessage(null);
229   }
230
231   @Override
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)) {
237         matchVsp = root;
238         break;
239       }
240     }
241
242     getEntityListWithErrors(matchVsp, entitiesWithErrors);
243     if (CollectionUtils.isNotEmpty(entitiesWithErrors)) {
244       updateValidationCompositionEntityName(entitiesWithErrors);
245       return entitiesWithErrors;
246     }
247
248     return null;
249   }
250
251   private boolean isThereErrorsInSubTree(CompositionEntityValidationData entity) {
252     if (Objects.isNull(entity)) {
253       return false;
254     }
255
256     if (CollectionUtils.isNotEmpty(entity.getErrors())) {
257       return true;
258     }
259
260     Collection<CompositionEntityValidationData> subEntitiesValidationData =
261             entity.getSubEntitiesValidationData();
262     return !CollectionUtils.isEmpty(subEntitiesValidationData) &&
263             checkForErrorsInChildren(subEntitiesValidationData);
264
265   }
266
267   private boolean checkForErrorsInChildren(
268           Collection<CompositionEntityValidationData> subEntitiesValidationData) {
269     boolean result = false;
270     for (CompositionEntityValidationData subEntity : subEntitiesValidationData) {
271       if (CollectionUtils.isNotEmpty(subEntity.getErrors())) {
272         return true;
273       }
274
275       result = result || isThereErrorsInSubTree(subEntity);
276       if (result) {
277         return true;
278       }
279     }
280     return false;
281   }
282
283   public void saveComponents(String vspId, Version version, CompositionData compositionData,
284                              Map<String, String> networkIdByName) {
285
286
287     mdcDataDebugMessage.debugEntryMessage(null);
288
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());
293
294         String componentId = createComponent(componentEntity).getId();
295
296         saveImagesByComponent(vspId, version, component, componentId);
297         saveComputesFlavorByComponent(vspId, version, component, componentId);
298
299         saveNicsByComponent(vspId, version, networkIdByName, component, componentId);
300       }
301     }
302
303     mdcDataDebugMessage.debugExitMessage(null);
304   }
305
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()));
313         }
314         nic.setNetworkName(null);
315         //For heat flow set network type to be internal by default for NIC
316         nic.setNetworkType(NetworkType.Internal);
317
318         NicEntity nicEntity = new NicEntity(vspId, version, componentId, null);
319         nicEntity.setNicCompositionData(nic);
320         createNic(nicEntity);
321       }
322     }
323   }
324
325   public Map<String, String> saveNetworks(String vspId, Version version,
326                                           CompositionData compositionData) {
327     mdcDataDebugMessage.debugEntryMessage(null);
328
329     Map<String, String> networkIdByName = new HashMap<>();
330     if (CollectionUtils.isNotEmpty(compositionData.getNetworks())) {
331       for (Network network : compositionData.getNetworks()) {
332
333         NetworkEntity networkEntity = new NetworkEntity(vspId, version, null);
334         networkEntity.setNetworkCompositionData(network);
335
336         if (network.getName() != null) {
337           networkIdByName.put(network.getName(), createNetwork(networkEntity).getId());
338         }
339       }
340     }
341
342     mdcDataDebugMessage.debugExitMessage(null);
343     return networkIdByName;
344   }
345
346   @Override
347   public NetworkEntity createNetwork(NetworkEntity network) {
348     mdcDataDebugMessage.debugEntryMessage(null);
349
350     //network.setId(CommonMethods.nextUuId()); will be set by the dao
351     networkDao.create(network);
352     mdcDataDebugMessage.debugExitMessage(null);
353     return network;
354   }
355
356   @Override
357   public ComponentEntity createComponent(ComponentEntity component) {
358     mdcDataDebugMessage.debugEntryMessage(null);
359
360     //component.setId(CommonMethods.nextUuId()); will be set by the dao
361     component.setQuestionnaireData(
362             new JsonSchemaDataGenerator(
363                     generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.component,
364                             null))
365                     .generateData());
366
367     componentDao.create(component);
368
369     mdcDataDebugMessage.debugExitMessage(null);
370     return component;
371   }
372
373   @Override
374   public NicEntity createNic(NicEntity nic) {
375     mdcDataDebugMessage.debugEntryMessage(null);
376
377     //nic.setId(CommonMethods.nextUuId()); will be set by the dao
378     nic.setQuestionnaireData(
379             new JsonSchemaDataGenerator(
380                     generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.nic, null))
381                     .generateData());
382
383     nicDao.create(nic);
384
385     mdcDataDebugMessage.debugExitMessage(null);
386     return nic;
387   }
388
389
390   public void addErrorsToTrees(Map<CompositionEntityId, Collection<String>> errors) {
391     roots.forEach(root -> addErrorsToTree(root, null, errors));
392   }
393
394   /* *
395   * get a flat list of all questionnaire entities that have validation errors
396   * */
397   public Set<CompositionEntityValidationData> getEntityListWithErrors() {
398     mdcDataDebugMessage.debugEntryMessage(null);
399     Set<CompositionEntityValidationData> treeAsList = new HashSet<>();
400
401     for (CompositionEntityValidationData entity : roots) {
402       if (CollectionUtils.isNotEmpty(entity.getErrors())) {
403         addNodeWithErrors(entity, treeAsList);
404       }
405       getEntityListWithErrors(entity, treeAsList);
406     }
407
408     updateValidationCompositionEntityName(treeAsList);
409
410     mdcDataDebugMessage.debugExitMessage(null);
411     return treeAsList;
412   }
413
414   public void getEntityListWithErrors(CompositionEntityValidationData entity,
415                                       Set<CompositionEntityValidationData> compositionSet) {
416     Collection<CompositionEntityValidationData> childNodes =
417             entity.getSubEntitiesValidationData();
418
419     if (CollectionUtils.isEmpty(childNodes)) {
420       return;
421     }
422
423     for (CompositionEntityValidationData child : childNodes) {
424       if (CollectionUtils.isNotEmpty(child.getErrors())) {
425         addNodeWithErrors(child, compositionSet);
426       }
427       getEntityListWithErrors(child, compositionSet);
428     }
429   }
430
431
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);
438
439     entitiesWithErrors.add(compositionNodeToAdd);
440   }
441
442   public void removeNodesWithoutErrors() {
443     roots.forEach(root -> removeNodesWithoutErrors(root, null));
444   }
445
446
447   private CompositionEntityData getCompositionEntityDataById(CompositionEntityValidationData
448                                                                      entity) {
449     for (Map.Entry<CompositionEntityId, CompositionEntityData> entityEntry : entities
450             .entrySet()) {
451       if (entityEntry.getKey().getId().equals(entity.getEntityId())) {
452         return entityEntry.getValue();
453       }
454     }
455     return null;
456   }
457
458
459   private void updateValidationCompositionEntityName(Set<CompositionEntityValidationData>
460                                                              compositionSet) {
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));
466       }
467     }
468   }
469
470   private String getCompositionDataAsString(CompositionEntityValidationData entity) {
471     CompositionEntityData compositionEntityData = getCompositionEntityDataById(entity);
472     return compositionEntityData == null ? null : compositionEntityData.entity.getCompositionData();
473   }
474
475
476   private String getEntityNameByEntityType(String compositionData,
477                                            CompositionEntityValidationData entity) {
478     switch (entity.getEntityType()) {
479       case component:
480         ComponentData component = JsonUtil.json2Object(compositionData, ComponentData.class);
481         return component.getDisplayName();
482
483       case nic:
484         Nic nic = JsonUtil.json2Object(compositionData, Nic.class);
485         return nic.getName();
486
487       case network:
488         Network network = JsonUtil.json2Object(compositionData, Network.class);
489         return network.getName();
490
491       case image:
492         Image image = JsonUtil.json2Object(compositionData, Image.class);
493         return image.getFileName();
494
495       case vsp:
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();
502     }
503
504     return null;
505   }
506
507   private void removeNodesWithoutErrors(CompositionEntityValidationData node,
508                                         CompositionEntityValidationData parent) {
509
510     if (Objects.isNull(node)) {
511       return;
512     }
513
514     if (hasChildren(node)) {
515       Collection<CompositionEntityValidationData> subNodes =
516               new ArrayList<>(node.getSubEntitiesValidationData());
517       subNodes.forEach(subNode -> removeNodesWithoutErrors(subNode, node));
518       node.setSubEntitiesValidationData(subNodes);
519
520       if (canNodeGetRemovedFromValidationDataTree(node)) {
521         removeNodeFromChildren(parent, node);
522       }
523     } else if (canNodeGetRemovedFromValidationDataTree(node)) {
524       removeNodeFromChildren(parent, node);
525     }
526   }
527
528   private void removeNodeFromChildren(CompositionEntityValidationData parent,
529                                       CompositionEntityValidationData childToRemove) {
530     if (!Objects.isNull(parent)) {
531       parent.getSubEntitiesValidationData().remove(childToRemove);
532     }
533   }
534
535   private boolean hasChildren(CompositionEntityValidationData node) {
536     return !CollectionUtils.isEmpty(node.getSubEntitiesValidationData());
537   }
538
539   private boolean canNodeGetRemovedFromValidationDataTree(CompositionEntityValidationData node) {
540     return !hasChildren(node) && CollectionUtils.isEmpty(node.getErrors());
541   }
542
543
544   private void addValidationDataEntity(
545           Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData,
546           CompositionEntityId entityId, CompositionEntity entity) {
547     if (entitiesValidationData.containsKey(entityId)) {
548       return;
549     }
550
551     CompositionEntityValidationData validationData =
552             new CompositionEntityValidationData(entity.getType(), entity.getId());
553     entitiesValidationData.put(entityId, validationData);
554
555     CompositionEntityId parentEntityId = entityId.getParentId();
556     if (parentEntityId == null) {
557       roots.add(validationData);
558     } else {
559       CompositionEntityData parentEntity = entities.get(parentEntityId);
560       if (parentEntity == null) {
561         roots.add(validationData);
562       } else {
563         addValidationDataEntity(entitiesValidationData, parentEntityId, parentEntity.entity);
564         entitiesValidationData.get(parentEntityId).addSubEntityValidationData(validationData);
565       }
566     }
567   }
568
569   private void addErrorsToTree(CompositionEntityValidationData node,
570                                CompositionEntityId parentNodeId,
571                                Map<CompositionEntityId, Collection<String>> errors) {
572     if (node == null) {
573       return;
574     }
575     CompositionEntityId nodeId = new CompositionEntityId(node.getEntityId(), parentNodeId);
576     node.setErrors(errors.get(nodeId));
577
578     if (node.getSubEntitiesValidationData() != null) {
579       node.getSubEntitiesValidationData()
580               .forEach(subNode -> addErrorsToTree(subNode, nodeId, errors));
581     }
582   }
583
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()));
590
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.");
596       return errors;
597     }
598
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));
605   }
606
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);
614   }
615
616   private static class CompositionEntityData {
617     private CompositionEntity entity;
618     private SchemaTemplateInput schemaTemplateInput;
619
620     CompositionEntityData(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
621       this.entity = entity;
622       this.schemaTemplateInput = schemaTemplateInput;
623     }
624
625   }
626
627   // todo - make SchemaGenerator non static and mock it in UT instead of mocking this method (and
628   // make the method private
629
630   protected String generateSchema(SchemaTemplateContext schemaTemplateContext,
631                                   CompositionEntityType compositionEntityType,
632                                   SchemaTemplateInput schemaTemplateInput) {
633     return SchemaGenerator
634             .generate(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
635   }
636
637   @Override
638   public DeploymentFlavorEntity createDeploymentFlavor(DeploymentFlavorEntity deploymentFlavor) {
639     mdcDataDebugMessage.debugEntryMessage(null, null);
640
641     deploymentFlavor.setId(CommonMethods.nextUuId());
642     deploymentFlavorDao.create(deploymentFlavor);
643     return deploymentFlavor;
644   }
645
646   @Override
647   public ImageEntity createImage(ImageEntity image) {
648     mdcDataDebugMessage.debugEntryMessage(null, null);
649
650     image.setId(CommonMethods.nextUuId());
651
652     image.setQuestionnaireData(
653             new JsonSchemaDataGenerator(SchemaGenerator
654                     .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.image, null))
655                     .generateData());
656
657     imageDao.create(image);
658     mdcDataDebugMessage.debugExitMessage(null, null);
659     return image;
660   }
661
662   @Override
663   public ComputeEntity createCompute(ComputeEntity compute) {
664     mdcDataDebugMessage.debugEntryMessage("VSP id, component id", compute.getVspId(),
665             compute.getComponentId());
666
667     compute.setId(CommonMethods.nextUuId());
668     compute.setQuestionnaireData(
669             new JsonSchemaDataGenerator(SchemaGenerator
670                     .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.compute,
671                             null)).generateData());
672
673     computeDao.create(compute);
674
675     mdcDataDebugMessage.debugExitMessage("VSP id, component id", compute.getVspId(),
676             compute.getComponentId());
677     return compute;
678   }
679
680   public void saveComputesFlavorByComponent(String vspId, Version version, Component component, String
681           componentId) {
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);
687       }
688     }
689   }
690
691   public void saveImagesByComponent(String vspId, Version version, Component component, String
692           componentId) {
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);
698       }
699     }
700   }
701
702 }