e9c75319f5ab53be488f49ea1dba6b7cbca151af
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.vendorsoftwareproduct.impl;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.EnumMap;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Set;
29 import org.apache.commons.collections4.CollectionUtils;
30 import org.apache.commons.collections4.MapUtils;
31 import org.openecomp.core.utilities.CommonMethods;
32 import org.openecomp.core.utilities.json.JsonSchemaDataGenerator;
33 import org.openecomp.core.utilities.json.JsonUtil;
34 import org.openecomp.sdc.common.errors.CoreException;
35 import org.openecomp.sdc.common.errors.ErrorCategory;
36 import org.openecomp.sdc.common.errors.ErrorCode;
37 import org.openecomp.sdc.logging.api.Logger;
38 import org.openecomp.sdc.logging.api.LoggerFactory;
39 import org.openecomp.sdc.vendorsoftwareproduct.CompositionEntityDataManager;
40 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDao;
41 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComputeDao;
42 import org.openecomp.sdc.vendorsoftwareproduct.dao.DeploymentFlavorDao;
43 import org.openecomp.sdc.vendorsoftwareproduct.dao.ImageDao;
44 import org.openecomp.sdc.vendorsoftwareproduct.dao.NetworkDao;
45 import org.openecomp.sdc.vendorsoftwareproduct.dao.NicDao;
46 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
47 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
48 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.CompositionEntity;
49 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComputeEntity;
50 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.DeploymentFlavorEntity;
51 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ImageEntity;
52 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NetworkEntity;
53 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NicEntity;
54 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
55 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspQuestionnaireEntity;
56 import org.openecomp.sdc.vendorsoftwareproduct.services.schemagenerator.SchemaGenerator;
57 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Component;
58 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentData;
59 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionData;
60 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityId;
61 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityType;
62 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityValidationData;
63 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComputeData;
64 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Image;
65 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Network;
66 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.NetworkType;
67 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
68 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.ComponentQuestionnaireSchemaInput;
69 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateContext;
70 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateInput;
71 import org.openecomp.sdc.versioning.dao.types.Version;
72
73 public class CompositionEntityDataManagerImpl implements CompositionEntityDataManager {
74
75   private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR =
76       "COMPOSITION_ENTITY_DATA_MANAGER_ERR";
77   private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG =
78       "Invalid input: %s may not be null";
79   private static final String MISSING_OR_INVALID_QUESTIONNAIRE_MSG =
80       "Data is missing/invalid for this %s. Please refill and resubmit.";
81
82   private static final Logger logger =
83       LoggerFactory.getLogger(CompositionEntityDataManagerImpl.class);
84   private Map<CompositionEntityId, CompositionEntityData> entities = new HashMap<>();
85   private Map<CompositionEntityType, String> nonDynamicSchemas =
86       new EnumMap<>(CompositionEntityType.class);
87   private List<CompositionEntityValidationData> roots = new ArrayList<>();
88
89   private VendorSoftwareProductInfoDao vspInfoDao;
90   private ComponentDao componentDao;
91   private NicDao nicDao;
92   private NetworkDao networkDao;
93   private ImageDao imageDao;
94   private ComputeDao computeDao;
95   private DeploymentFlavorDao deploymentFlavorDao;
96
97   public CompositionEntityDataManagerImpl(VendorSoftwareProductInfoDao vspInfoDao,
98                                           ComponentDao componentDao,
99                                           NicDao nicDao, NetworkDao networkDao,
100                                           ImageDao imageDao, ComputeDao computeDao,
101                                           DeploymentFlavorDao deploymentFlavorDao) {
102     this.vspInfoDao = vspInfoDao;
103     this.componentDao = componentDao;
104     this.nicDao = nicDao;
105     this.networkDao = networkDao;
106     this.imageDao = imageDao;
107     this.computeDao = computeDao;
108     this.deploymentFlavorDao = deploymentFlavorDao;
109   }
110
111   /**
112    * Validate entity composition entity validation data.
113    *
114    * @param entity                the entity
115    * @param schemaTemplateContext the schema template context
116    * @param schemaTemplateInput   the schema template input
117    * @return the composition entity validation data
118    */
119   @Override
120   public CompositionEntityValidationData validateEntity(CompositionEntity entity,
121                                                         SchemaTemplateContext schemaTemplateContext,
122                                                         SchemaTemplateInput schemaTemplateInput) {
123     if (entity == null) {
124       throw new CoreException(
125           new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
126               .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
127               String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
128               .build());
129     }
130     if (schemaTemplateContext == 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, "schema template context"))
135               .build());
136     }
137
138     CompositionEntityValidationData validationData =
139         new CompositionEntityValidationData(entity.getType(), entity.getId());
140     String json =
141         schemaTemplateContext == SchemaTemplateContext.composition ? entity.getCompositionData()
142             : entity.getQuestionnaireData();
143     validationData.setErrors(JsonUtil.validate(
144         json == null ? JsonUtil.object2Json(new Object()) : json,
145         generateSchema(schemaTemplateContext, entity.getType(), schemaTemplateInput)));
146     return validationData;
147   }
148
149   /**
150    * Add entity.
151    *
152    * @param entity              the entity
153    * @param schemaTemplateInput the schema template input
154    */
155   @Override
156   public void addEntity(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
157     if (entity == null) {
158       throw new CoreException(
159           new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
160               .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
161               String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
162               .build());
163     }
164     entities.put(entity.getCompositionEntityId(),
165         new CompositionEntityData(entity, schemaTemplateInput));
166   }
167
168   /**
169    * Validate entities questionnaire map.
170    *
171    * @return the map
172    */
173   @Override
174   public Map<CompositionEntityId, Collection<String>> validateEntitiesQuestionnaire() {
175     Map<CompositionEntityId, Collection<String>> errorsByEntityId = new HashMap<>();
176     entities.forEach((key, value) -> {
177       Collection<String> errors = validateQuestionnaire(value);
178       if (errors != null) {
179         errorsByEntityId.put(key, errors);
180       }
181     });
182     return errorsByEntityId;
183   }
184
185   /**
186    * Build trees.
187    */
188   @Override
189   public void buildTrees() {
190     Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData =
191         new HashMap<>();
192     entities.forEach((key, value) -> addValidationDataEntity(entitiesValidationData, key,
193         value.entity));
194   }
195
196   public Collection<CompositionEntityValidationData> getTrees() {
197     return roots;
198   }
199
200   @Override
201   public void saveCompositionData(String vspId, Version version, CompositionData compositionData) {
202     if (Objects.isNull(compositionData)) {
203       return;
204     }
205
206     Map<String, String> networkIdByName = saveNetworks(vspId, version, compositionData);
207     saveComponents(vspId, version, compositionData, networkIdByName);
208   }
209
210   @Override
211   public Set<CompositionEntityValidationData> getAllErrorsByVsp(String vspId) {
212     Set<CompositionEntityValidationData> entitiesWithErrors = new HashSet<>();
213     for (CompositionEntityValidationData root : roots) {
214       if (root.getEntityId().equals(vspId)) {
215         getEntityListWithErrors(root, entitiesWithErrors);
216         break;
217       }
218     }
219
220     if (CollectionUtils.isNotEmpty(entitiesWithErrors)) {
221       updateValidationCompositionEntityName(entitiesWithErrors);
222       return entitiesWithErrors;
223     }
224
225     return new HashSet<>();
226   }
227
228   private void saveComponents(String vspId, Version version, CompositionData compositionData,
229                               Map<String, String> networkIdByName) {
230     if (CollectionUtils.isNotEmpty(compositionData.getComponents())) {
231       for (Component component : compositionData.getComponents()) {
232         ComponentEntity componentEntity = new ComponentEntity(vspId, version, null);
233         componentEntity.setComponentCompositionData(component.getData());
234
235         String componentId = createComponent(componentEntity, false).getId();
236
237         saveImagesByComponent(vspId, version, component, componentId);
238         saveComputesFlavorByComponent(vspId, version, component, componentId);
239
240         saveNicsByComponent(vspId, version, networkIdByName, component, componentId);
241       }
242     }
243   }
244
245   private void saveNicsByComponent(String vspId, Version version,
246                                    Map<String, String> networkIdByName, Component component,
247                                    String componentId) {
248     if (CollectionUtils.isNotEmpty(component.getNics())) {
249       for (Nic nic : component.getNics()) {
250         if (nic.getNetworkName() != null && MapUtils.isNotEmpty(networkIdByName)) {
251           nic.setNetworkId(networkIdByName.get(nic.getNetworkName()));
252         }
253         nic.setNetworkName(null);
254         //For heat flow set network type to be internal by default for NIC
255         nic.setNetworkType(NetworkType.Internal);
256
257         NicEntity nicEntity = new NicEntity(vspId, version, componentId, null);
258         nicEntity.setNicCompositionData(nic);
259         createNic(nicEntity);
260       }
261     }
262   }
263
264   private Map<String, String> saveNetworks(String vspId, Version version,
265                                            CompositionData compositionData) {
266     Map<String, String> networkIdByName = new HashMap<>();
267     if (CollectionUtils.isNotEmpty(compositionData.getNetworks())) {
268       for (Network network : compositionData.getNetworks()) {
269
270         NetworkEntity networkEntity = new NetworkEntity(vspId, version, null);
271         networkEntity.setNetworkCompositionData(network);
272
273         if (network.getName() != null) {
274           networkIdByName.put(network.getName(), createNetwork(networkEntity).getId());
275         }
276       }
277     }
278     return networkIdByName;
279   }
280
281   private NetworkEntity createNetwork(NetworkEntity network) {
282     //network.setId(CommonMethods.nextUuId()); will be set by the dao
283     networkDao.create(network);
284     return network;
285   }
286
287   @Override
288   public ComponentEntity createComponent(ComponentEntity component, boolean isManualVsp) {
289     //component.setId(CommonMethods.nextUuId()); will be set by the dao
290     ComponentQuestionnaireSchemaInput schemaInput = new ComponentQuestionnaireSchemaInput(null,
291         null, component.getComponentCompositionData().getDisplayName(), isManualVsp);
292     String questionnarieData = new JsonSchemaDataGenerator(generateSchema(SchemaTemplateContext.questionnaire,
293             CompositionEntityType.component, schemaInput)).generateData();
294     component.setQuestionnaireData(questionnarieData);
295
296     componentDao.create(component);
297     return component;
298   }
299
300   @Override
301   public NicEntity createNic(NicEntity nic) {
302     //nic.setId(CommonMethods.nextUuId()); will be set by the dao
303     nic.setQuestionnaireData(
304         new JsonSchemaDataGenerator(
305             generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.nic, null))
306             .generateData());
307
308     nicDao.create(nic);
309     return nic;
310   }
311
312
313   public void addErrorsToTrees(Map<CompositionEntityId, Collection<String>> errors) {
314     roots.forEach(root -> addErrorsToTree(root, null, errors));
315   }
316
317   /* *
318    * get a flat list of all questionnaire entities that have validation errors
319    * */
320   public Set<CompositionEntityValidationData> getEntityListWithErrors() {
321     Set<CompositionEntityValidationData> treeAsList = new HashSet<>();
322
323     for (CompositionEntityValidationData entity : roots) {
324       if (CollectionUtils.isNotEmpty(entity.getErrors())) {
325         addNodeWithErrors(entity, treeAsList);
326       }
327       getEntityListWithErrors(entity, treeAsList);
328     }
329
330     updateValidationCompositionEntityName(treeAsList);
331     return treeAsList;
332   }
333
334   private void getEntityListWithErrors(CompositionEntityValidationData entity,
335                                        Set<CompositionEntityValidationData> compositionSet) {
336     if (CollectionUtils.isNotEmpty(entity.getErrors())) {
337       addNodeWithErrors(entity, compositionSet);
338     }
339
340     if (CollectionUtils.isEmpty(entity.getSubEntitiesValidationData())) {
341       return;
342     }
343
344     for (CompositionEntityValidationData child : entity.getSubEntitiesValidationData()) {
345       getEntityListWithErrors(child, compositionSet);
346     }
347   }
348
349
350   private void addNodeWithErrors(CompositionEntityValidationData node,
351                                  Set<CompositionEntityValidationData> entitiesWithErrors) {
352     CompositionEntityValidationData compositionNodeToAdd = new CompositionEntityValidationData(node
353         .getEntityType(), node.getEntityId());
354     compositionNodeToAdd.setErrors(node.getErrors());
355     compositionNodeToAdd.setSubEntitiesValidationData(null);
356
357     entitiesWithErrors.add(compositionNodeToAdd);
358   }
359
360   public void removeNodesWithoutErrors() {
361     roots.forEach(root -> removeNodesWithoutErrors(root, null));
362   }
363
364
365   private CompositionEntityData getCompositionEntityDataById(CompositionEntityValidationData
366                                                                  entity) {
367     for (Map.Entry<CompositionEntityId, CompositionEntityData> entityEntry : entities
368         .entrySet()) {
369       if (entityEntry.getKey().getId().equals(entity.getEntityId())) {
370         return entityEntry.getValue();
371       }
372     }
373     return null;
374   }
375
376
377   private void updateValidationCompositionEntityName(Set<CompositionEntityValidationData>
378                                                          compositionSet) {
379     for (CompositionEntityValidationData entity : compositionSet) {
380       String compositionData = getCompositionDataAsString(entity);
381       if (entity.getEntityType().equals(CompositionEntityType.vsp) ||
382           Objects.nonNull(compositionData)) {
383         entity.setEntityName(getEntityNameByEntityType(compositionData, entity));
384       }
385     }
386   }
387
388   private String getCompositionDataAsString(CompositionEntityValidationData entity) {
389     CompositionEntityData compositionEntityData = getCompositionEntityDataById(entity);
390     return compositionEntityData == null ? null : compositionEntityData.entity.getCompositionData();
391   }
392
393
394   private String getEntityNameByEntityType(String compositionData,
395                                            CompositionEntityValidationData entity) {
396     switch (entity.getEntityType()) {
397       case component:
398         ComponentData component = JsonUtil.json2Object(compositionData, ComponentData.class);
399         return component.getDisplayName();
400
401       case nic:
402         Nic nic = JsonUtil.json2Object(compositionData, Nic.class);
403         return nic.getName();
404
405       case network:
406         Network network = JsonUtil.json2Object(compositionData, Network.class);
407         return network.getName();
408
409       case image:
410         Image image = JsonUtil.json2Object(compositionData, Image.class);
411         return image.getFileName();
412
413       case compute:
414         ComputeData compute = JsonUtil.json2Object(compositionData, ComputeData.class);
415         return compute.getName();
416
417       case vsp:
418         CompositionEntityData vspEntity = getCompositionEntityDataById(entity);
419         if (Objects.isNull(vspEntity)) {
420           return null;
421         }
422         VspQuestionnaireEntity vspQuestionnaireEntity = (VspQuestionnaireEntity) vspEntity.entity;
423         VspDetails vspDetails =
424             vspInfoDao.get(new VspDetails(vspQuestionnaireEntity.getId(),
425                 vspQuestionnaireEntity.getVersion()));
426         return vspDetails.getName();
427       default:
428         return null;
429     }
430   }
431
432   private void removeNodesWithoutErrors(CompositionEntityValidationData node,
433                                         CompositionEntityValidationData parent) {
434
435     if (Objects.isNull(node)) {
436       return;
437     }
438
439     if (hasChildren(node)) {
440       Collection<CompositionEntityValidationData> subNodes =
441           new ArrayList<>(node.getSubEntitiesValidationData());
442       subNodes.forEach(subNode -> removeNodesWithoutErrors(subNode, node));
443       node.setSubEntitiesValidationData(subNodes);
444
445       if (canNodeGetRemovedFromValidationDataTree(node)) {
446         removeNodeFromChildren(parent, node);
447       }
448     } else if (canNodeGetRemovedFromValidationDataTree(node)) {
449       removeNodeFromChildren(parent, node);
450     }
451   }
452
453   private void removeNodeFromChildren(CompositionEntityValidationData parent,
454                                       CompositionEntityValidationData childToRemove) {
455     if (!Objects.isNull(parent)) {
456       parent.getSubEntitiesValidationData().remove(childToRemove);
457     }
458   }
459
460   private boolean hasChildren(CompositionEntityValidationData node) {
461     return !CollectionUtils.isEmpty(node.getSubEntitiesValidationData());
462   }
463
464   private boolean canNodeGetRemovedFromValidationDataTree(CompositionEntityValidationData node) {
465     return !hasChildren(node) && CollectionUtils.isEmpty(node.getErrors());
466   }
467
468
469   private void addValidationDataEntity(
470       Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData,
471       CompositionEntityId entityId, CompositionEntity entity) {
472     if (entitiesValidationData.containsKey(entityId)) {
473       return;
474     }
475
476     CompositionEntityValidationData validationData =
477         new CompositionEntityValidationData(entity.getType(), entity.getId());
478     entitiesValidationData.put(entityId, validationData);
479
480     CompositionEntityId parentEntityId = entityId.getParentId();
481     if (parentEntityId == null) {
482       roots.add(validationData);
483     } else {
484       CompositionEntityData parentEntity = entities.get(parentEntityId);
485       if (parentEntity == null) {
486         roots.add(validationData);
487       } else {
488         addValidationDataEntity(entitiesValidationData, parentEntityId, parentEntity.entity);
489         entitiesValidationData.get(parentEntityId).addSubEntityValidationData(validationData);
490       }
491     }
492   }
493
494   private void addErrorsToTree(CompositionEntityValidationData node,
495                                CompositionEntityId parentNodeId,
496                                Map<CompositionEntityId, Collection<String>> errors) {
497     if (node == null) {
498       return;
499     }
500     CompositionEntityId nodeId = new CompositionEntityId(node.getEntityId(), parentNodeId);
501     node.setErrors(errors.get(nodeId));
502
503     if (node.getSubEntitiesValidationData() != null) {
504       node.getSubEntitiesValidationData()
505           .forEach(subNode -> addErrorsToTree(subNode, nodeId, errors));
506     }
507   }
508
509   private Collection<String> validateQuestionnaire(CompositionEntityData compositionEntityData) {
510     logger.debug(String.format("validateQuestionnaire start:  " +
511             "[entity.type]=%s, [entity.id]=%s, [entity.questionnaireString]=%s",
512         compositionEntityData.entity.getType().name(),
513         compositionEntityData.entity.getCompositionEntityId().toString(),
514         compositionEntityData.entity.getQuestionnaireData()));
515
516     if (Objects.isNull(compositionEntityData.entity.getQuestionnaireData()) ||
517         !JsonUtil.isValidJson(compositionEntityData.entity.getQuestionnaireData())) {
518       return Collections.singletonList(String
519           .format(MISSING_OR_INVALID_QUESTIONNAIRE_MSG, compositionEntityData.entity.getType()));
520     }
521
522     return JsonUtil.validate(
523         compositionEntityData.entity.getQuestionnaireData() == null
524             ? JsonUtil.object2Json(new Object())
525             : compositionEntityData.entity.getQuestionnaireData(),
526         getSchema(compositionEntityData.entity.getType(), SchemaTemplateContext.questionnaire,
527             compositionEntityData.schemaTemplateInput));
528   }
529
530   private String getSchema(CompositionEntityType compositionEntityType,
531                            SchemaTemplateContext schemaTemplateContext,
532                            SchemaTemplateInput schemaTemplateInput) {
533     return schemaTemplateInput == null
534         ? nonDynamicSchemas.computeIfAbsent(compositionEntityType,
535         k -> generateSchema(schemaTemplateContext, compositionEntityType, null))
536         : generateSchema(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
537   }
538
539   private static class CompositionEntityData {
540     private CompositionEntity entity;
541     private SchemaTemplateInput schemaTemplateInput;
542
543     CompositionEntityData(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
544       this.entity = entity;
545       this.schemaTemplateInput = schemaTemplateInput;
546     }
547
548   }
549
550   // todo - make SchemaGenerator non static and mock it in UT instead of mocking this method (and
551   // make the method private
552   protected String generateSchema(SchemaTemplateContext schemaTemplateContext,
553                                   CompositionEntityType compositionEntityType,
554                                   SchemaTemplateInput schemaTemplateInput) {
555     return SchemaGenerator
556         .generate(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
557   }
558
559   @Override
560   public DeploymentFlavorEntity createDeploymentFlavor(DeploymentFlavorEntity deploymentFlavor) {
561     deploymentFlavor.setId(CommonMethods.nextUuId());
562     deploymentFlavorDao.create(deploymentFlavor);
563     return deploymentFlavor;
564   }
565
566   @Override
567   public ImageEntity createImage(ImageEntity image) {
568     image.setId(CommonMethods.nextUuId());
569
570     image.setQuestionnaireData(
571         new JsonSchemaDataGenerator(SchemaGenerator
572             .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.image, null))
573             .generateData());
574
575     imageDao.create(image);
576     return image;
577   }
578
579   public void saveComputesFlavorByComponent(String vspId, Version version, Component component,
580                                             String componentId) {
581     if (CollectionUtils.isNotEmpty(component.getCompute())) {
582       for (ComputeData flavor : component.getCompute()) {
583         ComputeEntity computeEntity = new ComputeEntity(vspId, version, componentId, null);
584         computeEntity.setComputeCompositionData(flavor);
585         computeEntity.setQuestionnaireData(
586             new JsonSchemaDataGenerator(SchemaGenerator
587                 .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.compute,
588                     null)).generateData());
589
590         computeDao.create(computeEntity);
591       }
592     }
593   }
594
595   public void saveImagesByComponent(String vspId, Version version, Component component, String
596       componentId) {
597     if (CollectionUtils.isNotEmpty(component.getImages())) {
598       for (Image img : component.getImages()) {
599         ImageEntity imageEntity = new ImageEntity(vspId, version, componentId, null);
600         imageEntity.setImageCompositionData(img);
601         createImage(imageEntity);
602       }
603     }
604   }
605
606 }