X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=catalog-be%2Fsrc%2Fmain%2Fjava%2Forg%2Fopenecomp%2Fsdc%2Fbe%2Fcomponents%2Fcsar%2FYamlTemplateParsingHandler.java;h=5556548b50c6aba7396fbeb43fcadd1468f2677e;hb=39dd951527bf62568cf5815a6b1e4901c2b89c3f;hp=0006f833b2b0108ba1726bd74fe6c687d8e99120;hpb=bc741a1eeb2455903734a5603281cc17ca898d11;p=sdc.git diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java index 0006f833b2..5556548b50 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java @@ -19,16 +19,20 @@ * Modifications copyright (c) 2019 Nokia * ================================================================================ */ + package org.openecomp.sdc.be.components.csar; import static java.util.stream.Collectors.toList; +import static org.openecomp.sdc.be.components.impl.ImportUtils.Constants.QUOTE; import static org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; import static org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaListElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaMapElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.loadYamlAsStrictMap; +import static org.openecomp.sdc.be.model.tosca.ToscaType.STRING; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ARTIFACTS; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ATTRIBUTES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.CAPABILITIES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.CAPABILITY; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE; @@ -36,36 +40,48 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.FILE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GET_INPUT; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GROUPS; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.IMPLEMENTATION; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INPUTS; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INTERFACES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.IS_PASSWORD; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.MEMBERS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE_TYPE; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OPERATIONS; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OUTPUTS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.POLICIES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.PROPERTIES; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.RELATIONSHIP; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.RELATIONSHIP_TEMPLATES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIREMENTS; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_FILTERS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TARGETS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.VALID_SOURCE_TYPES; +import com.att.aft.dme2.internal.gson.reflect.TypeToken; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gson.Gson; import fj.data.Either; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; +import java.util.LinkedHashMap; 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.regex.Pattern; +import java.util.UUID; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -74,75 +90,127 @@ import org.openecomp.sdc.be.components.impl.GroupTypeBusinessLogic; import org.openecomp.sdc.be.components.impl.ImportUtils; import org.openecomp.sdc.be.components.impl.NodeFilterUploadCreator; import org.openecomp.sdc.be.components.impl.PolicyTypeBusinessLogic; +import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.components.utils.PropertiesUtils; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao; +import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyFilterConstraintDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.SubPropertyToscaFunction; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunction; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType; +import org.openecomp.sdc.be.datatypes.enums.ConstraintType; +import org.openecomp.sdc.be.datatypes.enums.FilterValueType; +import org.openecomp.sdc.be.datatypes.enums.PropertyFilterTargetType; import org.openecomp.sdc.be.model.CapabilityDefinition; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupTypeDefinition; import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.NodeTypeInfo; +import org.openecomp.sdc.be.model.OutputDefinition; import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; import org.openecomp.sdc.be.model.PolicyDefinition; import org.openecomp.sdc.be.model.PolicyTypeDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.UploadArtifactInfo; +import org.openecomp.sdc.be.model.UploadAttributeInfo; import org.openecomp.sdc.be.model.UploadCapInfo; import org.openecomp.sdc.be.model.UploadComponentInstanceInfo; +import org.openecomp.sdc.be.model.UploadInterfaceInfo; import org.openecomp.sdc.be.model.UploadPropInfo; import org.openecomp.sdc.be.model.UploadReqInfo; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition; +import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil; +import org.openecomp.sdc.be.ui.model.OperationUi; +import org.openecomp.sdc.be.ui.model.PropertyAssignmentUi; +import org.openecomp.sdc.be.utils.PropertyFilterConstraintDataDefinitionHelper; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.log.wrappers.Logger; -import org.springframework.stereotype.Component; import org.yaml.snakeyaml.parser.ParserException; /** * A handler class designed to parse the YAML file of the service template for a JAVA object */ -@Component +@org.springframework.stereotype.Component public class YamlTemplateParsingHandler { - private static final Pattern propertyValuePattern = Pattern.compile("[ ]*\\{[ ]*(str_replace=|token=|get_property=|concat=|get_attribute=)+"); private static final int SUB_MAPPING_CAPABILITY_OWNER_NAME_IDX = 0; private static final int SUB_MAPPING_CAPABILITY_NAME_IDX = 1; private static final Logger log = Logger.getLogger(YamlTemplateParsingHandler.class); - private Gson gson = new Gson(); - private JanusGraphDao janusGraphDao; - private GroupTypeBusinessLogic groupTypeBusinessLogic; - private AnnotationBusinessLogic annotationBusinessLogic; - private PolicyTypeBusinessLogic policyTypeBusinessLogic; - - public YamlTemplateParsingHandler(JanusGraphDao janusGraphDao, GroupTypeBusinessLogic groupTypeBusinessLogic, - AnnotationBusinessLogic annotationBusinessLogic, PolicyTypeBusinessLogic policyTypeBusinessLogic) { + private final Gson gson = new Gson(); + private final JanusGraphDao janusGraphDao; + private final GroupTypeBusinessLogic groupTypeBusinessLogic; + private final AnnotationBusinessLogic annotationBusinessLogic; + private final PolicyTypeBusinessLogic policyTypeBusinessLogic; + private final ServiceBusinessLogic serviceBusinessLogic; + private final ToscaFunctionYamlParsingHandler toscaFunctionYamlParsingHandler; + + public YamlTemplateParsingHandler(JanusGraphDao janusGraphDao, + GroupTypeBusinessLogic groupTypeBusinessLogic, + AnnotationBusinessLogic annotationBusinessLogic, + PolicyTypeBusinessLogic policyTypeBusinessLogic, + ServiceBusinessLogic serviceBusinessLogic, + final ToscaFunctionYamlParsingHandler toscaFunctionYamlParsingHandler + ) { this.janusGraphDao = janusGraphDao; this.groupTypeBusinessLogic = groupTypeBusinessLogic; this.annotationBusinessLogic = annotationBusinessLogic; this.policyTypeBusinessLogic = policyTypeBusinessLogic; + this.serviceBusinessLogic = serviceBusinessLogic; + this.toscaFunctionYamlParsingHandler = toscaFunctionYamlParsingHandler; } public ParsedToscaYamlInfo parseResourceInfoFromYAML(String fileName, String resourceYml, Map createdNodesToscaResourceNames, Map nodeTypesInfo, String nodeName, - org.openecomp.sdc.be.model.Component component) { + Component component, String interfaceTemplateYaml) { log.debug("#parseResourceInfoFromYAML - Going to parse yaml {} ", fileName); Map mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName); ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo(); - findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL).left().on(err -> failIfNotTopologyTemplate(fileName)); - parsedToscaYamlInfo.setInputs(getInputs(mappedToscaTemplate)); - parsedToscaYamlInfo.setInstances(getInstances(fileName, mappedToscaTemplate, createdNodesToscaResourceNames)); - parsedToscaYamlInfo.setGroups(getGroups(fileName, mappedToscaTemplate, component.getModel())); - if (component instanceof Resource) { - parsedToscaYamlInfo.setPolicies(getPolicies(fileName, mappedToscaTemplate, component.getModel())); - } - if (getSubstitutionMappings(mappedToscaTemplate) != null) { - parsedToscaYamlInfo.setSubstitutionMappingNodeType((String) getSubstitutionMappings(mappedToscaTemplate).get(NODE_TYPE.getElementName())); + Map mappedTopologyTemplate = (Map) findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE, + ToscaElementTypeEnum.ALL).left().on(err -> failIfNotTopologyTemplate(fileName)); + final Map mappedTopologyTemplateInputs = mappedTopologyTemplate.entrySet().stream() + .filter(entry -> entry.getKey().equals(INPUTS.getElementName())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + final Map mappedTopologyTemplateOutputs = mappedTopologyTemplate.entrySet().stream() + .filter(entry -> entry.getKey().equals(OUTPUTS.getElementName())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + parsedToscaYamlInfo.setInputs(getInputs(mappedTopologyTemplateInputs)); + parsedToscaYamlInfo.setOutputs(getOutputs(mappedTopologyTemplateOutputs)); + parsedToscaYamlInfo.setInstances(getInstances( + mappedToscaTemplate, + createdNodesToscaResourceNames + )); + associateRelationshipTemplatesToInstances(parsedToscaYamlInfo.getInstances(), mappedTopologyTemplate); + parsedToscaYamlInfo.setGroups(getGroups(mappedToscaTemplate, component.getModel())); + parsedToscaYamlInfo.setPolicies(getPolicies(mappedToscaTemplate, component.getModel())); + Map substitutionMappings = getSubstitutionMappings(mappedToscaTemplate); + if (substitutionMappings != null) { + if (component.isService()) { + if (interfaceTemplateYaml.isEmpty()) { + List properties = serviceBusinessLogic.fetchDerivedFromGenericType(component, null).getProperties(); + parsedToscaYamlInfo.setProperties(properties.stream().collect(Collectors.toMap(PropertyDefinition::getName, prop -> prop))); + } else { + parsedToscaYamlInfo.setProperties(getProperties(loadYamlAsStrictMap(interfaceTemplateYaml))); + } + parsedToscaYamlInfo.setSubstitutionFilterProperties(getSubstitutionFilterProperties(mappedToscaTemplate)); + } + if (substitutionMappings.get("properties") != null) { + parsedToscaYamlInfo.setSubstitutionMappingProperties((Map>) substitutionMappings.get("properties")); + } + parsedToscaYamlInfo.setSubstitutionMappingNodeType((String) substitutionMappings.get(NODE_TYPE.getElementName())); } log.debug("#parseResourceInfoFromYAML - The yaml {} has been parsed ", fileName); return parsedToscaYamlInfo; @@ -181,10 +249,80 @@ public class YamlTemplateParsingHandler { return inputs; } - private Map getPolicies(String fileName, Map toscaJson, String model) { - Map foundPolicies = findFirstToscaMapElement(toscaJson, POLICIES).left().on(err -> logPoliciesNotFound(fileName)); + private Map getOutputs(Map toscaJson) { + return ImportUtils.getOutputs(toscaJson).left().on(err -> new HashMap<>()); + } + + private Map getProperties(Map toscaJson) { + return ImportUtils.getProperties(toscaJson).left().on(err -> new HashMap<>()); + } + + private ListDataDefinition getSubstitutionFilterProperties(final Map toscaJson) { + final ListDataDefinition propertyList = new ListDataDefinition<>(); + final Map substitutionFilters = findFirstToscaMapElement(toscaJson, SUBSTITUTION_FILTERS).left().on(err -> new HashMap<>()); + if (MapUtils.isEmpty(substitutionFilters)) { + return propertyList; + } + final List> substitutionFilterProperties = (List>) substitutionFilters.get("properties"); + if (CollectionUtils.isEmpty(substitutionFilterProperties)) { + return propertyList; + } + for (final Map filterProps : substitutionFilterProperties) { + for (final Map.Entry propertyFilterEntry : filterProps.entrySet()) { + final String propertyName = propertyFilterEntry.getKey(); + final Object value = propertyFilterEntry.getValue(); + if (value instanceof List) { + final List> propertyFilterEntryValue = (List>) value; + for (final Map filterValueMap : propertyFilterEntryValue) { + final var substitutionFilterPropertyDataDefinition = new SubstitutionFilterPropertyDataDefinition(); + substitutionFilterPropertyDataDefinition.setName(propertyName); + substitutionFilterPropertyDataDefinition.setConstraints(createSubstitutionFilterConstraints(propertyName, filterValueMap)); + propertyList.add(substitutionFilterPropertyDataDefinition); + } + } else if (value instanceof Map) { + final Map filterValueMap = (Map) value; + final var substitutionFilterPropertyDataDefinition = new SubstitutionFilterPropertyDataDefinition(); + substitutionFilterPropertyDataDefinition.setName(propertyName); + substitutionFilterPropertyDataDefinition.setConstraints(createSubstitutionFilterConstraints(propertyName, filterValueMap)); + propertyList.add(substitutionFilterPropertyDataDefinition); + } + } + } + return propertyList; + } + + private List createSubstitutionFilterConstraints(final String name, final Map value) { + final List constraints = new ArrayList<>(); + for (final Map.Entry valueEntry : value.entrySet()) { + final var propertyFilterConstraint = new PropertyFilterConstraintDataDefinition(); + propertyFilterConstraint.setPropertyName(name); + propertyFilterConstraint.setOperator(ConstraintType.findByType(valueEntry.getKey()).orElse(null)); + propertyFilterConstraint.setTargetType(PropertyFilterTargetType.PROPERTY); + final Optional toscaFunction = PropertyFilterConstraintDataDefinitionHelper + .createToscaFunctionFromLegacyConstraintValue(valueEntry.getValue()); + if (toscaFunction.isPresent()) { + final ToscaFunction toscaFunction1 = toscaFunction.get(); + propertyFilterConstraint.setValue(toscaFunction1); + propertyFilterConstraint.setValueType( + PropertyFilterConstraintDataDefinitionHelper.convertFromToscaFunctionType(toscaFunction1.getType()).orElse(null) + ); + } else { + propertyFilterConstraint.setValue(valueEntry.getValue()); + propertyFilterConstraint.setValueType(FilterValueType.STATIC); + } + constraints.add(propertyFilterConstraint); + } + + return constraints; + } + + private Map getPolicies(Map toscaJson, String model) { + Map mappedTopologyTemplate = (Map) findToscaElement(toscaJson, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL) + .left().on(err -> new HashMap<>()); + Map foundPolicies = (Map) mappedTopologyTemplate.get(POLICIES.getElementName()); if (MapUtils.isNotEmpty(foundPolicies)) { - return foundPolicies.entrySet().stream().map(policyToCreate -> createPolicy(policyToCreate, model)).collect(Collectors.toMap(PolicyDefinition::getName, p -> p)); + return foundPolicies.entrySet().stream().map(policyToCreate -> createPolicy(policyToCreate, model)) + .collect(Collectors.toMap(PolicyDefinition::getName, p -> p)); } return Collections.emptyMap(); } @@ -208,11 +346,6 @@ public class YamlTemplateParsingHandler { return emptyPolicyDef; } - private Map logPoliciesNotFound(String fileName) { - log.debug("#logPoliciesNotFound - Policies were not found in the yaml template {}.", fileName); - return Collections.emptyMap(); - } - private void validateAndFillPolicy(PolicyDefinition emptyPolicyDefinition, Map policyTemplateJsonMap, String model) { String policyTypeName = (String) policyTemplateJsonMap.get(TYPE.getElementName()); if (StringUtils.isEmpty(policyTypeName)) { @@ -236,31 +369,41 @@ public class YamlTemplateParsingHandler { return policyTypeDefinition; } - private List validateFillPolicyProperties(PolicyTypeDefinition policyTypeDefinition, - Map policyTemplateJsonMap) { - if (MapUtils.isEmpty(policyTemplateJsonMap) || Objects.isNull(policyTypeDefinition)) { + private List validateFillPolicyProperties(final PolicyTypeDefinition policyTypeDefinition, + final Map policyTemplateJsonMap) { + if (policyTypeDefinition == null || CollectionUtils.isEmpty(policyTypeDefinition.getProperties()) + || MapUtils.isEmpty(policyTemplateJsonMap)) { return Collections.emptyList(); } - List propertyDataDefinitionList = new ArrayList<>(); - Map propertiesMap = (Map) policyTemplateJsonMap.get(PROPERTIES.getElementName()); - if (MapUtils.isEmpty(propertiesMap)) { + final Map propertiesJsonMap = (Map) policyTemplateJsonMap.get(PROPERTIES.getElementName()); + if (MapUtils.isEmpty(propertiesJsonMap)) { return Collections.emptyList(); } - if (CollectionUtils.isNotEmpty(policyTypeDefinition.getProperties())) { - propertyDataDefinitionList = policyTypeDefinition.getProperties().stream() - .map(propertyDefinition -> setPropertyValue(propertiesMap, propertyDefinition)).collect(Collectors.toList()); - } - return propertyDataDefinitionList; - } - - private PropertyDataDefinition setPropertyValue(Map propertiesMap, PropertyDataDefinition srcPropertyDataDefinition) { - PropertyDataDefinition newPropertyDef = new PropertyDataDefinition(srcPropertyDataDefinition); - String propertyName = newPropertyDef.getName(); - if (Objects.nonNull(propertiesMap.get(propertyName))) { - Object propValue = propertiesMap.get(propertyName); - newPropertyDef.setValue(PropertiesUtils.trimQuotes(gson.toJson(propValue))); - } - return newPropertyDef; + return propertiesJsonMap.entrySet().stream() + .map(propertyJson -> { + final PropertyDefinition originalProperty = + policyTypeDefinition.getProperties().stream() + .filter(propertyDefinition -> propertyDefinition.getName().equals(propertyJson.getKey())) + .findFirst() + .orElse(null); + if (originalProperty == null) { + return null; + } + final UploadPropInfo uploadPropInfo = buildProperty(propertyJson.getKey(), propertyJson.getValue()); + final PropertyDefinition propertyDefinition = new PropertyDefinition(originalProperty); + propertyDefinition.setToscaFunction(uploadPropInfo.getToscaFunction()); + propertyDefinition.setSubPropertyToscaFunctions(uploadPropInfo.getSubPropertyToscaFunctions()); + propertyDefinition.setGetInputValues(uploadPropInfo.getGet_input()); + propertyDefinition.setDescription(uploadPropInfo.getDescription()); + String propertyValue = gson.toJson(uploadPropInfo.getValue()); + if (!propertyDefinition.isToscaFunction()) { + propertyValue = PropertiesUtils.trimQuotes(propertyValue); + } + propertyDefinition.setValue(propertyValue); + return propertyDefinition; + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } private Map> validateFillPolicyTargets(Map policyTemplateJson) { @@ -272,66 +415,156 @@ public class YamlTemplateParsingHandler { return targets; } - private Map getInstances(String yamlName, Map toscaJson, - Map createdNodesToscaResourceNames) { - Map nodeTemlates = findFirstToscaMapElement(toscaJson, NODE_TEMPLATES).left().on(err -> failIfNoNodeTemplates(yamlName)); - return getInstances(toscaJson, createdNodesToscaResourceNames, nodeTemlates); + private Map getInstances( + Map toscaJson, + Map createdNodesToscaResourceNames + ) { + Map nodeTemplates = findFirstToscaMapElement(toscaJson, NODE_TEMPLATES) + .left().on(err -> new HashMap<>()); + if (nodeTemplates.isEmpty()) { + return Collections.emptyMap(); + } + return getInstances( + toscaJson, + createdNodesToscaResourceNames, + nodeTemplates + ); } - private Map getInstances(Map toscaJson, Map createdNodesToscaResourceNames, - Map nodeTemlates) { - Map moduleComponentInstances; + private Map getInstances( + Map toscaJson, + Map createdNodesToscaResourceNames, + Map nodeTemplates + ) { Map substitutionMappings = getSubstitutionMappings(toscaJson); - moduleComponentInstances = nodeTemlates.entrySet().stream() - .map(node -> buildModuleComponentInstanceInfo(node, substitutionMappings, createdNodesToscaResourceNames)) + return nodeTemplates.entrySet().stream() + .map(node -> buildModuleComponentInstanceInfo( + node, + substitutionMappings, + createdNodesToscaResourceNames + )) .collect(Collectors.toMap(UploadComponentInstanceInfo::getName, i -> i)); - return moduleComponentInstances; } private Map getSubstitutionMappings(Map toscaJson) { - Map substitutionMappings = null; Either, ResultStatusEnum> eitherSubstitutionMappings = findFirstToscaMapElement(toscaJson, SUBSTITUTION_MAPPINGS); if (eitherSubstitutionMappings.isLeft()) { - substitutionMappings = eitherSubstitutionMappings.left().value(); + return eitherSubstitutionMappings.left().value(); + } + return null; + } + + private void associateRelationshipTemplatesToInstances(final Map instances, + final Map toscaJson) { + if (MapUtils.isEmpty(instances)) { + return; + } + for (UploadComponentInstanceInfo instance : instances.values()) { + final Map> operations = new HashMap<>(); + final Map> requirements = instance.getRequirements(); + if (MapUtils.isNotEmpty(requirements)) { + requirements.values() + .forEach(requirementInfoList -> requirementInfoList.stream() + .filter(requirement -> StringUtils.isNotEmpty(requirement.getRelationshipTemplate())) + .forEach(requirement -> operations.put(requirement.getRelationshipTemplate(), + getOperationsFromRelationshipTemplate(toscaJson, requirement.getRelationshipTemplate())))); + } + instance.setOperations(operations); + } + } + + private Map getRelationshipTemplates(final Map toscaJson, final String relationshipTemplate) { + final Either, ResultStatusEnum> eitherRelationshipTemplates = findFirstToscaMapElement(toscaJson, RELATIONSHIP_TEMPLATES); + if (eitherRelationshipTemplates.isRight()) { + throw new ByActionStatusComponentException(ActionStatus.RELATIONSHIP_TEMPLATE_NOT_FOUND); + } + final Map relationshipTemplateMap = eitherRelationshipTemplates.left().value(); + final Map> relationship = (Map>) relationshipTemplateMap.get(relationshipTemplate); + if (relationship == null) { + throw new ByActionStatusComponentException(ActionStatus.RELATIONSHIP_TEMPLATE_DEFINITION_NOT_FOUND); + } + return relationship.get(INTERFACES.getElementName()); + } + + private List buildToscaInterfacesFromRelationship(final Map interfaces) { + return interfaces.entrySet().stream() + .map(entry -> { + final var toscaInterfaceDefinition = new ToscaInterfaceDefinition(); + toscaInterfaceDefinition.setType(entry.getKey()); + final Map toscaInterfaceMap = (Map) entry.getValue(); + toscaInterfaceDefinition.setOperations((Map) toscaInterfaceMap.get(OPERATIONS.getElementName())); + return toscaInterfaceDefinition; + }) + .collect(toList()); + } + + private Optional getImplementation(final Map operationToscaMap) { + if (MapUtils.isEmpty(operationToscaMap) || !operationToscaMap.containsKey(IMPLEMENTATION.getElementName())) { + return Optional.empty(); + } + return Optional.ofNullable(operationToscaMap.get(IMPLEMENTATION.getElementName())); + } + + private List getOperationsInputs(final Map operationToscaMap) { + if (MapUtils.isEmpty(operationToscaMap) || !operationToscaMap.containsKey(INPUTS.getElementName())) { + return Collections.emptyList(); + } + final Map inputsMap = (Map) operationToscaMap.get(INPUTS.getElementName()); + return inputsMap.entrySet().stream().map(this::buildInputAssignment).collect(toList()); + } + + private PropertyAssignmentUi buildInputAssignment(final Entry inputAssignmentMap) { + var propertyAssignmentUi = new PropertyAssignmentUi(); + propertyAssignmentUi.setName(inputAssignmentMap.getKey()); + propertyAssignmentUi.setValue(inputAssignmentMap.getValue().toString()); + propertyAssignmentUi.setType(STRING.getType()); + return propertyAssignmentUi; + } + + private List getOperationsFromRelationshipTemplate(final Map toscaJson, final String relationshipTemplate) { + final List operationUiList = new ArrayList<>(); + final List interfaces = + buildToscaInterfacesFromRelationship(getRelationshipTemplates(toscaJson, relationshipTemplate)); + interfaces.stream() + .filter(interfaceDefinition -> MapUtils.isNotEmpty(interfaceDefinition.getOperations())) + .forEach(interfaceDefinition -> + interfaceDefinition.getOperations() + .forEach((operationType, operationValue) -> + operationUiList.add(buildOperation(interfaceDefinition.getType(), operationType, (Map) operationValue)) + )); + return operationUiList; + } + + private OperationUi buildOperation(final String interfaceType, final String operationType, final Map operationToscaMap) { + var operationUi = new OperationUi(); + operationUi.setInterfaceType(interfaceType); + operationUi.setOperationType(operationType); + getImplementation(operationToscaMap).ifPresent(operationUi::setImplementation); + final List operationsInputs = getOperationsInputs(operationToscaMap); + if (CollectionUtils.isNotEmpty(operationsInputs)) { + operationUi.setInputs(operationsInputs); } - return substitutionMappings; + return operationUi; } @SuppressWarnings("unchecked") - private Map getGroups(String fileName, Map toscaJson, String model) { - Map foundGroups = findFirstToscaMapElement(toscaJson, GROUPS).left().on(err -> logGroupsNotFound(fileName)); - if (MapUtils.isNotEmpty(foundGroups) && matcheKey(foundGroups)) { + private Map getGroups(Map toscaJson, String model) { + Map mappedTopologyTemplate = (Map) findToscaElement(toscaJson, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL) + .left().on(err -> new HashMap<>()); + Map foundGroups = (Map) mappedTopologyTemplate.get(GROUPS.getElementName()); + if (MapUtils.isNotEmpty(foundGroups)) { Map groups = foundGroups.entrySet().stream().map(groupToCreate -> createGroup(groupToCreate, model)) .collect(Collectors.toMap(GroupDefinition::getName, g -> g)); Map substitutionMappings = getSubstitutionMappings(toscaJson); if (capabilitiesSubstitutionMappingsExist(substitutionMappings)) { - groups.entrySet().forEach(entry -> updateCapabilitiesNames(entry.getValue(), - getNamesToUpdate(entry.getKey(), (Map>) substitutionMappings.get(CAPABILITIES.getElementName())))); + groups.forEach((key, value) -> updateCapabilitiesNames(value, + getNamesToUpdate(key, (Map>) substitutionMappings.get(CAPABILITIES.getElementName())))); } return groups; } return new HashMap<>(); } - private boolean matcheKey(Map foundGroups) { - if (foundGroups != null && !foundGroups.isEmpty()) { - for (Map.Entry stringObjectEntry : foundGroups.entrySet()) { - String key = stringObjectEntry.getKey(); - if (key.contains("group")) { - if (foundGroups.get(key) instanceof Map) { - return true; - } - } - } - } - return false; - } - - private Map logGroupsNotFound(String fileName) { - log.debug("#logGroupsNotFound - Groups were not found in the yaml template {}.", fileName); - return new HashMap<>(); - } - private void updateCapabilitiesNames(GroupDefinition group, Map capabilityNames) { if (MapUtils.isNotEmpty(group.getCapabilities())) { group.getCapabilities().values().stream().flatMap(Collection::stream).filter(cap -> capabilityNames.containsKey(cap.getName())) @@ -361,7 +594,7 @@ public class YamlTemplateParsingHandler { rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); } } catch (ClassCastException e) { - log.debug("#createGroup - Failed to create the group {}. The exception occure", groupNameValue.getKey(), e); + log.debug("#createGroup - Failed to create the group {}. The exception occurres", groupNameValue.getKey(), e); rollbackWithException(ActionStatus.INVALID_YAML); } return group; @@ -406,28 +639,22 @@ public class YamlTemplateParsingHandler { } } - private void mergeGroupProperties(GroupDefinition groupInfo, Map parsedProperties) { - if (CollectionUtils.isNotEmpty(groupInfo.getProperties())) { - validateGroupProperties(parsedProperties, groupInfo); - groupInfo.getProperties().forEach(p -> mergeGroupProperty(p, parsedProperties)); + private void mergeGroupProperties(final GroupDefinition groupDefinition, final Map parsedProperties) { + if (CollectionUtils.isEmpty(groupDefinition.getProperties())) { + return; } + validateGroupProperties(parsedProperties, groupDefinition); + groupDefinition.getProperties().stream() + .filter(property -> parsedProperties.containsKey(property.getName())) + .forEach(property -> mergeGroupProperty(property, parsedProperties.get(property.getName()))); } - private void mergeGroupProperty(PropertyDataDefinition property, Map parsedProperties) { - if (parsedProperties.containsKey(property.getName())) { - Object propValue = parsedProperties.get(property.getName()); - if (valueNotContainsPattern(propertyValuePattern, propValue)) { - setPropertyValueAndGetInputsValues(property, propValue); - } - } - } - - private void setPropertyValueAndGetInputsValues(PropertyDataDefinition property, Object propValue) { - if (propValue != null) { - UploadPropInfo uploadPropInfo = buildProperty(property.getName(), propValue); - property.setValue(convertPropertyValue(ToscaPropertyType.isValidType(property.getType()), uploadPropInfo.getValue())); - property.setGetInputValues(uploadPropInfo.getGet_input()); - } + private void mergeGroupProperty(final PropertyDataDefinition property, final Object propertyYaml) { + final UploadPropInfo uploadPropInfo = buildProperty(property.getName(), propertyYaml); + property.setToscaFunction(uploadPropInfo.getToscaFunction()); + property.setSubPropertyToscaFunctions(uploadPropInfo.getSubPropertyToscaFunctions()); + property.setValue(convertPropertyValue(ToscaPropertyType.isValidType(property.getType()), uploadPropInfo.getValue())); + property.setGetInputValues(uploadPropInfo.getGet_input()); } private String convertPropertyValue(ToscaPropertyType type, Object value) { @@ -526,7 +753,7 @@ public class YamlTemplateParsingHandler { } private void validateGroupProperties(Map parsedProperties, GroupDefinition groupInfo) { - List parsedPropertiesNames = parsedProperties.entrySet().stream().map(Map.Entry::getKey).collect(toList()); + List parsedPropertiesNames = new ArrayList<>(parsedProperties.keySet()); validateProperties(groupInfo.getProperties().stream().map(PropertyDataDefinition::getName).collect(toList()), parsedPropertiesNames, ActionStatus.GROUP_PROPERTY_NOT_FOUND, groupInfo.getName(), groupInfo.getType()); } @@ -542,7 +769,7 @@ public class YamlTemplateParsingHandler { if (CollectionUtils.isNotEmpty(missingProperties)) { if (log.isDebugEnabled()) { log.debug("#validateProperties - Failed to validate properties. The properties {} are missing on {} of the type {}. ", - missingProperties.toString(), name, type); + missingProperties.toString(), name, type); } rollbackWithException(actionStatus, missingProperties.toString(), missingProperties.toString(), name, type); } @@ -592,9 +819,11 @@ public class YamlTemplateParsingHandler { } @SuppressWarnings("unchecked") - private UploadComponentInstanceInfo buildModuleComponentInstanceInfo(Map.Entry nodeTemplateJsonEntry, - Map substitutionMappings, - Map createdNodesToscaResourceNames) { + private UploadComponentInstanceInfo buildModuleComponentInstanceInfo( + Map.Entry nodeTemplateJsonEntry, + Map substitutionMappings, + Map createdNodesToscaResourceNames + ) { UploadComponentInstanceInfo nodeTemplateInfo = new UploadComponentInstanceInfo(); nodeTemplateInfo.setName(nodeTemplateJsonEntry.getKey()); try { @@ -608,9 +837,12 @@ public class YamlTemplateParsingHandler { setCapabilities(nodeTemplateInfo, nodeTemplateJsonMap); setArtifacts(nodeTemplateInfo, nodeTemplateJsonMap); updateProperties(nodeTemplateInfo, nodeTemplateJsonMap); + updateAttributes(nodeTemplateInfo, nodeTemplateJsonMap); + updateInterfaces(nodeTemplateInfo, nodeTemplateJsonMap); setDirectives(nodeTemplateInfo, nodeTemplateJsonMap); setNodeFilter(nodeTemplateInfo, nodeTemplateJsonMap); setSubstitutions(substitutionMappings, nodeTemplateInfo); + setOccurrencesAndInstanceCount(nodeTemplateInfo, nodeTemplateJsonMap); } else { rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); } @@ -638,13 +870,37 @@ public class YamlTemplateParsingHandler { private void updateProperties(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { - Map> properties = buildPropModuleFromYaml(nodeTemplateJsonMap); + Map> properties = + buildPropModuleFromYaml((Map) nodeTemplateJsonMap.get(PROPERTIES.getElementName())); if (!properties.isEmpty()) { nodeTemplateInfo.setProperties(properties); } } } + private void updateAttributes(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { + if (nodeTemplateJsonMap.containsKey(ATTRIBUTES.getElementName())) { + Map attributes = buildAttributeModuleFromYaml(nodeTemplateJsonMap); + if (!attributes.isEmpty()) { + nodeTemplateInfo.setAttributes(attributes); + } + } + } + + private void updateInterfaces( + UploadComponentInstanceInfo nodeTemplateInfo, + Map nodeTemplateJsonMap + ) { + if (nodeTemplateJsonMap.containsKey(INTERFACES.getElementName())) { + Map interfaces = buildInterfacesModuleFromYaml( + nodeTemplateJsonMap + ); + if (!interfaces.isEmpty()) { + nodeTemplateInfo.setInterfaces(interfaces); + } + } + } + private void setCapabilities(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(CAPABILITIES.getElementName())) { Map> eitherCapRes = createCapModuleFromYaml(nodeTemplateJsonMap); @@ -665,7 +921,7 @@ public class YamlTemplateParsingHandler { private void setRequirements(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(REQUIREMENTS.getElementName())) { - Map> regResponse = createReqModuleFromYaml(nodeTemplateJsonMap); + Map> regResponse = createReqModuleFromYaml(nodeTemplateJsonMap, nodeTemplateInfo.getName()); if (!regResponse.isEmpty()) { nodeTemplateInfo.setRequirements(regResponse); } @@ -696,14 +952,32 @@ public class YamlTemplateParsingHandler { } @SuppressWarnings("unchecked") - private Map> createReqModuleFromYaml(Map nodeTemplateJsonMap) { + private void setOccurrencesAndInstanceCount(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { + if (nodeTemplateJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName())) { + List occurrences = (List) nodeTemplateJsonMap.get(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName()); + nodeTemplateInfo.setMinOccurrences(occurrences.get(0).toString()); + nodeTemplateInfo.setMaxOccurrences(occurrences.get(1).toString()); + } + if (nodeTemplateJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.INSTANCE_COUNT.getElementName())) { + Object instanceCount = nodeTemplateJsonMap.get(TypeUtils.ToscaTagNamesEnum.INSTANCE_COUNT.getElementName()); + if (instanceCount instanceof Map) { + String instanceCountAsString = "{get_input:" + (String)((Map)instanceCount).get("get_input") + "}"; + nodeTemplateInfo.setInstanceCount(instanceCountAsString); + } else { + nodeTemplateInfo.setInstanceCount(instanceCount.toString()); + } + } + } + + @SuppressWarnings("unchecked") + private Map> createReqModuleFromYaml(Map nodeTemplateJsonMap, String nodeName) { Map> moduleRequirements = new HashMap<>(); Either, ResultStatusEnum> requirementsListRes = findFirstToscaListElement(nodeTemplateJsonMap, REQUIREMENTS); if (requirementsListRes.isLeft()) { for (Object jsonReqObj : requirementsListRes.left().value()) { String reqName = ((Map) jsonReqObj).keySet().iterator().next(); Object reqJson = ((Map) jsonReqObj).get(reqName); - addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName); + addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName, nodeName); } } else { Either, ResultStatusEnum> requirementsMapRes = findFirstToscaMapElement(nodeTemplateJsonMap, REQUIREMENTS); @@ -711,15 +985,16 @@ public class YamlTemplateParsingHandler { for (Map.Entry entry : requirementsMapRes.left().value().entrySet()) { String reqName = entry.getKey(); Object reqJson = entry.getValue(); - addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName); + addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName, nodeName); } } } return moduleRequirements; } - private void addModuleNodeTemplateReq(Map> moduleRequirements, Object requirementJson, String requirementName) { - UploadReqInfo requirement = buildModuleNodeTemplateReg(requirementJson); + private void addModuleNodeTemplateReq(Map> moduleRequirements, Object requirementJson, String requirementName, + String nodeName) { + UploadReqInfo requirement = buildModuleNodeTemplateReg(requirementJson, nodeName); requirement.setName(requirementName); if (moduleRequirements.containsKey(requirementName)) { moduleRequirements.get(requirementName).add(requirement); @@ -782,26 +1057,25 @@ public class YamlTemplateParsingHandler { if (nodeTemplateJsonMap.containsKey(FILE.getElementName())) { artifactTemplateInfo.setFile((String) nodeTemplateJsonMap.get(FILE.getElementName())); } + if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { + Map> props = + buildPropModuleFromYaml((Map) nodeTemplateJsonMap.get(PROPERTIES.getElementName())); + if (!props.isEmpty()) { + List properties = props.values().stream().flatMap(Collection::stream).collect(toList()); + artifactTemplateInfo.setProperties(properties); + } + } } @SuppressWarnings("unchecked") private Map> createCapModuleFromYaml(Map nodeTemplateJsonMap) { Map> moduleCap = new HashMap<>(); - Either, ResultStatusEnum> capabilitiesListRes = findFirstToscaListElement(nodeTemplateJsonMap, CAPABILITIES); - if (capabilitiesListRes.isLeft()) { - for (Object jsonCapObj : capabilitiesListRes.left().value()) { - String key = ((Map) jsonCapObj).keySet().iterator().next(); - Object capJson = ((Map) jsonCapObj).get(key); - addModuleNodeTemplateCap(moduleCap, capJson, key); - } - } else { - Either, ResultStatusEnum> capabilitiesMapRes = findFirstToscaMapElement(nodeTemplateJsonMap, CAPABILITIES); - if (capabilitiesMapRes.isLeft()) { - for (Map.Entry entry : capabilitiesMapRes.left().value().entrySet()) { - String capName = entry.getKey(); - Object capJson = entry.getValue(); - addModuleNodeTemplateCap(moduleCap, capJson, capName); - } + Map capabilities = (Map) nodeTemplateJsonMap.get(CAPABILITIES.getElementName()); + if (MapUtils.isNotEmpty(capabilities)) { + for (Map.Entry entry : capabilities.entrySet()) { + String capName = entry.getKey(); + Object capJson = entry.getValue(); + addModuleNodeTemplateCap(moduleCap, capJson, capName); } } return moduleCap; @@ -845,7 +1119,8 @@ public class YamlTemplateParsingHandler { } } if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) { - Map> props = buildPropModuleFromYaml(nodeTemplateJsonMap); + Map> props = + buildPropModuleFromYaml((Map) nodeTemplateJsonMap.get(PROPERTIES.getElementName())); if (!props.isEmpty()) { List properties = props.values().stream().flatMap(Collection::stream).collect(toList()); capTemplateInfo.setProperties(properties); @@ -854,7 +1129,7 @@ public class YamlTemplateParsingHandler { } @SuppressWarnings("unchecked") - private UploadReqInfo buildModuleNodeTemplateReg(Object regObject) { + private UploadReqInfo buildModuleNodeTemplateReg(Object regObject, String nodeName) { UploadReqInfo regTemplateInfo = new UploadReqInfo(); if (regObject instanceof String) { String nodeTemplateJsonString = (String) regObject; @@ -867,24 +1142,57 @@ public class YamlTemplateParsingHandler { if (nodeTemplateJsonMap.containsKey(CAPABILITY.getElementName())) { regTemplateInfo.setCapabilityName((String) nodeTemplateJsonMap.get(CAPABILITY.getElementName())); } + if (nodeTemplateJsonMap.containsKey(RELATIONSHIP.getElementName())) { + final String template = (String) nodeTemplateJsonMap.get(RELATIONSHIP.getElementName()); + if (StringUtils.isNotEmpty(nodeName) && template.contains(nodeName)) { + regTemplateInfo.setRelationshipTemplate(template); + } + } } return regTemplateInfo; } - private Map> buildPropModuleFromYaml(Map nodeTemplateJsonMap) { - Map> moduleProp = new HashMap<>(); - Either, ResultStatusEnum> toscaProperties = findFirstToscaMapElement(nodeTemplateJsonMap, PROPERTIES); - if (toscaProperties.isLeft()) { - Map jsonProperties = toscaProperties.left().value(); - for (Map.Entry jsonPropObj : jsonProperties.entrySet()) { - if (valueNotContainsPattern(propertyValuePattern, jsonPropObj.getValue())) { - addProperty(moduleProp, jsonPropObj); - } + private Map buildAttributeModuleFromYaml( + Map nodeTemplateJsonMap) { + Map moduleAttribute = new HashMap<>(); + Either, ResultStatusEnum> toscaAttributes = findFirstToscaMapElement(nodeTemplateJsonMap, ATTRIBUTES); + if (toscaAttributes.isLeft()) { + Map jsonAttributes = toscaAttributes.left().value(); + for (Map.Entry jsonAttributeObj : jsonAttributes.entrySet()) { + UploadAttributeInfo attributeDef = buildAttribute(jsonAttributeObj.getKey(), jsonAttributeObj.getValue()); + moduleAttribute.put(attributeDef.getName(), attributeDef); } } + return moduleAttribute; + } + + private UploadAttributeInfo buildAttribute(String attributeName, Object attributeValue) { + UploadAttributeInfo attributeDef = new UploadAttributeInfo(); + attributeDef.setValue(attributeValue); + attributeDef.setName(attributeName); + return attributeDef; + } + + private Map> buildPropModuleFromYaml(final Map propertyMap) { + final Map> moduleProp = new HashMap<>(); + propertyMap.entrySet().forEach(propertyMapEntry -> addProperty(moduleProp, propertyMapEntry)); return moduleProp; } + private Map buildInterfacesModuleFromYaml( + Map nodeTemplateJsonMap + ) { + Map moduleInterfaces = new HashMap<>(); + Either, ResultStatusEnum> toscaInterfaces = findFirstToscaMapElement(nodeTemplateJsonMap, INTERFACES); + if (toscaInterfaces.isLeft()) { + Map jsonInterfaces = toscaInterfaces.left().value(); + for (Map.Entry jsonInterfacesObj : jsonInterfaces.entrySet()) { + addInterfaces(moduleInterfaces, jsonInterfacesObj); + } + } + return moduleInterfaces; + } + private void addProperty(Map> moduleProp, Map.Entry jsonPropObj) { UploadPropInfo propertyDef = buildProperty(jsonPropObj.getKey(), jsonPropObj.getValue()); if (moduleProp.containsKey(propertyDef.getName())) { @@ -896,37 +1204,239 @@ public class YamlTemplateParsingHandler { } } + private void addInterfaces(Map moduleInterface, Map.Entry jsonPropObj) { + UploadInterfaceInfo interfaceInfo = buildInterface(jsonPropObj.getKey(), jsonPropObj.getValue()); + moduleInterface.put(jsonPropObj.getKey(), interfaceInfo); + } + @SuppressWarnings("unchecked") - private UploadPropInfo buildProperty(String propName, Object propValue) { - UploadPropInfo propertyDef = new UploadPropInfo(); - propertyDef.setValue(propValue); + private UploadPropInfo buildProperty(String propName, Object propValueObj) { + final var propertyDef = new UploadPropInfo(); + propertyDef.setValue(propValueObj); propertyDef.setName(propName); - if (propValue instanceof Map) { - if (((Map) propValue).containsKey(TYPE.getElementName())) { - propertyDef.setType(((Map) propValue).get(TYPE.getElementName()).toString()); + if (propValueObj instanceof Map) { + final Map propValueMap = (Map) propValueObj; + if (propValueMap.containsKey(TYPE.getElementName())) { + propertyDef.setType(propValueMap.get(TYPE.getElementName()).toString()); } - if (containsGetInput(propValue)) { - fillInputRecursively(propName, (Map) propValue, propertyDef); + if (containsGetInput(propValueObj)) { + fillInputRecursively(propName, propValueMap, propertyDef); } - if (((Map) propValue).containsKey(DESCRIPTION.getElementName())) { - propertyDef.setDescription(((Map) propValue).get(DESCRIPTION.getElementName()).toString()); + if (toscaFunctionYamlParsingHandler.isPropertyValueToscaFunction(propValueObj)) { + toscaFunctionYamlParsingHandler.buildToscaFunctionBasedOnPropertyValue(propValueMap).ifPresent(propertyDef::setToscaFunction); + } else { + final Collection subPropertyToscaFunctions = + buildSubPropertyToscaFunctions(propValueMap, new ArrayList<>()); + if (CollectionUtils.isNotEmpty(subPropertyToscaFunctions)) { + Collection existingSubPropertyToscaFunctions = propertyDef.getSubPropertyToscaFunctions(); + if (existingSubPropertyToscaFunctions == null) { + propertyDef.setSubPropertyToscaFunctions(subPropertyToscaFunctions); + } else { + propertyDef.getSubPropertyToscaFunctions().addAll(subPropertyToscaFunctions); + } + } + } + if (propValueMap.containsKey(DESCRIPTION.getElementName())) { + propertyDef.setDescription((propValueMap).get(DESCRIPTION.getElementName()).toString()); } - if (((Map) propValue).containsKey(DEFAULT_VALUE.getElementName())) { - propertyDef.setValue(((Map) propValue).get(DEFAULT_VALUE.getElementName())); + if (propValueMap.containsKey(DEFAULT_VALUE.getElementName())) { + propertyDef.setValue(propValueMap.get(DEFAULT_VALUE.getElementName())); } - if (((Map) propValue).containsKey(IS_PASSWORD.getElementName())) { - propertyDef.setPassword(Boolean.getBoolean(((Map) propValue).get(IS_PASSWORD.getElementName()).toString())); + if (propValueMap.containsKey(IS_PASSWORD.getElementName())) { + propertyDef.setPassword(Boolean.getBoolean(propValueMap.get(IS_PASSWORD.getElementName()).toString())); } else { - propertyDef.setValue(propValue); + propertyDef.setValue(propValueObj); } - } else if (propValue instanceof List) { - List propValueList = (List) propValue; - fillInputsListRecursively(propertyDef, propValueList); - propertyDef.setValue(propValue); + } else if (propValueObj instanceof List) { + fillInputsListRecursively(propertyDef, (List) propValueObj); + propertyDef.setValue(propValueObj); } return propertyDef; } + private Collection buildSubPropertyToscaFunctions(final Map propValueMap, final List path) { + Collection subPropertyToscaFunctions = new ArrayList<>(); + propValueMap.entrySet().stream().filter(entry -> entry.getValue() instanceof Map).forEach(entry -> { + List subPropertyPath = new ArrayList<>(path); + subPropertyPath.add(entry.getKey()); + if (ToscaFunctionType.findType(((Map) entry.getValue()).keySet().iterator().next()).isPresent()) { + Optional toscaFunction = + toscaFunctionYamlParsingHandler.buildToscaFunctionBasedOnPropertyValue((Map) entry.getValue()); + if (toscaFunction.isPresent()) { + SubPropertyToscaFunction subPropertyToscaFunction = new SubPropertyToscaFunction(); + subPropertyToscaFunction.setToscaFunction(toscaFunction.get()); + subPropertyToscaFunction.setSubPropertyPath(subPropertyPath); + subPropertyToscaFunctions.add(subPropertyToscaFunction); + } + } else { + subPropertyToscaFunctions.addAll(buildSubPropertyToscaFunctions((Map) entry.getValue(), subPropertyPath)); + } + }); + return subPropertyToscaFunctions; + } + + private UploadInterfaceInfo buildInterface(String interfaceName, Object interfaceValue) { + UploadInterfaceInfo interfaceDef = new UploadInterfaceInfo(); + interfaceDef.setValue(interfaceValue); + interfaceDef.setName(interfaceName); + interfaceDef.setKey(interfaceName); + Map operations = new HashMap<>(); + if (interfaceValue instanceof Map) { + Map operationsMap = (Map) interfaceValue; + for (Map.Entry operationEntry : operationsMap.entrySet()) { + OperationDataDefinition operationDef = new OperationDataDefinition(); + operationDef.setName(operationEntry.getKey()); + Map operationValue = (Map) operationEntry.getValue(); + if (operationValue.containsKey(DESCRIPTION.getElementName())) { + operationDef.setDescription(operationValue.get(DESCRIPTION.getElementName()).toString()); + } + operationDef.setImplementation(handleOperationImplementation(operationValue).orElse(new ArtifactDataDefinition())); + if (operationValue.containsKey(INPUTS.getElementName())) { + final Map interfaceInputs = (Map) operationValue.get(INPUTS.getElementName()); + operationDef.setInputs(handleInterfaceOperationInputs(interfaceInputs)); + } + operations.put(operationEntry.getKey(), operationDef); + } + interfaceDef.setOperations(operations); + if (operationsMap.containsKey(TYPE.getElementName())) { + interfaceDef.setType(((Map) interfaceValue).get(TYPE.getElementName()).toString()); + } + } + return interfaceDef; + } + + private ListDataDefinition handleInterfaceOperationInputs(final Map interfaceInputs) { + final ListDataDefinition inputs = new ListDataDefinition<>(); + for (final Entry interfaceInput : interfaceInputs.entrySet()) { + final OperationInputDefinition operationInput = new OperationInputDefinition(); + operationInput.setUniqueId(UUID.randomUUID().toString()); + operationInput.setInputId(operationInput.getUniqueId()); + operationInput.setName(interfaceInput.getKey()); + + handleInputToscaDefinition(interfaceInput.getKey(), interfaceInput.getValue(), operationInput); + inputs.add(operationInput); + } + return inputs; + } + + private void handleInputToscaDefinition( + final String inputName, + final Object value, + final OperationInputDefinition operationInput + ) { + if (value instanceof Map) { + final Map valueMap = (Map) value; + log.debug("Creating interface operation input '{}'", inputName); + Type type = new TypeToken>() { + }.getType(); + String stringValue = gson.toJson(value, type); + if (toscaFunctionYamlParsingHandler.isPropertyValueToscaFunction(value)) { + toscaFunctionYamlParsingHandler.buildToscaFunctionBasedOnPropertyValue((Map) value) + .ifPresent(operationInput::setToscaFunction); + } else { + final Collection subPropertyToscaFunctions = buildSubPropertyToscaFunctions(valueMap, new ArrayList<>()); + if (CollectionUtils.isNotEmpty(subPropertyToscaFunctions)) { + Collection existingSubPropertyToscaFunctions = operationInput.getSubPropertyToscaFunctions(); + if (existingSubPropertyToscaFunctions == null) { + operationInput.setSubPropertyToscaFunctions(subPropertyToscaFunctions); + } else { + operationInput.getSubPropertyToscaFunctions().addAll(subPropertyToscaFunctions); + } + } + } + operationInput.setValue(stringValue); + } + if (value instanceof String) { + final String stringValue = (String) value; + operationInput.setDefaultValue(stringValue); + operationInput.setToscaDefaultValue(stringValue); + operationInput.setValue(stringValue); + } + operationInput.setType("string"); + if (operationInput.getValue() == null) { + operationInput.setValue(String.valueOf(value)); + } + } + + private Optional handleOperationImplementation( + final Map operationDefinitionMap + ) { + if (!operationDefinitionMap.containsKey(IMPLEMENTATION.getElementName())) { + return Optional.empty(); + } + final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition(); + if (operationDefinitionMap.get(IMPLEMENTATION.getElementName()) instanceof Map && + ((Map) operationDefinitionMap.get(IMPLEMENTATION.getElementName())).containsKey("primary")) { + + final Object primary = ((Map) operationDefinitionMap.get(IMPLEMENTATION.getElementName())).get("primary"); + if (primary instanceof Map) { + Map implDetails = (Map) primary; + + if (implDetails.get("file") != null) { + final String file = implDetails.get("file").toString(); + artifactDataDefinition.setArtifactName(generateArtifactName(file)); + } + if (implDetails.get("type") != null) { + artifactDataDefinition.setArtifactType(implDetails.get("type").toString()); + } + if (implDetails.get("artifact_version") != null) { + artifactDataDefinition.setArtifactVersion(implDetails.get("artifact_version").toString()); + } + + if (implDetails.get("properties") instanceof Map) { + Map properties = (Map) implDetails.get("properties"); + properties.forEach((k, v) -> { + ToscaPropertyType type = getTypeFromObject(v); + if (type != null) { + PropertyDataDefinition propertyDef = new PropertyDataDefinition(); + propertyDef.setName(k); + propertyDef.setValue(v.toString()); + artifactDataDefinition.addProperty(propertyDef); + } + }); + } + } else { + artifactDataDefinition.setArtifactName(generateArtifactName(primary.toString())); + } + } + + if (operationDefinitionMap.get(IMPLEMENTATION.getElementName()) instanceof Map && + ((Map) operationDefinitionMap.get(IMPLEMENTATION.getElementName())).containsKey("timeout")) { + final Object timeOut = ((Map) operationDefinitionMap.get(IMPLEMENTATION.getElementName())).get("timeout"); + artifactDataDefinition.setTimeout((Integer)timeOut); + } + + if (operationDefinitionMap.get(IMPLEMENTATION.getElementName()) instanceof String) { + final String implementation = (String) operationDefinitionMap.get(IMPLEMENTATION.getElementName()); + artifactDataDefinition.setArtifactName(generateArtifactName(implementation)); + } + return Optional.of(artifactDataDefinition); + } + + private String generateArtifactName(final String name) { + if (OperationArtifactUtil.artifactNameIsALiteralValue(name)) { + return name; + } else { + return QUOTE + name + QUOTE; + } + } + + private ToscaPropertyType getTypeFromObject(final Object value) { + if (value instanceof String) { + return ToscaPropertyType.STRING; + } + if (value instanceof Integer) { + return ToscaPropertyType.INTEGER; + } + if (value instanceof Boolean) { + return ToscaPropertyType.BOOLEAN; + } + if (value instanceof Float || value instanceof Double) { + return ToscaPropertyType.FLOAT; + } + return null; + } + @SuppressWarnings("unchecked") private boolean containsGetInput(Object propValue) { return ((Map) propValue).containsKey(GET_INPUT.getElementName()) || ImportUtils.containsGetInput(propValue); @@ -934,9 +1444,22 @@ public class YamlTemplateParsingHandler { @SuppressWarnings("unchecked") private void fillInputsListRecursively(UploadPropInfo propertyDef, List propValueList) { + int index = 0; for (Object objValue : propValueList) { if (objValue instanceof Map) { Map objMap = (Map) objValue; + Map propValueMap = new HashMap<>(); + propValueMap.put(String.valueOf(index), objValue); + final Collection subPropertyToscaFunctions = + buildSubPropertyToscaFunctions(propValueMap, new ArrayList<>()); + if (CollectionUtils.isNotEmpty(subPropertyToscaFunctions)) { + Collection existingSubPropertyToscaFunctions = propertyDef.getSubPropertyToscaFunctions(); + if (existingSubPropertyToscaFunctions == null) { + propertyDef.setSubPropertyToscaFunctions(subPropertyToscaFunctions); + } else { + propertyDef.getSubPropertyToscaFunctions().addAll(subPropertyToscaFunctions); + } + } if (objMap.containsKey(GET_INPUT.getElementName())) { fillInputRecursively(propertyDef.getName(), objMap, propertyDef); } else { @@ -947,6 +1470,7 @@ public class YamlTemplateParsingHandler { List propSubValueList = (List) objValue; fillInputsListRecursively(propertyDef, propSubValueList); } + index++; } } @@ -987,7 +1511,7 @@ public class YamlTemplateParsingHandler { @SuppressWarnings("unchecked") private void findAndFillInputRecursively(Map propValue, UploadPropInfo propertyDef) { - for (Map.Entry entry : propValue.entrySet()) { + for (Map.Entry entry : propValue.entrySet()) { String propName = entry.getKey(); Object value = entry.getValue(); if (value instanceof Map) { @@ -999,9 +1523,7 @@ public class YamlTemplateParsingHandler { } private void fillInputsRecursively(UploadPropInfo propertyDef, String propName, List inputs) { - inputs.stream() - .filter(Map.class::isInstance) - .forEach(o -> fillInputRecursively(propName, (Map) o, propertyDef)); + inputs.stream().filter(Map.class::isInstance).forEach(o -> fillInputRecursively(propName, (Map) o, propertyDef)); } @SuppressWarnings("unchecked") @@ -1027,15 +1549,6 @@ public class YamlTemplateParsingHandler { } } - private boolean valueNotContainsPattern(Pattern pattern, Object propValue) { - return propValue == null || !pattern.matcher(propValue.toString()).find(); - } - - private Map failIfNoNodeTemplates(String fileName) { - janusGraphDao.rollback(); - throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName); - } - private Object failIfNotTopologyTemplate(String fileName) { janusGraphDao.rollback(); throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName); @@ -1049,8 +1562,8 @@ public class YamlTemplateParsingHandler { private void failOnMissingCapabilityTypes(GroupDefinition groupDefinition, List missingCapTypes) { if (log.isDebugEnabled()) { log.debug( - "#failOnMissingCapabilityTypes - Failed to validate the capabilities of the group {}. The capability types {} are missing on the group type {}. ", - groupDefinition.getName(), missingCapTypes.toString(), groupDefinition.getType()); + "#failOnMissingCapabilityTypes - Failed to validate the capabilities of the group {}. The capability types {} are missing on the group type {}. ", + groupDefinition.getName(), missingCapTypes.toString(), groupDefinition.getType()); } if (CollectionUtils.isNotEmpty(missingCapTypes)) { rollbackWithException(ActionStatus.MISSING_CAPABILITY_TYPE, missingCapTypes.toString()); @@ -1060,8 +1573,8 @@ public class YamlTemplateParsingHandler { private void failOnMissingCapabilityNames(GroupDefinition groupDefinition, List missingCapNames) { if (log.isDebugEnabled()) { log.debug( - "#failOnMissingCapabilityNames - Failed to validate the capabilities of the group {}. The capabilities with the names {} are missing on the group type {}. ", - groupDefinition.getName(), missingCapNames.toString(), groupDefinition.getType()); + "#failOnMissingCapabilityNames - Failed to validate the capabilities of the group {}. The capabilities with the names {} are missing on the group type {}. ", + groupDefinition.getName(), missingCapNames.toString(), groupDefinition.getType()); } rollbackWithException(ActionStatus.MISSING_CAPABILITIES, missingCapNames.toString(), CapabilityDataDefinition.OwnerType.GROUP.getValue(), groupDefinition.getName());