e3c7d6ecdd0ab805b5f1f9aee6e7942138e761ea
[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), null,
770                                                      OnboardingMethod.Manual.name().equals(onboardingMethod))));
771
772     Collection<ComputeEntity> computes = computeDao.listByVsp(vspId, version);
773     computes.forEach(compute -> compositionEntityDataManager.addEntity(compute, null));
774
775     if (OnboardingMethod.Manual.name().equals(onboardingMethod)) {
776       Collection<ImageEntity> images = imageDao.listByVsp(vspId, version);
777       images.forEach(image -> compositionEntityDataManager.addEntity(image, null));
778     }
779
780     Map<CompositionEntityId, Collection<String>> errorsByEntityId =
781         compositionEntityDataManager.validateEntitiesQuestionnaire();
782     if (MapUtils.isNotEmpty(errorsByEntityId)) {
783       compositionEntityDataManager.buildTrees();
784       compositionEntityDataManager.addErrorsToTrees(errorsByEntityId);
785       return new QuestionnaireValidationResult(
786           compositionEntityDataManager.getAllErrorsByVsp(vspId));
787     }
788     return null;
789   }
790
791   @Override
792   public File getInformationArtifact(String vspId, Version version) {
793     VspDetails vspDetails = vspInfoDao.get(new VspDetails(vspId, version));
794
795     if (vspDetails == null) {
796       return null;
797     }
798
799     String vspName = vspDetails.getName();
800     ByteBuffer infoArtifactAsByteBuffer;
801     File infoArtifactFile;
802     try {
803       infoArtifactAsByteBuffer = ByteBuffer.wrap(informationArtifactGenerator.generate(vspId,
804           version).getBytes());
805
806       infoArtifactFile =
807           new File(
808               String.format(VendorSoftwareProductConstants.INFORMATION_ARTIFACT_NAME, vspName));
809       try (OutputStream out = new BufferedOutputStream(new FileOutputStream(infoArtifactFile))) {
810         out.write(infoArtifactAsByteBuffer.array());
811       }
812
813     } catch (IOException ex) {
814       throw new CoreException(new InformationArtifactCreationErrorBuilder(vspId).build(), ex);
815     }
816     return infoArtifactFile;
817   }
818
819   String getVspQuestionnaireSchema(SchemaTemplateInput schemaInput) {
820     return SchemaGenerator
821         .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.vsp, schemaInput);
822   }
823
824   @Override
825   public Optional<Pair<String, byte[]>> get(String vspId, Version version) throws IOException {
826
827     OrchestrationTemplateEntity orchestrationTemplateEntity =
828         orchestrationTemplateDao.get(vspId, version);
829
830     if (isOrchestrationTemplateMissing(orchestrationTemplateEntity)) {
831       return Optional.empty();
832     }
833
834     if (CommonUtil.isFileOriginFromZip(orchestrationTemplateEntity.getFileSuffix())) {
835       return Optional.of(new ImmutablePair<>(OnboardingTypesEnum.ZIP.toString(), candidateService
836           .getZipData(orchestrationTemplateEntity.getContentData())));
837     }
838     return Optional.of(new ImmutablePair<>(orchestrationTemplateEntity.getFileSuffix(),
839         orchestrationTemplateEntity.getContentData().array()));
840   }
841
842   void updateUniqueName(String oldVspName, String newVspName) {
843     uniqueValueUtil.updateUniqueValue(
844         VendorSoftwareProductConstants.UniqueValues.VENDOR_SOFTWARE_PRODUCT_NAME,
845         oldVspName, newVspName);
846   }
847
848   @Override
849   public Collection<ComputeEntity> getComputeByVsp(String vspId, Version version) {
850     return computeDao.listByVsp(vspId, version);
851   }
852
853   private boolean isOrchestrationTemplateMissing(
854       OrchestrationTemplateEntity orchestrationTemplate) {
855     return orchestrationTemplate == null
856         || orchestrationTemplate.getContentData() == null
857         || orchestrationTemplate.getFileSuffix() == null
858         || orchestrationTemplate.getFileName() == null;
859   }
860
861   private boolean isServiceModelMissing(ToscaServiceModel serviceModel) {
862     return serviceModel == null || serviceModel.getEntryDefinitionServiceTemplate() == null;
863   }
864
865 }