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