19d06ed493969e1ecdb1c08214b225e8fd8edcd9
[sdc.git] / openecomp-be / backend / openecomp-sdc-vendor-software-product-manager / src / main / java / org / openecomp / sdc / vendorsoftwareproduct / impl / VendorSoftwareProductManagerImpl.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.vendorsoftwareproduct.impl;
18
19 import static org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductInvalidErrorBuilder.candidateDataNotProcessedOrAbortedErrorBuilder;
20 import static org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductInvalidErrorBuilder.invalidProcessedCandidate;
21 import static org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductInvalidErrorBuilder.vspMissingDeploymentFlavorErrorBuilder;
22 import static org.openecomp.sdc.tosca.csar.CSARConstants.MAIN_SERVICE_TEMPLATE_MF_FILE_NAME;
23
24 import java.io.BufferedOutputStream;
25 import java.io.ByteArrayInputStream;
26 import java.io.ByteArrayOutputStream;
27 import java.io.File;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.nio.ByteBuffer;
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.Optional;
41 import java.util.Set;
42 import java.util.zip.ZipInputStream;
43 import java.util.zip.ZipOutputStream;
44 import org.apache.commons.collections4.CollectionUtils;
45 import org.apache.commons.collections4.MapUtils;
46 import org.apache.commons.lang3.tuple.ImmutablePair;
47 import org.apache.commons.lang3.tuple.Pair;
48 import org.openecomp.core.dao.UniqueValueDao;
49 import org.openecomp.core.enrichment.api.EnrichmentManager;
50 import org.openecomp.core.enrichment.factory.EnrichmentManagerFactory;
51 import org.openecomp.core.model.dao.EnrichedServiceModelDao;
52 import org.openecomp.core.model.dao.ServiceModelDao;
53 import org.openecomp.core.model.types.ServiceElement;
54 import org.openecomp.core.util.UniqueValueUtil;
55 import org.openecomp.core.utilities.file.FileContentHandler;
56 import org.openecomp.core.utilities.json.JsonSchemaDataGenerator;
57 import org.openecomp.core.utilities.json.JsonUtil;
58 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
59 import org.openecomp.core.validation.api.ValidationManager;
60 import org.openecomp.core.validation.util.MessageContainerUtil;
61 import org.openecomp.sdc.common.errors.CoreException;
62 import org.openecomp.sdc.common.errors.ErrorCode;
63 import org.openecomp.sdc.common.errors.ValidationErrorBuilder;
64 import org.openecomp.sdc.common.utils.CommonUtil;
65 import org.openecomp.sdc.datatypes.error.ErrorLevel;
66 import org.openecomp.sdc.datatypes.error.ErrorMessage;
67 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
68 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
69 import org.openecomp.sdc.validation.util.ValidationManagerUtil;
70 import org.openecomp.sdc.vendorlicense.facade.VendorLicenseFacade;
71 import org.openecomp.sdc.vendorlicense.licenseartifacts.VendorLicenseArtifactsService;
72 import org.openecomp.sdc.vendorsoftwareproduct.CompositionEntityDataManager;
73 import org.openecomp.sdc.vendorsoftwareproduct.CompositionEntityDataManagerFactory;
74 import org.openecomp.sdc.vendorsoftwareproduct.ManualVspToscaManager;
75 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
76 import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductConstants;
77 import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager;
78 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDao;
79 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDependencyModelDao;
80 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComputeDao;
81 import org.openecomp.sdc.vendorsoftwareproduct.dao.DeploymentFlavorDao;
82 import org.openecomp.sdc.vendorsoftwareproduct.dao.ImageDao;
83 import org.openecomp.sdc.vendorsoftwareproduct.dao.NicDao;
84 import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateDao;
85 import org.openecomp.sdc.vendorsoftwareproduct.dao.PackageInfoDao;
86 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
87 import org.openecomp.sdc.vendorsoftwareproduct.dao.VspMergeDao;
88 import org.openecomp.sdc.vendorsoftwareproduct.dao.errors.VendorSoftwareProductNotFoundErrorBuilder;
89 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentDependencyModelEntity;
90 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
91 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComputeEntity;
92 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.DeploymentFlavorEntity;
93 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ImageEntity;
94 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NicEntity;
95 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OnboardingMethod;
96 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateEntity;
97 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.PackageInfo;
98 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
99 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspQuestionnaireEntity;
100 import org.openecomp.sdc.vendorsoftwareproduct.errors.ComponentDependencyModelErrorBuilder;
101 import org.openecomp.sdc.vendorsoftwareproduct.errors.ComponentErrorBuilder;
102 import org.openecomp.sdc.vendorsoftwareproduct.errors.DeploymentFlavorErrorBuilder;
103 import org.openecomp.sdc.vendorsoftwareproduct.errors.FileCreationErrorBuilder;
104 import org.openecomp.sdc.vendorsoftwareproduct.errors.InformationArtifactCreationErrorBuilder;
105 import org.openecomp.sdc.vendorsoftwareproduct.errors.NicInternalNetworkErrorBuilder;
106 import org.openecomp.sdc.vendorsoftwareproduct.errors.PackageInvalidErrorBuilder;
107 import org.openecomp.sdc.vendorsoftwareproduct.errors.PackageNotFoundErrorBuilder;
108 import org.openecomp.sdc.vendorsoftwareproduct.errors.TranslationFileCreationErrorBuilder;
109 import org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductInvalidErrorBuilder;
110 import org.openecomp.sdc.tosca.csar.Manifest;
111 import org.openecomp.sdc.tosca.csar.OnboardingManifest;
112 import org.openecomp.sdc.vendorsoftwareproduct.informationArtifact.InformationArtifactGenerator;
113 import org.openecomp.sdc.vendorsoftwareproduct.services.impl.etsi.ETSIService;
114 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
115 import org.openecomp.sdc.vendorsoftwareproduct.services.impl.etsi.ETSIServiceImpl;
116 import org.openecomp.sdc.vendorsoftwareproduct.services.schemagenerator.SchemaGenerator;
117 import org.openecomp.sdc.vendorsoftwareproduct.types.QuestionnaireResponse;
118 import org.openecomp.sdc.vendorsoftwareproduct.types.QuestionnaireValidationResult;
119 import org.openecomp.sdc.vendorsoftwareproduct.types.ValidationResponse;
120 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
121 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentComputeAssociation;
122 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityId;
123 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityType;
124 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityValidationData;
125 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.DeploymentFlavor;
126 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.NetworkType;
127 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
128 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.ComponentQuestionnaireSchemaInput;
129 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateContext;
130 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateInput;
131 import org.openecomp.sdc.vendorsoftwareproduct.utils.ComponentDependencyTracker;
132 import org.openecomp.sdc.versioning.VersioningManager;
133 import org.openecomp.sdc.versioning.VersioningManagerFactory;
134 import org.openecomp.sdc.versioning.VersioningUtil;
135 import org.openecomp.sdc.versioning.dao.types.Version;
136
137 public class VendorSoftwareProductManagerImpl implements VendorSoftwareProductManager {
138
139   private final VspMergeDao vspMergeDao;
140   private final OrchestrationTemplateDao orchestrationTemplateDao;
141   private final OrchestrationTemplateCandidateManager orchestrationTemplateCandidateManager;
142   private final VendorSoftwareProductInfoDao vspInfoDao;
143   private final VendorLicenseFacade vendorLicenseFacade;
144   private final ServiceModelDao<ToscaServiceModel, ServiceElement> serviceModelDao;
145   private final EnrichedServiceModelDao<ToscaServiceModel, ServiceElement> enrichedServiceModelDao;
146   private final VendorLicenseArtifactsService licenseArtifactsService;
147   private final InformationArtifactGenerator informationArtifactGenerator;
148   private final PackageInfoDao packageInfoDao;
149   private final DeploymentFlavorDao deploymentFlavorDao;
150   private final ComponentDao componentDao;
151   private final ComponentDependencyModelDao componentDependencyModelDao;
152   private final NicDao nicDao;
153   private final ComputeDao computeDao;
154   private final ImageDao imageDao;
155   private final ManualVspToscaManager manualVspToscaManager;
156   private final UniqueValueUtil uniqueValueUtil;
157   private final CandidateService candidateService;
158
159   public VendorSoftwareProductManagerImpl(
160       VspMergeDao vspMergeDao,
161       OrchestrationTemplateDao orchestrationTemplateDataDao,
162       OrchestrationTemplateCandidateManager orchestrationTemplateCandidateManager,
163       VendorSoftwareProductInfoDao vspInfoDao,
164       VendorLicenseFacade vendorLicenseFacade,
165       ServiceModelDao<ToscaServiceModel, ServiceElement> serviceModelDao,
166       EnrichedServiceModelDao<ToscaServiceModel, ServiceElement> enrichedServiceModelDao,
167       VendorLicenseArtifactsService licenseArtifactsService,
168       InformationArtifactGenerator informationArtifactGenerator,
169       PackageInfoDao packageInfoDao,
170       DeploymentFlavorDao deploymentFlavorDao,
171       ComponentDao componentDao,
172       ComponentDependencyModelDao componentDependencyModelDao,
173       NicDao nicDao,
174       ComputeDao computeDao,
175       ImageDao imageDao,
176       ManualVspToscaManager manualVspToscaManager,
177       UniqueValueDao uniqueValueDao,
178       CandidateService candidateService) {
179     this.vspMergeDao = vspMergeDao;
180     this.orchestrationTemplateDao = orchestrationTemplateDataDao;
181     this.orchestrationTemplateCandidateManager = orchestrationTemplateCandidateManager;
182     this.vspInfoDao = vspInfoDao;
183     this.vendorLicenseFacade = vendorLicenseFacade;
184     this.serviceModelDao = serviceModelDao;
185     this.enrichedServiceModelDao = enrichedServiceModelDao;
186     this.licenseArtifactsService = licenseArtifactsService;
187     this.informationArtifactGenerator = informationArtifactGenerator;
188     this.packageInfoDao = packageInfoDao;
189     this.deploymentFlavorDao = deploymentFlavorDao;
190     this.componentDao = componentDao;
191     this.componentDependencyModelDao = componentDependencyModelDao;
192     this.nicDao = nicDao;
193     this.computeDao = computeDao;
194     this.imageDao = imageDao;
195     this.manualVspToscaManager = manualVspToscaManager;
196     this.uniqueValueUtil = new UniqueValueUtil(uniqueValueDao);
197     this.candidateService = candidateService;
198
199     registerToVersioning();
200   }
201
202   private void registerToVersioning() {
203     serviceModelDao.registerVersioning(
204         VendorSoftwareProductConstants.VENDOR_SOFTWARE_PRODUCT_VERSIONABLE_TYPE);
205     enrichedServiceModelDao.registerVersioning(
206         VendorSoftwareProductConstants.VENDOR_SOFTWARE_PRODUCT_VERSIONABLE_TYPE);
207   }
208
209   @Override
210   public ValidationResponse validate(VspDetails vspDetails) throws IOException {
211     List<ErrorCode> vspErrors = new ArrayList<>(validateVspFields(vspDetails));
212     ValidationResponse validationResponse = new ValidationResponse();
213     if (Objects.nonNull(vspDetails.getOnboardingMethod())
214         && OnboardingMethod.Manual.name().equals(vspDetails.getOnboardingMethod())) {
215       validateManualOnboardingMethod(vspDetails, validationResponse, vspErrors);
216     } else {
217       validateOrchestrationTemplateCandidate(validationResponse, vspErrors, vspDetails.getId(), vspDetails.getVersion());
218       if (!validationResponse.isValid()) {
219         return validationResponse;
220       }
221       if (vspDetails.getVlmVersion() != null || vspDetails.getLicenseAgreement() != null
222           || vspDetails.getFeatureGroups() != null) {
223         vspErrors.addAll(validateMandatoryLicenseFields(vspDetails));
224       }
225       OrchestrationTemplateEntity orchestrationTemplate =
226           orchestrationTemplateDao.get(vspDetails.getId(), vspDetails.getVersion());
227       ToscaServiceModel serviceModel =
228           serviceModelDao.getServiceModel( vspDetails.getId(), vspDetails.getVersion());
229       if (isOrchestrationTemplateMissing(orchestrationTemplate)
230           || isServiceModelMissing(serviceModel)) {
231         vspErrors.add(VendorSoftwareProductInvalidErrorBuilder
232             .vendorSoftwareProductMissingServiceModelErrorBuilder(vspDetails.getId(),
233                 vspDetails.getVersion()));
234       }
235       validationResponse.setUploadDataErrors(validateOrchestrationTemplate(orchestrationTemplate));
236     }
237
238     QuestionnaireValidationResult questionnaireValidationResult = validateQuestionnaire
239         (vspDetails.getId(), vspDetails.getVersion(), vspDetails.getOnboardingMethod());
240
241     if (Objects.nonNull(questionnaireValidationResult)) {
242       if (validationResponse.getQuestionnaireValidationResult() == null || validationResponse
243           .getQuestionnaireValidationResult().getValidationData() == null) {
244         validationResponse.setQuestionnaireValidationResult(questionnaireValidationResult);
245       } else {
246         validationResponse.getQuestionnaireValidationResult().getValidationData().addAll
247             (questionnaireValidationResult.getValidationData());
248       }
249     }
250
251     Collection<ComponentDependencyModelEntity> componentDependencies =
252         componentDependencyModelDao.list(new ComponentDependencyModelEntity(vspDetails.getId(), vspDetails.getVersion(), null));
253
254     if (validateComponentDependencies(componentDependencies)) {
255       vspErrors
256           .add(ComponentDependencyModelErrorBuilder.getcyclicDependencyComponentErrorBuilder());
257     }
258     validationResponse
259         .setVspErrors(vspErrors);
260     validationResponse.setLicensingDataErrors(validateLicensingData(vspDetails));
261     return validationResponse;
262   }
263
264   private void validateOrchestrationTemplateCandidate(ValidationResponse validationResponse,
265                                                       List<ErrorCode> vspErrors, String vspId,
266                                                       Version version) {
267     orchestrationTemplateCandidateManager.getInfo(vspId, version)
268         .ifPresent(candidateInfo -> {
269           String fileName = candidateInfo.getFileName();
270           vspErrors.add(candidateInfo.getValidationData().isEmpty()
271               ? candidateDataNotProcessedOrAbortedErrorBuilder(fileName)
272               : invalidProcessedCandidate(fileName));
273           validationResponse.setVspErrors(vspErrors);
274         });
275   }
276
277   private void validateManualOnboardingMethod(VspDetails vspDetails,
278                                               ValidationResponse validationResponse,
279                                               List<ErrorCode> vspErrors) {
280     vspErrors.addAll(validateMandatoryLicenseFields(vspDetails));
281
282     Collection<DeploymentFlavorEntity> deploymentFlavors = deploymentFlavorDao
283         .list(new DeploymentFlavorEntity(vspDetails.getId(), vspDetails.getVersion(), null));
284     if (CollectionUtils.isEmpty(deploymentFlavors)) {
285       vspErrors.add(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) {
506       Optional<ErrorCode> errorCode = vendorLicenseFacade.validateVendorForUsage(vspDetails.getVendorId(),vspDetails.getVlmVersion());
507       if (errorCode.isPresent()) {
508         return Collections.singleton(errorCode.get());
509       }
510     }
511
512     if (vspDetails.getVendorId() == null || vspDetails.getVlmVersion() == null
513         || vspDetails.getLicenseAgreement() == null
514         || CollectionUtils.isEmpty(vspDetails.getFeatureGroups())) {
515       return Collections.emptyList();
516     }
517     return vendorLicenseFacade
518         .validateLicensingData(vspDetails.getVendorId(), vspDetails.getVlmVersion(),
519             vspDetails.getLicenseAgreement(), vspDetails.getFeatureGroups());
520   }
521
522   @Override
523   public VspDetails createVsp(VspDetails vspDetails) {
524     vspInfoDao.create(vspDetails);
525     vspInfoDao.updateQuestionnaireData(vspDetails.getId(), vspDetails.getVersion(),
526         new JsonSchemaDataGenerator(getVspQuestionnaireSchema(null)).generateData());
527     return vspDetails;
528   }
529
530   @Override
531   public void updateVsp(VspDetails vspDetails) {
532     VspDetails retrieved = vspInfoDao.get(vspDetails);
533     if (retrieved == null) {
534       throw new CoreException((new ErrorCode.ErrorCodeBuilder()
535           .withMessage(String.format("Vsp with id %s and version %s does not exist.",
536               vspDetails.getId(), vspDetails.getVersion().getId()))).build());
537     }
538     vspDetails.setOnboardingMethod(retrieved.getOnboardingMethod());
539
540     //If any existing feature group is removed from VSP which is also associated in DF then
541     //update DF to remove feature group associations.
542     updateDeploymentFlavor(vspDetails);
543
544     updateUniqueName(retrieved.getName(), vspDetails.getName());
545     vspInfoDao.update(vspDetails);
546   }
547
548   private void updateDeploymentFlavor(VspDetails vspDetails) {
549     final List<String> featureGroups = vspDetails.getFeatureGroups();
550     if (featureGroups != null) {
551       final Collection<DeploymentFlavorEntity> deploymentFlavorEntities = deploymentFlavorDao
552           .list(new DeploymentFlavorEntity(vspDetails.getId(), vspDetails
553               .getVersion(), null));
554       if (Objects.nonNull(deploymentFlavorEntities)) {
555         for (DeploymentFlavorEntity deploymentFlavorEntity : deploymentFlavorEntities) {
556           updateDeploymentFlavourEntity(featureGroups, deploymentFlavorEntity);
557         }
558       }
559     }
560   }
561
562   private void updateDeploymentFlavourEntity(List<String> featureGroups,
563                                              DeploymentFlavorEntity deploymentFlavorEntity) {
564     final String featureGroupId =
565         deploymentFlavorEntity.getDeploymentFlavorCompositionData().getFeatureGroupId();
566     if (!featureGroups.contains(featureGroupId)) {
567       DeploymentFlavor deploymentFlavorCompositionData =
568           deploymentFlavorEntity.getDeploymentFlavorCompositionData();
569       deploymentFlavorCompositionData.setFeatureGroupId(null);
570       deploymentFlavorEntity.setDeploymentFlavorCompositionData
571           (deploymentFlavorCompositionData);
572       deploymentFlavorDao.update(deploymentFlavorEntity);
573     }
574   }
575
576
577   @Override
578   public VspDetails getVsp(String vspId, Version version) {
579     return getValidatedVsp(vspId, version);
580   }
581
582   private VspDetails getValidatedVsp(String vspId, Version version) {
583     VspDetails vsp = vspInfoDao.get(new VspDetails(vspId, version));
584     if (vsp == null) {
585       throw new CoreException(new VendorSoftwareProductNotFoundErrorBuilder(vspId).build());
586     }
587     return vsp;
588   }
589
590   @Override
591   public void deleteVsp(String vspId, Version version) {
592     vspMergeDao.deleteHint(vspId, version);
593   }
594
595   @Override
596   public List<PackageInfo> listPackages(String category, String subCategory) {
597     return packageInfoDao.listByCategory(category, subCategory);
598   }
599
600   @Override
601   public File getTranslatedFile(String vspId, Version version) {
602     PackageInfo packageInfo = packageInfoDao.get(new PackageInfo(vspId, version));
603     if (packageInfo == null) {
604       throw new CoreException(new PackageNotFoundErrorBuilder(vspId, version).build());
605     }
606
607     ByteBuffer translatedFileBuffer = packageInfo.getTranslatedFile();
608     if (translatedFileBuffer == null) {
609       throw new CoreException(new PackageInvalidErrorBuilder(vspId, version).build());
610     }
611
612     File translatedFile = new File(VendorSoftwareProductConstants.VSP_PACKAGE_ZIP);
613
614     try (FileOutputStream fos = new FileOutputStream(translatedFile)) {
615       fos.write(translatedFileBuffer.array());
616     } catch (IOException exception) {
617       throw new CoreException(new TranslationFileCreationErrorBuilder(vspId, version).build(),
618           exception);
619     }
620     return translatedFile;
621   }
622
623   @Override
624   public byte[] getOrchestrationTemplateFile(String vspId, Version version) {
625     OrchestrationTemplateEntity uploadData = orchestrationTemplateDao.get(vspId, version);
626     ByteBuffer contentData = uploadData.getContentData();
627     if (contentData == null) {
628       return null;
629     }
630
631     ByteArrayOutputStream baos = new ByteArrayOutputStream();
632
633     try (final ZipOutputStream zos = new ZipOutputStream(baos);
634          ZipInputStream ignored = new ZipInputStream(
635              new ByteArrayInputStream(contentData.array()))) {
636       zos.write(contentData.array());
637     } catch (IOException exception) {
638       throw new CoreException(new FileCreationErrorBuilder(vspId).build(), exception);
639     }
640     return baos.toByteArray();
641   }
642
643   @Override
644   public OrchestrationTemplateEntity getOrchestrationTemplateInfo(String vspId, Version version) {
645     return orchestrationTemplateDao.getInfo(vspId, version);
646   }
647
648   @Override
649   public Optional<FilesDataStructure> getOrchestrationTemplateStructure(String vspId,
650                                                                         Version version) {
651     Optional<String> jsonFileDataStructure =
652         orchestrationTemplateDao.getOrchestrationTemplateStructure(vspId, version);
653
654     if (jsonFileDataStructure.isPresent() && JsonUtil.isValidJson(jsonFileDataStructure.get())) {
655       return Optional
656           .of(JsonUtil.json2Object(jsonFileDataStructure.get(), FilesDataStructure.class));
657     } else {
658       return Optional.empty();
659     }
660   }
661
662   @Override
663   public PackageInfo createPackage(String vspId, Version version) throws IOException {
664     ToscaServiceModel toscaServiceModel = enrichedServiceModelDao.getServiceModel(vspId, version);
665     VspDetails vspDetails = vspInfoDao.get(new VspDetails(vspId, version));
666     Version vlmVersion = vspDetails.getVlmVersion();
667     if (vlmVersion != null) {
668       populateVersionsForVlm(vspDetails.getVendorId(), vlmVersion);
669     }
670     PackageInfo packageInfo = createPackageInfo(vspDetails);
671
672     ToscaFileOutputServiceCsarImpl toscaServiceTemplateServiceCsar =
673         new ToscaFileOutputServiceCsarImpl();
674     FileContentHandler licenseArtifacts = licenseArtifactsService
675         .createLicenseArtifacts(vspDetails.getId(), vspDetails.getVendorId(), vlmVersion,
676             vspDetails.getFeatureGroups());
677     ETSIService etsiService = new ETSIServiceImpl();
678     if(etsiService.isSol004WithToscaMetaDirectory(toscaServiceModel.getArtifactFiles())){
679         FileContentHandler handler = toscaServiceModel.getArtifactFiles();
680         Manifest onboardingManifest = OnboardingManifest.parse(handler.getFileContent(MAIN_SERVICE_TEMPLATE_MF_FILE_NAME));
681       etsiService.moveNonManoFileToArtifactFolder(handler, onboardingManifest);
682
683     }
684     packageInfo.setTranslatedFile(ByteBuffer.wrap(
685         toscaServiceTemplateServiceCsar.createOutputFile(toscaServiceModel, licenseArtifacts)));
686
687     packageInfoDao.create(packageInfo);
688     return packageInfo;
689   }
690
691   void populateVersionsForVlm(String vlmId, Version vlmVersion) {
692     VersioningManager versioningManager = VersioningManagerFactory.getInstance().createInterface();
693     versioningManager.list(vlmId).stream()
694         .filter(version -> version.getId().equalsIgnoreCase(vlmVersion.getId()))
695         .findAny()
696         .ifPresent(version -> {
697           vlmVersion.setMinor(version.getMinor());
698           vlmVersion.setMajor(version.getMajor());
699         });
700   }
701
702   private PackageInfo createPackageInfo(VspDetails vspDetails) {
703     PackageInfo packageInfo = new PackageInfo(vspDetails.getId(), vspDetails.getVersion());
704     packageInfo.setVspName(vspDetails.getName());
705     packageInfo.setVspDescription(vspDetails.getDescription());
706     packageInfo.setCategory(vspDetails.getCategory());
707     packageInfo.setSubCategory(vspDetails.getSubCategory());
708     packageInfo.setVendorName(vspDetails.getVendorName());
709     packageInfo.setPackageType(VendorSoftwareProductConstants.CSAR);
710     packageInfo.setVendorRelease("1.0"); //todo TBD
711     return packageInfo;
712   }
713
714   @Override
715
716   public QuestionnaireResponse getVspQuestionnaire(String vspId, Version version) {
717     VspQuestionnaireEntity retrieved = vspInfoDao.getQuestionnaire(vspId, version);
718     VersioningUtil.validateEntityExistence(retrieved, new VspQuestionnaireEntity(vspId, version),
719         VspDetails.ENTITY_TYPE);
720
721     String questionnaireData = retrieved.getQuestionnaireData();
722
723     QuestionnaireResponse questionnaireResponse = new QuestionnaireResponse();
724     questionnaireResponse.setData(questionnaireData);
725     questionnaireResponse.setSchema(getVspQuestionnaireSchema(null));
726     return questionnaireResponse;
727   }
728
729   @Override
730   public void updateVspQuestionnaire(String vspId, Version version, String questionnaireData) {
731     vspInfoDao.updateQuestionnaireData(vspId, version, questionnaireData);
732   }
733
734
735   private Map<String, List<ErrorMessage>> validateOrchestrationTemplate(
736       OrchestrationTemplateEntity orchestrationTemplate) throws IOException {
737
738     if (isOrchestrationTemplateMissing(orchestrationTemplate)) {
739       return null;
740     }
741     Map<String, List<ErrorMessage>> validationErrors = new HashMap<>();
742
743     FileContentHandler fileContentMap = CommonUtil.validateAndUploadFileContent(
744         OnboardingTypesEnum.getOnboardingTypesEnum(orchestrationTemplate.getFileSuffix()),
745         orchestrationTemplate.getContentData().array());
746
747     if (CommonUtil.isFileOriginFromZip(orchestrationTemplate.getFileSuffix())) {
748       ValidationManager validationManager =
749           ValidationManagerUtil.initValidationManager(fileContentMap);
750       validationErrors.putAll(validationManager.validate());
751     }
752
753     return
754         MapUtils.isEmpty(MessageContainerUtil.getMessageByLevel(ErrorLevel.ERROR, validationErrors))
755             ? null : validationErrors;
756   }
757
758   private QuestionnaireValidationResult validateQuestionnaire(String vspId, Version version,
759                                                               String onboardingMethod) {
760     // The apis of CompositionEntityDataManager used here are stateful!
761     // so, it must be re-created from scratch when it is used!
762     CompositionEntityDataManager compositionEntityDataManager =
763         CompositionEntityDataManagerFactory.getInstance().createInterface();
764     compositionEntityDataManager
765         .addEntity(vspInfoDao.getQuestionnaire(vspId, version), null);
766
767     Collection<NicEntity> nics = nicDao.listByVsp(vspId, version);
768
769     Map<String, List<String>> nicNamesByComponent = new HashMap<>();
770     for (NicEntity nicEntity : nics) {
771       compositionEntityDataManager.addEntity(nicEntity, null);
772
773       Nic nic = nicEntity.getNicCompositionData();
774       if (nic != null && nic.getName() != null) {
775         List<String> nicNames =
776             nicNamesByComponent.computeIfAbsent(nicEntity.getComponentId(), k -> new ArrayList<>());
777         nicNames.add(nic.getName());
778       }
779     }
780
781     Collection<ComponentEntity> components =
782         componentDao.listCompositionAndQuestionnaire(vspId, version);
783     components.forEach(component -> compositionEntityDataManager.addEntity(component,
784         new ComponentQuestionnaireSchemaInput(nicNamesByComponent.get(component.getId()),
785             JsonUtil.json2Object(component.getQuestionnaireData(), Map.class), null,
786                                                      OnboardingMethod.Manual.name().equals(onboardingMethod))));
787
788     Collection<ComputeEntity> computes = computeDao.listByVsp(vspId, version);
789     computes.forEach(compute -> compositionEntityDataManager.addEntity(compute, null));
790
791     if (OnboardingMethod.Manual.name().equals(onboardingMethod)) {
792       Collection<ImageEntity> images = imageDao.listByVsp(vspId, version);
793       images.forEach(image -> compositionEntityDataManager.addEntity(image, null));
794     }
795
796     Map<CompositionEntityId, Collection<String>> errorsByEntityId =
797         compositionEntityDataManager.validateEntitiesQuestionnaire();
798     if (MapUtils.isNotEmpty(errorsByEntityId)) {
799       compositionEntityDataManager.buildTrees();
800       compositionEntityDataManager.addErrorsToTrees(errorsByEntityId);
801       return new QuestionnaireValidationResult(
802           compositionEntityDataManager.getAllErrorsByVsp(vspId));
803     }
804     return null;
805   }
806
807   @Override
808   public File getInformationArtifact(String vspId, Version version) {
809     VspDetails vspDetails = vspInfoDao.get(new VspDetails(vspId, version));
810
811     if (vspDetails == null) {
812       return null;
813     }
814
815     String vspName = vspDetails.getName();
816     ByteBuffer infoArtifactAsByteBuffer;
817     File infoArtifactFile;
818     try {
819       infoArtifactAsByteBuffer = ByteBuffer.wrap(informationArtifactGenerator.generate(vspId,
820           version).getBytes());
821
822       infoArtifactFile =
823           new File(
824               String.format(VendorSoftwareProductConstants.INFORMATION_ARTIFACT_NAME, vspName));
825       try (OutputStream out = new BufferedOutputStream(new FileOutputStream(infoArtifactFile))) {
826         out.write(infoArtifactAsByteBuffer.array());
827       }
828
829     } catch (IOException ex) {
830       throw new CoreException(new InformationArtifactCreationErrorBuilder(vspId).build(), ex);
831     }
832     return infoArtifactFile;
833   }
834
835   String getVspQuestionnaireSchema(SchemaTemplateInput schemaInput) {
836     return SchemaGenerator
837         .generate(SchemaTemplateContext.questionnaire, CompositionEntityType.vsp, schemaInput);
838   }
839
840   @Override
841   public Optional<Pair<String, byte[]>> get(String vspId, Version version) throws IOException {
842
843     OrchestrationTemplateEntity orchestrationTemplateEntity =
844         orchestrationTemplateDao.get(vspId, version);
845
846     if (isOrchestrationTemplateMissing(orchestrationTemplateEntity)) {
847       return Optional.empty();
848     }
849
850     if (CommonUtil.isFileOriginFromZip(orchestrationTemplateEntity.getFileSuffix())) {
851       return Optional.of(new ImmutablePair<>(OnboardingTypesEnum.ZIP.toString(), candidateService
852           .getZipData(orchestrationTemplateEntity.getContentData())));
853     }
854     return Optional.of(new ImmutablePair<>(orchestrationTemplateEntity.getFileSuffix(),
855         orchestrationTemplateEntity.getContentData().array()));
856   }
857
858   void updateUniqueName(String oldVspName, String newVspName) {
859     uniqueValueUtil.updateUniqueValue(
860         VendorSoftwareProductConstants.UniqueValues.VENDOR_SOFTWARE_PRODUCT_NAME,
861         oldVspName, newVspName);
862   }
863
864   @Override
865   public Collection<ComputeEntity> getComputeByVsp(String vspId, Version version) {
866     return computeDao.listByVsp(vspId, version);
867   }
868
869   private boolean isOrchestrationTemplateMissing(
870       OrchestrationTemplateEntity orchestrationTemplate) {
871     return orchestrationTemplate == null
872         || orchestrationTemplate.getContentData() == null
873         || orchestrationTemplate.getFileSuffix() == null
874         || orchestrationTemplate.getFileName() == null;
875   }
876
877   private boolean isServiceModelMissing(ToscaServiceModel serviceModel) {
878     return serviceModel == null || serviceModel.getEntryDefinitionServiceTemplate() == null;
879   }
880
881 }