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