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