X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=catalog-be%2Fsrc%2Fmain%2Fjava%2Forg%2Fopenecomp%2Fsdc%2Fbe%2Ftosca%2FToscaExportHandler.java;h=ef63a86d39fde50455f4ba805912fabe44b638c7;hb=d77bdf472a4fb5b6cf8e17f2d0d8e8d2bababeaf;hp=1f29eb211308e880e51e63da22798dd4ed85cdc2;hpb=0566f581c0f310384f42838c388f57234ed1d60e;p=sdc.git diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 1f29eb2113..ef63a86d39 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -7,9 +7,9 @@ * 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. @@ -17,72 +17,118 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - package org.openecomp.sdc.be.tosca; -import java.beans.IntrospectionException; +import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.apache.commons.collections.MapUtils.isNotEmpty; +import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput; +import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.addInterfaceTypeElement; +import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE; +import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT; +import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY; + +import fj.data.Either; +import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; - import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutableTriple; import org.apache.commons.lang3.tuple.Triple; +import org.onap.sdc.tosca.services.YamlUtil; +import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundException; +import org.openecomp.sdc.be.config.Configuration; import org.openecomp.sdc.be.config.ConfigurationManager; -import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.data.model.ToscaImportByModel; import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterCapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaArtifactDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.exception.ToscaExportException; import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.AttributeDefinition; import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.CapabilityRequirementRelationship; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceAttribute; import org.openecomp.sdc.be.model.ComponentInstanceInput; +import org.openecomp.sdc.be.model.ComponentInstanceInterface; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; -import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupInstance; -import org.openecomp.sdc.be.model.GroupProperty; import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.InterfaceDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; -import org.openecomp.sdc.be.model.RequirementAndRelationshipPair; +import org.openecomp.sdc.be.model.RelationshipInfo; import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; import org.openecomp.sdc.be.model.RequirementDefinition; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.category.CategoryDefinition; -import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; -import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; -import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter; -import org.openecomp.sdc.be.tosca.model.IToscaMetadata; +import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.be.model.operations.impl.ModelOperation; +import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType; +import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder; +import org.openecomp.sdc.be.tosca.exception.ToscaConversionException; +import org.openecomp.sdc.be.tosca.model.CapabilityFilter; +import org.openecomp.sdc.be.tosca.model.NodeFilter; import org.openecomp.sdc.be.tosca.model.SubstitutionMapping; +import org.openecomp.sdc.be.tosca.model.ToscaAttribute; import org.openecomp.sdc.be.tosca.model.ToscaCapability; +import org.openecomp.sdc.be.tosca.model.ToscaDataType; import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate; -import org.openecomp.sdc.be.tosca.model.ToscaMetadata; import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate; import org.openecomp.sdc.be.tosca.model.ToscaNodeType; +import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate; import org.openecomp.sdc.be.tosca.model.ToscaProperty; +import org.openecomp.sdc.be.tosca.model.ToscaPropertyAssignment; +import org.openecomp.sdc.be.tosca.model.ToscaRelationshipTemplate; +import org.openecomp.sdc.be.tosca.model.ToscaRequirement; import org.openecomp.sdc.be.tosca.model.ToscaTemplate; +import org.openecomp.sdc.be.tosca.model.ToscaTemplateArtifact; import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement; import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate; -import org.openecomp.sdc.be.tosca.model.VfModuleToscaMetadata; -import org.openecomp.sdc.common.api.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil; +import org.openecomp.sdc.be.tosca.utils.InputConverter; +import org.openecomp.sdc.be.tosca.utils.OutputConverter; +import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode; +import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions.FlowStyle; @@ -97,1031 +143,1760 @@ import org.yaml.snakeyaml.nodes.Tag; import org.yaml.snakeyaml.representer.Represent; import org.yaml.snakeyaml.representer.Representer; -import fj.data.Either; - @org.springframework.stereotype.Component("tosca-export-handler") public class ToscaExportHandler { - @Autowired - private ApplicationDataTypeCache dataTypeCache; - - @Autowired - private ToscaOperationFacade toscaOperationFacade; - @Autowired - private CapabiltyRequirementConvertor capabiltyRequirementConvertor; - private PropertyConvertor propertyConvertor = PropertyConvertor.getInstance(); - Map originComponents = new HashMap<>(); - - private static Logger log = LoggerFactory.getLogger(ToscaExportHandler.class.getName()); - - public static final String TOSCA_VERSION = "tosca_simple_yaml_1_1"; - public static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service."; - public static final String IMPORTS_FILE_KEY = "file"; - public static final String TOSCA_TEMPLATE_NAME = "-template.yml"; - public static final String TOSCA_INTERFACE_NAME = "-interface.yml"; - public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate"; - public static final String VF_MODULE_TYPE_KEY = "vf_module_type"; - public static final String VF_MODULE_DESC_KEY = "vf_module_description"; - public static final String VOLUME_GROUP_KEY = "volume_group"; - public static final String VF_MODULE_TYPE_BASE = "Base"; - public static final String VF_MODULE_TYPE_EXPANSION = "Expansion"; - private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration"; - private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}"; - protected static final List>> DEFAULT_IMPORTS = ConfigurationManager.getConfigurationManager().getConfiguration().getDefaultImports(); - - public Either exportComponent(Component component) { - - Either toscaTemplateRes = convertToToscaTemplate(component); - if (toscaTemplateRes.isRight()) { - return Either.right(toscaTemplateRes.right().value()); - } - - ToscaTemplate toscaTemplate = toscaTemplateRes.left().value(); - ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate); - return Either.left(toscaRepresentation); - } - - public Either exportComponentInterface(Component component) { - if (null == DEFAULT_IMPORTS) { - log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); - return Either.right(ToscaError.GENERAL_ERROR); - } - - ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION); - toscaTemplate.setImports(new ArrayList<>(DEFAULT_IMPORTS)); - Map nodeTypes = new HashMap<>(); - Either toscaTemplateRes = convertInterfaceNodeType(component, toscaTemplate, - nodeTypes); - if (toscaTemplateRes.isRight()) { - return Either.right(toscaTemplateRes.right().value()); - } - - toscaTemplate = toscaTemplateRes.left().value(); - ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate); - return Either.left(toscaRepresentation); - } - - public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) { - CustomRepresenter representer = new CustomRepresenter(); - DumperOptions options = new DumperOptions(); - options.setAllowReadOnlyProperties(false); - options.setPrettyFlow(true); - - options.setDefaultFlowStyle(FlowStyle.FLOW); - options.setCanonical(false); - - representer.addClassTag(toscaTemplate.getClass(), Tag.MAP); - - representer.setPropertyUtils(new UnsortedPropertyUtils()); - Yaml yaml = new Yaml(representer, options); - - String yamlAsString = yaml.dumpAsMap(toscaTemplate); - - StringBuilder sb = new StringBuilder(); - sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactHeader()); - sb.append(yamlAsString); - sb.append(ConfigurationManager.getConfigurationManager().getConfiguration().getHeatEnvArtifactFooter()); - - ToscaRepresentation toscaRepresentation = new ToscaRepresentation(); - toscaRepresentation.setMainYaml(sb.toString()); - toscaRepresentation.setDependencies(toscaTemplate.getDependencies()); - - return toscaRepresentation; - } - - public Either getDependencies(Component component) { - ToscaTemplate toscaTemplate = new ToscaTemplate(null); - Either>, ToscaError> fillImports = fillImports(component, - toscaTemplate); - if (fillImports.isRight()) { - return Either.right(fillImports.right().value()); - } - return Either.left(fillImports.left().value().left); - } - - private Either convertToToscaTemplate(Component component) { - if (null == DEFAULT_IMPORTS) { - log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); - return Either.right(ToscaError.GENERAL_ERROR); - } - - log.trace("start tosca export for {}", component.getUniqueId()); - ToscaTemplate toscaTemplate = new ToscaTemplate(TOSCA_VERSION); - - toscaTemplate.setMetadata(convertMetadata(component)); - toscaTemplate.setImports(new ArrayList<>(DEFAULT_IMPORTS)); - Map nodeTypes = new HashMap<>(); - if (ModelConverter.isAtomicComponent(component)) { - log.trace("convert component as node type"); - return convertNodeType(component, toscaTemplate, nodeTypes); - } else { - log.trace("convert component as topology template"); - return convertToscaTemplate(component, toscaTemplate); - } - - } - - private Either convertToscaTemplate(Component component, ToscaTemplate toscaNode) { - - Either>, ToscaError> importsRes = fillImports(component, - toscaNode); - if (importsRes.isRight()) { - return Either.right(importsRes.right().value()); - } - toscaNode = importsRes.left().value().left; - /*Either, ToscaError> nodeTypesMapEither = createProxyNodeTypes(component); - if (nodeTypesMapEither.isRight()) { - log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", - nodeTypesMapEither.right().value()); - return Either.right(nodeTypesMapEither.right().value()); - } - Map nodeTypesMap = nodeTypesMapEither.left().value(); - if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) - toscaNode.setNode_types(nodeTypesMap);*/ - - Map componentCache = importsRes.left().value().right; - Either, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll(); - if (dataTypesEither.isRight()) { - log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value()); - return Either.right(ToscaError.GENERAL_ERROR); - } - Map dataTypes = dataTypesEither.left().value(); - - ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate(); - - Either inputs = fillInputs(component, topologyTemplate, dataTypes); - if (inputs.isRight()) { - return Either.right(inputs.right().value()); - } - topologyTemplate = inputs.left().value(); - - List componentInstances = component.getComponentInstances(); - Map> componentInstancesProperties = component - .getComponentInstancesProperties(); - List groups = component.getGroups(); - if (componentInstances != null && !componentInstances.isEmpty()) { - - Either, ToscaError> nodeTemplates = convertNodeTemplates(component, - componentInstances, componentInstancesProperties, componentCache, dataTypes, topologyTemplate); - if (nodeTemplates.isRight()) { - return Either.right(nodeTemplates.right().value()); - } - log.debug("node templates converted"); - - topologyTemplate.setNode_templates(nodeTemplates.left().value()); - } - Map groupsMap; - if (groups != null && !groups.isEmpty()) { - groupsMap = new HashMap<>(); - for (GroupDefinition group : groups) { - ToscaGroupTemplate toscaGroup = convertGroup(group); - groupsMap.put(group.getName(), toscaGroup); - - } - log.debug("groups converted"); - topologyTemplate.addGroups(groupsMap); - } - SubstitutionMapping substitutionMapping = new SubstitutionMapping(); - String toscaResourceName; - switch (component.getComponentType()) { - case RESOURCE: - toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition() - .getMetadataDataDefinition()).getToscaResourceName(); - break; - case SERVICE: - toscaResourceName = SERVICE_NODE_TYPE_PREFIX - + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName(); - break; - default: - log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType()); - return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); - } - substitutionMapping.setNode_type(toscaResourceName); - - Either capabilities = convertCapabilities(component, substitutionMapping); - if (capabilities.isRight()) { - return Either.right(capabilities.right().value()); - } - substitutionMapping = capabilities.left().value(); - - Either requirements = capabiltyRequirementConvertor - .convertSubstitutionMappingRequirements(originComponents, component, substitutionMapping); - if (requirements.isRight()) { - return Either.right(requirements.right().value()); - } - substitutionMapping = requirements.left().value(); - - topologyTemplate.setSubstitution_mappings(substitutionMapping); - - toscaNode.setTopology_template(topologyTemplate); - return Either.left(toscaNode); - } - - private Either fillInputs(Component component, - ToscaTopolgyTemplate topologyTemplate, Map dataTypes) { - if (log.isDebugEnabled()) - log.debug("fillInputs for component {}", component.getUniqueId()); - List inputDef = component.getInputs(); - Map inputs = new HashMap<>(); - - if (inputDef != null) { - inputDef.forEach(i -> { - ToscaProperty property = propertyConvertor.convertProperty(dataTypes, i, false); - inputs.put(i.getName(), property); - }); - if (!inputs.isEmpty()) { - topologyTemplate.setInputs(inputs); - } - } - return Either.left(topologyTemplate); - } - - private ToscaMetadata convertMetadata(Component component) { - return convertMetadata(component, false, null); - } - - private ToscaMetadata convertMetadata(Component component, boolean isInstance, - ComponentInstance componentInstance) { - ToscaMetadata toscaMetadata = new ToscaMetadata(); - toscaMetadata.setName(component.getComponentMetadataDefinition().getMetadataDataDefinition().getName()); - toscaMetadata.setInvariantUUID(component.getInvariantUUID()); - toscaMetadata.setUUID(component.getUUID()); - toscaMetadata.setDescription(component.getDescription()); - - List categories = component.getCategories(); - CategoryDefinition categoryDefinition = categories.get(0); - toscaMetadata.setCategory(categoryDefinition.getName()); - - if (isInstance) { - toscaMetadata.setVersion(component.getVersion()); - toscaMetadata.setCustomizationUUID(componentInstance.getCustomizationUUID()); - } - switch (component.getComponentType()) { - case RESOURCE: - Resource resource = (Resource) component; - toscaMetadata.setType(resource.getResourceType().name()); - toscaMetadata.setSubcategory(categoryDefinition.getSubcategories().get(0).getName()); - toscaMetadata.setResourceVendor(resource.getVendorName()); - toscaMetadata.setResourceVendorRelease(resource.getVendorRelease()); - toscaMetadata.setResourceVendorModelNumber(resource.getResourceVendorModelNumber()); - break; - case SERVICE: - Service service = (Service) component; - toscaMetadata.setType(component.getComponentType().getValue()); - toscaMetadata.setServiceType(service.getServiceType()); - toscaMetadata.setServiceRole(service.getServiceRole()); - if (!isInstance) { - // DE268546 - toscaMetadata.setServiceEcompNaming(((Service)component).isEcompGeneratedNaming()); - toscaMetadata.setEcompGeneratedNaming(((Service)component).isEcompGeneratedNaming()); - toscaMetadata.setNamingPolicy(((Service)component).getNamingPolicy()); - } - break; - default: - log.debug("Not supported component type {}", component.getComponentType()); - } - return toscaMetadata; - } - - private Either>, ToscaError> fillImports(Component component, - ToscaTemplate toscaTemplate) { - - if (null == DEFAULT_IMPORTS) { - log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); - return Either.right(ToscaError.GENERAL_ERROR); - } - - Map componentCache = new HashMap<>(); - - if (!ModelConverter.isAtomicComponent(component)) { - List componentInstances = component.getComponentInstances(); - if (componentInstances != null && !componentInstances.isEmpty()) { - - List>> additionalImports = toscaTemplate.getImports() == null - ? new ArrayList<>(DEFAULT_IMPORTS) : new ArrayList<>(toscaTemplate.getImports()); - - List> dependecies = new ArrayList<>(); - - Map toscaArtifacts = component.getToscaArtifacts(); - ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE); - - Map> importsListMember = new HashMap<>(); - Map interfaceFiles = new HashMap<>(); - interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName())); - StringBuilder keyNameBuilder = new StringBuilder(); - keyNameBuilder.append(component.getComponentType().toString().toLowerCase()); - keyNameBuilder.append("-"); - keyNameBuilder.append(component.getName()); - keyNameBuilder.append("-interface"); - importsListMember.put(keyNameBuilder.toString(), interfaceFiles); - additionalImports.add(importsListMember); - - componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependecies, ci)); - originComponents.putAll(componentCache); - toscaTemplate.setDependencies(dependecies); - toscaTemplate.setImports(additionalImports); - } - } else { - log.debug("currently imports supported for VF and service only"); - } - return Either.left(new ImmutablePair>(toscaTemplate, componentCache)); - } - - private void createDependency(Map componentCache, List>> imports, - List> dependecies, ComponentInstance ci) { - Map files = new HashMap<>(); - Map> importsListMember = new HashMap<>(); - StringBuilder keyNameBuilder; - - Component componentRI = componentCache.get(ci.getComponentUid()); - if (componentRI == null) { - // all resource must be only once! - Either resource = toscaOperationFacade - .getToscaFullElement(ci.getComponentUid()); - if (resource.isRight()) { - log.debug("Failed to fetch resource with id {} for instance {}"); - } - Component fetchedComponent = resource.left().value(); - componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent); - componentRI = fetchedComponent; - - Map toscaArtifacts = componentRI.getToscaArtifacts(); - ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE); - if (artifactDefinition != null) { - String artifactName = artifactDefinition.getArtifactName(); - files.put(IMPORTS_FILE_KEY, artifactName); - keyNameBuilder = new StringBuilder(); - keyNameBuilder.append(fetchedComponent.getComponentType().toString().toLowerCase()); - keyNameBuilder.append("-"); - keyNameBuilder.append(ci.getComponentName()); - importsListMember.put(keyNameBuilder.toString(), files); - imports.add(importsListMember); - dependecies.add(new ImmutableTriple(artifactName, - artifactDefinition.getEsId(), fetchedComponent)); - - if (!ModelConverter.isAtomicComponent(componentRI)) { - importsListMember = new HashMap<>(); - Map interfaceFiles = new HashMap<>(); - interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName)); - keyNameBuilder.append("-interface"); - importsListMember.put(keyNameBuilder.toString(), interfaceFiles); - imports.add(importsListMember); - } - } - } - } - - public static String getInterfaceFilename(String artifactName) { - return artifactName.substring(0, artifactName.lastIndexOf('.')) + ToscaExportHandler.TOSCA_INTERFACE_NAME; - } - - private Either convertNodeType(Component component, ToscaTemplate toscaNode, - Map nodeTypes) { - log.debug("start convert node type for {}", component.getUniqueId()); - ToscaNodeType toscaNodeType = createNodeType(component); - - Either, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll(); - if (dataTypesEither.isRight()) { - log.debug("Failed to fetch all data types :", dataTypesEither.right().value()); - return Either.right(ToscaError.GENERAL_ERROR); - } - - Map dataTypes = dataTypesEither.left().value(); - Either properties = propertyConvertor.convertProperties(component, toscaNodeType, - dataTypes); - if (properties.isRight()) { - return Either.right(properties.right().value()); - } - toscaNodeType = properties.left().value(); - log.debug("Properties converted for {}", component.getUniqueId()); - - // Extracted to method for code reuse - return convertReqCapAndTypeName(component, toscaNode, nodeTypes, toscaNodeType, dataTypes); - } - - private Either convertInterfaceNodeType(Component component, ToscaTemplate toscaNode, - Map nodeTypes) { - log.debug("start convert node type for {}", component.getUniqueId()); - ToscaNodeType toscaNodeType = createNodeType(component); - - Either, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll(); - if (dataTypesEither.isRight()) { - log.debug("Failed to fetch all data types :", dataTypesEither.right().value()); - return Either.right(ToscaError.GENERAL_ERROR); - } - - Map dataTypes = dataTypesEither.left().value(); - - List inputDef = component.getInputs(); - Map inputs = new HashMap<>(); - - if (inputDef != null) { - inputDef.forEach(i -> { - ToscaProperty property = propertyConvertor.convertProperty(dataTypes, i, false); - inputs.put(i.getName(), property); - }); - if (!inputs.isEmpty()) { - toscaNodeType.setProperties(inputs); - } - } - - // Extracted to method for code reuse - return convertReqCapAndTypeName(component, toscaNode, nodeTypes, toscaNodeType, dataTypes); - } - - private Either convertReqCapAndTypeName(Component component, ToscaTemplate toscaNode, - Map nodeTypes, ToscaNodeType toscaNodeType, - Map dataTypes) { - Either capabilities = convertCapabilities(component, toscaNodeType, dataTypes); - if (capabilities.isRight()) { - return Either.right(capabilities.right().value()); - } - toscaNodeType = capabilities.left().value(); - log.debug("Capabilities converted for {}", component.getUniqueId()); - - Either requirements = capabiltyRequirementConvertor.convertRequirements(component, toscaNodeType); - if (requirements.isRight()) { - return Either.right(requirements.right().value()); - } - toscaNodeType = requirements.left().value(); - log.debug("Requirements converted for {}", component.getUniqueId()); - - String toscaResourceName; - switch (component.getComponentType()) { - case RESOURCE: - toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition() - .getMetadataDataDefinition()).getToscaResourceName(); - break; - case SERVICE: - toscaResourceName = SERVICE_NODE_TYPE_PREFIX - + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName(); - break; - default: - log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType()); - return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); - } - - nodeTypes.put(toscaResourceName, toscaNodeType); - toscaNode.setNode_types(nodeTypes); - log.debug("finish convert node type for {}", component.getUniqueId()); - return Either.left(toscaNode); - } - - private Either, ToscaError> convertNodeTemplates(Component component, - List componentInstances, - Map> componentInstancesProperties, - Map componentCache, Map dataTypes, - ToscaTopolgyTemplate topologyTemplate) { - - Either, ToscaError> convertNodeTemplatesRes = null; - log.debug("start convert topology template for {} for type {}", component.getUniqueId(), - component.getComponentType()); - Map nodeTemplates = new HashMap<>(); - Map> componentInstancesInputs = component.getComponentInstancesInputs(); - - Map groupsMap = null; - for (ComponentInstance componentInstance : componentInstances) { - ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate(); - nodeTemplate.setType(componentInstance.getToscaComponentName()); - - Either requirements = convertComponentInstanceRequirements(component, - componentInstance, component.getComponentInstancesRelations(), nodeTemplate, - componentCache.get(componentInstance.getComponentUid())); - if (requirements.isRight()) { - convertNodeTemplatesRes = Either.right(requirements.right().value()); - break; - } - String instanceUniqueId = componentInstance.getUniqueId(); - log.debug("Component instance Requirements converted for instance {}", instanceUniqueId); - - nodeTemplate = requirements.left().value(); - - Component componentOfInstance = componentCache.get(componentInstance.getComponentUid()); - nodeTemplate.setMetadata(convertMetadata(componentOfInstance, true, componentInstance)); - - Either capabilities = capabiltyRequirementConvertor - .convertComponentInstanceCapabilties(componentInstance, dataTypes, nodeTemplate); - if (capabilities.isRight()) { - convertNodeTemplatesRes = Either.right(requirements.right().value()); - break; - } - log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId); - - nodeTemplate = capabilities.left().value(); - Map props = new HashMap<>(); - - if (componentOfInstance.getComponentType() == ComponentTypeEnum.RESOURCE) { - // Adds the properties of parent component to map - addPropertiesOfParentComponent(dataTypes, componentInstance, componentOfInstance, props); - } - - if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) { - addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, componentInstance, - instanceUniqueId, props); - } - - if (componentInstancesInputs != null && componentInstancesInputs.containsKey(instanceUniqueId)) { - addComponentInstanceInputs(dataTypes, componentInstancesInputs, componentInstance, instanceUniqueId, - props); - } - if (props != null && !props.isEmpty()) { - nodeTemplate.setProperties(props); - } - - List groupInstances = componentInstance.getGroupInstances(); - if (groupInstances != null) { - if (groupsMap == null) { - groupsMap = new HashMap<>(); - } - for (GroupInstance groupInst : groupInstances) { - ToscaGroupTemplate toscaGroup = convertGroupInstance(groupInst); - - groupsMap.put(groupInst.getName(), toscaGroup); - } - } - - nodeTemplates.put(componentInstance.getName(), nodeTemplate); - } - if (groupsMap != null) { - log.debug("instance groups added"); - topologyTemplate.addGroups(groupsMap); - } - - if (convertNodeTemplatesRes == null) { - convertNodeTemplatesRes = Either.left(nodeTemplates); - } - log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), - component.getComponentType()); - return convertNodeTemplatesRes; - } - - private void addComponentInstanceInputs(Map dataTypes, - Map> componentInstancesInputs, ComponentInstance componentInstance, - String instanceUniqueId, Map props) { - - List instanceInputsList = componentInstancesInputs.get(instanceUniqueId); - if (instanceInputsList != null) { - instanceInputsList.forEach(input -> { - - Supplier supplier = () -> input.getValue() != null && !input.getValue().isEmpty() - ? input.getValue() : input.getDefaultValue(); - convertAndAddValue(dataTypes, componentInstance, props, input, supplier); - }); - } - } - - private void addPropertiesOfComponentInstance( - Map> componentInstancesProperties, - Map dataTypes, ComponentInstance componentInstance, String instanceUniqueId, - Map props) { - - if (!MapUtils.isEmpty(componentInstancesProperties)) { - componentInstancesProperties.get(instanceUniqueId).stream() - // Collects filtered properties to List - .collect(Collectors.toList()).stream() - // Converts and adds each value to property map - .forEach(prop -> convertAndAddValue(dataTypes, componentInstance, props, prop, - () -> prop.getValue())); - } - } - - private void addPropertiesOfParentComponent(Map dataTypes, - ComponentInstance componentInstance, Component componentOfInstance, Map props) { - - List componentProperties = ((Resource) componentOfInstance).getProperties(); - if (!CollectionUtils.isEmpty(componentProperties)) { - componentProperties.stream() - // Filters out properties with empty default values - .filter(prop -> !StringUtils.isEmpty(prop.getDefaultValue())) - // Collects filtered properties to List - .collect(Collectors.toList()).stream() - // Converts and adds each value to property map - .forEach(prop -> convertAndAddValue(dataTypes, componentInstance, props, prop, - () -> prop.getDefaultValue())); - } - } - - /** - * @param dataTypes - * @param componentInstance - * @param props - * @param prop - * @param supplier - */ - private void convertAndAddValue(Map dataTypes, ComponentInstance componentInstance, - Map props, PropertyDefinition prop, Supplier supplier) { - Object convertedValue = convertValue(dataTypes, componentInstance, prop, supplier); - if (!ToscaValueBaseConverter.isEmptyObjectValue(convertedValue)) { - props.put(prop.getName(), convertedValue); - } - } - - private Object convertValue(Map dataTypes, - ComponentInstance componentInstance, T input, Supplier supplier) { - log.debug("Convert property or input value {} for instance {}", input.getName(), - componentInstance.getUniqueId()); - String propertyType = input.getType(); - String innerType = null; - if (input.getSchema() != null && input.getSchema().getProperty() != null) { - innerType = input.getSchema().getProperty().getType(); - } - return propertyConvertor.convertToToscaObject(propertyType, supplier.get(), innerType, dataTypes); - } - - private ToscaGroupTemplate convertGroup(GroupDefinition group) { - ToscaGroupTemplate toscaGroup = new ToscaGroupTemplate(); - Map members = group.getMembers(); - if (members != null) - toscaGroup.setMembers(new ArrayList(members.keySet())); - - Supplier supplGroupType = () -> group.getType(); - Supplier supplDescription = () -> group.getDescription(); - Supplier> supplProperties = () -> group.convertToGroupProperties(); - Supplier supplgroupName = () -> group.getName(); - Supplier supplInvariantUUID = () -> group.getInvariantUUID(); - Supplier supplGroupUUID = () -> group.getGroupUUID(); - Supplier supplVersion = () -> group.getVersion(); - - IToscaMetadata toscaMetadata = fillGroup(toscaGroup, supplProperties, supplDescription, supplgroupName, - supplInvariantUUID, supplGroupUUID, supplVersion, supplGroupType); - toscaGroup.setMetadata(toscaMetadata); - return toscaGroup; - } - - private ToscaGroupTemplate convertGroupInstance(GroupInstance groupInstance) { - ToscaGroupTemplate toscaGroup = new ToscaGroupTemplate(); - - Supplier supplGroupType = () -> groupInstance.getType(); - Supplier supplDescription = () -> groupInstance.getDescription(); - Supplier> supplProperties = () -> groupInstance - .convertToGroupInstancesProperties(); - Supplier supplgroupName = () -> groupInstance.getGroupName(); - Supplier supplInvariantUUID = () -> groupInstance.getInvariantUUID(); - Supplier supplGroupUUID = () -> groupInstance.getGroupUUID(); - Supplier supplVersion = () -> groupInstance.getVersion(); - - IToscaMetadata toscaMetadata = fillGroup(toscaGroup, supplProperties, supplDescription, supplgroupName, - supplInvariantUUID, supplGroupUUID, supplVersion, supplGroupType); - - toscaMetadata.setCustomizationUUID(groupInstance.getCustomizationUUID()); - toscaGroup.setMetadata(toscaMetadata); - return toscaGroup; - } - - private IToscaMetadata fillGroup(ToscaGroupTemplate toscaGroup, Supplier> props, - Supplier description, Supplier groupName, Supplier invariantUUID, - Supplier groupUUID, Supplier version, Supplier groupType) { - boolean isVfModule = groupType.get().equals(Constants.DEFAULT_GROUP_VF_MODULE) ? true : false; - toscaGroup.setType(groupType.get()); - - IToscaMetadata toscaMetadata; - if (!isVfModule) { - toscaMetadata = new ToscaMetadata(); - } else { - toscaMetadata = new VfModuleToscaMetadata(); - - Map properties = fillGroupProperties(props.get()); - if (!properties.containsKey(VF_MODULE_DESC_KEY) - || StringUtils.isEmpty((String) properties.get(VF_MODULE_DESC_KEY))) { - properties.put(VF_MODULE_DESC_KEY, description.get()); - } - toscaGroup.setProperties(properties); - } - toscaMetadata.setName(groupName.get()); - toscaMetadata.setInvariantUUID(invariantUUID.get()); - toscaMetadata.setUUID(groupUUID.get()); - toscaMetadata.setVersion(version.get()); - return toscaMetadata; - } - - private Map fillGroupProperties(List groupProps) { - Map properties = new HashMap<>(); - if (groupProps != null) { - for (GroupProperty gp : groupProps) { - if (gp.getName().equals(Constants.IS_BASE)) { - Boolean isBase = Boolean.parseBoolean(gp.getValue()); - String type = isBase ? VF_MODULE_TYPE_BASE : VF_MODULE_TYPE_EXPANSION; - properties.put(VF_MODULE_TYPE_KEY, type); - } else { - Object value = null; - String type = gp.getType(); - - switch (type) { - case "integer": - if (gp.getValue() != null) { - value = Integer.valueOf(gp.getValue()); - } - break; - case "boolean": - if (gp.getValue() != null) { - value = Boolean.valueOf(gp.getValue()); - } - break; - - default: - value = gp.getValue(); - break; - } - properties.put(gp.getName(), value); - } - } - } - return properties; - } - - private ToscaNodeType createNodeType(Component component) { - ToscaNodeType toscaNodeType = new ToscaNodeType(); - if (ModelConverter.isAtomicComponent(component)) { - if (((Resource) component).getDerivedFrom() != null) { - toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0)); - } - toscaNodeType.setDescription(component.getDescription()); // or - // name?? - } else { - String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType() - : "tosca.nodes.Root"; - toscaNodeType.setDerived_from(derivedFrom); - } - return toscaNodeType; - } - - /*private Either, ToscaError> createProxyNodeTypes(Component container) { - - Map nodeTypesMap = null; - Either, ToscaError> res = Either.left(nodeTypesMap); - - List componetInstances = container.getComponentInstances(); - - if (componetInstances == null || componetInstances.isEmpty()) - return res; - Map serviceProxyInstanceList = new HashMap<>(); - List proxyInst = componetInstances.stream().filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name())).collect(Collectors.toList()); - if(proxyInst != null && !proxyInst.isEmpty()){ - for(ComponentInstance inst: proxyInst){ - serviceProxyInstanceList.put(inst.getToscaComponentName(), inst); - } - } - - if (serviceProxyInstanceList.isEmpty()) - return res; - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreCapabilities(false); - filter.setIgnoreComponentInstances(false); - Either serviceProxyOrigin = toscaOperationFacade - .getLatestByName("serviceProxy"); - if (serviceProxyOrigin.isRight()) { - log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", - serviceProxyOrigin.right().value()); - return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); - } - Component origComponent = serviceProxyOrigin.left().value(); - - nodeTypesMap = new HashMap<>(); - for (Entry entryProxy : serviceProxyInstanceList.entrySet()) { - Component serviceComponent = null; - ComponentParametersView componentParametersView = new ComponentParametersView(); - componentParametersView.disableAll(); - componentParametersView.setIgnoreCategories(false); - Either service = toscaOperationFacade - .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView); - if (service.isRight()) { - log.debug("Failed to fetch resource with id {} for instance {}"); - } else - serviceComponent = service.left().value(); - - ToscaNodeType toscaNodeType = createProxyNodeType(origComponent, serviceComponent, entryProxy.getValue()); - nodeTypesMap.put(entryProxy.getKey(), toscaNodeType); - } - - return Either.left(nodeTypesMap); - }*/ - - private ToscaNodeType createProxyNodeType(Component origComponent, Component proxyComponent, - ComponentInstance instance) { - ToscaNodeType toscaNodeType = new ToscaNodeType(); - String derivedFrom = ((Resource) origComponent).getToscaResourceName(); - - toscaNodeType.setDerived_from(derivedFrom); - Either, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll(); - if (dataTypesEither.isRight()) { - log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value()); - } - Map dataTypes = dataTypesEither.left().value(); - Map capabilities = this.capabiltyRequirementConvertor - .convertProxyCapabilities(origComponent, proxyComponent, instance, dataTypes); - - toscaNodeType.setCapabilities(capabilities); - - return toscaNodeType; - } - - private Either convertComponentInstanceRequirements(Component component, - ComponentInstance componentInstance, List relations, - ToscaNodeTemplate nodeTypeTemplate, Component originComponent) { - - List> toscaRequirements = new ArrayList<>(); - if(!addRequirements(component, componentInstance, relations, originComponent, toscaRequirements)){ - log.debug("Failed to convert component instance requirements for the component instance {}. ", componentInstance.getName()); - return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR); - } - if (!toscaRequirements.isEmpty()) { - nodeTypeTemplate.setRequirements(toscaRequirements); - } - log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName()); - return Either.left(nodeTypeTemplate); - } - - private boolean addRequirements(Component component, ComponentInstance componentInstance, List relations, Component originComponent, - List> toscaRequirements) { - boolean result; - List filteredRelations = relations.stream().filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList()); - if(CollectionUtils.isEmpty(filteredRelations)){ - result = true; - } else { - result = !filteredRelations.stream().filter(rel -> !addRequirement(component,componentInstance, originComponent, component.getComponentInstances(), rel, toscaRequirements)).findFirst().isPresent(); - } - return result; - } - - private boolean addRequirement(Component component,ComponentInstance fromInstance, Component originComponent, List instancesList, RequirementCapabilityRelDef rel, List> toscaRequirements){ - - boolean result = true; - Map originComponents = new HashMap<>(); - Map> reqMap = originComponent.getRequirements(); - RequirementAndRelationshipPair reqAndRelationshipPair = rel.getRelationships().get(0); - Either getOriginRes = null; - Optional reqOpt = null; - Component toOriginComponent = null; - Optional cap = null; - Either buildCapNameRes = null; - Either buildReqNameRes = null; - - ComponentInstance toInstance = instancesList.stream().filter(i -> rel.getToNode().equals(i.getUniqueId())).findFirst().orElse(null); - if (toInstance == null) { - log.debug("Failed to find a relation from the node {} to the node {}", fromInstance.getName(), rel.getToNode()); - result = false; - } - if(result){ - - if(component.getComponentType().equals(ComponentTypeEnum.SERVICE)) { - reqOpt = findRequirement(reqMap, reqAndRelationshipPair); - } - else { - reqOpt = findRequirement(reqMap, reqAndRelationshipPair.getRequirementUid()); - } - if(!reqOpt.isPresent()){ - log.debug("Failed to find a requirement with uniqueId {} on a component with uniqueId {}", reqAndRelationshipPair.getRequirementUid(), originComponent.getUniqueId()); - result = false; - } - } - if(result){ - ComponentParametersView filter = new ComponentParametersView(true); - filter.setIgnoreComponentInstances(false); - filter.setIgnoreCapabilities(false); - getOriginRes = toscaOperationFacade.getToscaElement(toInstance.getComponentUid(), filter); - if(getOriginRes.isRight()){ - log.debug("Failed to build substituted name for the requirement {}. Failed to get an origin component with uniqueId {}", reqOpt.get().getName(), toInstance.getComponentUid()); - result = false; - } - } - if(result){ - toOriginComponent = getOriginRes.left().value(); - cap = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream().filter(c -> c.getName().equals(reqAndRelationshipPair.getCapability())).findFirst(); - if(!cap.isPresent()){ - log.debug("Failed to find a capability with name {} on a component with uniqueId {}", reqAndRelationshipPair.getCapability(), originComponent.getUniqueId()); - result = false; - } - } - if(result){ - buildCapNameRes = capabiltyRequirementConvertor.buildSubstitutedName(originComponents, toOriginComponent, cap.get().getPath(), reqAndRelationshipPair.getCapability()); - if(buildCapNameRes.isRight()){ - log.debug("Failed to build a substituted capability name for the capability with name {} on a component with uniqueId {}", reqAndRelationshipPair.getCapability(), originComponent.getUniqueId()); - result = false; - } - } - if(result){ - buildReqNameRes = capabiltyRequirementConvertor.buildSubstitutedName(originComponents, originComponent, reqOpt.get().getPath(), reqAndRelationshipPair.getRequirement()); - if(buildReqNameRes.isRight()){ - log.debug("Failed to build a substituted requirement name for the requirement with name {} on a component with uniqueId {}", reqAndRelationshipPair.getRequirement(), originComponent.getUniqueId()); - result = false; - } - } - if(result){ - ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement(); - Map toscaReqMap = new HashMap<>(); - toscaRequirement.setNode(toInstance.getName()); - toscaRequirement.setCapability(buildCapNameRes.left().value()); - toscaReqMap.put(buildReqNameRes.left().value(), toscaRequirement); - toscaRequirements.add(toscaReqMap); - } - return result; - } - - private Optional findRequirement(Map> reqMap, String reqId) { - for(List reqList: reqMap.values()){ - Optional reqOpt = reqList.stream().filter(r -> r.getUniqueId().equals(reqId)).findFirst(); - if(reqOpt.isPresent()){ - return reqOpt; - } - } - return Optional.empty(); - } - - private Optional findRequirement(Map> reqMap, RequirementAndRelationshipPair reqAndRelationshipPair) { - for(List reqList: reqMap.values()){ - Optional reqOpt = reqList.stream().filter(r -> - isRequirmentBelongTo(reqAndRelationshipPair, r)) - .findFirst(); - if(reqOpt.isPresent()){ - return reqOpt; - } - } - return Optional.empty(); - } - - private boolean isRequirmentBelongTo(RequirementAndRelationshipPair reqAndRelationshipPair, RequirementDefinition r) { - return StringUtils.isNotEmpty(r.getOwnerId()) && r.getOwnerId().equals(reqAndRelationshipPair.getRequirementOwnerId()) - && StringUtils.isNotEmpty(r.getName()) && r.getName().equals(reqAndRelationshipPair.getRequirement()); - } - - private Either convertCapabilities(Component component, SubstitutionMapping substitutionMappings) { - - Either result = Either.left(substitutionMappings);; - Either, ToscaError> toscaCapabilitiesRes = capabiltyRequirementConvertor - .convertSubstitutionMappingCapabilities(originComponents, component); - if(toscaCapabilitiesRes.isRight()){ - result = Either.right(toscaCapabilitiesRes.right().value()); - log.error("Failed convert capabilities for the component {}. ", component.getName()); - } else if (MapUtils.isNotEmpty(toscaCapabilitiesRes.left().value())) { - substitutionMappings.setCapabilities(toscaCapabilitiesRes.left().value()); - log.debug("Finish convert capabilities for the component {}. ", component.getName()); - } - log.debug("Finished to convert capabilities for the component {}. ", component.getName()); - return result; - } - - private Either convertCapabilities(Component component, ToscaNodeType nodeType, - Map dataTypes) { - Map toscaCapabilities = capabiltyRequirementConvertor.convertCapabilities(component, - dataTypes); - if (!toscaCapabilities.isEmpty()) { - nodeType.setCapabilities(toscaCapabilities); - } - log.debug("Finish convert Capabilities for node type"); - - return Either.left(nodeType); - } - - private static class CustomRepresenter extends Representer { - public CustomRepresenter() { - super(); - // null representer is exceptional and it is stored as an instance - // variable. - this.nullRepresenter = new RepresentNull(); - - } - - @Override - protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, - Tag customTag) { - if (propertyValue == null) { - return null; - } else { - // skip not relevant for Tosca property - if ("dependencies".equals(property.getName())) { - return null; - } - NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag); - - return "_defaultp_".equals(property.getName()) - ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode; - } - } - - @Override - protected MappingNode representJavaBean(Set properties, Object javaBean) { - // remove the bean type from the output yaml (!! ...) - if (!classTags.containsKey(javaBean.getClass())) - addClassTag(javaBean.getClass(), Tag.MAP); - - return super.representJavaBean(properties, javaBean); - } - - private class RepresentNull implements Represent { - public Node representData(Object data) { - // possible values are here http://yaml.org/type/null.html - return representScalar(Tag.NULL, ""); - } - } - } - - private static class UnsortedPropertyUtils extends PropertyUtils { - @Override - protected Set createPropertySet(Class type, BeanAccess bAccess) - throws IntrospectionException { - Collection fields = getPropertiesMap(type, BeanAccess.FIELD).values(); - return new LinkedHashSet<>(fields); - } - } + public static final String ASSET_TOSCA_TEMPLATE = "assettoscatemplate"; + private static final Logger log = Logger.getLogger(ToscaExportHandler.class); + private static final String INVARIANT_UUID = "invariantUUID"; + private static final String TOSCA_VERSION = "tosca_simple_yaml_1_3"; + private static final String SERVICE_NODE_TYPE_PREFIX = "org.openecomp.service."; + private static final String IMPORTS_FILE_KEY = "file"; + private static final String TOSCA_INTERFACE_NAME = "-interface.yml"; + private static final String FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION = "convertToToscaTemplate - failed to get Default Imports section from configuration"; + private static final String NOT_SUPPORTED_COMPONENT_TYPE = "Not supported component type {}"; + private static final String NATIVE_ROOT = "tosca.nodes.Root"; + private static final List EXCLUDED_CATEGORY_SPECIFIC_METADATA = List + .of("Service Function", "Service Role", "Naming Policy", "Service Type"); + private static final YamlUtil yamlUtil = new YamlUtil(); + private final ApplicationDataTypeCache applicationDataTypeCache; + private final ToscaOperationFacade toscaOperationFacade; + private final CapabilityRequirementConverter capabilityRequirementConverter; + private final PolicyExportParser policyExportParser; + private final GroupExportParser groupExportParser; + private final PropertyConvertor propertyConvertor; + private final AttributeConverter attributeConverter; + private final InputConverter inputConverter; + private final OutputConverter outputConverter; + private final InterfaceLifecycleOperation interfaceLifecycleOperation; + private final InterfacesOperationsConverter interfacesOperationsConverter; + private final ModelOperation modelOperation; + + @Autowired + public ToscaExportHandler(final ApplicationDataTypeCache applicationDataTypeCache, + final ToscaOperationFacade toscaOperationFacade, + final CapabilityRequirementConverter capabilityRequirementConverter, + final PolicyExportParser policyExportParser, + final GroupExportParser groupExportParser, + final PropertyConvertor propertyConvertor, + final AttributeConverter attributeConverter, + final InputConverter inputConverter, + final OutputConverter outputConverter, + final InterfaceLifecycleOperation interfaceLifecycleOperation, + final InterfacesOperationsConverter interfacesOperationsConverter, + final ModelOperation modelOperation) { + this.applicationDataTypeCache = applicationDataTypeCache; + this.toscaOperationFacade = toscaOperationFacade; + this.capabilityRequirementConverter = capabilityRequirementConverter; + this.policyExportParser = policyExportParser; + this.groupExportParser = groupExportParser; + this.propertyConvertor = propertyConvertor; + this.attributeConverter = attributeConverter; + this.inputConverter = inputConverter; + this.outputConverter = outputConverter; + this.interfaceLifecycleOperation = interfaceLifecycleOperation; + this.interfacesOperationsConverter = interfacesOperationsConverter; + this.modelOperation = modelOperation; + } + + public static String getInterfaceFilename(String artifactName) { + return artifactName.substring(0, artifactName.lastIndexOf('.')) + TOSCA_INTERFACE_NAME; + } + + private static void removeOperationImplementationForProxyNodeType(Map proxyComponentInterfaces) { + if (MapUtils.isEmpty(proxyComponentInterfaces)) { + return; + } + proxyComponentInterfaces.values().stream().map(InterfaceDataDefinition::getOperations).filter(MapUtils::isNotEmpty) + .forEach(operations -> operations.values().forEach(operation -> operation.setImplementation(null))); + } + + public Either exportComponent(Component component) { + return convertToToscaTemplate(component).left().map(this::createToscaRepresentation); + } + + public Either exportComponentInterface(final Component component, final boolean isAssociatedComponent) { + final List>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel())); + if (CollectionUtils.isEmpty(imports)) { + log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); + return Either.right(ToscaError.GENERAL_ERROR); + } + List> dependencies = new ArrayList<>(); + if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType() + .startsWith("org.openecomp.resource.abstract.nodes.")) { + final Either baseType = toscaOperationFacade + .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(), component.getModel()); + if (baseType.isLeft() && baseType.left().value() != null) { + addDependencies(imports, dependencies, baseType.left().value()); + } else { + log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType()); + } + } + + String toscaVersion = null; + if (component instanceof Resource) { + toscaVersion = ((Resource) component).getToscaVersion(); + } + ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION); + toscaTemplate.setImports(imports); + final Map nodeTypes = new HashMap<>(); + final Either toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes, + isAssociatedComponent); + if (toscaTemplateRes.isRight()) { + return Either.right(toscaTemplateRes.right().value()); + } + toscaTemplate = toscaTemplateRes.left().value(); + toscaTemplate.setDependencies(dependencies); + ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate); + return Either.left(toscaRepresentation); + } + + public ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) { + CustomRepresenter representer = new CustomRepresenter(); + DumperOptions options = new DumperOptions(); + options.setAllowReadOnlyProperties(false); + options.setPrettyFlow(true); + options.setDefaultFlowStyle(FlowStyle.FLOW); + options.setCanonical(false); + representer.addClassTag(toscaTemplate.getClass(), Tag.MAP); + representer.setPropertyUtils(new UnsortedPropertyUtils()); + Yaml yaml = new Yaml(representer, options); + String yamlAsString = yaml.dumpAsMap(toscaTemplate); + StringBuilder sb = new StringBuilder(); + sb.append(getConfiguration().getHeatEnvArtifactHeader()); + sb.append(yamlAsString); + sb.append(getConfiguration().getHeatEnvArtifactFooter()); + return ToscaRepresentation.make(sb.toString().getBytes(), toscaTemplate); + } + + public Either getDependencies(Component component) { + ToscaTemplate toscaTemplate = new ToscaTemplate(null); + Either>, ToscaError> fillImports = fillImports(component, toscaTemplate); + if (fillImports.isRight()) { + return Either.right(fillImports.right().value()); + } + return Either.left(fillImports.left().value().left); + } + + public Either convertToToscaTemplate(final Component component) { + final List>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel()); + if (CollectionUtils.isEmpty(defaultToscaImportConfig)) { + log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); + return Either.right(ToscaError.GENERAL_ERROR); + } + log.trace("start tosca export for {}", component.getUniqueId()); + String toscaVersion = null; + if (component instanceof Resource) { + toscaVersion = ((Resource) component).getToscaVersion(); + } + final ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION); + toscaTemplate.setMetadata(convertMetadata(component)); + toscaTemplate.setImports(new ArrayList<>(defaultToscaImportConfig)); + final Map nodeTypes = new HashMap<>(); + if (ModelConverter.isAtomicComponent(component)) { + log.trace("convert component as node type"); + return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes); + } else { + log.trace("convert component as topology template"); + return convertToscaTemplate(component, toscaTemplate); + } + } + + public List>> getDefaultToscaImports(final String modelId) { + if (modelId == null) { + return getDefaultToscaImportConfig(); + } + + final List allModelImports = modelOperation.findAllModelImports(modelId, true); + final List>> importList = new ArrayList<>(); + final Set addedPathList = new HashSet<>(); + for (final ToscaImportByModel toscaImportByModel : allModelImports) { + var importPath = Path.of(toscaImportByModel.getFullPath()); + if (addedPathList.contains(importPath)) { + importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId()); + } + final String fileName = FilenameUtils.getBaseName(importPath.toString()); + importList.add(Map.of(fileName, Map.of("file", importPath.toString()))); + addedPathList.add(importPath); + } + return importList; + } + + private Either convertToscaTemplate(Component component, ToscaTemplate toscaNode) { + Either>, ToscaError> importsRes = fillImports(component, toscaNode); + if (importsRes.isRight()) { + return Either.right(importsRes.right().value()); + } + toscaNode = importsRes.left().value().left; + Map componentCache = importsRes.left().value().right; + Either, ToscaError> nodeTypesMapEither = createProxyNodeTypes(componentCache, component); + if (nodeTypesMapEither.isRight()) { + log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", nodeTypesMapEither.right().value()); + return Either.right(nodeTypesMapEither.right().value()); + } + Map nodeTypesMap = nodeTypesMapEither.left().value(); + if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) { + toscaNode.setNode_types(nodeTypesMap); + } + createServiceSubstitutionNodeTypes(componentCache, component, toscaNode); + Either, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component); + if (proxyInterfaceTypesEither.isRight()) { + log.debug("Failed to populate service proxy local interface types in tosca, error {}", nodeTypesMapEither.right().value()); + return Either.right(proxyInterfaceTypesEither.right().value()); + } + Map proxyInterfaceTypes = proxyInterfaceTypesEither.left().value(); + if (MapUtils.isNotEmpty(proxyInterfaceTypes)) { + toscaNode.setInterface_types(proxyInterfaceTypes); + } + Either, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel()); + if (dataTypesEither.isRight()) { + log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value()); + return Either.right(ToscaError.GENERAL_ERROR); + } + Map dataTypes = dataTypesEither.left().value(); + ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate(); + List inputDef = component.getInputs(); + Map inputs = inputConverter.convertInputs(inputDef, dataTypes); + if (!inputs.isEmpty()) { + topologyTemplate.setInputs(inputs); + } + final Map outputs; + try { + outputs = outputConverter.convert(component.getOutputs(), dataTypes); + } catch (final ToscaConversionException e) { + log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(), + "Could not parse component '{}' outputs. Component unique id '{}'.", component.getName(), component.getUniqueId(), e); + return Either.right(ToscaError.GENERAL_ERROR); + } + if (!outputs.isEmpty()) { + topologyTemplate.setOutputs(outputs); + } + if (CollectionUtils.isNotEmpty(component.getComponentInstances())) { + final Either, ToscaError> nodeTemplates = + convertNodeTemplates(component, componentCache, dataTypes, topologyTemplate); + if (nodeTemplates.isRight()) { + return Either.right(nodeTemplates.right().value()); + } + log.debug("node templates converted"); + topologyTemplate.setNode_templates(nodeTemplates.left().value()); + } + final Map relationshipTemplatesMap = new ToscaExportRelationshipTemplatesHandler() + .createFrom(topologyTemplate.getNode_templates()); + if (!relationshipTemplatesMap.isEmpty()) { + topologyTemplate.setRelationshipTemplates(relationshipTemplatesMap); + } + addGroupsToTopologyTemplate(component, topologyTemplate); + try { + addPoliciesToTopologyTemplate(component, topologyTemplate); + } catch (SdcResourceNotFoundException e) { + log.debug("Fail to add policies to topology template:", e); + return Either.right(ToscaError.GENERAL_ERROR); + } + try { + createSubstitutionMapping(component, componentCache).ifPresent(topologyTemplate::setSubstitution_mappings); + } catch (final ToscaExportException e) { + log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ToscaExportHandler.class.getName(), e.getMessage()); + return Either.right(e.getToscaError()); + } + if (!topologyTemplate.isEmpty()) { + toscaNode.setTopology_template(topologyTemplate); + } + return Either.left(toscaNode); + } + + private Either createComponentToscaName(final Component component) { + switch (component.getComponentType()) { + case RESOURCE: + final ResourceMetadataDataDefinition resourceMetadata = + (ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition(); + return Either.left(resourceMetadata.getToscaResourceName()); + case SERVICE: + return Either.left(SERVICE_NODE_TYPE_PREFIX + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName()); + default: + log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType()); + return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); + } + } + + private Optional createSubstitutionMapping(final Component component, + final Map componentCache) throws ToscaExportException { + if (component instanceof Service && !((Service) component).isSubstituteCandidate()) { + return Optional.empty(); + } + + final Either toscaResourceNameEither = createComponentToscaName(component); + if (toscaResourceNameEither.isRight()) { + throw new ToscaExportException("Could not create component TOSCA name", toscaResourceNameEither.right().value()); + } + final String toscaResourceName = toscaResourceNameEither.left().value(); + + final SubstitutionMapping substitutionMapping = new SubstitutionMapping(); + substitutionMapping.setNode_type(toscaResourceName); + convertSubstitutionMappingFilter(component).ifPresent(substitutionMapping::setSubstitution_filter); + + final Either, ToscaError> capabilitiesEither = convertSubstitutionMappingCapabilities(component, componentCache); + if (capabilitiesEither.isRight()) { + throw new ToscaExportException("Could not convert substitution mapping capabilities", capabilitiesEither.right().value()); + } + final Map capabilityMap = capabilitiesEither.left().value(); + if (!capabilityMap.isEmpty()) { + substitutionMapping.setCapabilities(capabilityMap); + } + + final Either, ToscaError> requirements = + capabilityRequirementConverter.convertSubstitutionMappingRequirements(component, componentCache); + if (requirements.isRight()) { + throw new ToscaExportException("Could not convert substitution mapping requirements", requirements.right().value()); + } + final Map requirementMap = requirements.left().value(); + if (!requirementMap.isEmpty()) { + substitutionMapping.setRequirements(requirementMap); + } + + final Map propertyMappingMap = buildSubstitutionMappingPropertyMapping(component); + if (!propertyMappingMap.isEmpty()) { + substitutionMapping.setProperties(propertyMappingMap); + } + + final Map attributesMappingMap = buildSubstitutionMappingAttributesMapping(component); + if (!attributesMappingMap.isEmpty()) { + substitutionMapping.setAttributes(attributesMappingMap); + } + + return Optional.of(substitutionMapping); + } + + private Optional convertSubstitutionMappingFilter(final Component component) { + if (component.getSubstitutionFilter() == null || (component.getSubstitutionFilter().getProperties()).getListToscaDataDefinition() == null) { + return Optional.empty(); + } + + return Optional.ofNullable(convertToSubstitutionFilterComponent(component.getSubstitutionFilter())); + } + + private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) { + Map groups = groupExportParser.getGroups(component); + if (groups != null) { + topologyTemplate.addGroups(groups); + } + } + + private void addPoliciesToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) throws SdcResourceNotFoundException { + Map policies = policyExportParser.getPolicies(component); + if (policies != null) { + topologyTemplate.addPolicies(policies); + } + } + + private Map convertMetadata(Component component) { + return convertMetadata(component, false, null); + } + + private Map convertMetadata(Component component, boolean isInstance, ComponentInstance componentInstance) { + Map toscaMetadata = new LinkedHashMap<>(); + toscaMetadata.put(convertMetadataKey(JsonPresentationFields.INVARIANT_UUID), component.getInvariantUUID()); + toscaMetadata.put(JsonPresentationFields.UUID.getPresentation(), component.getUUID()); + toscaMetadata + .put(JsonPresentationFields.NAME.getPresentation(), component.getComponentMetadataDefinition().getMetadataDataDefinition().getName()); + toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), component.getDescription()); + List categories = component.getCategories(); + CategoryDefinition categoryDefinition = categories.get(0); + toscaMetadata.put(JsonPresentationFields.CATEGORY.getPresentation(), categoryDefinition.getName()); + if (isInstance) { + toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), component.getVersion()); + toscaMetadata.put(JsonPresentationFields.CUSTOMIZATION_UUID.getPresentation(), componentInstance.getCustomizationUUID()); + if (componentInstance.getSourceModelInvariant() != null && !componentInstance.getSourceModelInvariant().isEmpty()) { + toscaMetadata.put(JsonPresentationFields.VERSION.getPresentation(), componentInstance.getComponentVersion()); + toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_INVARIANT.getPresentation(), componentInstance.getSourceModelInvariant()); + toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_UUID.getPresentation(), componentInstance.getSourceModelUuid()); + toscaMetadata.put(JsonPresentationFields.CI_SOURCE_MODEL_NAME.getPresentation(), componentInstance.getSourceModelName()); + if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) { + toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(), + componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue()); + } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) { + toscaMetadata.put(JsonPresentationFields.NAME.getPresentation(), + componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue()); + } + toscaMetadata.put(JsonPresentationFields.DESCRIPTION.getPresentation(), componentInstance.getDescription()); + } + } + switch (component.getComponentType()) { + case RESOURCE: + Resource resource = (Resource) component; + if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy + || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) { + toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), componentInstance.getOriginType().getDisplayValue()); + } else { + toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), resource.getResourceType().name()); + } + toscaMetadata.put(JsonPresentationFields.SUB_CATEGORY.getPresentation(), categoryDefinition.getSubcategories().get(0).getName()); + toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR.getPresentation(), resource.getVendorName()); + toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_RELEASE.getPresentation(), resource.getVendorRelease()); + toscaMetadata.put(JsonPresentationFields.RESOURCE_VENDOR_MODEL_NUMBER.getPresentation(), resource.getResourceVendorModelNumber()); + break; + case SERVICE: + Service service = (Service) component; + toscaMetadata.put(JsonPresentationFields.TYPE.getPresentation(), component.getComponentType().getValue()); + toscaMetadata.put(JsonPresentationFields.SERVICE_TYPE.getPresentation(), service.getServiceType()); + toscaMetadata.put(JsonPresentationFields.SERVICE_ROLE.getPresentation(), service.getServiceRole()); + toscaMetadata.put(JsonPresentationFields.SERVICE_FUNCTION.getPresentation(), service.getServiceFunction()); + toscaMetadata.put(JsonPresentationFields.ENVIRONMENT_CONTEXT.getPresentation(), service.getEnvironmentContext()); + toscaMetadata.put(JsonPresentationFields.INSTANTIATION_TYPE.getPresentation(), + service.getEnvironmentContext() == null ? StringUtils.EMPTY : service.getInstantiationType()); + if (!isInstance) { + // DE268546 + toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString()); + toscaMetadata.put(JsonPresentationFields.ECOMP_GENERATED_NAMING.getPresentation(), service.isEcompGeneratedNaming().toString()); + toscaMetadata.put(JsonPresentationFields.NAMING_POLICY.getPresentation(), service.getNamingPolicy()); + } + break; + default: + log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType()); + } + for (final String key : component.getCategorySpecificMetadata().keySet()) { + if (!EXCLUDED_CATEGORY_SPECIFIC_METADATA.contains(key)) { + toscaMetadata.put(key, component.getCategorySpecificMetadata().get(key)); + } + } + return toscaMetadata; + } + + private String convertMetadataKey(JsonPresentationFields jsonPresentationField) { + if (JsonPresentationFields.INVARIANT_UUID.equals(jsonPresentationField)) { + return INVARIANT_UUID; + } + return jsonPresentationField.getPresentation(); + } + + private Either>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) { + final List>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel()); + if (CollectionUtils.isEmpty(defaultToscaImportConfig)) { + log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION); + return Either.right(ToscaError.GENERAL_ERROR); + } + Map componentCache = new HashMap<>(); + if (!ModelConverter.isAtomicComponent(component)) { + final List>> additionalImports = + toscaTemplate.getImports() == null ? new ArrayList<>(defaultToscaImportConfig) : new ArrayList<>(toscaTemplate.getImports()); + List> dependencies = new ArrayList<>(); + Map toscaArtifacts = component.getToscaArtifacts(); + final Map> substituteTypeImportEntry = generateComponentSubstituteTypeImport(component, toscaArtifacts); + if (!substituteTypeImportEntry.isEmpty()) { + additionalImports.add(substituteTypeImportEntry); + } + List componentInstances = component.getComponentInstances(); + if (componentInstances != null && !componentInstances.isEmpty()) { + componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci)); + } + toscaTemplate.setDependencies(dependencies); + toscaTemplate.setImports(additionalImports); + } else { + log.debug("currently imports supported for VF and service only"); + } + return Either.left(new ImmutablePair<>(toscaTemplate, componentCache)); + } + + private Map> generateComponentSubstituteTypeImport(final Component component, + final Map toscaArtifacts) { + + if (component instanceof Service && !((Service) component).isSubstituteCandidate()) { + return Collections.emptyMap(); + } + if (MapUtils.isEmpty(toscaArtifacts)) { + return Collections.emptyMap(); + } + final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE); + if (artifactDefinition == null) { + return Collections.emptyMap(); + } + final var importEntryName = component.getComponentType().toString().toLowerCase() + "-" + component.getName() + "-interface"; + return Map.of(importEntryName, + Map.of(IMPORTS_FILE_KEY, getInterfaceFilename(artifactDefinition.getArtifactName())) + ); + } + + private List>> getDefaultToscaImportConfig() { + return getConfiguration().getDefaultImports(); + } + + private void createDependency(final Map componentCache, final List>> imports, + final List> dependencies, final ComponentInstance componentInstance) { + log.debug("createDependency componentCache {}", componentCache); + Component componentRI = componentCache.get(componentInstance.getComponentUid()); + if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) { + // all resource must be only once! + final Either resource = toscaOperationFacade.getToscaFullElement(componentInstance.getComponentUid()); + if ((resource.isRight()) && (log.isDebugEnabled())) { + log.debug("Failed to fetch resource with id {} for instance {}", componentInstance.getComponentUid(), + componentInstance.getUniqueId()); + return; + } + final Component fetchedComponent = resource.left().value(); + componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent); + addDependencies(imports, dependencies, componentRI); + } + } + + /** + * Sets a componentCache from the given component/resource. + */ + private Component setComponentCache(final Map componentCache, final ComponentInstance componentInstance, + final Component fetchedComponent) { + componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent); + if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy + || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) { + final Either sourceService = toscaOperationFacade + .getToscaFullElement(componentInstance.getSourceModelUid()); + if (sourceService.isRight() && (log.isDebugEnabled())) { + log.debug("Failed to fetch source service with id {} for proxy {}", componentInstance.getSourceModelUid(), + componentInstance.getUniqueId()); + } + final Component fetchedSource = sourceService.left().value(); + componentCache.put(fetchedSource.getUniqueId(), fetchedSource); + return fetchedSource; + } + return fetchedComponent; + } + + /** + * Retrieves all derived_from nodes and stores it in a predictable order. + */ + private void addDependencies(final List>> imports, final List> dependencies, + final Component fetchedComponent) { + final Set componentsList = new LinkedHashSet<>(); + if (fetchedComponent instanceof Resource) { + log.debug("fetchedComponent is a resource {}", fetchedComponent); + final Optional> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList); + if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) { + derivedFromMapOfIdToName.get().entrySet().forEach(entry -> { + log.debug("Started entry.getValue() : {}", entry.getValue()); + if (!NATIVE_ROOT.equals(entry.getValue())) { + Either resourcefetched = toscaOperationFacade.getToscaElement(entry.getKey()); + if (resourcefetched != null && resourcefetched.isLeft()) { + componentsList.add(resourcefetched.left().value()); + } + } + }); + setImports(imports, dependencies, componentsList); + } else { + setImports(imports, dependencies, fetchedComponent); + } + } + } + + /** + * Returns all derived_from nodes found. + */ + private Optional> getDerivedFromMapOfIdToName(final Component fetchedComponent, final Set componentsList) { + final Resource parentResource = (Resource) fetchedComponent; + Map derivedFromMapOfIdToName = new HashMap<>(); + if (CollectionUtils.isNotEmpty(parentResource.getComponentInstances())) { + componentsList.add(fetchedComponent); + for (final ComponentInstance componentInstance : parentResource.getComponentInstances()) { + final Either resourcefetched = toscaOperationFacade + .getToscaElement(componentInstance.getComponentUid()); + if (resourcefetched != null && resourcefetched.isLeft()) { + final Map derivedWithId = resourcefetched.left().value().getDerivedFromMapOfIdToName(); + if (MapUtils.isNotEmpty(derivedWithId)) { + derivedFromMapOfIdToName.putAll(derivedWithId); + } + } + } + } else { + derivedFromMapOfIdToName = parentResource.getDerivedFromMapOfIdToName(); + } + log.debug("Started derivedFromMapOfIdToName: {}", derivedFromMapOfIdToName); + return Optional.ofNullable(derivedFromMapOfIdToName); + } + + /** + * Creates a resource map and adds it to the import list. + */ + private void setImports(final List>> imports, final List> dependencies, + final Set componentsList) { + componentsList.forEach(component -> setImports(imports, dependencies, component)); + } + + private void setImports(final List>> imports, final List> dependencies, + final Component component) { + final Map toscaArtifacts = component.getToscaArtifacts(); + final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ASSET_TOSCA_TEMPLATE); + if (artifactDefinition != null) { + final Map files = new HashMap<>(); + final String artifactName = artifactDefinition.getArtifactName(); + files.put(IMPORTS_FILE_KEY, artifactName); + final StringBuilder keyNameBuilder = new StringBuilder(); + keyNameBuilder.append(component.getComponentType().toString().toLowerCase()); + keyNameBuilder.append("-"); + keyNameBuilder.append(component.getName()); + addImports(imports, keyNameBuilder, files); + dependencies.add(new ImmutableTriple<>(artifactName, artifactDefinition.getEsId(), component)); + if (!ModelConverter.isAtomicComponent(component)) { + final Map interfaceFiles = new HashMap<>(); + interfaceFiles.put(IMPORTS_FILE_KEY, getInterfaceFilename(artifactName)); + keyNameBuilder.append("-interface"); + addImports(imports, keyNameBuilder, interfaceFiles); + } + } + } + + /** + * Adds the found resource to the import definition list. + */ + private void addImports(final List>> imports, final StringBuilder keyNameBuilder, + final Map files) { + final String mapKey = keyNameBuilder.toString(); + if (imports.stream().allMatch(stringMapMap -> stringMapMap.get(mapKey) == null)) { + final Map> importsListMember = new HashMap<>(); + importsListMember.put(keyNameBuilder.toString(), files); + imports.add(importsListMember); + } + } + + private Either convertNodeType(Map componentsCache, Component component, ToscaTemplate toscaNode, + Map nodeTypes) { + return convertInterfaceNodeType(componentsCache, component, toscaNode, nodeTypes, false); + } + + public Either convertInterfaceNodeType(Map componentsCache, Component component, + ToscaTemplate toscaNode, Map nodeTypes, + boolean isAssociatedComponent) { + log.debug("start convert node type for {}", component.getUniqueId()); + ToscaNodeType toscaNodeType = createNodeType(component); + Either, StorageOperationStatus> lifecycleTypeEither = interfaceLifecycleOperation + .getAllInterfaceLifecycleTypes(component.getModel()); + if (lifecycleTypeEither.isRight() && !StorageOperationStatus.NOT_FOUND.equals(lifecycleTypeEither.right().value())) { + log.debug("Failed to fetch all interface types :", lifecycleTypeEither.right().value()); + return Either.right(ToscaError.GENERAL_ERROR); + } + if (lifecycleTypeEither.isLeft()) { + List allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream().map(InterfaceDataDefinition::getType) + .collect(Collectors.toList()); + toscaNode.setInterface_types(addInterfaceTypeElement(component, allGlobalInterfaceTypes)); + } + Either, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(component.getModel()); + if (dataTypesEither.isRight()) { + log.debug("Failed to fetch all data types :", dataTypesEither.right().value()); + return Either.right(ToscaError.GENERAL_ERROR); + } + Map dataTypes = dataTypesEither.left().value(); + List inputDef = component.getInputs(); + Map mergedProperties = new HashMap<>(); + interfacesOperationsConverter.addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent); + addInputsToProperties(dataTypes, inputDef, mergedProperties); + final Map toscaAttributeMap; + toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes); + if (!toscaAttributeMap.isEmpty()) { + toscaNodeType.setAttributes(toscaAttributeMap); + } + if (CollectionUtils.isNotEmpty(component.getProperties())) { + List properties = component.getProperties(); + Map convertedProperties = properties.stream() + .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, component.getInputs())).collect(Collectors + .toMap(PropertyDataDefinition::getName, + property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY))); + // merge component properties and inputs properties + mergedProperties.putAll(convertedProperties); + } + if (MapUtils.isNotEmpty(mergedProperties)) { + toscaNodeType.setProperties(mergedProperties); + } + /* convert private data_types */ + List privateDataTypes = component.getDataTypes(); + if (CollectionUtils.isNotEmpty(privateDataTypes)) { + Map toscaDataTypeMap = new HashMap<>(); + for (DataTypeDefinition dataType : privateDataTypes) { + log.debug("Emitting private data type: component.name={} dataType.name={}", + component.getNormalizedName(), dataType.getName()); + ToscaDataType toscaDataType = new ToscaDataType(); + toscaDataType.setDerived_from(dataType.getDerivedFromName()); + toscaDataType.setDescription(dataType.getDescription()); + toscaDataType.setVersion(dataType.getVersion()); + if (CollectionUtils.isNotEmpty(dataType.getProperties())) { + toscaDataType.setProperties(dataType.getProperties().stream() + .collect(Collectors.toMap( + PropertyDataDefinition::getName, + s -> propertyConvertor.convertProperty(dataTypes, s, PropertyType.PROPERTY), + (toscaPropertyTobeValidated, toscaProperty) -> validateToscaProperty(privateDataTypes, toscaPropertyTobeValidated, toscaProperty) + ))); + } + toscaDataTypeMap.put(dataType.getName(), toscaDataType); + } + toscaNode.setData_types(toscaDataTypeMap); + } + + // Extracted to method for code reuse + return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes); + } + + private ToscaProperty validateToscaProperty(final List privateDataTypes, final ToscaProperty toscaPropertyTobeValidated, + final ToscaProperty toscaProperty) { + final Optional match = privateDataTypes.stream() + .filter(dataType -> dataType.getName().equals(toscaPropertyTobeValidated.getType())).findFirst(); + return match.isPresent() ? toscaPropertyTobeValidated : toscaProperty; + } + + private Map convertToToscaAttributes(final List attributeList, + final Map dataTypes) { + if (CollectionUtils.isEmpty(attributeList)) { + return Collections.emptyMap(); + } + final AttributeConverter converter = new AttributeConverter(dataTypes); + final Map toscaAttributeMap = new HashMap<>(); + for (final AttributeDefinition attributeDefinition : attributeList) { + toscaAttributeMap.put(attributeDefinition.getName(), converter.convert(attributeDefinition)); + } + return toscaAttributeMap; + } + + private Either convertReqCapAndTypeName(Map componentsCache, + Component component, ToscaTemplate toscaNode, + Map nodeTypes, + ToscaNodeType toscaNodeType, + Map dataTypes) { + Either capabilities = convertCapabilities(componentsCache, component, toscaNodeType, + dataTypes); + if (capabilities.isRight()) { + return Either.right(capabilities.right().value()); + } + toscaNodeType = capabilities.left().value(); + log.debug("Capabilities converted for {}", component.getUniqueId()); + + Either requirements = capabilityRequirementConverter + .convertRequirements(componentsCache, component, toscaNodeType); + if (requirements.isRight()) { + return Either.right(requirements.right().value()); + } + toscaNodeType = requirements.left().value(); + log.debug("Requirements converted for {}", component.getUniqueId()); + + String toscaResourceName; + switch (component.getComponentType()) { + case RESOURCE: + toscaResourceName = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition() + .getMetadataDataDefinition()).getToscaResourceName(); + break; + case SERVICE: + toscaResourceName = SERVICE_NODE_TYPE_PREFIX + + component.getComponentMetadataDefinition().getMetadataDataDefinition().getSystemName(); + break; + default: + log.debug(NOT_SUPPORTED_COMPONENT_TYPE, component.getComponentType()); + return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); + } + + nodeTypes.put(toscaResourceName, toscaNodeType); + toscaNode.setNode_types(nodeTypes); + log.debug("finish convert node type for {}", component.getUniqueId()); + return Either.left(toscaNode); + } + + private Either, ToscaError> convertNodeTemplates(final Component component, + final Map componentCache, + final Map dataTypes, + final ToscaTopolgyTemplate topologyTemplate) { + + final Map> componentInstancesProperties = component.getComponentInstancesProperties(); + final Map> componentInstancesAttributes = component.getComponentInstancesAttributes(); + final Map> componentInstancesInputs = component.getComponentInstancesInputs(); + final Map> componentInstanceInterfaces = component.getComponentInstancesInterfaces(); + final List componentInstancesRelations = component.getComponentInstancesRelations(); + + Either, ToscaError> convertNodeTemplatesRes = null; + log.debug("start convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType()); + final Map nodeTemplates = new HashMap<>(); + + Map groupsMap = null; + for (final ComponentInstance componentInstance : component.getComponentInstances()) { + ToscaNodeTemplate nodeTemplate = new ToscaNodeTemplate(); + if (MapUtils.isNotEmpty(componentInstance.getToscaArtifacts())) { + nodeTemplate.setArtifacts(convertToNodeTemplateArtifacts(componentInstance.getToscaArtifacts())); + } + nodeTemplate.setType(componentInstance.getToscaComponentName()); + nodeTemplate.setDirectives(componentInstance.getDirectives()); + nodeTemplate.setNode_filter(convertToNodeTemplateNodeFilterComponent(componentInstance.getNodeFilter())); + + final Either originComponentRes = capabilityRequirementConverter + .getOriginComponent(componentCache, componentInstance); + if (originComponentRes.isRight()) { + convertNodeTemplatesRes = Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR); + break; + } + final Either requirements = convertComponentInstanceRequirements(component, componentInstance, + componentInstancesRelations, nodeTemplate, originComponentRes.left().value(), componentCache); + if (requirements.isRight()) { + convertNodeTemplatesRes = Either.right(requirements.right().value()); + break; + } + final String instanceUniqueId = componentInstance.getUniqueId(); + log.debug("Component instance Requirements converted for instance {}", instanceUniqueId); + + nodeTemplate = requirements.left().value(); + + final Component originalComponent = componentCache.get(componentInstance.getActualComponentUid()); + + if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) { + final Component componentOfProxy = componentCache.get(componentInstance.getComponentUid()); + nodeTemplate.setMetadata(convertMetadata(componentOfProxy, true, componentInstance)); + } else { + nodeTemplate.setMetadata(convertMetadata(originalComponent, true, componentInstance)); + } + + final Either capabilities = + capabilityRequirementConverter.convertComponentInstanceCapabilities(componentInstance, dataTypes, nodeTemplate); + if (capabilities.isRight()) { + convertNodeTemplatesRes = Either.right(capabilities.right().value()); + break; + } + log.debug("Component instance Capabilities converted for instance {}", instanceUniqueId); + + nodeTemplate = capabilities.left().value(); + final Map props = new HashMap<>(); + final Map attribs = new HashMap<>(); + + if (originalComponent.getComponentType() == ComponentTypeEnum.RESOURCE) { + // Adds the properties of parent component to map + addPropertiesOfParentComponent(dataTypes, originalComponent, props); + addAttributesOfParentComponent(originalComponent, attribs); + } + + if (null != componentInstancesProperties && componentInstancesProperties.containsKey(instanceUniqueId)) { + addPropertiesOfComponentInstance(componentInstancesProperties, dataTypes, instanceUniqueId, props); + } + if (null != componentInstancesAttributes && componentInstancesAttributes.containsKey(instanceUniqueId)) { + addAttributesOfComponentInstance(componentInstancesAttributes, instanceUniqueId, attribs); + } + + if (componentInstancesInputs != null + && componentInstancesInputs.containsKey(instanceUniqueId) + && !isComponentOfTypeServiceProxy(componentInstance)) { + //For service proxy the inputs are already handled under instance properties above + addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId, props); + } + + //M3[00001] - NODE TEMPLATE INTERFACES - START + handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate, instanceUniqueId, component); + //M3[00001] - NODE TEMPLATE INTERFACES - END + if (MapUtils.isNotEmpty(props)) { + nodeTemplate.setProperties(props); + } + if (MapUtils.isNotEmpty(attribs)) { + nodeTemplate.setAttributes(attribs); + } + + final List groupInstances = componentInstance.getGroupInstances(); + if (CollectionUtils.isNotEmpty(groupInstances)) { + if (groupsMap == null) { + groupsMap = new HashMap<>(); + } + for (final GroupInstance groupInst : groupInstances) { + if (CollectionUtils.isNotEmpty(groupInst.getArtifacts())) { + groupsMap.put(groupInst.getName(), groupExportParser.getToscaGroupTemplate(groupInst, componentInstance.getInvariantName())); + } + } + } + + nodeTemplates.put(componentInstance.getName(), nodeTemplate); + } + if (groupsMap != null) { + log.debug("instance groups added"); + topologyTemplate.addGroups(groupsMap); + } + if (component.getComponentType() == ComponentTypeEnum.SERVICE && isNotEmpty( + ((Service) component).getForwardingPaths())) { + log.debug("Starting converting paths for component {}, name {}", component.getUniqueId(), component.getName()); + ForwardingPathToscaUtil + .addForwardingPaths((Service) component, nodeTemplates, capabilityRequirementConverter, componentCache, toscaOperationFacade); + log.debug("Finished converting paths for component {}, name {}", component.getUniqueId(), component.getName()); + } + if (convertNodeTemplatesRes == null) { + convertNodeTemplatesRes = Either.left(nodeTemplates); + } + log.debug("finish convert topology template for {} for type {}", component.getUniqueId(), component.getComponentType()); + return convertNodeTemplatesRes; + } + + private void handleInstanceInterfaces( + Map> componentInstanceInterfaces, + ComponentInstance componentInstance, Map dataTypes, ToscaNodeTemplate nodeTemplate, + String instanceUniqueId, + Component parentComponent) { + + if (MapUtils.isEmpty(componentInstanceInterfaces) + || !componentInstanceInterfaces.containsKey(instanceUniqueId)) { + nodeTemplate.setInterfaces(null); + return; + } + + final List currServiceInterfaces = + componentInstanceInterfaces.get(instanceUniqueId); + + final Map tmpInterfaces = new HashMap<>(); + currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface + .getUniqueId(), instInterface)); + + final Map interfaceMap = interfacesOperationsConverter + .getInterfacesMap(parentComponent, componentInstance, tmpInterfaces, dataTypes, isComponentOfTypeServiceProxy(componentInstance), + isComponentOfTypeServiceProxy(componentInstance)); + + interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap); + nodeTemplate.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap); + } + + private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) { + return Objects.nonNull(componentInstance.getOriginType()) + && componentInstance.getOriginType().getValue().equals("Service Proxy"); + } + + private void addComponentInstanceInputs(Map dataTypes, + Map> componentInstancesInputs, + String instanceUniqueId, Map props) { + + List instanceInputsList = componentInstancesInputs.get(instanceUniqueId); + if (instanceInputsList != null) { + instanceInputsList.forEach(input -> { + Supplier supplier = () -> input.getValue() != null && !Objects.isNull(input.getValue()) ? input.getValue() : input.getDefaultValue(); + propertyConvertor.convertAndAddValue(dataTypes, props, input, supplier); + }); + } + } + + private void addPropertiesOfComponentInstance(final Map> componentInstancesProperties, + final Map dataTypes, + final String instanceUniqueId, + final Map props) { + + if (isNotEmpty(componentInstancesProperties)) { + componentInstancesProperties.get(instanceUniqueId) + // Converts and adds each value to property map + .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getValue)); + } + } + + private void addAttributesOfComponentInstance(final Map> componentInstancesAttributes, + final String instanceUniqueId, + final Map attribs) { + + if (isNotEmpty(componentInstancesAttributes) && componentInstancesAttributes.containsKey(instanceUniqueId)) { + componentInstancesAttributes.get(instanceUniqueId).stream() + // Filters out Attributes with empty default values + .filter(attributeDefinition -> StringUtils.isNotEmpty(attributeDefinition.getDefaultValue())) + // Converts and adds each value to attribute map + .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition)); + } + } + + private void addPropertiesOfParentComponent(Map dataTypes, + Component componentOfInstance, Map props) { + + List componentProperties = componentOfInstance.getProperties(); + if (isNotEmpty(componentProperties)) { + componentProperties.stream() + // Filters out properties with empty default values + .filter(prop -> StringUtils.isNotEmpty(prop.getDefaultValue())) + // Converts and adds each value to property map + .forEach(prop -> propertyConvertor.convertAndAddValue(dataTypes, props, prop, prop::getDefaultValue)); + } + } + + private void addAttributesOfParentComponent(final Component componentOfInstance, final Map attribs) { + + final List componentAttributes = componentOfInstance.getAttributes(); + if (isNotEmpty(componentAttributes)) { + componentAttributes.stream() + // Filters out Attributes with empty default values + .filter(attrib -> StringUtils.isNotEmpty(attrib.getDefaultValue())) + // Converts and adds each value to attribute map + .forEach(attributeDefinition -> attributeConverter.convertAndAddValue(attribs, attributeDefinition)); + } + } + + private ToscaNodeType createNodeType(Component component) { + ToscaNodeType toscaNodeType = new ToscaNodeType(); + if (ModelConverter.isAtomicComponent(component)) { + if (((Resource) component).getDerivedFrom() != null) { + toscaNodeType.setDerived_from(((Resource) component).getDerivedFrom().get(0)); + } + toscaNodeType.setDescription(component.getDescription()); + } else { + String derivedFrom = null != component.getDerivedFromGenericType() ? component.getDerivedFromGenericType() + : NATIVE_ROOT; + toscaNodeType.setDerived_from(derivedFrom); + } + return toscaNodeType; + } + + private Either, ToscaError> createProxyInterfaceTypes(Component container) { + + Map proxyInterfaceTypes = new HashMap<>(); + Either, ToscaError> res = Either.left(proxyInterfaceTypes); + List componentInstances = container.getComponentInstances(); + if (CollectionUtils.isEmpty(componentInstances)) { + return res; + } + Map serviceProxyInstanceList = new HashMap<>(); + componentInstances.stream() + .filter(this::isComponentOfTypeServiceProxy) + .forEach(inst -> serviceProxyInstanceList.put(inst.getToscaComponentName(), inst)); + if (MapUtils.isEmpty(serviceProxyInstanceList)) { + return res; + } + for (Entry entryProxy : serviceProxyInstanceList.entrySet()) { + Component serviceComponent; + ComponentParametersView componentParametersView = new ComponentParametersView(); + componentParametersView.disableAll(); + componentParametersView.setIgnoreInterfaces(false); + Either service = toscaOperationFacade + .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView); + if (service.isRight()) { + log.debug("Failed to fetch original service component with id {} for instance {}", + entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName()); + return Either.right(ToscaError.GENERAL_ERROR); + } else { + serviceComponent = service.left().value(); + } + + Either, StorageOperationStatus> lifecycleTypeEither = + interfaceLifecycleOperation.getAllInterfaceLifecycleTypes(serviceComponent.getModel()); + if (lifecycleTypeEither.isRight()) { + log.debug("Failed to retrieve global interface types :", lifecycleTypeEither.right().value()); + return Either.right(ToscaError.GENERAL_ERROR); + } + + List allGlobalInterfaceTypes = lifecycleTypeEither.left().value().values().stream() + .map(InterfaceDataDefinition::getType) + .collect(Collectors.toList()); + //Add interface types for local interfaces in the original service component for proxy + Map localInterfaceTypes = addInterfaceTypeElement(serviceComponent, + allGlobalInterfaceTypes); + if (MapUtils.isNotEmpty(localInterfaceTypes)) { + proxyInterfaceTypes.putAll(localInterfaceTypes); + } + + } + return Either.left(proxyInterfaceTypes); + } + + private Either, ToscaError> createProxyNodeTypes(Map componentCache, + Component container) { + + Map nodeTypesMap = new HashMap<>(); + Either, ToscaError> res = Either.left(nodeTypesMap); + + List componentInstances = container.getComponentInstances(); + + if (componentInstances == null || componentInstances.isEmpty()) { + return res; + } + Map serviceProxyInstanceList = new HashMap<>(); + List proxyInst = componentInstances.stream() + .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceProxy.name())) + .collect(Collectors.toList()); + if (proxyInst != null && !proxyInst.isEmpty()) { + for (ComponentInstance inst : proxyInst) { + serviceProxyInstanceList.put(inst.getToscaComponentName(), inst); + } + } + + if (serviceProxyInstanceList.isEmpty()) { + return res; + } + Either serviceProxyOrigin = toscaOperationFacade + .getLatestByName("serviceProxy", null); + if (serviceProxyOrigin.isRight()) { + log.debug("Failed to fetch normative service proxy resource by tosca name, error {}", + serviceProxyOrigin.right().value()); + return Either.right(ToscaError.NOT_SUPPORTED_TOSCA_TYPE); + } + Component origComponent = serviceProxyOrigin.left().value(); + + for (Entry entryProxy : serviceProxyInstanceList.entrySet()) { + Component serviceComponent = null; + ComponentParametersView componentParametersView = new ComponentParametersView(); + componentParametersView.disableAll(); + componentParametersView.setIgnoreCategories(false); + componentParametersView.setIgnoreProperties(false); + componentParametersView.setIgnoreInputs(false); + componentParametersView.setIgnoreInterfaces(false); + componentParametersView.setIgnoreRequirements(false); + Either service = toscaOperationFacade + .getToscaElement(entryProxy.getValue().getSourceModelUid(), componentParametersView); + if (service.isRight()) { + log.debug("Failed to fetch resource with id {} for instance {}", + entryProxy.getValue().getSourceModelUid(), entryProxy.getValue().getName()); + } else { + serviceComponent = service.left().value(); + } + + ToscaNodeType toscaNodeType = createProxyNodeType(componentCache, origComponent, serviceComponent, + entryProxy.getValue()); + nodeTypesMap.put(entryProxy.getKey(), toscaNodeType); + } + + return Either.left(nodeTypesMap); + } + + private void createServiceSubstitutionNodeTypes(final Map componentCache, + final Component container, final ToscaTemplate toscaNode) { + final List componentInstances = container.getComponentInstances(); + + if (CollectionUtils.isEmpty(componentInstances)) { + return; + } + final List serviceSubstitutionInstanceList = componentInstances.stream() + .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name())) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) { + for (ComponentInstance inst : serviceSubstitutionInstanceList) { + final Map nodeTypes = + toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types(); + convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode, + nodeTypes, true); + } + } + } + + private ToscaNodeType createProxyNodeType(Map componentCache, Component origComponent, + Component proxyComponent, ComponentInstance componentInstance) { + ToscaNodeType toscaNodeType = new ToscaNodeType(); + String derivedFrom = ((Resource) origComponent).getToscaResourceName(); + + toscaNodeType.setDerived_from(derivedFrom); + Either, JanusGraphOperationStatus> dataTypesEither = applicationDataTypeCache.getAll(origComponent.getModel()); + if (dataTypesEither.isRight()) { + log.debug("Failed to retrieve all data types {}", dataTypesEither.right().value()); + } + Map dataTypes = dataTypesEither.left().value(); + Map capabilities = this.capabilityRequirementConverter + .convertProxyCapabilities(componentCache, componentInstance, dataTypes); + + if (MapUtils.isNotEmpty(capabilities)) { + toscaNodeType.setCapabilities(capabilities); + } + List> proxyNodeTypeRequirements = this.capabilityRequirementConverter + .convertProxyRequirements(componentCache, componentInstance); + if (CollectionUtils.isNotEmpty(proxyNodeTypeRequirements)) { + toscaNodeType.setRequirements(proxyNodeTypeRequirements); + } + Optional> proxyProperties = getProxyNodeTypeProperties(proxyComponent, dataTypes); + proxyProperties.ifPresent(toscaNodeType::setProperties); + + Map interfaceMap = new HashMap<>(); + if (MapUtils.isEmpty(componentInstance.getInterfaces())) { + final Optional> proxyInterfaces = getProxyNodeTypeInterfaces(proxyComponent, dataTypes); + if (proxyInterfaces.isPresent()) { + interfaceMap = proxyInterfaces.get(); + } + } else { + interfaceMap = interfacesOperationsConverter + .getInterfacesMapFromComponentInstance(proxyComponent, componentInstance, dataTypes, false, false); + + } + interfacesOperationsConverter.removeInterfacesWithoutOperations(interfaceMap); + toscaNodeType.setInterfaces(MapUtils.isEmpty(interfaceMap) ? null : interfaceMap); + + return toscaNodeType; + } + + private Either convertComponentInstanceRequirements(Component component, + ComponentInstance componentInstance, + List relations, + ToscaNodeTemplate nodeTypeTemplate, + Component originComponent, + Map componentCache) { + + final List requirementDefinitionList = filterRequirements(componentInstance, + relations); + if (isNotEmpty(requirementDefinitionList)) { + try { + final List> toscaRequirements = buildRequirements(component, componentInstance, requirementDefinitionList, originComponent, componentCache); + if (!toscaRequirements.isEmpty()) { + nodeTypeTemplate.setRequirements(toscaRequirements); + } + } catch (final Exception e) { + log.debug("Failed to convert component instance requirements for the component instance {}. ", + componentInstance.getName(), e); + return Either.right(ToscaError.NODE_TYPE_REQUIREMENT_ERROR); + } + } + log.debug("Finished to convert requirements for the node type {} ", componentInstance.getName()); + return Either.left(nodeTypeTemplate); + } + + private List> buildRequirements(final Component component, + final ComponentInstance componentInstance, + final List filteredRelations, + final Component originComponent, + final Map componentCache) + throws ToscaExportException { + + final List> toscaRequirements = new ArrayList<>(); + for (RequirementCapabilityRelDef relationshipDefinition : filteredRelations) { + final Map toscaTemplateRequirementMap = + buildRequirement(componentInstance, originComponent, component.getComponentInstances(), relationshipDefinition, componentCache); + toscaRequirements.add(toscaTemplateRequirementMap); + } + + return toscaRequirements; + } + + private List filterRequirements(ComponentInstance componentInstance, + List relations) { + return relations.stream() + .filter(p -> componentInstance.getUniqueId().equals(p.getFromNode())).collect(Collectors.toList()); + } + + private Map buildRequirement(final ComponentInstance fromInstance, + final Component fromOriginComponent, + final List instancesList, + final RequirementCapabilityRelDef relationshipDefinition, + final Map componentCache) + throws ToscaExportException { + + final Map> reqMap = fromOriginComponent.getRequirements(); + final CapabilityRequirementRelationship capabilityRequirementRelationship = relationshipDefinition + .getRelationships().get(0); + final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation(); + + final ComponentInstance toInstance = instancesList.stream() + .filter(i -> relationshipDefinition.getToNode().equals(i.getUniqueId())) + .findFirst().orElse(null); + if (toInstance == null) { + final String errorMsg = String + .format("Failed to find a relation from the node %s to the node %s", fromInstance.getName(), + relationshipDefinition.getToNode()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + final Optional reqOpt = + findRequirement(fromOriginComponent, reqMap, relationshipInfo, fromInstance.getUniqueId()); + if (reqOpt.isEmpty()) { + final String errorMsg = String + .format("Failed to find a requirement with uniqueId %s on a component with uniqueId %s", + relationshipInfo.getRequirementUid(), fromOriginComponent.getUniqueId()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + final ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreComponentInstances(false); + filter.setIgnoreCapabilities(false); + filter.setIgnoreGroups(false); + final Either getOriginRes = + toscaOperationFacade.getToscaElement(toInstance.getActualComponentUid(), filter); + if (getOriginRes.isRight()) { + final String errorMsg = String.format( + "Failed to build substituted name for the requirement %s. " + + "Failed to get an origin component with uniqueId %s", + reqOpt.get().getName(), toInstance.getActualComponentUid()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + final Component toOriginComponent = getOriginRes.left().value(); + Optional capOpt = toOriginComponent.getCapabilities().get(reqOpt.get().getCapability()).stream() + .filter(c -> isCapabilityBelongToRelation(relationshipInfo, c)).findFirst(); + if (capOpt.isEmpty()) { + capOpt = findCapability(relationshipInfo, toOriginComponent, fromOriginComponent, reqOpt.get()); + if (capOpt.isEmpty()) { + final String errorMsg = String + .format("Failed to find a capability with name %s on a component with uniqueId %s", + relationshipInfo.getCapability(), fromOriginComponent.getUniqueId()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + } + return buildRequirement(fromOriginComponent, toOriginComponent, capOpt.get(), reqOpt.get(), + capabilityRequirementRelationship, toInstance, componentCache); + } + + private boolean isCapabilityBelongToRelation(RelationshipInfo reqAndRelationshipPair, + CapabilityDefinition capability) { + return capability.getName().equals(reqAndRelationshipPair.getCapability()) && (capability.getOwnerId() != null + && capability.getOwnerId().equals(reqAndRelationshipPair.getCapabilityOwnerId())); + } + + private Optional findCapability(RelationshipInfo reqAndRelationshipPair, + Component toOriginComponent, Component fromOriginComponent, + RequirementDefinition requirement) { + Optional cap = toOriginComponent.getCapabilities().get(requirement.getCapability()) + .stream().filter(c -> c.getType().equals(requirement.getCapability())).findFirst(); + if (!cap.isPresent()) { + log.debug("Failed to find a capability with name {} on a component with uniqueId {}", + reqAndRelationshipPair.getCapability(), fromOriginComponent.getUniqueId()); + } + return cap; + } + + private Map buildRequirement(final Component fromOriginComponent, + final Component toOriginComponent, + final CapabilityDefinition capability, + final RequirementDefinition requirement, + final CapabilityRequirementRelationship capabilityRequirementRelationship, + final ComponentInstance toInstance, + final Map componentCache) + throws ToscaExportException { + + List reducedPath = capability.getPath(); + if (capability.getOwnerId() != null) { + reducedPath = capabilityRequirementConverter + .getReducedPathByOwner(capability.getPath(), capability.getOwnerId()); + } + final RelationshipInfo relationshipInfo = capabilityRequirementRelationship.getRelation(); + final Either capabilityNameEither = capabilityRequirementConverter.buildSubstitutedName(componentCache, + toOriginComponent, reducedPath, relationshipInfo.getCapability(), capability.getPreviousName(), capability.getExternalName()); + if (capabilityNameEither.isRight()) { + final String errorMsg = String.format( + "Failed to build a substituted capability name for the capability with name %s on a component with uniqueId %s", + capabilityRequirementRelationship.getCapability(), toOriginComponent.getUniqueId()); + log.debug( + errorMsg); + throw new ToscaExportException(errorMsg); + } + final Either requirementNameEither = capabilityRequirementConverter + .buildSubstitutedName(componentCache, fromOriginComponent, + requirement.getPath(), relationshipInfo.getRequirement(), requirement.getPreviousName(), requirement.getExternalName()); + if (requirementNameEither.isRight()) { + final String errorMsg = String.format("Failed to build a substituted requirement name for the requirement " + + "with name %s on a component with uniqueId %s", + capabilityRequirementRelationship.getRequirement(), fromOriginComponent.getUniqueId()); + log.debug(errorMsg); + throw new ToscaExportException(errorMsg); + } + final ToscaTemplateRequirement toscaRequirement = new ToscaTemplateRequirement(); + final Map toscaReqMap = new HashMap<>(); + toscaRequirement.setNode(toInstance.getName()); + toscaRequirement.setCapability(capabilityNameEither.left().value()); + if (isNotEmpty(capabilityRequirementRelationship.getOperations())) { + toscaRequirement.setRelationship(new ToscaRelationshipBuilder().from(capabilityRequirementRelationship)); + } + toscaReqMap.put(requirementNameEither.left().value(), toscaRequirement); + return toscaReqMap; + } + + private Optional findRequirement(Component fromOriginComponent, + Map> reqMap, + RelationshipInfo reqAndRelationshipPair, + String fromInstanceId) { + for (List reqList : reqMap.values()) { + Optional reqOpt = reqList.stream().filter( + r -> isRequirementBelongToRelation(fromOriginComponent, reqAndRelationshipPair, r, fromInstanceId)) + .findFirst(); + if (reqOpt.isPresent()) { + return reqOpt; + } + } + return Optional.empty(); + } + + /** + * Allows detecting the requirement belonging to the received relationship The detection logic is: A requirement belongs to a relationship IF + * 1.The name of the requirement equals to the "requirement" field of the relation; AND 2. In case of a non-atomic resource, OwnerId of the + * requirement equals to requirementOwnerId of the relation OR uniqueId of toInstance equals to capabilityOwnerId of the relation + */ + private boolean isRequirementBelongToRelation(Component originComponent, RelationshipInfo reqAndRelationshipPair, + RequirementDefinition requirement, String fromInstanceId) { + if (!StringUtils.equals(requirement.getName(), reqAndRelationshipPair.getRequirement())) { + log.debug("Failed to find a requirement with name {} and reqAndRelationshipPair {}", requirement.getName(), + reqAndRelationshipPair.getRequirement()); + return false; + } + return ModelConverter.isAtomicComponent(originComponent) || isRequirementBelongToOwner(reqAndRelationshipPair, requirement, fromInstanceId, + originComponent); + } + + private boolean isRequirementBelongToOwner(RelationshipInfo reqAndRelationshipPair, RequirementDefinition requirement, String fromInstanceId, + Component originComponent) { + return StringUtils.equals(requirement.getOwnerId(), reqAndRelationshipPair.getRequirementOwnerId()) || ( + isCvfc(originComponent) && StringUtils.equals(fromInstanceId, reqAndRelationshipPair.getRequirementOwnerId()) || StringUtils + .equals(requirement.getOwnerId(), originComponent.getUniqueId())); + } + + private boolean isCvfc(Component component) { + return component.getComponentType() == ComponentTypeEnum.RESOURCE && ((Resource) component).getResourceType() == ResourceTypeEnum.CVFC; + } + + private Either, ToscaError> convertSubstitutionMappingCapabilities(final Component component, + final Map componentCache) { + Either, ToscaError> toscaCapabilitiesRes = + capabilityRequirementConverter.convertSubstitutionMappingCapabilities(componentCache, component); + if (toscaCapabilitiesRes.isRight()) { + log.debug("Failed convert capabilities for the component {}. ", component.getName()); + return Either.right(toscaCapabilitiesRes.right().value()); + } + if (isNotEmpty(toscaCapabilitiesRes.left().value())) { + log.debug("Finish convert capabilities for the component {}. ", component.getName()); + return Either.left(toscaCapabilitiesRes.left().value()); + } + log.debug("Finished to convert capabilities for the component {}. ", component.getName()); + + return Either.left(Collections.emptyMap()); + } + + private Either convertCapabilities(Map componentsCache, Component component, ToscaNodeType nodeType, + Map dataTypes) { + Map toscaCapabilities = capabilityRequirementConverter.convertCapabilities(componentsCache, component, dataTypes); + if (!toscaCapabilities.isEmpty()) { + nodeType.setCapabilities(toscaCapabilities); + } + log.debug("Finish convert Capabilities for node type"); + return Either.left(nodeType); + } + + private Map convertToNodeTemplateArtifacts(Map artifacts) { + if (artifacts == null) { + return null; + } + Map arts = new HashMap<>(); + for (Map.Entry entry : artifacts.entrySet()) { + ToscaTemplateArtifact artifact = new ToscaTemplateArtifact(); + artifact.setFile(entry.getValue().getFile()); + artifact.setType(entry.getValue().getType()); + artifact.setProperties(entry.getValue().getProperties()); + arts.put(entry.getKey(), artifact); + } + return arts; + } + + private NodeFilter convertToNodeTemplateNodeFilterComponent(CINodeFilterDataDefinition inNodeFilter) { + if (inNodeFilter == null) { + return null; + } + NodeFilter nodeFilter = new NodeFilter(); + ListDataDefinition origCapabilities = inNodeFilter.getCapabilities(); + ListDataDefinition origProperties = inNodeFilter.getProperties(); + List> capabilitiesCopy = new ArrayList<>(); + List>> propertiesCopy = new ArrayList<>(); + copyNodeFilterCapabilitiesTemplate(origCapabilities, capabilitiesCopy); + copyNodeFilterProperties(origProperties, propertiesCopy); + if (CollectionUtils.isNotEmpty(capabilitiesCopy)) { + nodeFilter.setCapabilities(capabilitiesCopy); + } + if (CollectionUtils.isNotEmpty(propertiesCopy)) { + nodeFilter.setProperties(propertiesCopy); + } + nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id())); + nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class); + return nodeFilter; + } + + private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) { + if (substitutionFilterDataDefinition == null) { + return null; + } + NodeFilter nodeFilter = new NodeFilter(); + ListDataDefinition origProperties = substitutionFilterDataDefinition.getProperties(); + List>> propertiesCopy = new ArrayList<>(); + copySubstitutionFilterProperties(origProperties, propertiesCopy); + if (CollectionUtils.isNotEmpty(propertiesCopy)) { + nodeFilter.setProperties(propertiesCopy); + } + nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id())); + return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class); + } + + private Object cloneToscaId(Object toscaId) { + return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass()); + } + + private Object cloneObjectFromYml(Object objToClone, Class classOfObj) { + String objectAsYml = yamlUtil.objectToYaml(objToClone); + return yamlUtil.yamlToObject(objectAsYml, classOfObj); + } + + private void copyNodeFilterCapabilitiesTemplate(ListDataDefinition origCapabilities, + List> capabilitiesCopy) { + if (origCapabilities == null || origCapabilities.getListToscaDataDefinition() == null || origCapabilities.getListToscaDataDefinition() + .isEmpty()) { + return; + } + for (RequirementNodeFilterCapabilityDataDefinition capability : origCapabilities.getListToscaDataDefinition()) { + Map capabilityFilterCopyMap = new HashMap<>(); + CapabilityFilter capabilityFilter = new CapabilityFilter(); + List>> propertiesCopy = new ArrayList<>(); + copyNodeFilterProperties(capability.getProperties(), propertiesCopy); + capabilityFilter.setProperties(propertiesCopy); + capabilityFilterCopyMap.put(capability.getName(), capabilityFilter); + capabilitiesCopy.add(capabilityFilterCopyMap); + } + } + + private void copyNodeFilterProperties(ListDataDefinition origProperties, + List>> propertiesCopy) { + if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) { + return; + } + Map> propertyMapCopy = new HashMap<>(); + for (RequirementNodeFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) { + for (String propertyInfoEntry : propertyDataDefinition.getConstraints()) { + Map> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class); + String propertyName = propertyDataDefinition.getName(); + if (propertyMapCopy.containsKey(propertyName)) { + addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName)); + } else { + if (propertyName != null) { + List propsList = new ArrayList<>(); + addPropertyConstraintValueToList(propertyName, propertyValObj, propsList); + propertyMapCopy.put(propertyName, propsList); + } else { + propertyMapCopy.putAll(propertyValObj); + } + } + } + } + propertyMapCopy.entrySet().stream().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry)); + } + + private void copySubstitutionFilterProperties(final ListDataDefinition origProperties, + final List>> propertiesCopy) { + if (origProperties == null || origProperties.getListToscaDataDefinition() == null || origProperties.isEmpty()) { + return; + } + final Map> propertyMapCopy = new HashMap<>(); + for (final RequirementSubstitutionFilterPropertyDataDefinition propertyDataDefinition : origProperties.getListToscaDataDefinition()) { + for (final String propertyInfoEntry : propertyDataDefinition.getConstraints()) { + final Map> propertyValObj = new YamlUtil().yamlToObject(propertyInfoEntry, Map.class); + final String propertyName = propertyDataDefinition.getName(); + if (propertyMapCopy.containsKey(propertyName)) { + addPropertyConstraintValueToList(propertyName, propertyValObj, propertyMapCopy.get(propertyName)); + } else { + if (propertyName != null) { + final List propsList = new ArrayList<>(); + addPropertyConstraintValueToList(propertyName, propertyValObj, propsList); + propertyMapCopy.put(propertyName, propsList); + } else { + propertyMapCopy.putAll(propertyValObj); + } + } + } + } + propertyMapCopy.entrySet().forEach(entry -> addCalculatedConstraintsIntoPropertiesList(propertiesCopy, entry)); + } + + private void addPropertyConstraintValueToList(String propertyName, Map> propertyValObj, List propsList) { + if (propertyValObj.containsKey(propertyName)) { + propsList.add(propertyValObj.get(propertyName)); + } else { + propsList.add(propertyValObj); + } + } + + private void addCalculatedConstraintsIntoPropertiesList(List>> propertiesCopy, Entry> entry) { + Map> tempMap = new HashMap<>(); + tempMap.put(entry.getKey(), entry.getValue()); + propertiesCopy.add(tempMap); + } + + private Map buildSubstitutionMappingPropertyMapping(final Component component) { + if (component == null || CollectionUtils.isEmpty(component.getInputs())) { + return Collections.emptyMap(); + } + return component.getInputs().stream().filter(InputDefinition::isMappedToComponentProperty).map(PropertyDataDefinition::getName) + .collect(Collectors.toMap(inputName -> inputName, inputName -> new String[]{inputName}, (inputName1, inputName2) -> inputName1)); + } + + private Map buildSubstitutionMappingAttributesMapping(final Component component) { + if (component == null || CollectionUtils.isEmpty(component.getOutputs())) { + return Collections.emptyMap(); + } + return component.getOutputs().stream().map(AttributeDataDefinition::getName) + .collect(Collectors.toMap(outputName -> outputName, outputName -> new String[]{outputName}, (outputName1, outputName2) -> outputName1)); + } + + Optional> getProxyNodeTypeProperties(Component proxyComponent, Map dataTypes) { + if (Objects.isNull(proxyComponent)) { + return Optional.empty(); + } + Map proxyProperties = new HashMap<>(); + addInputsToProperties(dataTypes, proxyComponent.getInputs(), proxyProperties); + if (CollectionUtils.isNotEmpty(proxyComponent.getProperties())) { + proxyProperties.putAll(proxyComponent.getProperties().stream() + .map(propertyDefinition -> resolvePropertyValueFromInput(propertyDefinition, proxyComponent.getInputs())).collect(Collectors + .toMap(PropertyDataDefinition::getName, + property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)))); + } + return MapUtils.isNotEmpty(proxyProperties) ? Optional.of(proxyProperties) : Optional.empty(); + } + + void addInputsToProperties(Map dataTypes, List componentInputs, + Map mergedProperties) { + if (CollectionUtils.isEmpty(componentInputs)) { + return; + } + for (InputDefinition input : componentInputs) { + ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT); + mergedProperties.put(input.getName(), property); + } + } + + Optional> getProxyNodeTypeInterfaces(Component proxyComponent, Map dataTypes) { + if (Objects.isNull(proxyComponent) || MapUtils.isEmpty(proxyComponent.getInterfaces())) { + return Optional.empty(); + } + Map proxyComponentInterfaces = proxyComponent.getInterfaces(); + //Unset artifact path for operation implementation for proxy node types as for operations with artifacts it is + + // always available in the proxy node template + removeOperationImplementationForProxyNodeType(proxyComponentInterfaces); + return Optional + .ofNullable(interfacesOperationsConverter.getInterfacesMap(proxyComponent, null, proxyComponentInterfaces, dataTypes, false, false)); + } + + private static class CustomRepresenter extends Representer { + + CustomRepresenter() { + super(); + this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment()); + this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute()); + // null representer is exceptional and it is stored as an instance + + // variable. + this.nullRepresenter = new RepresentNull(); + } + + public boolean validateGetInputValue(final Object valueObj) { + if (!(valueObj instanceof List) && !(valueObj instanceof String)) { + return false; + } + if (valueObj instanceof List) { + return ((List) valueObj).size() > 1; + } + return true; + } + + public boolean validateGetPropertyOrAttributeValue(final Object valueObj) { + if (valueObj instanceof List) { + return ((List) valueObj).size() > 1; + } + return false; + } + + @Override + protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { + if (propertyValue == null) { + return null; + } + // skip not relevant for Tosca property + if ("dependencies".equals(property.getName())) { + return null; + } + if (javaBean instanceof ToscaRelationshipTemplate && "name".equals(property.getName())) { + return null; + } + removeDefaultP(propertyValue); + NodeTuple defaultNode = super.representJavaBeanProperty(javaBean, property, propertyValue, customTag); + if (javaBean instanceof ToscaTopolgyTemplate && "relationshipTemplates".equals(property.getName())) { + return new NodeTuple(representData("relationship_templates"), defaultNode.getValueNode()); + } + return "_defaultp_".equals(property.getName()) ? new NodeTuple(representData("default"), defaultNode.getValueNode()) : defaultNode; + } + + private void removeDefaultP(final Object propertyValue) { + if (propertyValue instanceof Map) { + final Map mapPropertyValue = ((Map) propertyValue); + final Iterator iter = mapPropertyValue.entrySet().iterator(); + Object defaultValue = null; + while (iter.hasNext()) { + final Map.Entry entry = iter.next(); + if ("_defaultp_".equals(entry.getKey())) { + defaultValue = entry.getValue(); + iter.remove(); + } else if (entry.getValue() instanceof Map) { + removeDefaultP(entry.getValue()); + } + } + if (defaultValue != null) { + mapPropertyValue.putIfAbsent("default", defaultValue); + } + } + } + + @Override + protected MappingNode representJavaBean(Set properties, Object javaBean) { + // remove the bean type from the output yaml (!! ...) + if (!classTags.containsKey(javaBean.getClass())) { + addClassTag(javaBean.getClass(), Tag.MAP); + } + return super.representJavaBean(properties, javaBean); + } + + private class RepresentToscaAttribute implements Represent { + + @Override + public Node representData(Object data) { + final ToscaAttribute toscaAttribute = (ToscaAttribute) data; + return represent(toscaAttribute.asToscaMap()); + } + } + + private class RepresentToscaPropertyAssignment implements Represent { + + public Node representData(Object data) { + final ToscaPropertyAssignment toscaOperationAssignment = (ToscaPropertyAssignment) data; + if (toscaOperationAssignment.getValue() instanceof String) { + final String stringValue = (String) toscaOperationAssignment.getValue(); + if (isPropertyOrAttributeFunction(stringValue)) { + return representGetAttribute(stringValue); + } + return representScalar(Tag.STR, stringValue); + } + return represent(null); + } + + public Node representGetAttribute(final String getAttributeFunction) { + return represent(new Yaml().load(getAttributeFunction)); + } + + public boolean isPropertyOrAttributeFunction(final String value) { + try { + final Yaml yaml = new Yaml(); + final Object yamlObj = yaml.load(value); + if (!(yamlObj instanceof Map)) { + return false; + } + final Map getAttributeMap = (Map) yamlObj; + if (getAttributeMap.size() != 1) { + return false; + } + final List functionList = Arrays + .asList(GET_ATTRIBUTE.getFunctionName(), GET_INPUT.getFunctionName(), GET_PROPERTY.getFunctionName()); + final Optional function = getAttributeMap.keySet().stream() + .filter(key -> functionList.stream().anyMatch(function1 -> function1.equals(key))).findFirst(); + if (function.isEmpty()) { + return false; + } + final String functionName = function.get(); + final Object getAttributeValueObj = getAttributeMap.get(functionName); + if (GET_INPUT.getFunctionName().equals(functionName)) { + return validateGetInputValue(getAttributeValueObj); + } else { + return validateGetPropertyOrAttributeValue(getAttributeValueObj); + } + } catch (final Exception ignored) { + return false; + } + } + } + + private class RepresentNull implements Represent { + + @Override + public Node representData(Object data) { + // possible values are here http://yaml.org/type/null.html + return representScalar(Tag.NULL, ""); + } + } + } + + private static class UnsortedPropertyUtils extends PropertyUtils { + + @Override + protected Set createPropertySet(Class type, BeanAccess bAccess) { + Collection fields = getPropertiesMap(type, BeanAccess.FIELD).values(); + return new LinkedHashSet<>(fields); + } + } + + private Configuration getConfiguration() { + return ConfigurationManager.getConfigurationManager().getConfiguration(); + } }