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