aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services
diff options
context:
space:
mode:
Diffstat (limited to 'openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services')
-rw-r--r--openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/composition/CompositionDataExtractorImpl.java470
-rw-r--r--openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/composition/CompositionEntityDataManagerImpl.java585
-rw-r--r--openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java621
-rw-r--r--openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/ManifestCreatorNamingConventionImpl.java309
-rw-r--r--openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/utils/CandidateServiceValidator.java97
5 files changed, 2082 insertions, 0 deletions
diff --git a/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/composition/CompositionDataExtractorImpl.java b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/composition/CompositionDataExtractorImpl.java
new file mode 100644
index 0000000000..d72a0dbe23
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/composition/CompositionDataExtractorImpl.java
@@ -0,0 +1,470 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.vendorsoftwareproduct.services.impl.composition;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+import org.openecomp.sdc.common.errors.CoreException;
+import org.openecomp.sdc.datatypes.error.ErrorLevel;
+import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
+import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
+import org.openecomp.sdc.logging.types.LoggerConstants;
+import org.openecomp.sdc.logging.types.LoggerErrorCode;
+import org.openecomp.sdc.logging.types.LoggerErrorDescription;
+import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
+import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
+import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
+import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
+import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
+import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
+import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
+import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
+import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
+import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
+import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
+import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplateErrorBuilder;
+import org.openecomp.sdc.tosca.errors.ToscaMissingSubstitutionMappingForReqCapErrorBuilder;
+import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
+import org.openecomp.sdc.tosca.services.ToscaConstants;
+import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
+import org.openecomp.sdc.tosca.services.yamlutil.ToscaExtensionYamlUtil;
+import org.openecomp.sdc.vendorsoftwareproduct.services.composition.CompositionDataExtractor;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Component;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentData;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionData;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ExtractCompositionDataContext;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Network;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class CompositionDataExtractorImpl implements CompositionDataExtractor {
+
+ protected static Logger logger;
+ private static ToscaAnalyzerService toscaAnalyzerService;
+ private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
+
+ static {
+ logger = LoggerFactory.getLogger(CompositionDataExtractorImpl.class);
+ toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
+ }
+
+ /**
+ * Extract service composition data composition data.
+ *
+ * @param toscaServiceModel the tosca service model
+ * @return the composition data
+ */
+ public CompositionData extractServiceCompositionData(ToscaServiceModel toscaServiceModel) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ ExtractCompositionDataContext context = new ExtractCompositionDataContext();
+ String entryDefinitionServiceTemplateFileName =
+ toscaServiceModel.getEntryDefinitionServiceTemplate();
+ ServiceTemplate entryDefinitionServiceTemplate =
+ toscaServiceModel.getServiceTemplates().get(entryDefinitionServiceTemplateFileName);
+ extractServiceCompositionData(entryDefinitionServiceTemplateFileName,
+ entryDefinitionServiceTemplate, toscaServiceModel, context);
+
+ CompositionData compositionData = new CompositionData();
+ compositionData.setNetworks(context.getNetworks());
+ compositionData.setComponents(context.getComponents());
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return compositionData;
+ }
+
+ private void extractServiceCompositionData(String serviceTemplateFileName,
+ ServiceTemplate serviceTemplate,
+ ToscaServiceModel toscaServiceModel,
+ ExtractCompositionDataContext context) {
+ if (context.getHandledServiceTemplates().contains(serviceTemplateFileName)) {
+ return;
+ }
+ context.addNetworks(extractNetworks(serviceTemplate, toscaServiceModel));
+ extractComponents(serviceTemplate, toscaServiceModel, context);
+ handleSubstitution(serviceTemplate, toscaServiceModel, context);
+ context.addHandledServiceTemplates(serviceTemplateFileName);
+ }
+
+ private void handleSubstitution(ServiceTemplate serviceTemplate,
+ ToscaServiceModel toscaServiceModel,
+ ExtractCompositionDataContext context) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ Map<String, NodeTemplate> substitutableNodeTemplates =
+ toscaAnalyzerService.getSubstitutableNodeTemplates(serviceTemplate);
+
+ if (substitutableNodeTemplates != null) {
+ for (String substitutableNodeTemplateId : substitutableNodeTemplates.keySet()) {
+ handleSubstitutableNodeTemplate(serviceTemplate, toscaServiceModel,
+ substitutableNodeTemplateId,
+ substitutableNodeTemplates.get(substitutableNodeTemplateId), context);
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ private void handleSubstitutableNodeTemplate(ServiceTemplate serviceTemplate,
+ ToscaServiceModel toscaServiceModel,
+ String substitutableNodeTemplateId,
+ NodeTemplate substitutableNodeTemplate,
+ ExtractCompositionDataContext context) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
+ Optional<String> substituteServiceTemplateFileName = toscaAnalyzerService
+ .getSubstituteServiceTemplateName(substitutableNodeTemplateId, substitutableNodeTemplate);
+ if (!substituteServiceTemplateFileName.isPresent()) {
+ MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
+ LoggerTragetServiceName.EXTRACT_COMPOSITION_DATA, ErrorLevel.ERROR.name(),
+ LoggerErrorCode.DATA_ERROR.getErrorCode(),
+ LoggerErrorDescription.EXTRACT_COMPOSITION_DATA);
+ throw new CoreException(
+ new ToscaInvalidSubstituteNodeTemplateErrorBuilder(substitutableNodeTemplateId).build());
+ }
+ if (context.getHandledServiceTemplates().contains(substituteServiceTemplateFileName.get())) {
+ //each substitution is should be handled once, and will get the connection to the upper
+ // service level according to the first one which was processed
+ mdcDataDebugMessage.debugExitMessage(null);
+ return;
+ }
+
+ ServiceTemplate substituteServiceTemplate =
+ toscaServiceModel.getServiceTemplates().get(substituteServiceTemplateFileName.get());
+ extractServiceCompositionData(substituteServiceTemplateFileName.get(),
+ substituteServiceTemplate, toscaServiceModel, context);
+
+ List<Map<String, RequirementAssignment>> substitutableRequirements =
+ substitutableNodeTemplate.getRequirements();
+
+ if (CollectionUtils.isEmpty(substitutableRequirements)) {
+ mdcDataDebugMessage.debugExitMessage(null);
+ return;
+ }
+
+ for (Map<String, RequirementAssignment> substitutableReq : substitutableRequirements) {
+ substitutableReq.keySet().stream().filter(reqId -> {
+ RequirementAssignment reqAssignment = toscaExtensionYamlUtil
+ .yamlToObject(toscaExtensionYamlUtil.objectToYaml(substitutableReq.get(reqId)),
+ RequirementAssignment.class);
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return isLinkToNetworkRequirementAssignment(reqAssignment);
+ }).forEach(reqId -> {
+ RequirementAssignment linkToNetworkRequirement = toscaExtensionYamlUtil
+ .yamlToObject(toscaExtensionYamlUtil.objectToYaml(substitutableReq.get(reqId)),
+ RequirementAssignment.class);
+ String connectedNodeId = linkToNetworkRequirement.getNode();
+ Optional<NodeTemplate> connectedNodeTemplate =
+ toscaAnalyzerService.getNodeTemplateById(serviceTemplate, connectedNodeId);
+
+ if (connectedNodeTemplate.isPresent() && toscaAnalyzerService
+ .isTypeOf(connectedNodeTemplate.get(), ToscaNodeType.NATIVE_NETWORK,
+ serviceTemplate, toscaServiceModel)) {
+ Optional<Map.Entry<String, NodeTemplate>> mappedNodeTemplate = toscaAnalyzerService
+ .getSubstitutionMappedNodeTemplateByExposedReq(
+ substituteServiceTemplateFileName.get(), substituteServiceTemplate, reqId);
+ if (!mappedNodeTemplate.isPresent()) {
+ MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
+ LoggerTragetServiceName.EXTRACT_COMPOSITION_DATA, ErrorLevel.ERROR.name(),
+ LoggerErrorCode.DATA_ERROR.getErrorCode(),
+ LoggerErrorDescription.EXTRACT_COMPOSITION_DATA);
+ throw new CoreException(new ToscaMissingSubstitutionMappingForReqCapErrorBuilder(
+ ToscaMissingSubstitutionMappingForReqCapErrorBuilder.MappingExposedEntry
+ .REQUIREMENT, connectedNodeId).build());
+ }
+
+ if (toscaAnalyzerService.isTypeOf(mappedNodeTemplate.get().getValue(),
+ ToscaNodeType.NATIVE_NETWORK_PORT, serviceTemplate,
+ toscaServiceModel)) {
+ Nic port = context.getNics().get(mappedNodeTemplate.get().getKey());
+ if (port != null) {
+ port.setNetworkName(connectedNodeId);
+ } else {
+ logger.warn(
+ "Different ports define for the same component which is used in different "
+ + "substitution service templates.");
+ }
+ }
+ } else if (!connectedNodeTemplate.isPresent()) {
+ MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
+ LoggerTragetServiceName.EXTRACT_COMPOSITION_DATA, ErrorLevel.ERROR.name(),
+ LoggerErrorCode.DATA_ERROR.getErrorCode(),
+ LoggerErrorDescription.EXTRACT_COMPOSITION_DATA);
+ throw new CoreException(
+ new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", connectedNodeId).build());
+ }
+ });
+ }
+ }
+
+ private boolean isLinkToNetworkRequirementAssignment(RequirementAssignment requirement) {
+ return toscaAnalyzerService.isDesiredRequirementAssignment(requirement,
+ ToscaCapabilityType.NATIVE_NETWORK_LINKABLE, null,
+ ToscaRelationshipType.NATIVE_NETWORK_LINK_TO);
+ }
+
+
+ private void connectPortToNetwork(Nic port, NodeTemplate portNodeTemplate) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ List<RequirementAssignment> linkRequirementsToNetwork =
+ toscaAnalyzerService.getRequirements(portNodeTemplate, ToscaConstants.LINK_REQUIREMENT_ID);
+
+ //port is connected to one network
+ for (RequirementAssignment linkRequirementToNetwork : linkRequirementsToNetwork) {
+ port.setNetworkName(linkRequirementToNetwork.getNode());
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ /*
+ return Map with key - compute node template id, value - list of connected port node template id
+ */
+ private Map<String, List<String>> getComputeToPortsConnection(
+ Map<String, NodeTemplate> portNodeTemplates) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ Map<String, List<String>> computeToPortConnection = new HashMap<>();
+ if (MapUtils.isEmpty(portNodeTemplates)) {
+ return computeToPortConnection;
+ }
+ for (String portId : portNodeTemplates.keySet()) {
+ List<RequirementAssignment> bindingRequirementsToCompute = toscaAnalyzerService
+ .getRequirements(portNodeTemplates.get(portId), ToscaConstants.BINDING_REQUIREMENT_ID);
+ for (RequirementAssignment bindingRequirementToCompute : bindingRequirementsToCompute) {
+ computeToPortConnection
+ .putIfAbsent(bindingRequirementToCompute.getNode(), new ArrayList<>());
+ computeToPortConnection.get(bindingRequirementToCompute.getNode()).add(portId);
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return computeToPortConnection;
+ }
+
+ private void extractComponents(ServiceTemplate serviceTemplate,
+ ToscaServiceModel toscaServiceModel,
+ ExtractCompositionDataContext context) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ Map<String, NodeTemplate> computeNodeTemplates = toscaAnalyzerService
+ .getNodeTemplatesByType(serviceTemplate, ToscaNodeType.NATIVE_COMPUTE,
+ toscaServiceModel);
+ if (MapUtils.isEmpty(computeNodeTemplates)) {
+ return;
+ }
+ Map<String, NodeTemplate> portNodeTemplates = toscaAnalyzerService
+ .getNodeTemplatesByType(serviceTemplate, ToscaNodeType.NATIVE_NETWORK_PORT,
+ toscaServiceModel);
+ Map<String, List<String>> computeToPortsConnection =
+ getComputeToPortsConnection(portNodeTemplates);
+ Map<String, List<String>> computesGroupedByType =
+ getNodeTemplatesGroupedByType(computeNodeTemplates);
+
+ computesGroupedByType.keySet()
+ .stream()
+ .filter(nodeType ->
+ !context.getCreatedComponents().contains(nodeType))
+ .forEach(nodeType -> extractComponent(serviceTemplate, computeToPortsConnection,
+ computesGroupedByType, nodeType, context));
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ private void extractComponent(ServiceTemplate serviceTemplate,
+ Map<String, List<String>> computeToPortsConnection,
+ Map<String, List<String>> computesGroupedByType,
+ String computeNodeType,
+ ExtractCompositionDataContext context) {
+ ComponentData component = new ComponentData();
+ component.setName(computeNodeType);
+ component.setDisplayName(getComponentDisplayName(component.getName()));
+ component.setVfcCode(component.getDisplayName());
+ Component componentModel = new Component();
+ componentModel.setData(component);
+
+ String computeId = computesGroupedByType.get(computeNodeType).get(0);
+ List<String> connectedPortIds = computeToPortsConnection.get(computeId);
+
+ if (connectedPortIds != null) {
+ componentModel.setNics(new ArrayList<>());
+ for (String portId : connectedPortIds) {
+ Nic port = extractPort(serviceTemplate, portId);
+ componentModel.getNics().add(port);
+ context.addNic(portId, port);
+ }
+ }
+ context.addComponent(componentModel);
+ context.getCreatedComponents().add(computeNodeType);
+ }
+
+ private Nic extractPort(ServiceTemplate serviceTemplate, String portNodeTemplateId) {
+ Optional<NodeTemplate> portNodeTemplate =
+ toscaAnalyzerService.getNodeTemplateById(serviceTemplate, portNodeTemplateId);
+ if (portNodeTemplate.isPresent()) {
+ Nic port = new Nic();
+ port.setName(portNodeTemplateId);
+ connectPortToNetwork(port, portNodeTemplate.get());
+ return port;
+ } else {
+ MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
+ LoggerTragetServiceName.EXTRACT_COMPOSITION_DATA, ErrorLevel.ERROR.name(),
+ LoggerErrorCode.DATA_ERROR.getErrorCode(),
+ LoggerErrorDescription.EXTRACT_COMPOSITION_DATA);
+ throw new CoreException(
+ new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", portNodeTemplateId).build());
+ }
+ }
+
+
+ private Map<String, List<String>> getNodeTemplatesGroupedByType(
+ Map<String, NodeTemplate> nodeTemplates) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ Map<String, List<String>> nodeTemplatesGrouped =
+ new HashMap<>(); //key - node type, value - list of node ids with this type
+ for (String nodeId : nodeTemplates.keySet()) {
+ String nodeType = nodeTemplates.get(nodeId).getType();
+ nodeTemplatesGrouped.putIfAbsent(nodeType, new ArrayList<>());
+ nodeTemplatesGrouped.get(nodeType).add(nodeId);
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return nodeTemplatesGrouped;
+ }
+
+ private List<Network> extractNetworks(ServiceTemplate serviceTemplate,
+ ToscaServiceModel toscaServiceModel) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ List<Network> networks = new ArrayList<>();
+ Map<String, NodeTemplate> networkNodeTemplates = toscaAnalyzerService
+ .getNodeTemplatesByType(serviceTemplate, ToscaNodeType.NATIVE_NETWORK,
+ toscaServiceModel);
+ if (MapUtils.isEmpty(networkNodeTemplates)) {
+ mdcDataDebugMessage.debugExitMessage(null);
+ return networks;
+ }
+ for (String networkId : networkNodeTemplates.keySet()) {
+ Network network = new Network();
+ network.setName(networkId);
+ Optional<Boolean> networkDhcpValue =
+ getNetworkDhcpValue(serviceTemplate, networkNodeTemplates.get(networkId));
+ network.setDhcp(networkDhcpValue.isPresent() ? networkDhcpValue.get() : true);
+ networks.add(network);
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return networks;
+ }
+
+ //dhcp default value is true
+ private Optional<Boolean> getNetworkDhcpValue(ServiceTemplate serviceTemplate,
+ NodeTemplate networkNodeTemplate) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ if (networkNodeTemplate == null) {
+ return Optional.empty();
+ }
+ if (networkNodeTemplate.getProperties() == null
+ || networkNodeTemplate.getProperties().get(ToscaConstants.DHCP_ENABLED_PROPERTY_NAME)
+ == null) {
+ mdcDataDebugMessage.debugExitMessage(null);
+ return Optional.of(true);
+ }
+
+ Object dhcp =
+ networkNodeTemplate.getProperties().get(ToscaConstants.DHCP_ENABLED_PROPERTY_NAME);
+ if (dhcp instanceof String) {
+ mdcDataDebugMessage.debugExitMessage(null);
+ return Optional.of(Boolean.valueOf((String) dhcp));
+ } else if (dhcp instanceof Boolean) {
+ mdcDataDebugMessage.debugExitMessage(null);
+ return Optional.of((Boolean) dhcp);
+ } else if (dhcp instanceof Map) {
+ String inputParameterName =
+ (String) ((Map) dhcp).get(ToscaFunctions.GET_INPUT.getDisplayName());
+ if (inputParameterName != null) {
+ ParameterDefinition inputParameterDefinition =
+ serviceTemplate.getTopology_template().getInputs().get(inputParameterName);
+ if (inputParameterDefinition != null) {
+ if (inputParameterDefinition.get_default() != null) {
+ mdcDataDebugMessage.debugExitMessage(null);
+ return Optional.of(Boolean.valueOf(inputParameterDefinition.get_default().toString()));
+ }
+ } else {
+ MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
+ LoggerTragetServiceName.EXTRACT_COMPOSITION_DATA, ErrorLevel.ERROR.name(),
+ LoggerErrorCode.DATA_ERROR.getErrorCode(),
+ LoggerErrorDescription.EXTRACT_COMPOSITION_DATA);
+ throw new CoreException(
+ new ToscaInvalidEntryNotFoundErrorBuilder("Input Parameter", inputParameterName)
+ .build());
+ }
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return Optional.of(true);
+ }
+
+ @Override
+ public String getComponentDisplayName(String componentName) {
+ if (componentName == null) {
+ return null;
+ }
+ String delimiterChar = ".";
+ if (componentName.contains(delimiterChar)) {
+ return componentName.substring(componentName.lastIndexOf(delimiterChar) + 1);
+ }
+ return componentName;
+
+ }
+
+}
diff --git a/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/composition/CompositionEntityDataManagerImpl.java b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/composition/CompositionEntityDataManagerImpl.java
new file mode 100644
index 0000000000..81cacf75ac
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/composition/CompositionEntityDataManagerImpl.java
@@ -0,0 +1,585 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.vendorsoftwareproduct.services.impl.composition;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.openecomp.core.utilities.json.JsonSchemaDataGenerator;
+import org.openecomp.core.utilities.json.JsonUtil;
+import org.openecomp.sdc.common.errors.CoreException;
+import org.openecomp.sdc.common.errors.ErrorCategory;
+import org.openecomp.sdc.common.errors.ErrorCode;
+import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDao;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.NetworkDao;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.NicDao;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.CompositionEntity;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NetworkEntity;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NicEntity;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspQuestionnaireEntity;
+import org.openecomp.sdc.vendorsoftwareproduct.services.composition.CompositionEntityDataManager;
+import org.openecomp.sdc.vendorsoftwareproduct.services.schemagenerator.SchemaGenerator;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Component;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentData;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionData;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityId;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityType;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityValidationData;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Network;
+import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
+import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateContext;
+import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateInput;
+import org.openecomp.sdc.versioning.dao.types.Version;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+public class CompositionEntityDataManagerImpl implements CompositionEntityDataManager {
+
+ private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR =
+ "COMPOSITION_ENTITY_DATA_MANAGER_ERR";
+ private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG =
+ "Invalid input: %s may not be null";
+
+ private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
+
+ private Map<CompositionEntityId, CompositionEntityData> entities = new HashMap<>();
+ private Map<CompositionEntityType, String> nonDynamicSchemas = new HashMap<>();
+ private List<CompositionEntityValidationData> roots = new ArrayList<>();
+
+ private VendorSoftwareProductInfoDao vspInfoDao;
+ private ComponentDao componentDao;
+ private NicDao nicDao;
+ private NetworkDao networkDao;
+
+ public CompositionEntityDataManagerImpl(VendorSoftwareProductInfoDao vspInfoDao,
+ ComponentDao componentDao,
+ NicDao nicDao, NetworkDao networkDao) {
+ this.vspInfoDao = vspInfoDao;
+ this.componentDao = componentDao;
+ this.nicDao = nicDao;
+ this.networkDao = networkDao;
+ }
+
+ /**
+ * Validate entity composition entity validation data.
+ *
+ * @param entity the entity
+ * @param schemaTemplateContext the schema template context
+ * @param schemaTemplateInput the schema template input
+ * @return the composition entity validation data
+ */
+ @Override
+ public CompositionEntityValidationData validateEntity(CompositionEntity entity,
+ SchemaTemplateContext schemaTemplateContext,
+ SchemaTemplateInput schemaTemplateInput) {
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ if (entity == null) {
+ throw new CoreException(
+ new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
+ .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
+ String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
+ .build());
+ }
+ if (schemaTemplateContext == null) {
+ throw new CoreException(
+ new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
+ .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
+ String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "schema template context"))
+ .build());
+ }
+
+ CompositionEntityValidationData validationData =
+ new CompositionEntityValidationData(entity.getType(), entity.getId());
+ String json =
+ schemaTemplateContext == SchemaTemplateContext.composition ? entity.getCompositionData()
+ : entity.getQuestionnaireData();
+ validationData.setErrors(JsonUtil.validate(
+ json == null ? JsonUtil.object2Json(new Object()) : json,
+ generateSchema(schemaTemplateContext, entity.getType(), schemaTemplateInput)));
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return validationData;
+ }
+
+ /**
+ * Add entity.
+ *
+ * @param entity the entity
+ * @param schemaTemplateInput the schema template input
+ */
+ @Override
+ public void addEntity(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
+ if (entity == null) {
+ throw new CoreException(
+ new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
+ .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
+ String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
+ .build());
+ }
+ entities.put(entity.getCompositionEntityId(),
+ new CompositionEntityData(entity, schemaTemplateInput));
+ }
+
+ /**
+ * Validate entities questionnaire map.
+ *
+ * @return the map
+ */
+ @Override
+ public Map<CompositionEntityId, Collection<String>> validateEntitiesQuestionnaire() {
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ Map<CompositionEntityId, Collection<String>> errorsByEntityId = new HashMap<>();
+ entities.entrySet().forEach(entry -> {
+ Collection<String> errors = validateQuestionnaire(entry.getValue());
+ if (errors != null) {
+ errorsByEntityId.put(entry.getKey(), errors);
+ }
+ });
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return errorsByEntityId;
+ }
+
+ /**
+ * Build trees.
+ */
+ @Override
+ public void buildTrees() {
+ Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData =
+ new HashMap<>();
+ entities.entrySet().forEach(
+ entry -> addValidationDataEntity(entitiesValidationData, entry.getKey(),
+ entry.getValue().entity));
+ }
+
+ public Collection<CompositionEntityValidationData> getTrees() {
+ return roots;
+ }
+
+ @Override
+ public void saveCompositionData(String vspId, Version version, CompositionData compositionData) {
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ if (Objects.isNull(compositionData)) {
+ return;
+ }
+
+ Map<String, String> networkIdByName = saveNetworks(vspId, version, compositionData);
+ saveComponents(vspId, version, compositionData, networkIdByName);
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ @Override
+ public Set<CompositionEntityValidationData> getAllErrorsByVsp(String vspId) {
+ CompositionEntityValidationData matchVsp = null;
+ Set<CompositionEntityValidationData> entitiesWithErrors = new HashSet<>();
+ for (CompositionEntityValidationData root : roots) {
+ if (root.getEntityId().equals(vspId)) {
+ matchVsp = root;
+ break;
+ }
+ }
+
+ getEntityListWithErrors(matchVsp, entitiesWithErrors);
+ if (CollectionUtils.isNotEmpty(entitiesWithErrors)) {
+ updateValidationCompositionEntityName(entitiesWithErrors);
+ return entitiesWithErrors;
+ }
+
+ return null;
+ }
+
+ private boolean isThereErrorsInSubTree(CompositionEntityValidationData entity) {
+ if (Objects.isNull(entity)) {
+ return false;
+ }
+
+ if (CollectionUtils.isNotEmpty(entity.getErrors())) {
+ return true;
+ }
+
+ Collection<CompositionEntityValidationData> subEntitiesValidationData =
+ entity.getSubEntitiesValidationData();
+ return !CollectionUtils.isEmpty(subEntitiesValidationData) &&
+ checkForErrorsInChildren(subEntitiesValidationData);
+
+ }
+
+ private boolean checkForErrorsInChildren(
+ Collection<CompositionEntityValidationData> subEntitiesValidationData) {
+ boolean result = false;
+ for (CompositionEntityValidationData subEntity : subEntitiesValidationData) {
+ if (CollectionUtils.isNotEmpty(subEntity.getErrors())) {
+ return true;
+ }
+
+ result = result || isThereErrorsInSubTree(subEntity);
+ if (result) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void saveComponents(String vspId, Version version, CompositionData compositionData,
+ Map<String, String> networkIdByName) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ if (CollectionUtils.isNotEmpty(compositionData.getComponents())) {
+ for (Component component : compositionData.getComponents()) {
+ ComponentEntity componentEntity = new ComponentEntity(vspId, version, null);
+ componentEntity.setComponentCompositionData(component.getData());
+
+ String componentId = createComponent(componentEntity).getId();
+
+ saveNicsByComponent(vspId, version, networkIdByName, component, componentId);
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ public void saveNicsByComponent(String vspId, Version version,
+ Map<String, String> networkIdByName, Component component,
+ String componentId) {
+ if (CollectionUtils.isNotEmpty(component.getNics())) {
+ for (Nic nic : component.getNics()) {
+ if (nic.getNetworkName() != null && MapUtils.isNotEmpty(networkIdByName)) {
+ nic.setNetworkId(networkIdByName.get(nic.getNetworkName()));
+ }
+ nic.setNetworkName(null);
+
+ NicEntity nicEntity = new NicEntity(vspId, version, componentId, null);
+ nicEntity.setNicCompositionData(nic);
+ createNic(nicEntity);
+ }
+ }
+ }
+
+ public Map<String, String> saveNetworks(String vspId, Version version,
+ CompositionData compositionData) {
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ Map<String, String> networkIdByName = new HashMap<>();
+ if (CollectionUtils.isNotEmpty(compositionData.getNetworks())) {
+ for (Network network : compositionData.getNetworks()) {
+
+ NetworkEntity networkEntity = new NetworkEntity(vspId, version, null);
+ networkEntity.setNetworkCompositionData(network);
+
+ if (network.getName() != null) {
+ networkIdByName.put(network.getName(), createNetwork(networkEntity).getId());
+ }
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return networkIdByName;
+ }
+
+ @Override
+ public NetworkEntity createNetwork(NetworkEntity network) {
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ //network.setId(CommonMethods.nextUuId()); will be set by the dao
+ networkDao.create(network);
+ mdcDataDebugMessage.debugExitMessage(null);
+ return network;
+ }
+
+ @Override
+ public ComponentEntity createComponent(ComponentEntity component) {
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ //component.setId(CommonMethods.nextUuId()); will be set by the dao
+ component.setQuestionnaireData(
+ new JsonSchemaDataGenerator(
+ generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.component,
+ null))
+ .generateData());
+
+ componentDao.create(component);
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return component;
+ }
+
+ @Override
+ public NicEntity createNic(NicEntity nic) {
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ //nic.setId(CommonMethods.nextUuId()); will be set by the dao
+ nic.setQuestionnaireData(
+ new JsonSchemaDataGenerator(
+ generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.nic, null))
+ .generateData());
+
+ nicDao.create(nic);
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return nic;
+ }
+
+
+ public void addErrorsToTrees(Map<CompositionEntityId, Collection<String>> errors) {
+ roots.forEach(root -> addErrorsToTree(root, null, errors));
+ }
+
+ /* *
+ * get a flat list of all questionnaire entities that have validation errors
+ * */
+ public Set<CompositionEntityValidationData> getEntityListWithErrors() {
+ mdcDataDebugMessage.debugEntryMessage(null);
+ Set<CompositionEntityValidationData> treeAsList = new HashSet<>();
+
+ for (CompositionEntityValidationData entity : roots) {
+ if (CollectionUtils.isNotEmpty(entity.getErrors())) {
+ addNodeWithErrors(entity, treeAsList);
+ }
+ getEntityListWithErrors(entity, treeAsList);
+ }
+
+ updateValidationCompositionEntityName(treeAsList);
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return treeAsList;
+ }
+
+ public void getEntityListWithErrors(CompositionEntityValidationData entity,
+ Set<CompositionEntityValidationData> compositionSet) {
+ Collection<CompositionEntityValidationData> childNodes =
+ entity.getSubEntitiesValidationData();
+
+ if (CollectionUtils.isEmpty(childNodes)) {
+ return;
+ }
+
+ for (CompositionEntityValidationData child : childNodes) {
+ if (CollectionUtils.isNotEmpty(child.getErrors())) {
+ addNodeWithErrors(child, compositionSet);
+ }
+ getEntityListWithErrors(child, compositionSet);
+ }
+ }
+
+
+ public void addNodeWithErrors(CompositionEntityValidationData node,
+ Set<CompositionEntityValidationData> entitiesWithErrors) {
+ CompositionEntityValidationData compositionNodeToAdd = new CompositionEntityValidationData(node
+ .getEntityType(), node.getEntityId());
+ compositionNodeToAdd.setErrors(node.getErrors());
+ compositionNodeToAdd.setSubEntitiesValidationData(null);
+
+ entitiesWithErrors.add(compositionNodeToAdd);
+ }
+
+ public void removeNodesWithoutErrors() {
+ roots.forEach(root -> removeNodesWithoutErrors(root, null));
+ }
+
+
+ private CompositionEntityData getCompositionEntityDataById(CompositionEntityValidationData
+ entity) {
+ for (Map.Entry<CompositionEntityId, CompositionEntityData> entityEntry : entities
+ .entrySet()) {
+ if (entityEntry.getKey().getId().equals(entity.getEntityId())) {
+ return entityEntry.getValue();
+ }
+ }
+ return null;
+ }
+
+
+ private void updateValidationCompositionEntityName(Set<CompositionEntityValidationData>
+ compositionSet) {
+ for (CompositionEntityValidationData entity : compositionSet) {
+ String compositionData = getCompositionDataAsString(entity);
+ if (entity.getEntityType().equals(CompositionEntityType.vsp) ||
+ Objects.nonNull(compositionData)) {
+ entity.setEntityName(getEntityNameByEntityType(compositionData, entity));
+ }
+ }
+ }
+
+ private String getCompositionDataAsString(CompositionEntityValidationData entity) {
+ CompositionEntityData compositionEntityData = getCompositionEntityDataById(entity);
+ return compositionEntityData == null ? null : compositionEntityData.entity.getCompositionData();
+ }
+
+
+ private String getEntityNameByEntityType(String compositionData,
+ CompositionEntityValidationData entity) {
+ switch (entity.getEntityType()) {
+ case component:
+ ComponentData component = JsonUtil.json2Object(compositionData, ComponentData.class);
+ return component.getDisplayName();
+
+ case nic:
+ Nic nic = JsonUtil.json2Object(compositionData, Nic.class);
+ return nic.getName();
+
+ case network:
+ Network network = JsonUtil.json2Object(compositionData, Network.class);
+ return network.getName();
+
+ case vsp:
+ CompositionEntityData vspEntity = getCompositionEntityDataById(entity);
+ VspQuestionnaireEntity vspQuestionnaireEntity = (VspQuestionnaireEntity) vspEntity.entity;
+ VspDetails vspDetails =
+ vspInfoDao.get(new VspDetails(vspQuestionnaireEntity.getId(),
+ vspQuestionnaireEntity.getVersion()));
+ return vspDetails.getName();
+ }
+
+ return null;
+ }
+
+ private void removeNodesWithoutErrors(CompositionEntityValidationData node,
+ CompositionEntityValidationData parent) {
+
+ if (Objects.isNull(node)) {
+ return;
+ }
+
+ if (hasChildren(node)) {
+ Collection<CompositionEntityValidationData> subNodes =
+ new ArrayList<>(node.getSubEntitiesValidationData());
+ subNodes.forEach(subNode -> removeNodesWithoutErrors(subNode, node));
+ node.setSubEntitiesValidationData(subNodes);
+
+ if (canNodeGetRemovedFromValidationDataTree(node)) {
+ removeNodeFromChildren(parent, node);
+ }
+ } else if (canNodeGetRemovedFromValidationDataTree(node)) {
+ removeNodeFromChildren(parent, node);
+ }
+ }
+
+ private void removeNodeFromChildren(CompositionEntityValidationData parent,
+ CompositionEntityValidationData childToRemove) {
+ if (!Objects.isNull(parent)) {
+ parent.getSubEntitiesValidationData().remove(childToRemove);
+ }
+ }
+
+ private boolean hasChildren(CompositionEntityValidationData node) {
+ return !CollectionUtils.isEmpty(node.getSubEntitiesValidationData());
+ }
+
+ private boolean canNodeGetRemovedFromValidationDataTree(CompositionEntityValidationData node) {
+ return !hasChildren(node) && CollectionUtils.isEmpty(node.getErrors());
+ }
+
+
+ private void addValidationDataEntity(
+ Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData,
+ CompositionEntityId entityId, CompositionEntity entity) {
+ if (entitiesValidationData.containsKey(entityId)) {
+ return;
+ }
+
+ CompositionEntityValidationData validationData =
+ new CompositionEntityValidationData(entity.getType(), entity.getId());
+ entitiesValidationData.put(entityId, validationData);
+
+ CompositionEntityId parentEntityId = entityId.getParentId();
+ if (parentEntityId == null) {
+ roots.add(validationData);
+ } else {
+ CompositionEntityData parentEntity = entities.get(parentEntityId);
+ if (parentEntity == null) {
+ roots.add(validationData);
+ } else {
+ addValidationDataEntity(entitiesValidationData, parentEntityId, parentEntity.entity);
+ entitiesValidationData.get(parentEntityId).addSubEntityValidationData(validationData);
+ }
+ }
+ }
+
+ private void addErrorsToTree(CompositionEntityValidationData node,
+ CompositionEntityId parentNodeId,
+ Map<CompositionEntityId, Collection<String>> errors) {
+ if (node == null) {
+ return;
+ }
+ CompositionEntityId nodeId = new CompositionEntityId(node.getEntityId(), parentNodeId);
+ node.setErrors(errors.get(nodeId));
+
+ if (node.getSubEntitiesValidationData() != null) {
+ node.getSubEntitiesValidationData()
+ .forEach(subNode -> addErrorsToTree(subNode, nodeId, errors));
+ }
+ }
+
+ private Collection<String> validateQuestionnaire(CompositionEntityData compositionEntityData) {
+ return JsonUtil.validate(
+ compositionEntityData.entity.getQuestionnaireData() == null
+ ? JsonUtil.object2Json(new Object())
+ : compositionEntityData.entity.getQuestionnaireData(),
+ getSchema(compositionEntityData.entity.getType(), SchemaTemplateContext.questionnaire,
+ compositionEntityData.schemaTemplateInput));
+ }
+
+ private String getSchema(CompositionEntityType compositionEntityType,
+ SchemaTemplateContext schemaTemplateContext,
+ SchemaTemplateInput schemaTemplateInput) {
+ return schemaTemplateInput == null
+ ? nonDynamicSchemas.computeIfAbsent(compositionEntityType,
+ k -> generateSchema(schemaTemplateContext, compositionEntityType, null))
+ : generateSchema(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
+ }
+
+ private static class CompositionEntityData {
+ private CompositionEntity entity;
+ private SchemaTemplateInput schemaTemplateInput;
+
+ CompositionEntityData(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
+ this.entity = entity;
+ this.schemaTemplateInput = schemaTemplateInput;
+ }
+
+ }
+
+ // todo - make SchemaGenerator non static and mock it in UT instead of mocking this method (and
+ // make the method private
+
+ protected String generateSchema(SchemaTemplateContext schemaTemplateContext,
+ CompositionEntityType compositionEntityType,
+ SchemaTemplateInput schemaTemplateInput) {
+ return SchemaGenerator
+ .generate(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java
new file mode 100644
index 0000000000..2822d958d0
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java
@@ -0,0 +1,621 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.vendorsoftwareproduct.services.impl.filedatastructuremodule;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.openecomp.core.utilities.file.FileContentHandler;
+import org.openecomp.core.utilities.json.JsonUtil;
+import org.openecomp.sdc.common.errors.CoreException;
+import org.openecomp.sdc.common.errors.ErrorCategory;
+import org.openecomp.sdc.common.errors.ErrorCode;
+import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.common.utils.SdcCommon;
+import org.openecomp.sdc.datatypes.error.ErrorLevel;
+import org.openecomp.sdc.datatypes.error.ErrorMessage;
+import org.openecomp.sdc.heat.datatypes.manifest.FileData;
+import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
+import org.openecomp.sdc.heat.datatypes.structure.Artifact;
+import org.openecomp.sdc.heat.datatypes.structure.HeatStructureTree;
+import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateCandidateDao;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateCandidateDaoFactory;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
+import org.openecomp.sdc.vendorsoftwareproduct.errors.utils.ErrorsUtil;
+import org.openecomp.sdc.vendorsoftwareproduct.services.HeatFileAnalyzer;
+import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
+import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.ManifestCreator;
+import org.openecomp.sdc.vendorsoftwareproduct.services.utils.CandidateServiceValidator;
+import org.openecomp.sdc.vendorsoftwareproduct.types.CandidateDataEntityTo;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.AnalyzedZipHeatFiles;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Module;
+import org.openecomp.sdc.versioning.dao.types.Version;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+public class CandidateServiceImpl implements CandidateService {
+ protected static final Logger logger = LoggerFactory.getLogger(CandidateServiceImpl.class);
+ private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
+
+ private CandidateServiceValidator candidateServiceValidator = new CandidateServiceValidator();
+ private ManifestCreator manifestCreator;
+ private OrchestrationTemplateCandidateDao orchestrationTemplateCandidateDataDao;
+
+ public CandidateServiceImpl(ManifestCreator manifestCreator,
+ OrchestrationTemplateCandidateDao orchestrationTemplateCandidateDataDao) {
+ this.manifestCreator = manifestCreator;
+ this.orchestrationTemplateCandidateDataDao = orchestrationTemplateCandidateDataDao;
+
+ }
+
+ public CandidateServiceImpl() {
+ }
+
+ @Override
+ public Optional<ErrorMessage> validateNonEmptyFileToUpload(InputStream heatFileToUpload) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ if (Objects.isNull(heatFileToUpload)) {
+ return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
+ Messages.NO_ZIP_FILE_WAS_UPLOADED_OR_ZIP_NOT_EXIST.getErrorMessage()));
+ } else {
+ try {
+ int available = heatFileToUpload.available();
+ if (available == 0) {
+ mdcDataDebugMessage.debugExitMessage(null);
+ return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
+ Messages.NO_ZIP_FILE_WAS_UPLOADED_OR_ZIP_NOT_EXIST.getErrorMessage()));
+ }
+ } catch (IOException e) {
+ mdcDataDebugMessage.debugExitMessage(null);
+ return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
+ Messages.NO_ZIP_FILE_WAS_UPLOADED_OR_ZIP_NOT_EXIST.getErrorMessage()));
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional<ErrorMessage> validateRawZipData(byte[] uploadedFileData) {
+ if (Objects.isNull(uploadedFileData)) {
+ return Optional.of(new ErrorMessage(ErrorLevel.ERROR,
+ Messages.NO_ZIP_FILE_WAS_UPLOADED_OR_ZIP_NOT_EXIST.getErrorMessage()));
+ }
+ return Optional.empty();
+ }
+
+ private String heatStructureTreeToFileDataStructure(HeatStructureTree tree,
+ FileContentHandler zipContentMap,
+ Map<String, List<ErrorMessage>> uploadErrors,
+ AnalyzedZipHeatFiles analyzedZipHeatFiles)
+ throws Exception {
+ FilesDataStructure structure = new FilesDataStructure();
+ Set<String> usedEnvFiles = new HashSet<>();
+ addHeatsToFileDataStructure(tree, usedEnvFiles, structure, uploadErrors,
+ analyzedZipHeatFiles);
+ handleOtherResources(tree, usedEnvFiles, structure);
+ FilesDataStructure fileDataStructureFromManifest =
+ createFileDataStructureFromManifest(zipContentMap.getFileContent
+ (SdcCommon.MANIFEST_NAME));
+ structure.getArtifacts().addAll(fileDataStructureFromManifest.getArtifacts());
+ handleArtifactsFromTree(tree, structure);
+
+ return JsonUtil.object2Json(structure);
+ }
+
+ @Override
+ public OrchestrationTemplateCandidateData createCandidateDataEntity(
+ CandidateDataEntityTo candidateDataEntityTo, InputStream zipFileManifest,
+ AnalyzedZipHeatFiles analyzedZipHeatFiles) throws Exception {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ FileContentHandler zipContentMap = candidateDataEntityTo.getContentMap();
+ FilesDataStructure filesDataStructure;
+ String dataStructureJson;
+
+ if (zipFileManifest != null) {
+ // create data structure from manifest
+ filesDataStructure = createFileDataStructureFromManifest(zipFileManifest);
+ Set<String> zipFileList = zipContentMap.getFileList();
+ balanceManifestFilesWithZipFiles(filesDataStructure,
+ zipContentMap, analyzedZipHeatFiles);
+ Set<String> filesDataStructureFiles = getFlatFileNames(filesDataStructure);
+ filesDataStructure.getUnassigned().addAll(zipFileList.stream()
+ .filter(fileName -> (!filesDataStructureFiles.contains(fileName) &&
+ !filesDataStructure.getNested().contains(fileName) &&
+ !fileName.equals(SdcCommon.MANIFEST_NAME)))
+ .collect(Collectors.toList()));
+ dataStructureJson = JsonUtil.object2Json(filesDataStructure);
+ } else {
+ // create data structure from based on naming convention
+ dataStructureJson =
+ heatStructureTreeToFileDataStructure(candidateDataEntityTo.getTree(), zipContentMap,
+ candidateDataEntityTo.getErrors(), analyzedZipHeatFiles);
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return new OrchestrationTemplateCandidateData(
+ ByteBuffer.wrap(candidateDataEntityTo.getUploadedFileData()), dataStructureJson);
+ }
+
+ private void balanceManifestFilesWithZipFiles(
+ FilesDataStructure filesDataStructure,
+ FileContentHandler fileContentHandler, AnalyzedZipHeatFiles analyzedZipHeatFiles)
+ throws Exception {
+ Set<String> zipFileList = fileContentHandler.getFileList();
+ filesDataStructure.getNested().addAll(analyzedZipHeatFiles.getNestedFiles());
+ List<Module> modules = filesDataStructure.getModules();
+ if (CollectionUtils.isEmpty(modules)) {
+ return;
+ }
+
+ for (int i = 0; i < modules.size(); i++) {
+ Module module = modules.get(i);
+ if (!isFileExistInZipContains(zipFileList, module.getYaml())) {
+ addFileToUnassigned(filesDataStructure, zipFileList, module.getEnv());
+ addFileToUnassigned(filesDataStructure, zipFileList, module.getVol());
+ addFileToUnassigned(filesDataStructure, zipFileList, module.getVolEnv());
+ modules.remove(i--);
+ } else if (Objects.nonNull(module.getVol()) && !zipFileList.contains(module.getVol())) {
+ module.setVol(null);
+ CollectionUtils.addIgnoreNull(filesDataStructure.getUnassigned(), module.getVolEnv());
+ } else {
+ if (filesDataStructure.getNested().contains(module.getYaml())) {
+ moveModuleFileToNested(filesDataStructure, i--, module);
+ }
+ }
+ }
+ }
+
+ private void addFileToUnassigned(FilesDataStructure filesDataStructure, Set<String> zipFileList,
+ String fileName) {
+ if (isFileExistInZipContains(zipFileList, fileName)) {
+ filesDataStructure.getUnassigned().add(fileName);
+ }
+ }
+
+ private boolean isFileExistInZipContains(Set<String> zipFileList, String fileName) {
+ return Objects.nonNull(fileName) && zipFileList.contains(fileName);
+ }
+
+ private void moveModuleFileToNested(FilesDataStructure filesDataStructure, int i, Module module) {
+ if (!filesDataStructure.getNested().contains(module.getYaml())) {
+ filesDataStructure.getNested().add(module.getYaml());
+ }
+ if (Objects.nonNull(module.getEnv())) {
+ filesDataStructure.getNested().add(module.getEnv());
+ }
+ if (Objects.nonNull(module.getVol())) {
+ filesDataStructure.getNested().add(module.getVol());
+ }
+ if (Objects.nonNull(module.getVolEnv())) {
+ filesDataStructure.getNested().add(module.getVolEnv());
+ }
+ filesDataStructure.getModules().remove(i);
+ }
+
+ private Set<String> getFlatFileNames(FilesDataStructure filesDataStructure) {
+ Set<String> fileNames = new HashSet<>();
+ if (!CollectionUtils.isEmpty(filesDataStructure.getModules())) {
+ for (Module module : filesDataStructure.getModules()) {
+ CollectionUtils.addIgnoreNull(fileNames, module.getEnv());
+ CollectionUtils.addIgnoreNull(fileNames, module.getVol());
+ CollectionUtils.addIgnoreNull(fileNames, module.getVolEnv());
+ CollectionUtils.addIgnoreNull(fileNames, module.getYaml());
+ }
+ }
+ fileNames.addAll(filesDataStructure.getArtifacts().stream().collect(Collectors.toSet()));
+ fileNames.addAll(filesDataStructure.getNested().stream().collect(Collectors.toSet()));
+ fileNames.addAll(filesDataStructure.getUnassigned().stream().collect(Collectors.toSet()));
+
+ return fileNames;
+ }
+
+ private FilesDataStructure createFileDataStructureFromManifest(InputStream isManifestContent) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ ManifestContent manifestContent =
+ JsonUtil.json2Object(isManifestContent, ManifestContent.class);
+ FilesDataStructure structure = new FilesDataStructure();
+ for (FileData fileData : manifestContent.getData()) {
+ if (Objects.nonNull(fileData.getType()) && fileData.getType().equals(FileData.Type.HEAT)) {
+ Module module = new Module();
+ module.setYaml(fileData.getFile());
+ module.setIsBase(fileData.getBase());
+ addHeatDependenciesToModule(module, fileData.getData());
+ structure.getModules().add(module);
+ } else if (HeatFileAnalyzer.isYamlOrEnvFile(fileData.getFile()) &&
+ !FileData.Type.isArtifact(fileData.getType())) {
+ structure.getUnassigned().add(fileData.getFile());
+ } else {
+ structure.getArtifacts().add(fileData.getFile());
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ return structure;
+ }
+
+ private void addHeatDependenciesToModule(Module module, List<FileData> data) {
+ if (CollectionUtils.isEmpty(data)) {
+ return;
+ }
+
+ for (FileData fileData : data) {
+ if (fileData.getType().equals(FileData.Type.HEAT_ENV)) {
+ module.setEnv(fileData.getFile());
+ } else if (fileData.getType().equals(FileData.Type.HEAT_VOL))// must be volume
+ {
+ module.setVol(fileData.getFile());
+ if (!CollectionUtils.isEmpty(fileData.getData())) {
+ FileData volEnv = fileData.getData().get(0);
+ if (volEnv.getType().equals(FileData.Type.HEAT_ENV)) {
+ module.setVolEnv(volEnv.getFile());
+ } else {
+ throw new CoreException((new ErrorCode.ErrorCodeBuilder())
+ .withMessage(Messages.ILLEGAL_MANIFEST.getErrorMessage())
+ .withId(Messages.ILLEGAL_MANIFEST.getErrorMessage())
+ .withCategory(ErrorCategory.APPLICATION).build());
+ }
+ }
+ } else {
+ throw new CoreException((new ErrorCode.ErrorCodeBuilder())
+ .withMessage(Messages.FILE_TYPE_NOT_LEGAL.getErrorMessage())
+ .withId(Messages.FILE_TYPE_NOT_LEGAL.getErrorMessage())
+ .withCategory(ErrorCategory.APPLICATION).build());
+ }
+ }
+ }
+
+ @Override
+ public void updateCandidateUploadData(OrchestrationTemplateCandidateData uploadData,
+ String itemId) {
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ //vendorSoftwareProductDao.updateCandidateUploadData(uploadData);
+ orchestrationTemplateCandidateDataDao.update(itemId, uploadData);
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ @Override
+ public Optional<FilesDataStructure> getOrchestrationTemplateCandidateFileDataStructure(
+ String vspId, Version version) {
+
+ mdcDataDebugMessage.debugEntryMessage("VSP Id", vspId);
+
+ Optional<String> jsonFileDataStructure =
+ orchestrationTemplateCandidateDataDao.getStructure(vspId, version);
+
+ if (jsonFileDataStructure.isPresent()) {
+ mdcDataDebugMessage.debugExitMessage("VSP Id", vspId);
+ return Optional
+ .of(JsonUtil.json2Object(jsonFileDataStructure.get(), FilesDataStructure.class));
+ } else {
+ mdcDataDebugMessage.debugExitMessage("VSP Id", vspId);
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public void updateOrchestrationTemplateCandidateFileDataStructure(String vspId, Version version,
+ FilesDataStructure fileDataStructure) {
+ OrchestrationTemplateCandidateDaoFactory.getInstance().createInterface()
+ .updateStructure(vspId, version, fileDataStructure);
+ }
+
+ @Override
+ public OrchestrationTemplateCandidateData getOrchestrationTemplateCandidate(String vspId,
+ Version version) {
+ mdcDataDebugMessage.debugEntryMessage("VSP Id", vspId);
+ mdcDataDebugMessage.debugExitMessage("VSP Id", vspId);
+
+ return orchestrationTemplateCandidateDataDao.get(vspId, version);
+ }
+
+ @Override
+ public String createManifest(VspDetails vspDetails, FilesDataStructure structure) {
+
+ mdcDataDebugMessage.debugEntryMessage("VSP Id", vspDetails.getId());
+
+ Optional<ManifestContent> manifest = manifestCreator.createManifest(vspDetails, structure);
+ if (!manifest.isPresent()) {
+ throw new RuntimeException(Messages.CREATE_MANIFEST_FROM_ZIP.getErrorMessage());
+ }
+
+ mdcDataDebugMessage.debugExitMessage("VSP Id", vspDetails.getId());
+ return JsonUtil.object2Json(manifest.get());
+ }
+
+ @Override
+ public Optional<ManifestContent> createManifest(VspDetails vspDetails,
+ FileContentHandler fileContentHandler,
+ AnalyzedZipHeatFiles analyzedZipHeatFiles) {
+
+
+ mdcDataDebugMessage.debugEntryMessage("VSP Id", vspDetails.getId());
+
+ mdcDataDebugMessage.debugExitMessage("VSP Id", vspDetails.getId());
+ return manifestCreator.createManifest(vspDetails, fileContentHandler, analyzedZipHeatFiles);
+ }
+
+ @Override
+ public Optional<ByteArrayInputStream> fetchZipFileByteArrayInputStream(String vspId,
+ OrchestrationTemplateCandidateData candidateDataEntity,
+ String manifest,
+ Map<String, List<ErrorMessage>> uploadErrors) {
+ byte[] file;
+ ByteArrayInputStream byteArrayInputStream = null;
+ try {
+ file = replaceManifestInZip(candidateDataEntity.getContentData(), manifest, vspId);
+ byteArrayInputStream = new ByteArrayInputStream(
+ Objects.isNull(file) ? candidateDataEntity.getContentData().array()
+ : file);
+ } catch (IOException e) {
+ ErrorMessage errorMessage =
+ new ErrorMessage(ErrorLevel.ERROR, Messages.CANDIDATE_PROCESS_FAILED.getErrorMessage());
+ logger.error(errorMessage.getMessage(), e);
+ ErrorsUtil.addStructureErrorToErrorMap(SdcCommon.UPLOAD_FILE, errorMessage, uploadErrors);
+ }
+ return Optional.ofNullable(byteArrayInputStream);
+ }
+
+ @Override
+ public byte[] replaceManifestInZip(ByteBuffer contentData, String manifest, String vspId)
+ throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try (final ZipOutputStream zos = new ZipOutputStream(baos);
+ ZipInputStream zipStream = new ZipInputStream(
+ new ByteArrayInputStream(contentData.array()))) {
+ ZipEntry zipEntry;
+ boolean manifestWritten = false;
+ while ((zipEntry = zipStream.getNextEntry()) != null) {
+ if (!zipEntry.getName().equalsIgnoreCase(SdcCommon.MANIFEST_NAME)) {
+ ZipEntry loc_ze = new ZipEntry(zipEntry.getName());
+ zos.putNextEntry(loc_ze);
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = zipStream.read(buf)) > 0) {
+ zos.write(buf, 0, (len < buf.length) ? len : buf.length);
+ }
+ } else {
+ manifestWritten = true;
+ writeManifest(manifest, zos);
+ }
+ zos.closeEntry();
+ }
+ if (!manifestWritten) {
+ writeManifest(manifest, zos);
+ zos.closeEntry();
+ }
+ }
+ return baos.toByteArray();
+ }
+
+ @Override
+ public Optional<List<ErrorMessage>> validateFileDataStructure(
+ FilesDataStructure filesDataStructure) {
+ return candidateServiceValidator.validateFileDataStructure(filesDataStructure);
+ }
+
+ private void writeManifest(String manifest, ZipOutputStream zos) throws IOException {
+ zos.putNextEntry(new ZipEntry(SdcCommon.MANIFEST_NAME));
+ try (InputStream manifestStream = new ByteArrayInputStream(
+ manifest.getBytes(StandardCharsets.UTF_8))) {
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = (manifestStream.read(buf))) > 0) {
+ zos.write(buf, 0, (len < buf.length) ? len : buf.length);
+ }
+ }
+ }
+
+ private void handleArtifactsFromTree(HeatStructureTree tree, FilesDataStructure structure) {
+
+ if (Objects.isNull(tree) || Objects.isNull(tree.getArtifacts())) {
+ return;
+ }
+
+ if (CollectionUtils.isNotEmpty(tree.getArtifacts())) {
+ structure.getArtifacts().addAll(
+ tree.getArtifacts()
+ .stream()
+ .map(Artifact::getFileName)
+ .filter(fileName -> !structure.getArtifacts().contains(fileName))
+ .collect(Collectors.toList()));
+ }
+ }
+
+ private void handleOtherResources(HeatStructureTree tree, Set<String> usedEnvFiles,
+ FilesDataStructure structure) {
+ Set<HeatStructureTree> others = tree.getOther();
+ if (Objects.isNull(others)) {
+ return;
+ }
+
+ List<String> artifacts = new ArrayList<>();
+ List<String> unassigned = new ArrayList<>();
+ for (HeatStructureTree other : others) {
+ if (HeatFileAnalyzer.isYamlOrEnvFile(other.getFileName())) {
+ if (isEnvFileUsedByHeatFile(usedEnvFiles, other)) {
+ continue;
+ }
+ unassigned.add(other.getFileName());
+ } else {
+ artifacts.add(other.getFileName());
+ }
+ handleArtifactsFromTree(other, structure);
+ }
+ structure.getArtifacts().addAll(artifacts);
+ structure.getUnassigned().addAll(unassigned);
+ }
+
+ private boolean isEnvFileUsedByHeatFile(Set<String> usedEnvFiles, HeatStructureTree other) {
+ if (HeatFileAnalyzer.isEnvFile(other.getFileName())) {
+ if (usedEnvFiles.contains(other.getFileName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void addHeatsToFileDataStructure(HeatStructureTree tree, Set<String> usedEnvFiles,
+ FilesDataStructure structure,
+ Map<String, List<ErrorMessage>> uploadErrors,
+ AnalyzedZipHeatFiles analyzedZipHeatFiles)
+ throws Exception {
+ List<Module> modules = new ArrayList<>();
+ Set<HeatStructureTree> heatsSet = tree.getHeat();
+ if (Objects.isNull(heatsSet)) {
+ return;
+ }
+ for (HeatStructureTree heat : heatsSet) {
+ if (isFileBaseFile(heat.getFileName())) {
+ handleSingleHeat(structure, modules, heat, uploadErrors);
+ } else if (isFileModuleFile(heat.getFileName(), analyzedZipHeatFiles.getModuleFiles())) {
+ handleSingleHeat(structure, modules, heat, uploadErrors);
+ } else {
+ structure.getUnassigned().add(heat.getFileName());
+ addNestedToFileDataStructure(heat, structure);
+ }
+ if (!Objects.isNull(heat.getEnv())) {
+ usedEnvFiles.add(heat.getEnv() == null ? null : heat.getEnv().getFileName());
+ }
+ }
+ structure.setModules(modules);
+
+ }
+
+ private boolean isFileModuleFile(String fileName, Set<String> modulesFileNames) {
+ return modulesFileNames.contains(fileName);
+ }
+
+ private boolean isFileBaseFile(String fileName) {
+ return manifestCreator.isFileBaseFile(fileName);
+ }
+
+ private void handleSingleHeat(FilesDataStructure structure, List<Module> modules,
+ HeatStructureTree heat,
+ Map<String, List<ErrorMessage>> uploadErrors) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ Module module = new Module();
+ module.setYaml(heat.getFileName());
+ module.setIsBase(heat.getBase());
+ addNestedToFileDataStructure(heat, structure);
+ Set<HeatStructureTree> volumeSet = heat.getVolume();
+ int inx = 0;
+ if (Objects.nonNull(volumeSet)) {
+ handleVolumes(module, volumeSet, structure, inx, uploadErrors);
+ }
+ handleEnv(module, heat, false, structure);
+ modules.add(module);
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ private void handleVolumes(Module module, Set<HeatStructureTree> volumeSet,
+ FilesDataStructure structure, int inx,
+ Map<String, List<ErrorMessage>> uploadErrors) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ for (HeatStructureTree volume : volumeSet) {
+ if (inx++ > 0) {
+ ErrorsUtil.addStructureErrorToErrorMap(SdcCommon.UPLOAD_FILE,
+ new ErrorMessage(ErrorLevel.WARNING,
+ Messages.MORE_THEN_ONE_VOL_FOR_HEAT.getErrorMessage()), uploadErrors);
+ break;
+ }
+ handleArtifactsFromTree(volume, structure);
+ module.setVol(volume.getFileName());
+ handleEnv(module, volume, true, structure);
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ private void handleEnv(Module module, HeatStructureTree tree, boolean isVolEnv,
+ FilesDataStructure structure) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null);
+
+ if (Objects.nonNull(tree.getEnv())) {
+ if (isVolEnv) {
+ module.setVolEnv(tree.getEnv().getFileName());
+ } else {
+ module.setEnv(tree.getEnv().getFileName());
+ }
+ handleArtifactsFromTree(tree.getEnv(), structure);
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null);
+ }
+
+ private void addNestedToFileDataStructure(HeatStructureTree heat, FilesDataStructure structure) {
+ Set<HeatStructureTree> nestedSet = heat.getNested();
+ if (Objects.isNull(nestedSet)) {
+ return;
+ }
+ for (HeatStructureTree nested : nestedSet) {
+ if (structure.getNested().contains(nested.getFileName())) {
+ continue;
+ }
+ structure.getNested().add(nested.getFileName());
+ if (CollectionUtils.isNotEmpty(nested.getArtifacts())) {
+ handleArtifactsFromTree(nested, structure);
+ }
+ addNestedToFileDataStructure(nested, structure);
+ }
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/ManifestCreatorNamingConventionImpl.java b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/ManifestCreatorNamingConventionImpl.java
new file mode 100644
index 0000000000..eed575ff02
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/ManifestCreatorNamingConventionImpl.java
@@ -0,0 +1,309 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.vendorsoftwareproduct.services.impl.filedatastructuremodule;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.openecomp.core.utilities.file.FileContentHandler;
+import org.openecomp.sdc.heat.datatypes.manifest.FileData;
+import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
+import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
+import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
+import org.openecomp.sdc.vendorsoftwareproduct.services.HeatFileAnalyzer;
+import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.ManifestCreator;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.AnalyzedZipHeatFiles;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Constants;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Module;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+public class ManifestCreatorNamingConventionImpl implements ManifestCreator {
+ protected static final Logger logger =
+ LoggerFactory.getLogger(ManifestCreatorNamingConventionImpl.class);
+ private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
+
+
+ @Override
+ public Optional<ManifestContent> createManifest(
+ VspDetails vspDetails, FilesDataStructure filesDataStructure) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null, null);
+
+ if (Objects.isNull(filesDataStructure)) {
+ return Optional.empty();
+ }
+
+ List<FileData> fileDataList = new ArrayList<>();
+ addModulesToManifestFileDataList(filesDataStructure, fileDataList);
+ addNestedToManifest(filesDataStructure, fileDataList);
+ addArtifactsToManifestFileDataList(filesDataStructure, fileDataList);
+ ManifestContent manifestContent = createManifest(vspDetails, fileDataList);
+
+ mdcDataDebugMessage.debugExitMessage(null, null);
+ return Optional.of(manifestContent);
+ }
+
+ private void addNestedToManifest(
+ FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null, null);
+
+ if (CollectionUtils.isNotEmpty(filesDataStructure.getNested())) {
+ for (String nested : filesDataStructure.getNested()) {
+ fileDataList.add(createBaseFileData(FileData.Type.HEAT, nested));
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null, null);
+ }
+
+ @Override
+ public Optional<ManifestContent> createManifest(VspDetails vspDetails,
+ FileContentHandler fileContentHandler,
+ AnalyzedZipHeatFiles analyzedZipHeatFiles) {
+ logger.info("Trying to generate manifest");
+ if (Objects.isNull(fileContentHandler)
+ || CollectionUtils.isEmpty(fileContentHandler.getFileList())) {
+ logger.info("fileContentHandler or filesList is empty. ManifestContent will not be created");
+ return Optional.empty();
+ }
+
+ Map<String, byte[]> files = fileContentHandler.getFiles();
+
+ List<FileData> fileDataList =
+ createFileDataListFromZipFiles(fileContentHandler, files,
+ analyzedZipHeatFiles.getFilesNotEligbleForModules());
+ ManifestContent manifestContent = createManifest(vspDetails, fileDataList);
+
+ return Optional.of(manifestContent);
+ }
+
+ private ManifestContent createManifest(VspDetails vspDetails, List<FileData> fileDataList) {
+ ManifestContent manifestContent = new ManifestContent();
+ manifestContent.setName(vspDetails.getName());
+ manifestContent.setDescription(vspDetails.getDescription());
+ manifestContent
+ .setVersion(vspDetails.getVersion() == null ? null : vspDetails.getVersion().toString());
+ // vsp version, need to check in confluence
+ manifestContent.setData(fileDataList);
+ return manifestContent;
+ }
+
+ private List<FileData> createFileDataListFromZipFiles(FileContentHandler fileContentHandler,
+ Map<String, byte[]> files,
+ Collection<String> filesNotEligibleForModules) {
+
+ Set<String> processedFiles = new HashSet<>();
+ List<FileData> fileDataList = new ArrayList<>();
+ for (String fileName : files.keySet()) {
+ if (processedFiles.contains(fileName)) {
+ continue;
+ }
+ if (isFileBaseFile(fileName)) {
+ fileDataList
+ .add(createModuleFileData(
+ fileName, true, processedFiles, fileContentHandler.getFileList(), fileDataList));
+ } else if (isFileModuleFile(fileName, filesNotEligibleForModules)) {
+ fileDataList
+ .add(createModuleFileData(
+ fileName, false, processedFiles, fileContentHandler.getFileList(), fileDataList));
+ } else {
+ if (HeatFileAnalyzer.isYamlFile(fileName)) {
+ fileDataList.add(createBasicFileData(fileName, FileData.Type.HEAT, null));
+ } else if (HeatFileAnalyzer.isEnvFile(fileName)) {
+ fileDataList.add(createBasicFileData(fileName, FileData.Type.HEAT_ENV, null));
+ } else {
+ fileDataList.add(createBasicFileData(fileName, FileData.Type.OTHER, null));
+ }
+ }
+ }
+ return fileDataList;
+ }
+
+ private boolean doesHeatTemplateVersionExist(byte[] value) {
+ return false;
+ }
+
+ private boolean isFileModuleFile(String fileName, Collection<String> filesCannotBeModule) {
+ return !filesCannotBeModule.contains(fileName);
+ }
+
+ @Override
+ public boolean isFileBaseFile(String fileName) {
+ return Pattern.matches(Constants.BASE_HEAT_REGEX, fileName) && !isVolFile(fileName);
+ }
+
+
+ private void addArtifactsToManifestFileDataList(
+ FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null, null);
+
+ Collection<String> forArtifacts = CollectionUtils
+ .union(filesDataStructure.getArtifacts(), filesDataStructure.getUnassigned());
+ if (CollectionUtils.isNotEmpty(forArtifacts)) {
+ for (String artifact : forArtifacts) {
+ fileDataList.add(createBaseFileData(FileData.Type.OTHER, artifact));
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null, null);
+ }
+
+ private void addModulesToManifestFileDataList(
+ FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
+
+
+ mdcDataDebugMessage.debugEntryMessage(null, null);
+
+ if (CollectionUtils.isNotEmpty(filesDataStructure.getModules())) {
+ for (Module module : filesDataStructure.getModules()) {
+ FileData fileData = createBaseFileData(FileData.Type.HEAT, module.getYaml());
+ fileData.setBase(module.getIsBase());
+ addEnv(module, fileData);
+ addVolume(module, fileData);
+ fileDataList.add(fileData);
+ }
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null, null);
+ }
+
+ private void addEnv(Module module, FileData fileData) {
+ if (Objects.nonNull(module.getEnv())) {
+ FileData env = createBaseFileData(FileData.Type.HEAT_ENV, module.getEnv());
+ fileData.addFileData(env);
+ }
+ }
+
+ private void addVolume(Module module, FileData fileData) {
+ String volModule = module.getVol();
+ if (Objects.nonNull(volModule)) {
+ FileData vol = createBaseFileData(FileData.Type.HEAT_VOL, volModule);
+ if (Objects.nonNull(module.getVolEnv())) {
+ vol.addFileData(createBaseFileData(FileData.Type.HEAT_ENV, module.getVolEnv()));
+ }
+ fileData.addFileData(vol);
+ }
+ }
+
+ private FileData createBaseFileData(FileData.Type heat, String yaml) {
+ FileData fileData = new FileData();
+ fileData.setType(heat);
+ fileData.setFile(yaml);
+ return fileData;
+ }
+
+ private FileData createModuleFileData(
+ String moduleFileName, boolean isBase, Set<String> processedFiles,
+ Set<String> fileNames, List<FileData> fileDataList) {
+ FileData moduleFileData = createBasicFileData(moduleFileName, FileData.Type.HEAT, isBase);
+ Optional<String> volFile = fetchRelatedVolume(moduleFileName, fileNames);
+ volFile.ifPresent(vol -> {
+ markFileAsProcessed(vol, processedFiles);
+ removeFromFileDataListIfAlreadyProcessed(fileDataList, vol);
+ FileData volFileData = createBasicFileData(vol, FileData.Type.HEAT_VOL, null);
+ Optional<String> envFile = fetchRelatedEnv(vol, fileNames);
+ envFile.ifPresent(env -> {
+ markFileAsProcessed(env, processedFiles);
+ removeFromFileDataListIfAlreadyProcessed(fileDataList, env);
+ FileData envFileData = createBasicFileData(env, FileData.Type.HEAT_ENV, null);
+ volFileData.addFileData(envFileData);
+ });
+ moduleFileData.addFileData(volFileData);
+ });
+ Optional<String> envFile = fetchRelatedEnv(moduleFileName, fileNames);
+ envFile.ifPresent(env -> {
+ markFileAsProcessed(env, processedFiles);
+ FileData envFileData = createBasicFileData(env, FileData.Type.HEAT_ENV, null);
+ moduleFileData.addFileData(envFileData);
+ });
+ return moduleFileData;
+ }
+
+ private void removeFromFileDataListIfAlreadyProcessed(List<FileData> fileDataList, String vol) {
+ fileDataList.removeIf(fileData -> fileData.getFile().equals(vol));
+ }
+
+ private FileData createBasicFileData(String fileName, FileData.Type type, Boolean isBase) {
+ FileData fileData = new FileData();
+ if (isBase != null) {
+ fileData.setBase(isBase);
+ }
+ fileData.setType(type);
+ fileData.setFile(fileName);
+ return fileData;
+ }
+
+ private Optional<String> fetchRelatedEnv(String fileName, Set<String> fileNames) {
+ String envFileName
+ = fileName.substring(0, fileName.lastIndexOf(".")) + Constants.ENV_FILE_EXTENSION;
+ return fileNames.contains(envFileName) ? Optional.of(envFileName) : Optional.empty();
+ }
+
+ private Optional<String> fetchRelatedVolume(String fileName, Set<String> fileNames) {
+
+ String volFile1stExt =
+ extractVolFileName(fileName, ".yaml");
+ String volFile2ndExt =
+ extractVolFileName(fileName, ".yml");
+
+ if (fileNames.contains(volFile1stExt)) {
+ return Optional.of(volFile1stExt);
+ }
+ if (fileNames.contains(volFile2ndExt)) {
+ return Optional.of(volFile2ndExt);
+ }
+ return Optional.empty();
+ }
+
+ private String extractVolFileName(String fileName, String fileExt) {
+ return fileName.substring(
+ 0, fileName.lastIndexOf("."))
+ + Constants.VOL_FILE_NAME_SUFFIX + fileExt;
+ }
+
+
+ private boolean isVolFile(String fileName) {
+ return fileName
+ .endsWith(
+ Constants.VOL_FILE_NAME_SUFFIX + ".yaml")
+ || fileName.endsWith(Constants.VOL_FILE_NAME_SUFFIX + ".yml");
+ }
+
+
+ private void markFileAsProcessed(String fileName, Set<String> processedFiles) {
+ processedFiles.add(fileName);
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/utils/CandidateServiceValidator.java b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/utils/CandidateServiceValidator.java
new file mode 100644
index 0000000000..05c95a7596
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/utils/CandidateServiceValidator.java
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.vendorsoftwareproduct.services.utils;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
+import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.datatypes.error.ErrorLevel;
+import org.openecomp.sdc.datatypes.error.ErrorMessage;
+import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
+import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Module;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Created by Talio on 12/6/2016.
+ */
+public class CandidateServiceValidator {
+ private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
+
+ public Optional<List<ErrorMessage>> validateFileDataStructure(
+ FilesDataStructure filesDataStructure) {
+ if (Objects.isNull(filesDataStructure)) {
+ return Optional.empty();
+ }
+ if (validateAtLeaseOneModuleExist(filesDataStructure)) {
+ return Optional.of(Arrays.asList(new ErrorMessage(ErrorLevel.ERROR, Messages
+ .NO_MODULES_IN_MANIFEST.getErrorMessage())));
+ }
+
+ List<ErrorMessage> errors = new ArrayList<>();
+ for (Module module : filesDataStructure.getModules()) {
+ validateModuleHaveYaml(errors, module);
+ validateNoVolEnvWithoutVol(errors, module);
+ }
+ return Optional.of(errors);
+ }
+
+
+ private boolean validateAtLeaseOneModuleExist(FilesDataStructure filesDataStructure) {
+
+ mdcDataDebugMessage.debugEntryMessage(null, null);
+
+ mdcDataDebugMessage.debugExitMessage(null, null);
+ return CollectionUtils.isEmpty(filesDataStructure.getModules());
+ }
+
+ private void validateNoVolEnvWithoutVol(List<ErrorMessage> errors, Module module) {
+
+ mdcDataDebugMessage.debugEntryMessage(null, null);
+
+ if (StringUtils.isEmpty(module.getVol()) && StringUtils.isNotEmpty(module.getVolEnv())) {
+ errors.add(new ErrorMessage(ErrorLevel.ERROR, ErrorMessagesFormatBuilder
+ .getErrorWithParameters(Messages.MODULE_IN_MANIFEST_VOL_ENV_NO_VOL.getErrorMessage(),
+ module.getName())));
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null, null);
+ }
+
+ private void validateModuleHaveYaml(List<ErrorMessage> errors, Module module) {
+
+ mdcDataDebugMessage.debugEntryMessage(null, null);
+
+ if (StringUtils.isEmpty(module.getYaml())) {
+ errors.add(new ErrorMessage(ErrorLevel.ERROR, ErrorMessagesFormatBuilder
+ .getErrorWithParameters(Messages.MODULE_IN_MANIFEST_NO_YAML.getErrorMessage(),
+ module.getName())));
+ }
+
+ mdcDataDebugMessage.debugExitMessage(null, null);
+ }
+}