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