ada88b8e1b0eabf65332c83db88ae09421e8b521
[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 org.apache.commons.collections4.CollectionUtils;
20 import org.apache.commons.collections4.MapUtils;
21 import org.openecomp.core.dao.UniqueValueDao;
22 import org.openecomp.core.enrichment.api.EnrichmentManager;
23 import org.openecomp.core.enrichment.factory.EnrichmentManagerFactory;
24 import org.openecomp.core.model.dao.EnrichedServiceModelDao;
25 import org.openecomp.core.model.dao.ServiceModelDao;
26 import org.openecomp.core.model.types.ServiceElement;
27 import org.openecomp.core.util.UniqueValueUtil;
28 import org.openecomp.core.utilities.file.FileContentHandler;
29 import org.openecomp.core.utilities.json.JsonSchemaDataGenerator;
30 import org.openecomp.core.utilities.json.JsonUtil;
31 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
32 import org.openecomp.core.validation.api.ValidationManager;
33 import org.openecomp.core.validation.util.MessageContainerUtil;
34 import org.openecomp.sdc.common.errors.CoreException;
35 import org.openecomp.sdc.common.errors.ErrorCode;
36 import org.openecomp.sdc.common.errors.ValidationErrorBuilder;
37 import org.openecomp.sdc.common.utils.CommonUtil;
38 import org.openecomp.sdc.datatypes.error.ErrorLevel;
39 import org.openecomp.sdc.datatypes.error.ErrorMessage;
40 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
41 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
42 import org.openecomp.sdc.validation.util.ValidationManagerUtil;
43 import org.openecomp.sdc.vendorlicense.facade.VendorLicenseFacade;
44 import org.openecomp.sdc.vendorlicense.licenseartifacts.VendorLicenseArtifactsService;
45 import org.openecomp.sdc.vendorsoftwareproduct.CompositionEntityDataManager;
46 import org.openecomp.sdc.vendorsoftwareproduct.CompositionEntityDataManagerFactory;
47 import org.openecomp.sdc.vendorsoftwareproduct.ManualVspToscaManager;
48 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
49 import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductConstants;
50 import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager;
51 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDao;
52 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDependencyModelDao;
53 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComputeDao;
54 import org.openecomp.sdc.vendorsoftwareproduct.dao.DeploymentFlavorDao;
55 import org.openecomp.sdc.vendorsoftwareproduct.dao.ImageDao;
56 import org.openecomp.sdc.vendorsoftwareproduct.dao.NicDao;
57 import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateDao;
58 import org.openecomp.sdc.vendorsoftwareproduct.dao.PackageInfoDao;
59 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
60 import org.openecomp.sdc.vendorsoftwareproduct.dao.VspMergeDao;
61 import org.openecomp.sdc.vendorsoftwareproduct.dao.errors.VendorSoftwareProductNotFoundErrorBuilder;
62 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentDependencyModelEntity;
63 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
64 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComputeEntity;
65 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.DeploymentFlavorEntity;
66 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ImageEntity;
67 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NicEntity;
68 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OnboardingMethod;
69 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
70 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateEntity;
71 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.PackageInfo;
72 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
73 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspQuestionnaireEntity;
74 import org.openecomp.sdc.vendorsoftwareproduct.errors.ComponentDependencyModelErrorBuilder;
75 import org.openecomp.sdc.vendorsoftwareproduct.errors.ComponentErrorBuilder;
76 import org.openecomp.sdc.vendorsoftwareproduct.errors.DeploymentFlavorErrorBuilder;
77 import org.openecomp.sdc.vendorsoftwareproduct.errors.FileCreationErrorBuilder;
78 import org.openecomp.sdc.vendorsoftwareproduct.errors.InformationArtifactCreationErrorBuilder;
79 import org.openecomp.sdc.vendorsoftwareproduct.errors.NicInternalNetworkErrorBuilder;
80 import org.openecomp.sdc.vendorsoftwareproduct.errors.PackageInvalidErrorBuilder;
81 import org.openecomp.sdc.vendorsoftwareproduct.errors.PackageNotFoundErrorBuilder;
82 import org.openecomp.sdc.vendorsoftwareproduct.errors.TranslationFileCreationErrorBuilder;
83 import org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductInvalidErrorBuilder;
84 import org.openecomp.sdc.vendorsoftwareproduct.informationArtifact.InformationArtifactGenerator;
85 import org.openecomp.sdc.vendorsoftwareproduct.services.schemagenerator.SchemaGenerator;
86 import org.openecomp.sdc.vendorsoftwareproduct.types.QuestionnaireResponse;
87 import org.openecomp.sdc.vendorsoftwareproduct.types.QuestionnaireValidationResult;
88 import org.openecomp.sdc.vendorsoftwareproduct.types.ValidationResponse;
89 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
90 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentComputeAssociation;
91 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityId;
92 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityType;
93 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityValidationData;
94 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.DeploymentFlavor;
95 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.NetworkType;
96 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
97 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.ComponentQuestionnaireSchemaInput;
98 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateContext;
99 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateInput;
100 import org.openecomp.sdc.vendorsoftwareproduct.utils.ComponentDependencyTracker;
101 import org.openecomp.sdc.versioning.VersioningManager;
102 import org.openecomp.sdc.versioning.VersioningManagerFactory;
103 import org.openecomp.sdc.versioning.VersioningUtil;
104 import org.openecomp.sdc.versioning.dao.types.Version;
105
106 import java.io.BufferedOutputStream;
107 import java.io.ByteArrayInputStream;
108 import java.io.ByteArrayOutputStream;
109 import java.io.File;
110 import java.io.FileOutputStream;
111 import java.io.IOException;
112 import java.io.OutputStream;
113 import java.nio.ByteBuffer;
114 import java.util.ArrayList;
115 import java.util.Collection;
116 import java.util.Collections;
117 import java.util.HashMap;
118 import java.util.HashSet;
119 import java.util.List;
120 import java.util.Map;
121 import java.util.Objects;
122 import java.util.Optional;
123 import java.util.Set;
124 import java.util.zip.ZipInputStream;
125 import java.util.zip.ZipOutputStream;
126
127 public class VendorSoftwareProductManagerImpl implements VendorSoftwareProductManager {
128
129   private final VspMergeDao vspMergeDao;
130   private final OrchestrationTemplateDao orchestrationTemplateDao;
131   private final OrchestrationTemplateCandidateManager orchestrationTemplateCandidateManager;
132   private final VendorSoftwareProductInfoDao vspInfoDao;
133   private final VendorLicenseFacade vendorLicenseFacade;
134   private final ServiceModelDao<ToscaServiceModel, ServiceElement> serviceModelDao;
135   private final EnrichedServiceModelDao<ToscaServiceModel, ServiceElement> enrichedServiceModelDao;
136   private final VendorLicenseArtifactsService licenseArtifactsService;
137   private final InformationArtifactGenerator informationArtifactGenerator;
138   private final PackageInfoDao packageInfoDao;
139   private final DeploymentFlavorDao deploymentFlavorDao;
140   private final ComponentDao componentDao;
141   private final ComponentDependencyModelDao componentDependencyModelDao;
142   private final NicDao nicDao;
143   private final ComputeDao computeDao;
144   private final ImageDao imageDao;
145   private final ManualVspToscaManager manualVspToscaManager;
146   private final UniqueValueUtil uniqueValueUtil;
147
148   public VendorSoftwareProductManagerImpl(
149       VspMergeDao vspMergeDao,
150       OrchestrationTemplateDao orchestrationTemplateDataDao,
151       OrchestrationTemplateCandidateManager orchestrationTemplateCandidateManager,
152       VendorSoftwareProductInfoDao vspInfoDao,
153       VendorLicenseFacade vendorLicenseFacade,
154       ServiceModelDao<ToscaServiceModel, ServiceElement> serviceModelDao,
155       EnrichedServiceModelDao<ToscaServiceModel, ServiceElement> enrichedServiceModelDao,
156       VendorLicenseArtifactsService licenseArtifactsService,
157       InformationArtifactGenerator informationArtifactGenerator,
158       PackageInfoDao packageInfoDao,
159       DeploymentFlavorDao deploymentFlavorDao,
160       ComponentDao componentDao,
161       ComponentDependencyModelDao componentDependencyModelDao,
162       NicDao nicDao,
163       ComputeDao computeDao,
164       ImageDao imageDao,
165       ManualVspToscaManager manualVspToscaManager,
166       UniqueValueDao uniqueValueDao) {
167     this.vspMergeDao = vspMergeDao;
168     this.orchestrationTemplateDao = orchestrationTemplateDataDao;
169     this.orchestrationTemplateCandidateManager = orchestrationTemplateCandidateManager;
170     this.vspInfoDao = vspInfoDao;
171     this.vendorLicenseFacade = vendorLicenseFacade;
172     this.serviceModelDao = serviceModelDao;
173     this.enrichedServiceModelDao = enrichedServiceModelDao;
174     this.licenseArtifactsService = licenseArtifactsService;
175     this.informationArtifactGenerator = informationArtifactGenerator;
176     this.packageInfoDao = packageInfoDao;
177     this.deploymentFlavorDao = deploymentFlavorDao;
178     this.componentDao = componentDao;
179     this.componentDependencyModelDao = componentDependencyModelDao;
180     this.nicDao = nicDao;
181     this.computeDao = computeDao;
182     this.imageDao = imageDao;
183     this.manualVspToscaManager = manualVspToscaManager;
184     this.uniqueValueUtil = new UniqueValueUtil(uniqueValueDao);
185
186     registerToVersioning();
187   }
188
189   private void registerToVersioning() {
190     serviceModelDao.registerVersioning(
191         VendorSoftwareProductConstants.VENDOR_SOFTWARE_PRODUCT_VERSIONABLE_TYPE);
192     enrichedServiceModelDao.registerVersioning(
193         VendorSoftwareProductConstants.VENDOR_SOFTWARE_PRODUCT_VERSIONABLE_TYPE);
194   }
195
196   @Override
197   public ValidationResponse validate(String vspId, Version version) throws IOException {
198     VspDetails vspDetails = getValidatedVsp(vspId, version);
199     List<ErrorCode> vspErrors = new ArrayList<>(validateVspFields(vspDetails));
200     ValidationResponse validationResponse = new ValidationResponse();
201     if (Objects.nonNull(vspDetails.getOnboardingMethod())
202         && OnboardingMethod.Manual.name().equals(vspDetails.getOnboardingMethod())) {
203       validateManualOnboardingMethod(vspDetails, validationResponse, vspErrors);
204     } else {
205       validateOrchestrationTemplateCandidate(validationResponse, vspErrors, vspId, version);
206       if (!validationResponse.isValid()) {
207         return validationResponse;
208       }
209       if (vspDetails.getVlmVersion() != null || vspDetails.getLicenseAgreement() != null
210           || vspDetails.getFeatureGroups() != null) {
211         vspErrors.addAll(validateMandatoryLicenseFields(vspDetails));
212       }
213       OrchestrationTemplateEntity orchestrationTemplate =
214           orchestrationTemplateDao.get(vspId, version);
215       ToscaServiceModel serviceModel =
216           serviceModelDao.getServiceModel(vspId, vspDetails.getVersion());
217       if (isOrchestrationTemplateMissing(orchestrationTemplate)
218           || isServiceModelMissing(serviceModel)) {
219         vspErrors.add(VendorSoftwareProductInvalidErrorBuilder
220             .vendorSoftwareProductMissingServiceModelErrorBuilder(vspDetails.getId(),
221                 vspDetails.getVersion()));
222       }
223       validationResponse.setUploadDataErrors(validateOrchestrationTemplate(orchestrationTemplate));
224     }
225
226     QuestionnaireValidationResult questionnaireValidationResult = validateQuestionnaire
227         (vspDetails.getId(), vspDetails.getVersion(), vspDetails.getOnboardingMethod());
228
229     if (Objects.nonNull(questionnaireValidationResult)) {
230       if (validationResponse.getQuestionnaireValidationResult() == null || validationResponse
231           .getQuestionnaireValidationResult().getValidationData() == null) {
232         validationResponse.setQuestionnaireValidationResult(questionnaireValidationResult);
233       } else {
234         validationResponse.getQuestionnaireValidationResult().getValidationData().addAll
235             (questionnaireValidationResult.getValidationData());
236       }
237     }
238
239     Collection<ComponentDependencyModelEntity> componentDependencies =
240         componentDependencyModelDao.list(new ComponentDependencyModelEntity(vspId, version, null));
241
242     if (validateComponentDependencies(componentDependencies)) {
243       vspErrors
244           .add(ComponentDependencyModelErrorBuilder.getcyclicDependencyComponentErrorBuilder());
245     }
246     validationResponse
247         .setVspErrors(vspErrors);
248     validationResponse.setLicensingDataErrors(validateLicensingData(vspDetails));
249     return validationResponse;
250   }
251
252   private void validateOrchestrationTemplateCandidate(ValidationResponse validationResponse,
253                                                       List<ErrorCode> vspErrors, String vspId,
254                                                       Version version) {
255     OrchestrationTemplateCandidateData orchestrationTemplateCandidateData =
256         orchestrationTemplateCandidateManager.getInfo(vspId, version);
257     String validationData = orchestrationTemplateCandidateData.getValidationData();
258     String fileName = orchestrationTemplateCandidateData.getFileName();
259     if (Objects.nonNull(orchestrationTemplateCandidateData.getFileSuffix())) {
260       if (validationData.isEmpty()) {
261         vspErrors.add(VendorSoftwareProductInvalidErrorBuilder
262             .candidateDataNotProcessedOrAbortedErrorBuilder(fileName));
263       } else {
264         vspErrors.add(VendorSoftwareProductInvalidErrorBuilder.invalidProcessedCandidate(fileName));
265       }
266       validationResponse.setVspErrors(vspErrors);
267     }
268   }
269
270   private void validateManualOnboardingMethod(VspDetails vspDetails,
271                                               ValidationResponse validationResponse,
272                                               List<ErrorCode> vspErrors) {
273     vspErrors.addAll(validateMandatoryLicenseFields(vspDetails));
274
275     Collection<DeploymentFlavorEntity> deploymentFlavors = deploymentFlavorDao
276         .list(new DeploymentFlavorEntity(vspDetails.getId(), vspDetails.getVersion(), null));
277     if (CollectionUtils.isEmpty(deploymentFlavors)) {
278       vspErrors
279           .add(VendorSoftwareProductInvalidErrorBuilder.vspMissingDeploymentFlavorErrorBuilder());
280     }
281     vspErrors.addAll(validateDeploymentFlavors(deploymentFlavors));
282
283     Set<CompositionEntityValidationData> componentValidationResult =
284         componentValidation(vspDetails.getId(), vspDetails.getVersion());
285     if (!CollectionUtils.isEmpty(componentValidationResult)) {
286       if (validationResponse.getQuestionnaireValidationResult() == null
287           || validationResponse.getQuestionnaireValidationResult().getValidationData() == null) {
288         validationResponse.setQuestionnaireValidationResult(
289             new QuestionnaireValidationResult(componentValidationResult));
290       } else {
291         validationResponse.getQuestionnaireValidationResult().getValidationData()
292             .addAll(componentValidationResult);
293       }
294     }
295   }
296
297   @Override
298   public Map<String, List<ErrorMessage>> compile(String vspId, Version version) {
299     ToscaServiceModel serviceModel =
300         OnboardingMethod.Manual.name().equals(getValidatedVsp(vspId, version).getOnboardingMethod())
301             //Generate Tosca service model for Manual Onboarding flow
302             ? manualVspToscaManager
303             .generateToscaModel(manualVspToscaManager.gatherVspInformation(vspId, version))
304             : serviceModelDao.getServiceModel(vspId, version);
305
306     return compile(vspId, version, serviceModel);
307   }
308
309   private boolean validateComponentDependencies(
310       Collection<ComponentDependencyModelEntity> componentDependencies) {
311     ComponentDependencyTracker dependencyTracker = new ComponentDependencyTracker();
312
313     for (ComponentDependencyModelEntity componentDependency : componentDependencies) {
314       dependencyTracker.addDependency(componentDependency.getSourceComponentId(),
315           componentDependency.getTargetComponentId());
316     }
317     return dependencyTracker.isCyclicDependencyPresent();
318   }
319
320   private Collection<ErrorCode> validateDeploymentFlavors(
321       Collection<DeploymentFlavorEntity> deploymentFlavors) {
322
323     Collection<ErrorCode> errorCodeList = new ArrayList<>();
324     if (!CollectionUtils.isEmpty(deploymentFlavors)) {
325       deploymentFlavors.forEach(deploymentFlavor -> {
326         DeploymentFlavorEntity deployment = deploymentFlavorDao.get(deploymentFlavor);
327         DeploymentFlavor deploymentLocalFlavor = deployment.getDeploymentFlavorCompositionData();
328         if (deploymentLocalFlavor != null) {
329           if (deploymentLocalFlavor.getFeatureGroupId() == null) {
330             ErrorCode deploymentFlavorErrorBuilder = DeploymentFlavorErrorBuilder.
331                 getFeatureGroupMandatoryErrorBuilder(deploymentLocalFlavor.getModel());
332             errorCodeList.add(deploymentFlavorErrorBuilder);
333           }
334           validateComponentComputeAssociations(errorCodeList, deploymentFlavor,
335               deployment, deploymentLocalFlavor);
336         }
337       });
338     }
339     return errorCodeList;
340   }
341
342   private void validateComponentComputeAssociations(Collection<ErrorCode> errorCodeList,
343                                                     DeploymentFlavorEntity deploymentFlavor,
344                                                     DeploymentFlavorEntity deployment,
345                                                     DeploymentFlavor deploymentlocalFlavor) {
346     List<ComponentComputeAssociation> componentComputeAssociations =
347         deploymentlocalFlavor.getComponentComputeAssociations();
348     if (CollectionUtils.isEmpty(componentComputeAssociations)) {
349       CompositionEntityValidationData compositionEntityValidationData = new
350           CompositionEntityValidationData(CompositionEntityType.deployment, deploymentFlavor
351           .getId());
352       compositionEntityValidationData.setEntityName(deployment
353           .getDeploymentFlavorCompositionData().getModel());
354       ErrorCode deploymentFlavorErrorBuilder = DeploymentFlavorErrorBuilder
355           .getInvalidComponentComputeAssociationErrorBuilder(
356               deploymentlocalFlavor.getModel());
357
358       errorCodeList.add(deploymentFlavorErrorBuilder);
359     } else {
360       componentComputeAssociations.forEach(componentComputeAssociation -> {
361         if (componentComputeAssociation == null
362             || !(componentComputeAssociation.getComponentId() != null
363             && componentComputeAssociation.getComputeFlavorId() != null)) {
364           CompositionEntityValidationData compositionEntityValidationData = new
365               CompositionEntityValidationData(CompositionEntityType.deployment,
366               deploymentFlavor.getId());
367           compositionEntityValidationData.setEntityName(deployment
368               .getDeploymentFlavorCompositionData().getModel());
369           ErrorCode deploymentFlavorErrorBuilder = DeploymentFlavorErrorBuilder
370               .getInvalidComponentComputeAssociationErrorBuilder(
371                   deploymentlocalFlavor.getModel());
372
373           errorCodeList.add(deploymentFlavorErrorBuilder);
374         }
375       });
376     }
377   }
378
379   private Set<CompositionEntityValidationData> componentValidation(String vspId, Version version) {
380     Set<CompositionEntityValidationData> validationData = new HashSet<>();
381     Collection<ComponentEntity> components =
382         componentDao.list(new ComponentEntity(vspId, version, null));
383     if (!CollectionUtils.isEmpty(components)) {
384       components.forEach(component -> {
385         validateImage(vspId, version, validationData, component);
386         validateNic(vspId, version, validationData, component);
387
388       });
389     }
390
391     return validationData;
392   }
393
394   private void validateNic(String vspId, Version version,
395                            Set<CompositionEntityValidationData> validationData,
396                            ComponentEntity component) {
397     Collection<NicEntity> nics =
398         nicDao.list(new NicEntity(vspId, version, component.getId(), null));
399     if (CollectionUtils.isNotEmpty(nics)) {
400       nics.forEach(nicEntity -> {
401         NicEntity nic = nicDao.get(new NicEntity(vspId, version, component.getId(),
402             nicEntity.getId()));
403         NetworkType networkType = nic.getNicCompositionData().getNetworkType();
404         String networkId = nic.getNicCompositionData().getNetworkId();
405         if (networkType.equals(NetworkType.Internal) && networkId == null) {
406           CompositionEntityValidationData compositionEntityValidationData = new
407               CompositionEntityValidationData(CompositionEntityType.nic, nic.getId());
408           compositionEntityValidationData.setEntityName(nic.getNicCompositionData().getName());
409           ErrorCode nicInternalNetworkErrorBuilder = NicInternalNetworkErrorBuilder
410               .getNicNullNetworkIdInternalNetworkIdErrorBuilder();
411           List<String> errors = new ArrayList<>();
412           errors.add(nicInternalNetworkErrorBuilder.message());
413           compositionEntityValidationData.setErrors(errors);
414           validationData.add(compositionEntityValidationData);
415         }
416       });
417     }
418   }
419
420   private void validateImage(String vspId, Version version,
421                              Set<CompositionEntityValidationData> validationData,
422                              ComponentEntity component) {
423     Collection<ImageEntity> images =
424         imageDao.list(new ImageEntity(vspId, version, component.getId(), null));
425     if (CollectionUtils.isEmpty(images)) {
426       CompositionEntityValidationData compositionEntityValidationData = new
427           CompositionEntityValidationData(component.getType(), component.getId());
428       compositionEntityValidationData
429           .setEntityName(component.getComponentCompositionData().getDisplayName());
430       ErrorCode vfcMissingImageErrorBuilder =
431           ComponentErrorBuilder.vfcMissingImageErrorBuilder();
432       List<String> errors = new ArrayList<>();
433       errors.add(vfcMissingImageErrorBuilder.message());
434       compositionEntityValidationData.setErrors(errors);
435       validationData.add(compositionEntityValidationData);
436     }
437   }
438
439   private List<ErrorCode> validateVspFields(VspDetails vspDetails) {
440     List<ErrorCode> errors = new ArrayList<>();
441
442     if (vspDetails.getName() == null) {
443       errors.add(createMissingMandatoryFieldError("name"));
444     }
445     if (vspDetails.getDescription() == null) {
446       errors.add(createMissingMandatoryFieldError("description"));
447     }
448     if (vspDetails.getVendorId() == null) {
449       errors.add(createMissingMandatoryFieldError("vendor Id"));
450     }
451     if (vspDetails.getCategory() == null) {
452       errors.add(createMissingMandatoryFieldError("category"));
453     }
454     if (vspDetails.getSubCategory() == null) {
455       errors.add(createMissingMandatoryFieldError("sub category"));
456     }
457     return errors;
458   }
459
460   private List<ErrorCode> validateMandatoryLicenseFields(VspDetails vspDetails) {
461     List<ErrorCode> errors = new ArrayList<>();
462     if (vspDetails.getVlmVersion() == null) {
463       errors.add(createMissingMandatoryFieldError("licensing version"));
464     }
465     if (vspDetails.getLicenseAgreement() == null) {
466       errors.add(createMissingMandatoryFieldError("license agreement"));
467     }
468     if (CollectionUtils.isEmpty(vspDetails.getFeatureGroups())) {
469       errors.add(createMissingMandatoryFieldError("feature groups"));
470     }
471     return errors;
472   }
473
474   private static ErrorCode createMissingMandatoryFieldError(String fieldName) {
475     return new ValidationErrorBuilder("must be supplied", fieldName).build();
476   }
477
478   private Map<String, List<ErrorMessage>> compile(String vendorSoftwareProductId, Version version,
479                                                   ToscaServiceModel serviceModel) {
480     if (isServiceModelMissing(serviceModel)) {
481       return null;
482     }
483
484     enrichedServiceModelDao.deleteAll(vendorSoftwareProductId, version);
485
486     EnrichmentManager<ToscaServiceModel> enrichmentManager =
487         EnrichmentManagerFactory.getInstance().createInterface();
488     enrichmentManager.init(vendorSoftwareProductId, version);
489     enrichmentManager.setModel(serviceModel);
490     Map<String, List<ErrorMessage>> enrichErrors = enrichmentManager.enrich();
491
492     enrichedServiceModelDao
493         .storeServiceModel(vendorSoftwareProductId, version, enrichmentManager.getModel());
494
495     return enrichErrors;
496   }
497
498   private Collection<ErrorCode> validateLicensingData(VspDetails vspDetails) {
499     if (vspDetails.getVendorId() == null || vspDetails.getVlmVersion() == null
500         || vspDetails.getLicenseAgreement() == null
501         || CollectionUtils.isEmpty(vspDetails.getFeatureGroups())) {
502       return Collections.emptyList();
503     }
504     return vendorLicenseFacade
505         .validateLicensingData(vspDetails.getVendorId(), vspDetails.getVlmVersion(),
506             vspDetails.getLicenseAgreement(), vspDetails.getFeatureGroups());
507   }
508
509   @Override
510   public VspDetails createVsp(VspDetails vspDetails) {
511     vspInfoDao.create(vspDetails);
512     vspInfoDao.updateQuestionnaireData(vspDetails.getId(), vspDetails.getVersion(),
513         new JsonSchemaDataGenerator(getVspQuestionnaireSchema(null)).generateData());
514     return vspDetails;
515   }
516
517   @Override
518   public void updateVsp(VspDetails vspDetails) {
519     VspDetails retrieved = vspInfoDao.get(vspDetails);
520     if (retrieved == null) {
521       throw new CoreException((new ErrorCode.ErrorCodeBuilder()
522           .withMessage(String.format("Vsp with id %s and version %s does not exist.",
523               vspDetails.getId(), vspDetails.getVersion().getId()))).build());
524     }
525     vspDetails.setOnboardingMethod(retrieved.getOnboardingMethod());
526
527     //If any existing feature group is removed from VSP which is also associated in DF then
528     //update DF to remove feature group associations.
529     updateDeploymentFlavor(vspDetails);
530
531     updateUniqueName(retrieved.getName(), vspDetails.getName());
532     vspInfoDao.update(vspDetails);
533   }
534
535   private void updateDeploymentFlavor(VspDetails vspDetails) {
536     final List<String> featureGroups = vspDetails.getFeatureGroups();
537     if (featureGroups != null) {
538       final Collection<DeploymentFlavorEntity> deploymentFlavorEntities = deploymentFlavorDao
539           .list(new DeploymentFlavorEntity(vspDetails.getId(), vspDetails
540               .getVersion(), null));
541       if (Objects.nonNull(deploymentFlavorEntities)) {
542         for (DeploymentFlavorEntity deploymentFlavorEntity : deploymentFlavorEntities) {
543           updateDeploymentFlavourEntity(featureGroups, deploymentFlavorEntity);
544         }
545       }
546     }
547   }
548
549   private void updateDeploymentFlavourEntity(List<String> featureGroups,
550                                              DeploymentFlavorEntity deploymentFlavorEntity) {
551     final String featureGroupId =
552         deploymentFlavorEntity.getDeploymentFlavorCompositionData().getFeatureGroupId();
553     if (!featureGroups.contains(featureGroupId)) {
554       DeploymentFlavor deploymentFlavorCompositionData =
555           deploymentFlavorEntity.getDeploymentFlavorCompositionData();
556       deploymentFlavorCompositionData.setFeatureGroupId(null);
557       deploymentFlavorEntity.setDeploymentFlavorCompositionData
558           (deploymentFlavorCompositionData);
559       deploymentFlavorDao.update(deploymentFlavorEntity);
560     }
561   }
562
563
564   @Override
565   public VspDetails getVsp(String vspId, Version version) {
566     return getValidatedVsp(vspId, version);
567   }
568
569   private VspDetails getValidatedVsp(String vspId, Version version) {
570     VspDetails vsp = vspInfoDao.get(new VspDetails(vspId, version));
571     if (vsp == null) {
572       throw new CoreException(new VendorSoftwareProductNotFoundErrorBuilder(vspId).build());
573     }
574     return vsp;
575   }
576
577   @Override
578   public void deleteVsp(String vspId, Version version) {
579     vspMergeDao.deleteHint(vspId, version);
580   }
581
582   @Override
583   public List<PackageInfo> listPackages(String category, String subCategory) {
584     return packageInfoDao.listByCategory(category, subCategory);
585   }
586
587   @Override
588   public File getTranslatedFile(String vspId, Version version) {
589     PackageInfo packageInfo = packageInfoDao.get(new PackageInfo(vspId, version));
590     if (packageInfo == null) {
591       throw new CoreException(new PackageNotFoundErrorBuilder(vspId, version).build());
592     }
593
594     ByteBuffer translatedFileBuffer = packageInfo.getTranslatedFile();
595     if (translatedFileBuffer == null) {
596       throw new CoreException(new PackageInvalidErrorBuilder(vspId, version).build());
597     }
598
599     File translatedFile = new File(VendorSoftwareProductConstants.VSP_PACKAGE_ZIP);
600
601     try (FileOutputStream fos = new FileOutputStream(translatedFile)) {
602       fos.write(translatedFileBuffer.array());
603     } catch (IOException exception) {
604       throw new CoreException(new TranslationFileCreationErrorBuilder(vspId, version).build(),
605           exception);
606     }
607     return translatedFile;
608   }
609
610   @Override
611   public byte[] getOrchestrationTemplateFile(String vspId, Version version) {
612     OrchestrationTemplateEntity uploadData = orchestrationTemplateDao.get(vspId, version);
613     ByteBuffer contentData = uploadData.getContentData();
614     if (contentData == null) {
615       return null;
616     }
617
618     ByteArrayOutputStream baos = new ByteArrayOutputStream();
619
620     try (final ZipOutputStream zos = new ZipOutputStream(baos);
621          ZipInputStream ignored = new ZipInputStream(
622              new ByteArrayInputStream(contentData.array()))) {
623       zos.write(contentData.array());
624     } catch (IOException exception) {
625       throw new CoreException(new FileCreationErrorBuilder(vspId).build(), exception);
626     }
627     return baos.toByteArray();
628   }
629
630   @Override
631   public OrchestrationTemplateEntity getOrchestrationTemplateInfo(String vspId, Version version) {
632     return orchestrationTemplateDao.getInfo(vspId, version);
633   }
634
635   @Override
636   public Optional<FilesDataStructure> getOrchestrationTemplateStructure(String vspId,
637                                                                         Version version) {
638     Optional<String> jsonFileDataStructure =
639         orchestrationTemplateDao.getOrchestrationTemplateStructure(vspId, version);
640
641     if (jsonFileDataStructure.isPresent() && JsonUtil.isValidJson(jsonFileDataStructure.get())) {
642       return Optional
643           .of(JsonUtil.json2Object(jsonFileDataStructure.get(), FilesDataStructure.class));
644     } else {
645       return Optional.empty();
646     }
647   }
648
649   @Override
650   public PackageInfo createPackage(String vspId, Version version) {
651     ToscaServiceModel toscaServiceModel = enrichedServiceModelDao.getServiceModel(vspId, version);
652     VspDetails vspDetails = vspInfoDao.get(new VspDetails(vspId, version));
653     Version vlmVersion = vspDetails.getVlmVersion();
654     if (vlmVersion != null) {
655       populateVersionsForVlm(vspDetails.getVendorId(), vlmVersion);
656     }
657     PackageInfo packageInfo = createPackageInfo(vspDetails);
658
659     ToscaFileOutputServiceCsarImpl toscaServiceTemplateServiceCsar =
660         new ToscaFileOutputServiceCsarImpl();
661     FileContentHandler licenseArtifacts = licenseArtifactsService
662         .createLicenseArtifacts(vspDetails.getId(), vspDetails.getVendorId(), vlmVersion,
663             vspDetails.getFeatureGroups());
664     //todo add tosca validation here
665     packageInfo.setTranslatedFile(ByteBuffer.wrap(
666         toscaServiceTemplateServiceCsar.createOutputFile(toscaServiceModel, licenseArtifacts)));
667
668     packageInfoDao.create(packageInfo);
669     return packageInfo;
670   }
671
672   protected void populateVersionsForVlm(String vlmId, Version vlmVersion) {
673     VersioningManager versioningManager = VersioningManagerFactory.getInstance().createInterface();
674     versioningManager.list(vlmId).stream()
675         .filter(version -> version.getId().equalsIgnoreCase(vlmVersion.getId()))
676         .findAny()
677         .ifPresent(version -> {
678           vlmVersion.setMinor(version.getMinor());
679           vlmVersion.setMajor(version.getMajor());
680         });
681   }
682
683   private PackageInfo createPackageInfo(VspDetails vspDetails) {
684     PackageInfo packageInfo = new PackageInfo(vspDetails.getId(), vspDetails.getVersion());
685     packageInfo.setVspName(vspDetails.getName());
686     packageInfo.setVspDescription(vspDetails.getDescription());
687     packageInfo.setCategory(vspDetails.getCategory());
688     packageInfo.setSubCategory(vspDetails.getSubCategory());
689     packageInfo.setVendorName(vspDetails.getVendorName());
690     packageInfo.setPackageType(VendorSoftwareProductConstants.CSAR);
691     packageInfo.setVendorRelease("1.0"); //todo TBD
692     return packageInfo;
693   }
694
695   @Override
696
697   public QuestionnaireResponse getVspQuestionnaire(String vspId, Version version) {
698     VspQuestionnaireEntity retrieved = vspInfoDao.getQuestionnaire(vspId, version);
699     VersioningUtil.validateEntityExistence(retrieved, new VspQuestionnaireEntity(vspId, version),
700         VspDetails.ENTITY_TYPE);
701
702     String questionnaireData = retrieved.getQuestionnaireData();
703
704     QuestionnaireResponse questionnaireResponse = new QuestionnaireResponse();
705     questionnaireResponse.setData(questionnaireData);
706     questionnaireResponse.setSchema(getVspQuestionnaireSchema(null));
707     return questionnaireResponse;
708   }
709
710   @Override
711   public void updateVspQuestionnaire(String vspId, Version version, String questionnaireData) {
712     vspInfoDao.updateQuestionnaireData(vspId, version, questionnaireData);
713   }
714
715
716   private Map<String, List<ErrorMessage>> validateOrchestrationTemplate(
717       OrchestrationTemplateEntity orchestrationTemplate) throws IOException {
718
719     if (isOrchestrationTemplateMissing(orchestrationTemplate)) {
720       return null;
721     }
722     Map<String, List<ErrorMessage>> validationErrors = new HashMap<>();
723
724     FileContentHandler fileContentMap = CommonUtil.validateAndUploadFileContent(
725         OnboardingTypesEnum.getOnboardingTypesEnum(orchestrationTemplate.getFileSuffix()),
726         orchestrationTemplate.getContentData().array());
727
728     if (CommonUtil.isFileOriginFromZip(orchestrationTemplate.getFileSuffix())) {
729       ValidationManager validationManager =
730           ValidationManagerUtil.initValidationManager(fileContentMap);
731       validationErrors.putAll(validationManager.validate());
732     }
733
734     return
735         MapUtils.isEmpty(MessageContainerUtil.getMessageByLevel(ErrorLevel.ERROR, validationErrors))
736             ? null : validationErrors;
737   }
738
739   private QuestionnaireValidationResult validateQuestionnaire(String vspId, Version version,
740                                                               String onboardingMethod) {
741     // The apis of CompositionEntityDataManager used here are stateful!
742     // so, it must be re-created from scratch when it is used!
743     CompositionEntityDataManager compositionEntityDataManager =
744         CompositionEntityDataManagerFactory.getInstance().createInterface();
745     compositionEntityDataManager
746         .addEntity(vspInfoDao.getQuestionnaire(vspId, version), null);
747
748     Collection<NicEntity> nics = nicDao.listByVsp(vspId, version);
749
750     Map<String, List<String>> nicNamesByComponent = new HashMap<>();
751     for (NicEntity nicEntity : nics) {
752       compositionEntityDataManager.addEntity(nicEntity, null);
753
754       Nic nic = nicEntity.getNicCompositionData();
755       if (nic != null && nic.getName() != null) {
756         List<String> nicNames =
757             nicNamesByComponent.computeIfAbsent(nicEntity.getComponentId(), k -> new ArrayList<>());
758         nicNames.add(nic.getName());
759       }
760     }
761
762     Collection<ComponentEntity> components =
763         componentDao.listCompositionAndQuestionnaire(vspId, version);
764     components.forEach(component -> compositionEntityDataManager.addEntity(component,
765         new ComponentQuestionnaireSchemaInput(nicNamesByComponent.get(component.getId()),
766             JsonUtil.json2Object(component.getQuestionnaireData(), Map.class))));
767
768     Collection<ComputeEntity> computes = computeDao.listByVsp(vspId, version);
769     computes.forEach(compute -> compositionEntityDataManager.addEntity(compute, null));
770
771     if (OnboardingMethod.Manual.name().equals(onboardingMethod)) {
772       Collection<ImageEntity> images = imageDao.listByVsp(vspId, version);
773       images.forEach(image -> compositionEntityDataManager.addEntity(image, null));
774     }
775
776     Map<CompositionEntityId, Collection<String>> errorsByEntityId =
777         compositionEntityDataManager.validateEntitiesQuestionnaire();
778     if (MapUtils.isNotEmpty(errorsByEntityId)) {
779       compositionEntityDataManager.buildTrees();
780       compositionEntityDataManager.addErrorsToTrees(errorsByEntityId);
781       return new QuestionnaireValidationResult(
782           compositionEntityDataManager.getAllErrorsByVsp(vspId));
783     }
784     return null;
785   }
786
787   @Override
788   public File getInformationArtifact(String vspId, Version version) {
789     VspDetails vspDetails = vspInfoDao.get(new VspDetails(vspId, version));
790
791     if (vspDetails == null) {
792       return null;
793     }
794
795     String vspName = vspDetails.getName();
796     ByteBuffer infoArtifactAsByteBuffer;
797     File infoArtifactFile;
798     try {
799       infoArtifactAsByteBuffer = ByteBuffer.wrap(informationArtifactGenerator.generate(vspId,
800           version).getBytes());
801
802       infoArtifactFile =
803           new File(
804               String.format(VendorSoftwareProductConstants.INFORMATION_ARTIFACT_NAME, vspName));
805       try (OutputStream out = new BufferedOutputStream(new FileOutputStream(infoArtifactFile))) {
806         out.write(infoArtifactAsByteBuffer.array());
807       }
808
809     } catch (IOException ex) {
810       throw new CoreException(new InformationArtifactCreationErrorBuilder(vspId).build(), ex);
811     }
812     return infoArtifactFile;
813   }
814
815   String getVspQuestionnaireSchema(SchemaTemplateInput schemaInput) {
816     return SchemaGenerator
817         .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.vsp, schemaInput);
818   }
819
820   void updateUniqueName(String oldVspName, String newVspName) {
821     uniqueValueUtil.updateUniqueValue(
822         VendorSoftwareProductConstants.UniqueValues.VENDOR_SOFTWARE_PRODUCT_NAME,
823         oldVspName, newVspName);
824   }
825
826   @Override
827   public Collection<ComputeEntity> getComputeByVsp(String vspId, Version version) {
828     return computeDao.listByVsp(vspId, version);
829   }
830
831   private boolean isOrchestrationTemplateMissing(OrchestrationTemplateEntity orchestrationTemplate) {
832     return orchestrationTemplate == null
833             || orchestrationTemplate.getContentData() == null
834             || orchestrationTemplate.getFileSuffix() == null
835             || orchestrationTemplate.getFileName() == null;
836   }
837
838   private boolean isServiceModelMissing(ToscaServiceModel serviceModel) {
839     return serviceModel == null || serviceModel.getEntryDefinitionServiceTemplate() == null;
840   }
841
842 }