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