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