Add collaboration feature
[sdc.git] / openecomp-be / lib / openecomp-sdc-vendor-software-product-lib / openecomp-sdc-vendor-software-product-core / src / main / java / org / openecomp / sdc / vendorsoftwareproduct / services / impl / composition / CompositionEntityDataManagerImpl.java
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.VendorSoftwareProductInfoDao;
41 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
42 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.CompositionEntity;
43 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComputeEntity;
44 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.DeploymentFlavorEntity;
45 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ImageEntity;
46 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NetworkEntity;
47 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NicEntity;
48 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
49 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspQuestionnaireEntity;
50 import org.openecomp.sdc.vendorsoftwareproduct.services.composition.CompositionEntityDataManager;
51 import org.openecomp.sdc.vendorsoftwareproduct.services.schemagenerator.SchemaGenerator;
52 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Component;
53 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentData;
54 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionData;
55 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityId;
56 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityType;
57 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityValidationData;
58 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComputeData;
59 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Image;
60 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Network;
61 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.NetworkType;
62 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
63 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateContext;
64 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateInput;
65 import org.openecomp.sdc.versioning.dao.types.Version;
66
67 import java.util.ArrayList;
68 import java.util.Collection;
69 import java.util.Collections;
70 import java.util.HashMap;
71 import java.util.HashSet;
72 import java.util.List;
73 import java.util.Map;
74 import java.util.Objects;
75 import java.util.Set;
76
77 public class CompositionEntityDataManagerImpl implements CompositionEntityDataManager {
78
79   private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR =
80       "COMPOSITION_ENTITY_DATA_MANAGER_ERR";
81   private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG =
82       "Invalid input: %s may not be null";
83   private static final String MISSING_OR_INVALID_QUESTIONNAIRE_MSG =
84       "Data is missing/invalid for this %s. Please refill and resubmit.";
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
102   public CompositionEntityDataManagerImpl(VendorSoftwareProductInfoDao vspInfoDao,
103                                           ComponentDao componentDao,
104                                           NicDao nicDao, NetworkDao networkDao,
105                                           ImageDao imageDao, ComputeDao computeDao,
106                                           DeploymentFlavorDao deploymentFlavorDao) {
107     this.vspInfoDao = vspInfoDao;
108     this.componentDao = componentDao;
109     this.nicDao = nicDao;
110     this.networkDao = networkDao;
111     this.imageDao = imageDao;
112     this.computeDao = computeDao;
113     this.deploymentFlavorDao = deploymentFlavorDao;
114   }
115
116   /**
117    * Validate entity composition entity validation data.
118    *
119    * @param entity                the entity
120    * @param schemaTemplateContext the schema template context
121    * @param schemaTemplateInput   the schema template input
122    * @return the composition entity validation data
123    */
124   @Override
125   public CompositionEntityValidationData validateEntity(CompositionEntity entity,
126                                                         SchemaTemplateContext schemaTemplateContext,
127                                                         SchemaTemplateInput schemaTemplateInput) {
128     mdcDataDebugMessage.debugEntryMessage(null);
129
130     if (entity == null) {
131       throw new CoreException(
132           new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
133               .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
134               String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
135               .build());
136     }
137     if (schemaTemplateContext == null) {
138       throw new CoreException(
139           new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
140               .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
141               String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "schema template context"))
142               .build());
143     }
144
145     CompositionEntityValidationData validationData =
146         new CompositionEntityValidationData(entity.getType(), entity.getId());
147     String json =
148         schemaTemplateContext == SchemaTemplateContext.composition ? entity.getCompositionData()
149             : entity.getQuestionnaireData();
150     validationData.setErrors(JsonUtil.validate(
151         json == null ? JsonUtil.object2Json(new Object()) : json,
152         generateSchema(schemaTemplateContext, entity.getType(), schemaTemplateInput)));
153
154     mdcDataDebugMessage.debugExitMessage(null);
155     return validationData;
156   }
157
158   /**
159    * Add entity.
160    *
161    * @param entity              the entity
162    * @param schemaTemplateInput the schema template input
163    */
164   @Override
165   public void addEntity(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
166     if (entity == null) {
167       throw new CoreException(
168           new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
169               .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
170               String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
171               .build());
172     }
173     entities.put(entity.getCompositionEntityId(),
174         new CompositionEntityData(entity, schemaTemplateInput));
175   }
176
177   /**
178    * Validate entities questionnaire map.
179    *
180    * @return the map
181    */
182   @Override
183   public Map<CompositionEntityId, Collection<String>> validateEntitiesQuestionnaire() {
184     mdcDataDebugMessage.debugEntryMessage(null);
185
186     Map<CompositionEntityId, Collection<String>> errorsByEntityId = new HashMap<>();
187     entities.entrySet().forEach(entry -> {
188       Collection<String> errors = validateQuestionnaire(entry.getValue());
189       if (errors != null) {
190         errorsByEntityId.put(entry.getKey(), errors);
191       }
192     });
193
194     mdcDataDebugMessage.debugExitMessage(null);
195     return errorsByEntityId;
196   }
197
198   /**
199    * Build trees.
200    */
201   @Override
202   public void buildTrees() {
203     Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData =
204         new HashMap<>();
205     entities.entrySet().forEach(
206         entry -> addValidationDataEntity(entitiesValidationData, entry.getKey(),
207             entry.getValue().entity));
208   }
209
210   public Collection<CompositionEntityValidationData> getTrees() {
211     return roots;
212   }
213
214   @Override
215   public void saveCompositionData(String vspId, Version version, CompositionData compositionData) {
216     mdcDataDebugMessage.debugEntryMessage(null);
217
218     if (Objects.isNull(compositionData)) {
219       return;
220     }
221
222     Map<String, String> networkIdByName = saveNetworks(vspId, version, compositionData);
223     saveComponents(vspId, version, compositionData, networkIdByName);
224
225     mdcDataDebugMessage.debugExitMessage(null);
226   }
227
228   @Override
229   public Set<CompositionEntityValidationData> getAllErrorsByVsp(String vspId) {
230     CompositionEntityValidationData matchVsp = null;
231     Set<CompositionEntityValidationData> entitiesWithErrors = new HashSet<>();
232     for (CompositionEntityValidationData root : roots) {
233       if (root.getEntityId().equals(vspId)) {
234         matchVsp = root;
235         break;
236       }
237     }
238
239     getEntityListWithErrors(matchVsp, entitiesWithErrors);
240     if (CollectionUtils.isNotEmpty(entitiesWithErrors)) {
241       updateValidationCompositionEntityName(entitiesWithErrors);
242       return entitiesWithErrors;
243     }
244
245     return null;
246   }
247
248   private boolean isThereErrorsInSubTree(CompositionEntityValidationData entity) {
249     if (Objects.isNull(entity)) {
250       return false;
251     }
252
253     if (CollectionUtils.isNotEmpty(entity.getErrors())) {
254       return true;
255     }
256
257     Collection<CompositionEntityValidationData> subEntitiesValidationData =
258         entity.getSubEntitiesValidationData();
259     return !CollectionUtils.isEmpty(subEntitiesValidationData) &&
260         checkForErrorsInChildren(subEntitiesValidationData);
261
262   }
263
264   private boolean checkForErrorsInChildren(
265       Collection<CompositionEntityValidationData> subEntitiesValidationData) {
266     boolean result = false;
267     for (CompositionEntityValidationData subEntity : subEntitiesValidationData) {
268       if (CollectionUtils.isNotEmpty(subEntity.getErrors())) {
269         return true;
270       }
271
272       result = isThereErrorsInSubTree(subEntity) || result;
273       if (result) {
274         return true;
275       }
276     }
277     return false;
278   }
279
280   public void saveComponents(String vspId, Version version, CompositionData compositionData,
281                              Map<String, String> networkIdByName) {
282
283
284     mdcDataDebugMessage.debugEntryMessage(null);
285
286     if (CollectionUtils.isNotEmpty(compositionData.getComponents())) {
287       for (Component component : compositionData.getComponents()) {
288         ComponentEntity componentEntity = new ComponentEntity(vspId, version, null);
289         componentEntity.setComponentCompositionData(component.getData());
290
291         String componentId = createComponent(componentEntity).getId();
292
293         saveImagesByComponent(vspId, version, component, componentId);
294         saveComputesFlavorByComponent(vspId, version, component, componentId);
295
296         saveNicsByComponent(vspId, version, networkIdByName, component, componentId);
297       }
298     }
299
300     mdcDataDebugMessage.debugExitMessage(null);
301   }
302
303   public void saveNicsByComponent(String vspId, Version version,
304                                   Map<String, String> networkIdByName, Component component,
305                                   String componentId) {
306     if (CollectionUtils.isNotEmpty(component.getNics())) {
307       for (Nic nic : component.getNics()) {
308         if (nic.getNetworkName() != null && MapUtils.isNotEmpty(networkIdByName)) {
309           nic.setNetworkId(networkIdByName.get(nic.getNetworkName()));
310         }
311         nic.setNetworkName(null);
312         //For heat flow set network type to be internal by default for NIC
313         nic.setNetworkType(NetworkType.Internal);
314
315         NicEntity nicEntity = new NicEntity(vspId, version, componentId, null);
316         nicEntity.setNicCompositionData(nic);
317         createNic(nicEntity);
318       }
319     }
320   }
321
322   public Map<String, String> saveNetworks(String vspId, Version version,
323                                           CompositionData compositionData) {
324     mdcDataDebugMessage.debugEntryMessage(null);
325
326     Map<String, String> networkIdByName = new HashMap<>();
327     if (CollectionUtils.isNotEmpty(compositionData.getNetworks())) {
328       for (Network network : compositionData.getNetworks()) {
329
330         NetworkEntity networkEntity = new NetworkEntity(vspId, version, null);
331         networkEntity.setNetworkCompositionData(network);
332
333         if (network.getName() != null) {
334           networkIdByName.put(network.getName(), createNetwork(networkEntity).getId());
335         }
336       }
337     }
338
339     mdcDataDebugMessage.debugExitMessage(null);
340     return networkIdByName;
341   }
342
343   @Override
344   public NetworkEntity createNetwork(NetworkEntity network) {
345     mdcDataDebugMessage.debugEntryMessage(null);
346
347     //network.setId(CommonMethods.nextUuId()); will be set by the dao
348     networkDao.create(network);
349     mdcDataDebugMessage.debugExitMessage(null);
350     return network;
351   }
352
353   @Override
354   public ComponentEntity createComponent(ComponentEntity component) {
355     mdcDataDebugMessage.debugEntryMessage(null);
356
357     //component.setId(CommonMethods.nextUuId()); will be set by the dao
358     component.setQuestionnaireData(
359         new JsonSchemaDataGenerator(
360             generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.component,
361                 null))
362             .generateData());
363
364     componentDao.create(component);
365
366     mdcDataDebugMessage.debugExitMessage(null);
367     return component;
368   }
369
370   @Override
371   public NicEntity createNic(NicEntity nic) {
372     mdcDataDebugMessage.debugEntryMessage(null);
373
374     //nic.setId(CommonMethods.nextUuId()); will be set by the dao
375     nic.setQuestionnaireData(
376         new JsonSchemaDataGenerator(
377             generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.nic, null))
378             .generateData());
379
380     nicDao.create(nic);
381
382     mdcDataDebugMessage.debugExitMessage(null);
383     return nic;
384   }
385
386
387   public void addErrorsToTrees(Map<CompositionEntityId, Collection<String>> errors) {
388     roots.forEach(root -> addErrorsToTree(root, null, errors));
389   }
390
391   /* *
392   * get a flat list of all questionnaire entities that have validation errors
393   * */
394   public Set<CompositionEntityValidationData> getEntityListWithErrors() {
395     mdcDataDebugMessage.debugEntryMessage(null);
396     Set<CompositionEntityValidationData> treeAsList = new HashSet<>();
397
398     for (CompositionEntityValidationData entity : roots) {
399       if (CollectionUtils.isNotEmpty(entity.getErrors())) {
400         addNodeWithErrors(entity, treeAsList);
401       }
402       getEntityListWithErrors(entity, treeAsList);
403     }
404
405     updateValidationCompositionEntityName(treeAsList);
406
407     mdcDataDebugMessage.debugExitMessage(null);
408     return treeAsList;
409   }
410
411   private void getEntityListWithErrors(CompositionEntityValidationData entity,
412                                       Set<CompositionEntityValidationData> compositionSet) {
413     if(CollectionUtils.isNotEmpty(entity.getErrors())){
414       addNodeWithErrors(entity, compositionSet);
415     }
416
417     if (CollectionUtils.isEmpty(entity.getSubEntitiesValidationData())) {
418       return;
419     }
420
421     for (CompositionEntityValidationData child : entity.getSubEntitiesValidationData()) {
422       getEntityListWithErrors(child, compositionSet);
423     }
424   }
425
426
427   private void addNodeWithErrors(CompositionEntityValidationData node,
428                                 Set<CompositionEntityValidationData> entitiesWithErrors) {
429     CompositionEntityValidationData compositionNodeToAdd = new CompositionEntityValidationData(node
430         .getEntityType(), node.getEntityId());
431     compositionNodeToAdd.setErrors(node.getErrors());
432     compositionNodeToAdd.setSubEntitiesValidationData(null);
433
434     entitiesWithErrors.add(compositionNodeToAdd);
435   }
436
437   public void removeNodesWithoutErrors() {
438     roots.forEach(root -> removeNodesWithoutErrors(root, null));
439   }
440
441
442   private CompositionEntityData getCompositionEntityDataById(CompositionEntityValidationData
443                                                                  entity) {
444     for (Map.Entry<CompositionEntityId, CompositionEntityData> entityEntry : entities
445         .entrySet()) {
446       if (entityEntry.getKey().getId().equals(entity.getEntityId())) {
447         return entityEntry.getValue();
448       }
449     }
450     return null;
451   }
452
453
454   private void updateValidationCompositionEntityName(Set<CompositionEntityValidationData>
455                                                          compositionSet) {
456     for (CompositionEntityValidationData entity : compositionSet) {
457       String compositionData = getCompositionDataAsString(entity);
458       if (entity.getEntityType().equals(CompositionEntityType.vsp) ||
459           Objects.nonNull(compositionData)) {
460         entity.setEntityName(getEntityNameByEntityType(compositionData, entity));
461       }
462     }
463   }
464
465   private String getCompositionDataAsString(CompositionEntityValidationData entity) {
466     CompositionEntityData compositionEntityData = getCompositionEntityDataById(entity);
467     return compositionEntityData == null ? null : compositionEntityData.entity.getCompositionData();
468   }
469
470
471   private String getEntityNameByEntityType(String compositionData,
472                                            CompositionEntityValidationData entity) {
473     switch (entity.getEntityType()) {
474       case component:
475         ComponentData component = JsonUtil.json2Object(compositionData, ComponentData.class);
476         return component.getDisplayName();
477
478       case nic:
479         Nic nic = JsonUtil.json2Object(compositionData, Nic.class);
480         return nic.getName();
481
482       case network:
483         Network network = JsonUtil.json2Object(compositionData, Network.class);
484         return network.getName();
485
486       case image:
487         Image image = JsonUtil.json2Object(compositionData, Image.class);
488         return image.getFileName();
489
490       case vsp:
491         CompositionEntityData vspEntity = getCompositionEntityDataById(entity);
492         VspQuestionnaireEntity vspQuestionnaireEntity = (VspQuestionnaireEntity) vspEntity.entity;
493         VspDetails vspDetails =
494             vspInfoDao.get(new VspDetails(vspQuestionnaireEntity.getId(),
495                 vspQuestionnaireEntity.getVersion()));
496         return vspDetails.getName();
497     }
498
499     return null;
500   }
501
502   private void removeNodesWithoutErrors(CompositionEntityValidationData node,
503                                         CompositionEntityValidationData parent) {
504
505     if (Objects.isNull(node)) {
506       return;
507     }
508
509     if (hasChildren(node)) {
510       Collection<CompositionEntityValidationData> subNodes =
511           new ArrayList<>(node.getSubEntitiesValidationData());
512       subNodes.forEach(subNode -> removeNodesWithoutErrors(subNode, node));
513       node.setSubEntitiesValidationData(subNodes);
514
515       if (canNodeGetRemovedFromValidationDataTree(node)) {
516         removeNodeFromChildren(parent, node);
517       }
518     } else if (canNodeGetRemovedFromValidationDataTree(node)) {
519       removeNodeFromChildren(parent, node);
520     }
521   }
522
523   private void removeNodeFromChildren(CompositionEntityValidationData parent,
524                                       CompositionEntityValidationData childToRemove) {
525     if (!Objects.isNull(parent)) {
526       parent.getSubEntitiesValidationData().remove(childToRemove);
527     }
528   }
529
530   private boolean hasChildren(CompositionEntityValidationData node) {
531     return !CollectionUtils.isEmpty(node.getSubEntitiesValidationData());
532   }
533
534   private boolean canNodeGetRemovedFromValidationDataTree(CompositionEntityValidationData node) {
535     return !hasChildren(node) && CollectionUtils.isEmpty(node.getErrors());
536   }
537
538
539   private void addValidationDataEntity(
540       Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData,
541       CompositionEntityId entityId, CompositionEntity entity) {
542     if (entitiesValidationData.containsKey(entityId)) {
543       return;
544     }
545
546     CompositionEntityValidationData validationData =
547         new CompositionEntityValidationData(entity.getType(), entity.getId());
548     entitiesValidationData.put(entityId, validationData);
549
550     CompositionEntityId parentEntityId = entityId.getParentId();
551     if (parentEntityId == null) {
552       roots.add(validationData);
553     } else {
554       CompositionEntityData parentEntity = entities.get(parentEntityId);
555       if (parentEntity == null) {
556         roots.add(validationData);
557       } else {
558         addValidationDataEntity(entitiesValidationData, parentEntityId, parentEntity.entity);
559         entitiesValidationData.get(parentEntityId).addSubEntityValidationData(validationData);
560       }
561     }
562   }
563
564   private void addErrorsToTree(CompositionEntityValidationData node,
565                                CompositionEntityId parentNodeId,
566                                Map<CompositionEntityId, Collection<String>> errors) {
567     if (node == null) {
568       return;
569     }
570     CompositionEntityId nodeId = new CompositionEntityId(node.getEntityId(), parentNodeId);
571     node.setErrors(errors.get(nodeId));
572
573     if (node.getSubEntitiesValidationData() != null) {
574       node.getSubEntitiesValidationData()
575           .forEach(subNode -> addErrorsToTree(subNode, nodeId, errors));
576     }
577   }
578
579   private Collection<String> validateQuestionnaire(CompositionEntityData compositionEntityData) {
580     logger.debug(String.format("validateQuestionnaire start:  " +
581             "[entity.type]=%s, [entity.id]=%s, [entity.questionnaireString]=%s",
582         compositionEntityData.entity.getType().name(),
583         compositionEntityData.entity.getCompositionEntityId().toString(),
584         compositionEntityData.entity.getQuestionnaireData()));
585
586     if (Objects.isNull(compositionEntityData.entity.getQuestionnaireData()) ||
587         !JsonUtil.isValidJson(compositionEntityData.entity.getQuestionnaireData())) {
588       return Collections.singletonList(String
589           .format(MISSING_OR_INVALID_QUESTIONNAIRE_MSG, compositionEntityData.entity.getType()));
590     }
591
592     return JsonUtil.validate(
593         compositionEntityData.entity.getQuestionnaireData() == null
594             ? JsonUtil.object2Json(new Object())
595             : compositionEntityData.entity.getQuestionnaireData(),
596         getSchema(compositionEntityData.entity.getType(), SchemaTemplateContext.questionnaire,
597             compositionEntityData.schemaTemplateInput));
598   }
599
600   private String getSchema(CompositionEntityType compositionEntityType,
601                            SchemaTemplateContext schemaTemplateContext,
602                            SchemaTemplateInput schemaTemplateInput) {
603     return schemaTemplateInput == null
604         ? nonDynamicSchemas.computeIfAbsent(compositionEntityType,
605         k -> generateSchema(schemaTemplateContext, compositionEntityType, null))
606         : generateSchema(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
607   }
608
609   private static class CompositionEntityData {
610     private CompositionEntity entity;
611     private SchemaTemplateInput schemaTemplateInput;
612
613     CompositionEntityData(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
614       this.entity = entity;
615       this.schemaTemplateInput = schemaTemplateInput;
616     }
617
618   }
619
620   // todo - make SchemaGenerator non static and mock it in UT instead of mocking this method (and
621   // make the method private
622
623   protected String generateSchema(SchemaTemplateContext schemaTemplateContext,
624                                   CompositionEntityType compositionEntityType,
625                                   SchemaTemplateInput schemaTemplateInput) {
626     return SchemaGenerator
627         .generate(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
628   }
629
630   @Override
631   public DeploymentFlavorEntity createDeploymentFlavor(DeploymentFlavorEntity deploymentFlavor) {
632     mdcDataDebugMessage.debugEntryMessage(null, null);
633
634     deploymentFlavor.setId(CommonMethods.nextUuId());
635     deploymentFlavorDao.create(deploymentFlavor);
636     return deploymentFlavor;
637   }
638
639   @Override
640   public ImageEntity createImage(ImageEntity image) {
641     mdcDataDebugMessage.debugEntryMessage(null, null);
642
643     image.setId(CommonMethods.nextUuId());
644
645     image.setQuestionnaireData(
646         new JsonSchemaDataGenerator(SchemaGenerator
647             .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.image, null))
648             .generateData());
649
650     imageDao.create(image);
651     mdcDataDebugMessage.debugExitMessage(null, null);
652     return image;
653   }
654
655   public void saveComputesFlavorByComponent(String vspId, Version version, Component component,
656                                             String componentId) {
657     if (CollectionUtils.isNotEmpty(component.getCompute())) {
658       for (ComputeData flavor : component.getCompute()) {
659         ComputeEntity computeEntity = new ComputeEntity(vspId, version, componentId, null);
660         computeEntity.setComputeCompositionData(flavor);
661         computeEntity.setQuestionnaireData(
662             new JsonSchemaDataGenerator(SchemaGenerator
663                 .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.compute,
664                     null)).generateData());
665
666         computeDao.create(computeEntity);
667       }
668     }
669   }
670
671   public void saveImagesByComponent(String vspId, Version version, Component component, String
672       componentId) {
673     if (CollectionUtils.isNotEmpty(component.getImages())) {
674       for (Image img : component.getImages()) {
675         ImageEntity imageEntity = new ImageEntity(vspId, version, componentId, null);
676         imageEntity.setImageCompositionData(img);
677         createImage(imageEntity);
678       }
679     }
680   }
681
682 }